Compare commits

...

461 Commits

Author SHA1 Message Date
snipe b1359c3277 Merge remote-tracking branch 'origin/develop'
Signed-off-by: snipe <snipe@snipe.net>

# Conflicts:
#	config/version.php
2025-08-28 18:34:14 +01:00
snipe 9c0202e5ce Bumped to 8.3.0
Signed-off-by: snipe <snipe@snipe.net>
2025-08-28 18:33:46 +01:00
snipe 39ef353073 Bumped version
Signed-off-by: snipe <snipe@snipe.net>
2025-08-28 18:32:07 +01:00
snipe 0ba8f5cc5a Merge remote-tracking branch 'origin/develop' 2025-08-28 18:06:29 +01:00
snipe d1129081df Asset nothing is sent if send_welcome is not checked/passed
Signed-off-by: snipe <snipe@snipe.net>
2025-08-28 18:05:40 +01:00
snipe 315a812df5 Fixed typos
Signed-off-by: snipe <snipe@snipe.net>
2025-08-28 16:41:56 +01:00
snipe 6fb9e2c38e Merge remote-tracking branch 'origin/develop' 2025-08-28 16:12:18 +01:00
snipe cfc979acf0 Merge pull request #17432 from oolivero45/patch-1
Fixed #17431: EULA not displaying on asset acceptance page
2025-08-28 16:09:36 +01:00
snipe d7407d70a3 Merge pull request #17741 from grokability/improved-user-create-tests
Improved user create tests
2025-08-28 13:32:46 +01:00
snipe 8ccd2e97a8 Improved user create tests
Signed-off-by: snipe <snipe@snipe.net>
2025-08-28 13:27:08 +01:00
snipe 988204619f Merge pull request #17740 from grokability/renamed-user-test
Renamed the test for consistency
2025-08-28 13:05:05 +01:00
snipe cad6cc3007 Renamed the test for consistency
Signed-off-by: snipe <snipe@snipe.net>
2025-08-28 13:02:01 +01:00
snipe eebc2ab8be Merge remote-tracking branch 'origin/develop' 2025-08-28 07:30:15 +01:00
snipe b303875f1d Merge pull request #17734 from grokability/#17726-add-welcome-email-to-new-user-form
Fixed #17726: add welcome email to new user form
2025-08-28 07:29:56 +01:00
snipe d5cc61f378 Added send to API call for creating users
Signed-off-by: snipe <snipe@snipe.net>
2025-08-28 07:28:51 +01:00
snipe 0d7ec43262 Fixed typo
Signed-off-by: snipe <snipe@snipe.net>
2025-08-28 06:19:41 +01:00
snipe d3747f4daa Added welcome email to controller
Signed-off-by: snipe <snipe@snipe.net>
2025-08-28 06:12:01 +01:00
snipe af695e7dc8 Added help to user importer
Signed-off-by: snipe <snipe@snipe.net>
2025-08-28 06:11:52 +01:00
snipe 1edbfd87df Added welcome email checkbox to user create form
Signed-off-by: snipe <snipe@snipe.net>
2025-08-28 06:11:40 +01:00
snipe 454be01a6c Updated translations
Signed-off-by: snipe <snipe@snipe.net>
2025-08-28 06:11:23 +01:00
snipe b65b3151ee Merge remote-tracking branch 'origin/develop' 2025-08-28 05:29:48 +01:00
snipe 745fc515f1 Merge pull request #17713 from Godmartinz/fix-localization-for-email-notifications
Adds #5554 locale for acceptance notifications and checkin/out emails
2025-08-28 05:29:28 +01:00
snipe 715b9c1182 Merge pull request #17730 from Godmartinz/update-asset-accepance-with-category
Adds #9000 Item type to Account Asset Acceptance index
2025-08-28 05:22:54 +01:00
Godfrey M 95be847d87 renamed attribute 2025-08-27 14:10:51 -07:00
Godfrey M c1a6546eba change column header 2025-08-27 14:09:13 -07:00
Godfrey M 648c25a0a7 adds item type to Accept asset index 2025-08-27 14:06:10 -07:00
Godfrey M f2ec7f2975 fix tests 2025-08-27 13:22:35 -07:00
Godfrey M f518af6d61 fix class name 2025-08-27 13:09:05 -07:00
snipe 13a0f49f5f Merge remote-tracking branch 'origin/develop' 2025-08-27 16:36:05 +01:00
snipe b11c6a5c06 Updated depreciation translation with more information.
Signed-off-by: snipe <snipe@snipe.net>
2025-08-27 16:35:49 +01:00
snipe 5822e4e692 Merge pull request #17729 from grokability/exit-early-if-ldap-troubleshooter-cannot-decrypt-ldap-pw
Put LDAP troubleshooter's decrypt in a try/catch to avoid crashing if it cannot decrypt the password
2025-08-27 15:47:22 +01:00
snipe e4f06b0ca8 One last time
Signed-off-by: snipe <snipe@snipe.net>
2025-08-27 15:43:48 +01:00
snipe 2f093c0e82 Added early exist on step 4 as well
Signed-off-by: snipe <snipe@snipe.net>
2025-08-27 15:41:39 +01:00
snipe 5d9dc0e74d Put decrypt in a try/catch
Signed-off-by: snipe <snipe@snipe.net>
2025-08-27 15:33:26 +01:00
snipe 199eefafa1 Merge remote-tracking branch 'origin/develop' 2025-08-27 14:38:47 +01:00
snipe adc3a34929 Fixed copy for encrypted custom fields
Signed-off-by: snipe <snipe@snipe.net>
2025-08-27 14:38:36 +01:00
snipe cb2ffe6b3f Updated translations
Signed-off-by: snipe <snipe@snipe.net>
2025-08-27 14:02:39 +01:00
snipe c5b58f9ecc Merge remote-tracking branch 'origin/develop' 2025-08-27 13:32:25 +01:00
snipe b3e3d01672 Fixed LDAP icon spacing
Signed-off-by: snipe <snipe@snipe.net>
2025-08-27 13:32:02 +01:00
snipe 6b68fe4de6 Merge remote-tracking branch 'origin/develop' 2025-08-27 13:30:19 +01:00
snipe 4a6520fc78 Fixed address field
Signed-off-by: snipe <snipe@snipe.net>
2025-08-27 13:30:07 +01:00
snipe 75ab6c9b13 Merge pull request #17723 from uberbrady/improve_ldap_certificate_ignoring
Improve ldap certificate ignoring
2025-08-27 13:29:33 +01:00
snipe 2f77fcb526 Merge pull request #17724 from Godmartinz/checkout2location_email_fix
Fixes #17642 Checkouts to location email for Assets and Accessories
2025-08-27 13:02:57 +01:00
snipe 3461bbfdb3 Merge remote-tracking branch 'origin/develop'
Signed-off-by: snipe <snipe@snipe.net>

# Conflicts:
#	public/css/build/app.css
#	public/css/build/app.css.map
#	public/css/build/overrides.css
#	public/css/build/overrides.css.map
#	public/css/dist/all.css
#	public/mix-manifest.json
2025-08-27 12:28:22 +01:00
Brady Wetherington 60604c3481 With the new SSL stuff, we are calling ldap_set_option() one more time now 2025-08-27 12:25:39 +01:00
Godfrey M 671c113cd2 add coma to translation" 2025-08-26 16:07:04 -07:00
Godfrey M 8a74d21ede fixes checkout emails to location for assets and accessories" 2025-08-26 16:00:26 -07:00
Godfrey M 75995b2109 fix checkout to location email 2025-08-26 15:34:38 -07:00
snipe d1eefc3fea Merge pull request #17692 from grokability/#17387-make-saml-key-size-an-env
Fixed #17386 - Added SAML key size to env - possible alternative to #17387
2025-08-26 16:28:27 +01:00
Brady Wetherington 16795382fc Many cleanups to default-mode of LDAP troubleshooter 2025-08-26 15:53:18 +01:00
snipe eb17974adc Merge pull request #17722 from grokability/#17704-retain-linebreaks
Fixed #17704 -  retain linebreaks on custom field clipboard copy
2025-08-26 15:44:38 +01:00
snipe 22852c27f8 Use generic length for asterisks
Signed-off-by: snipe <snipe@snipe.net>
2025-08-26 15:38:56 +01:00
snipe f4a94d975d Fixes #17704 - retain linebreaks in clipboard for multi-line custom field copying
Signed-off-by: snipe <snipe@snipe.net>
2025-08-26 15:33:19 +01:00
snipe 7a36bbbd1e Merge pull request #17721 from grokability/small-ldap-preview-display-tweaks
Improved LDAP field sync preview
2025-08-26 15:26:09 +01:00
snipe 2b401b965b Fixed casing
Signed-off-by: snipe <snipe@snipe.net>
2025-08-26 15:22:00 +01:00
snipe 314bc5b44f Added manager
Signed-off-by: snipe <snipe@snipe.net>
2025-08-26 15:14:29 +01:00
snipe 76374f0d5a Updated text
Signed-off-by: snipe <snipe@snipe.net>
2025-08-26 15:14:22 +01:00
snipe 264efb015e Fixed jobtitle field mapping
Signed-off-by: snipe <snipe@snipe.net>
2025-08-26 15:05:05 +01:00
Brady Wetherington e74460aefc Merge branch 'develop' into improve_ldap_certifcate_ignoring 2025-08-26 15:01:11 +01:00
Brady Wetherington 55a5a12b30 Formalize the 'double-barrel' method of setting TLS cert ignores 2025-08-26 15:00:33 +01:00
snipe 58944a38eb Make screen and table wider
Signed-off-by: snipe <snipe@snipe.net>
2025-08-26 14:59:11 +01:00
snipe 469e3bd475 Nicer ldap preview layout, show all mapped fields
Signed-off-by: snipe <snipe@snipe.net>
2025-08-26 14:51:34 +01:00
snipe 17650c5735 Changed field title
Signed-off-by: snipe <snipe@snipe.net>
2025-08-26 14:03:11 +01:00
Brady Wetherington 15e64155b5 Add version checking to LDAP troubleshooter, clean up ldap model 2025-08-26 13:57:25 +01:00
snipe 39955ac760 Add @akaspeh1 as a contributor 2025-08-26 12:42:20 +01:00
snipe 855a176ca9 Add @nickwest as a contributor 2025-08-26 12:42:15 +01:00
snipe 47b2b30455 Merge pull request #17710 from akaspeh1/develop
Adds support for label sheets Avery L4736 & L6009
2025-08-26 12:42:02 +01:00
snipe b702e3e2de Merge pull request #17492 from ischooluw/17448-feature-notes-api-endpoints
Fixes #17448: feat(api) - API endpoint for Adding Ad-Hoc Notes to Assets
2025-08-26 12:40:52 +01:00
snipe a6b74d56c6 Merge pull request #17709 from grokability/add-display-name-to-users-fixed
Added display name to users for LDAP/SCIM, added new sync fields (replaced #17650)
2025-08-26 12:39:25 +01:00
snipe a4222bcaef Merge pull request #17711 from grokability/dependabot/github_actions/develop/actions/checkout-5
Bump actions/checkout from 4 to 5
2025-08-26 12:10:24 +01:00
snipe ecf24511cd Fixed tests for real this time tho
Signed-off-by: snipe <snipe@snipe.net>
2025-08-26 12:09:55 +01:00
snipe abb097a391 Merge pull request #17714 from Godmartinz/Audit_null_fix
Added null checks to MS Teams Audit notification
2025-08-26 10:44:51 +01:00
Godfrey M dd742a2e4a add a check for audit notification variables in MS Teams and a translation 2025-08-25 15:10:41 -07:00
Godfrey M 128bdf500a sends an email for to locale and cc locale 2025-08-25 12:02:23 -07:00
dependabot[bot] 73ac00bc51 Bump actions/checkout from 4 to 5
Bumps [actions/checkout](https://github.com/actions/checkout) from 4 to 5.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v4...v5)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-version: '5'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-08-25 16:25:39 +00:00
snipe 3524e23e38 Fixed tests
Signed-off-by: snipe <snipe@snipe.net>
2025-08-25 17:17:45 +01:00
Jakub Aqaba Štarman be0f3910bb Fixed: Old computation 2025-08-25 16:57:32 +02:00
snipe 07dbc6842c Are you KIDDING ME, Github??
This reverts commit c8e79aa5ca, reversing
changes made to e60f2b2332.

Signed-off-by: snipe <snipe@snipe.net>
2025-08-25 15:56:28 +01:00
Jakub Aqaba Štarman 5a16b59462 Adds support for label sheets Avery L4736 & L6009 2025-08-25 16:47:52 +02:00
Brady Wetherington 13cd7071b8 WIP improving some LDAP stuff 2025-08-25 15:41:01 +01:00
snipe 40108b196c Trying to fix import tests :(
Signed-off-by: snipe <snipe@snipe.net>
2025-08-25 15:28:43 +01:00
snipe c8e79aa5ca Merge branch 'develop' into add-display-name-to-users-fixed 2025-08-25 15:28:20 +01:00
snipe e60f2b2332 Tightened up accessor code for better inheritence
Signed-off-by: snipe <snipe@snipe.net>
2025-08-25 15:00:10 +01:00
snipe b6d397bcca Updated ->present()->fullName() to ->display_name
Signed-off-by: snipe <snipe@snipe.net>
2025-08-25 14:57:34 +01:00
snipe 6503f9c667 Revert "Merge pull request #17650 from grokability/add-displayName-to-users"
This reverts commit 4770e469b4, reversing
changes made to 29a18c7c8b.

Signed-off-by: snipe <snipe@snipe.net>
2025-08-21 20:23:47 +01:00
snipe 4770e469b4 Merge pull request #17650 from grokability/add-displayName-to-users
Add display name to users for LDAP/SCIM, added new sync fields
2025-08-21 18:22:34 +01:00
snipe 29a18c7c8b Merge pull request #17696 from uberbrady/add_created_at_index_to_models
Fixed [FD-49550] - added a 'created_at' index to the models table
2025-08-21 14:54:20 +01:00
Brady Wetherington 6db0003e3f Adds a 'created_at' index to the models table 2025-08-21 13:44:14 +01:00
snipe c538c460fa Merge pull request #17695 from grokability/#17482-better-localization-indates-on-asset-view
Use nicer local for purchase date
2025-08-21 13:13:26 +01:00
snipe 822339fe42 Moved warning
Signed-off-by: snipe <snipe@snipe.net>
2025-08-21 13:13:11 +01:00
snipe b84d9282ca Use normal locale for warranty
Signed-off-by: snipe <snipe@snipe.net>
2025-08-21 13:05:01 +01:00
snipe 00a17cd55e Merge remote-tracking branch 'origin/develop' 2025-08-21 11:51:50 +01:00
snipe 952b6f33bb Add @strobelm as a contributor 2025-08-21 11:51:37 +01:00
snipe c57c4b8ff2 Merge pull request #17691 from qay21/fix-components-url
Fix components presenting wrong URLs
2025-08-21 11:37:27 +01:00
snipe 39e6223ff2 POssible alternative to #17386 - adding SAML key size to env
Signed-off-by: snipe <snipe@snipe.net>
2025-08-21 11:27:50 +01:00
qay d8dd274c08 Fix components presenting wrong URLs 2025-08-21 12:26:13 +02:00
snipe 15f97b6cb9 Merge pull request #17591 from Godmartinz/add-serial-to-expiring-asset-report
Adds #17440 serial number column to Expiring Assets Report
2025-08-21 11:14:45 +01:00
snipe fc091c1174 Added comments
Signed-off-by: snipe <snipe@snipe.net>
2025-08-21 09:29:12 +01:00
snipe c07ef4d87f A few small tweaks
Signed-off-by: snipe <snipe@snipe.net>
2025-08-21 09:25:42 +01:00
snipe f39afe5a65 Merge remote-tracking branch 'origin/develop' 2025-08-20 15:56:19 +01:00
snipe 11eee833bb Fixed #17667 - Switch to hyphens for windows
Signed-off-by: snipe <snipe@snipe.net>
2025-08-20 15:56:10 +01:00
snipe 7612ee6b08 Merge remote-tracking branch 'origin/develop' 2025-08-20 14:17:38 +01:00
snipe 2ed2b0101a Merge remote-tracking branch 'origin/develop' 2025-08-20 12:43:57 +01:00
snipe 5ca9d31964 Merge remote-tracking branch 'origin/develop' 2025-08-20 11:32:27 +01:00
snipe 2fcd8cd261 Merge remote-tracking branch 'origin/develop' 2025-08-20 11:00:26 +01:00
snipe 0ffa47a2c6 Merge remote-tracking branch 'origin/develop' 2025-08-20 09:58:54 +01:00
snipe 56e687bed2 Retuen the display name in the API call
Signed-off-by: snipe <snipe@snipe.net>
2025-08-20 09:33:00 +01:00
snipe 07b25fe376 Add display name to summary
Signed-off-by: snipe <snipe@snipe.net>
2025-08-19 20:52:18 +01:00
snipe c2ecd20b7d Updated field text
Signed-off-by: snipe <snipe@snipe.net>
2025-08-19 20:47:48 +01:00
snipe 1b42abcc98 Fixed mapping
Signed-off-by: snipe <snipe@snipe.net>
2025-08-19 19:54:32 +01:00
snipe 2d6270c697 Updated validation, switch to string() as db field type
Signed-off-by: snipe <snipe@snipe.net>
2025-08-19 19:19:29 +01:00
snipe 0823c23a6e Fixed placeholder text
Signed-off-by: snipe <snipe@snipe.net>
2025-08-19 18:51:56 +01:00
snipe b3f0ce4b2a Use fieldsets for LDAP settings
Signed-off-by: snipe <snipe@snipe.net>
2025-08-19 18:38:47 +01:00
snipe 8b83584b67 Added mapping fields to LDAP
Signed-off-by: snipe <snipe@snipe.net>
2025-08-19 18:31:58 +01:00
Godfrey M ed402e0122 adds serial underneath name 2025-08-19 10:10:20 -07:00
snipe e203d4dee3 Merge remote-tracking branch 'origin/develop' 2025-08-19 14:49:00 +01:00
snipe b47d773e13 Merge remote-tracking branch 'origin/develop' 2025-08-19 14:34:32 +01:00
snipe a8d0a4a95d Merge remote-tracking branch 'origin/develop'
Signed-off-by: snipe <snipe@snipe.net>

# Conflicts:
#	public/js/dist/all.js
#	public/js/dist/all.js.map
#	public/mix-manifest.json
2025-08-19 14:12:58 +01:00
snipe 3fb0804cef Merge remote-tracking branch 'origin/develop' 2025-08-19 13:57:36 +01:00
snipe 270401c693 Added display name to user create modal
Signed-off-by: snipe <snipe@snipe.net>
2025-08-19 13:12:57 +01:00
snipe 90fbf6da46 Modify the presenter to see if they have a display_name set
Signed-off-by: snipe <snipe@snipe.net>
2025-08-19 12:56:44 +01:00
snipe 0c3103e3d2 Modify the getter
Signed-off-by: snipe <snipe@snipe.net>
2025-08-19 12:56:30 +01:00
snipe 6a8e1566fe Added display_name to a few more places
Signed-off-by: snipe <snipe@snipe.net>
2025-08-19 12:56:11 +01:00
snipe ced30082a6 Added display_name as user field
Signed-off-by: snipe <snipe@snipe.net>
2025-08-19 12:10:28 +01:00
snipe 6811ebcd52 Merge remote-tracking branch 'origin/develop' 2025-08-19 10:12:56 +01:00
snipe 4fe7bfb851 Merge remote-tracking branch 'origin/develop' 2025-08-18 15:24:25 +01:00
snipe fb60985d03 Merge remote-tracking branch 'origin/develop' 2025-08-18 12:47:19 +01:00
snipe 8f575923cf Merge remote-tracking branch 'origin/develop'
Signed-off-by: snipe <snipe@snipe.net>

# Conflicts:
#	public/css/build/app.css
#	public/css/build/app.css.map
#	public/css/build/overrides.css
#	public/css/build/overrides.css.map
#	public/css/dist/all.css
#	public/mix-manifest.json
2025-08-18 11:26:43 +01:00
snipe 0ecfd02649 Merge remote-tracking branch 'origin/develop' 2025-08-18 11:00:30 +01:00
snipe 420aaf4f61 Merge remote-tracking branch 'origin/develop' 2025-08-18 09:45:19 +01:00
snipe 0c35f213e1 Merge remote-tracking branch 'origin/develop' 2025-08-17 14:54:43 +01:00
snipe f68813af13 Merge remote-tracking branch 'origin/develop' 2025-08-17 14:11:41 +01:00
snipe 37a90d0ce9 Merge remote-tracking branch 'origin/develop' 2025-08-15 15:07:29 +02:00
snipe 02f1291e8f Merge remote-tracking branch 'origin/develop' 2025-08-15 14:41:24 +02:00
snipe 92e4f6b5d9 Merge remote-tracking branch 'origin/develop' 2025-08-15 14:31:53 +02:00
snipe 7b7738fbcc Merge remote-tracking branch 'origin/develop'
Signed-off-by: snipe <snipe@snipe.net>

# Conflicts:
#	public/css/build/app.css
#	public/css/build/app.css.map
#	public/css/build/overrides.css
#	public/css/build/overrides.css.map
#	public/css/dist/all.css
#	public/mix-manifest.json
2025-08-15 14:24:30 +02:00
snipe 31197604a3 Merge pull request #17602 from grokability/develop
Merge develop into master
2025-08-13 21:19:39 +02:00
Godfrey M ba85af11aa adds serial to expiring assets report email 2025-08-12 14:59:20 -07:00
snipe f42a2d7457 Merge remote-tracking branch 'origin/develop' 2025-08-11 20:45:38 +01:00
snipe d29619b67c Merge remote-tracking branch 'origin/develop' 2025-08-11 18:50:17 +01:00
snipe f5235cb835 Merge remote-tracking branch 'origin/develop' 2025-08-11 18:12:51 +01:00
snipe ee830e0cb4 Merge remote-tracking branch 'origin/develop'
Signed-off-by: snipe <snipe@snipe.net>

# Conflicts:
#	public/css/build/app.css
#	public/css/build/app.css.map
#	public/css/build/overrides.css
#	public/css/build/overrides.css.map
#	public/css/dist/all.css
#	public/mix-manifest.json
2025-08-11 14:58:57 +01:00
snipe 0cd3be003d Merge remote-tracking branch 'origin/develop' 2025-08-11 13:07:00 +01:00
snipe c93e35ec77 Merge remote-tracking branch 'origin/develop' 2025-08-11 11:18:31 +01:00
snipe 9538a76232 Merge remote-tracking branch 'origin/develop' 2025-08-11 06:26:29 +01:00
snipe 05876bb124 Merge remote-tracking branch 'origin/develop' 2025-08-11 05:05:13 +01:00
snipe 8bcd5a6d2a Merge remote-tracking branch 'origin/develop'
Signed-off-by: snipe <snipe@snipe.net>

# Conflicts:
#	config/version.php
2025-08-10 21:04:55 +01:00
snipe a36afbcb25 Merge remote-tracking branch 'origin/develop' 2025-08-10 21:02:48 +01:00
snipe ebd8d085cf Merge remote-tracking branch 'origin/develop' 2025-08-10 21:01:34 +01:00
snipe 505148b024 Merge remote-tracking branch 'origin/develop' 2025-08-10 20:51:27 +01:00
snipe e87e924ac2 Merge remote-tracking branch 'origin/develop' 2025-08-08 11:37:46 +01:00
snipe 90f261bab6 Merge remote-tracking branch 'origin/develop' 2025-08-08 11:32:14 +01:00
snipe f7dfb09a4d Merge remote-tracking branch 'origin/develop' 2025-08-08 09:56:23 +01:00
snipe 3135917127 Merge remote-tracking branch 'origin/develop' 2025-08-07 17:03:01 +01:00
snipe 52afa3d36d Merge remote-tracking branch 'origin/develop' 2025-08-06 16:35:59 +01:00
snipe 242aa60e04 Merge remote-tracking branch 'origin/develop' 2025-08-06 16:26:14 +01:00
snipe 7a3c2c27ff Merge remote-tracking branch 'origin/develop' 2025-08-05 23:19:38 +01:00
snipe 5d124360c2 Merge remote-tracking branch 'origin/develop' 2025-08-05 19:35:12 +01:00
snipe 365d7448d5 Merge remote-tracking branch 'origin/develop' 2025-08-05 19:06:34 +01:00
snipe 9a0102c723 Merge remote-tracking branch 'origin/develop' 2025-08-05 19:03:00 +01:00
snipe 2f77f2cb2b Merge remote-tracking branch 'origin/develop' 2025-08-05 18:13:27 +01:00
snipe 528e3a2106 Merge remote-tracking branch 'origin/develop' 2025-08-05 17:48:12 +01:00
snipe 032a664d4c Merge remote-tracking branch 'origin/develop' 2025-08-04 22:27:59 +01:00
snipe aac1864c9b Merge remote-tracking branch 'origin/develop' 2025-08-04 21:23:41 +01:00
snipe e3477f3306 Merge remote-tracking branch 'origin/develop' 2025-08-02 18:41:39 +01:00
snipe 6620a4f87b Merge remote-tracking branch 'origin/develop' 2025-08-02 14:47:09 +01:00
snipe c0e9dff5bf Merge remote-tracking branch 'origin/develop'
Signed-off-by: snipe <snipe@snipe.net>

# Conflicts:
#	public/js/dist/all.js
#	public/js/dist/all.js.map
#	public/js/dist/bootstrap-table.js
#	public/mix-manifest.json
2025-08-01 23:13:22 +01:00
snipe 2d961c435a Merge remote-tracking branch 'origin/develop' 2025-07-31 04:11:31 +01:00
Nicky West c94a8c42f4 Changed NotesController::getList() to NotesController::index() & reordered methods for consistency 2025-07-28 16:57:46 -07:00
Nicky West 16fdb16a56 Changed over to route model binding and simplified logic & gates 2025-07-28 16:55:11 -07:00
Nicky West 822f9a6f28 Fixed deviations from code standards 2025-07-28 16:37:08 -07:00
Nicky West b264bbf69f feat(api): Add API endpoints for managing asset history notes
- Add POST endpoint to create a history note attached to an asset
- Add GET endpoint to retrieve history notes for an asset
- Add ActionLog factory state for manual notes
- Implement controller methods with authorization checks
- Add feature tests for note creation, retrieval, and access control
- Register new API routes for these endpoints

Supports automation by enabling programmatic asset history note management.
2025-07-28 15:55:37 -07:00
snipe 7c95f03166 Merge remote-tracking branch 'origin/develop'
Signed-off-by: snipe <snipe@snipe.net>

# Conflicts:
#	public/css/build/AdminLTE.css
#	public/css/build/app.css
#	public/css/build/overrides.css
#	public/css/dist/all.css
#	public/css/dist/bootstrap-table.css
#	public/css/dist/skins/_all-skins.css
#	public/css/dist/skins/_all-skins.min.css
#	public/css/dist/skins/skin-black-dark.css
#	public/css/dist/skins/skin-black-dark.min.css
#	public/css/dist/skins/skin-black.css
#	public/css/dist/skins/skin-black.min.css
#	public/css/dist/skins/skin-blue-dark.css
#	public/css/dist/skins/skin-blue-dark.min.css
#	public/css/dist/skins/skin-blue.css
#	public/css/dist/skins/skin-blue.min.css
#	public/css/dist/skins/skin-contrast.css
#	public/css/dist/skins/skin-contrast.min.css
#	public/css/dist/skins/skin-green-dark.css
#	public/css/dist/skins/skin-green-dark.min.css
#	public/css/dist/skins/skin-green.css
#	public/css/dist/skins/skin-green.min.css
#	public/css/dist/skins/skin-orange-dark.css
#	public/css/dist/skins/skin-orange-dark.min.css
#	public/css/dist/skins/skin-orange.css
#	public/css/dist/skins/skin-orange.min.css
#	public/css/dist/skins/skin-purple-dark.css
#	public/css/dist/skins/skin-purple-dark.min.css
#	public/css/dist/skins/skin-purple.css
#	public/css/dist/skins/skin-purple.min.css
#	public/css/dist/skins/skin-red-dark.css
#	public/css/dist/skins/skin-red-dark.min.css
#	public/css/dist/skins/skin-red.css
#	public/css/dist/skins/skin-red.min.css
#	public/css/dist/skins/skin-yellow-dark.css
#	public/css/dist/skins/skin-yellow-dark.min.css
#	public/css/dist/skins/skin-yellow.css
#	public/css/dist/skins/skin-yellow.min.css
#	public/js/build/app.js
#	public/js/build/vendor.js
#	public/js/dist/all.js
#	public/js/dist/bootstrap-table.js
#	public/mix-manifest.json
2025-07-28 17:41:13 +01:00
snipe 31e5c13b50 Merge remote-tracking branch 'origin/develop' 2025-07-28 03:30:22 +01:00
snipe 4a9fe4f981 Merge remote-tracking branch 'origin/develop' 2025-07-24 15:54:54 +01:00
snipe 4fcc5587ee Merge remote-tracking branch 'origin/develop'
Signed-off-by: snipe <snipe@snipe.net>

# Conflicts:
#	config/version.php
2025-07-24 15:36:06 +01:00
snipe 6ca49a20ce Merge remote-tracking branch 'origin/develop' 2025-07-24 15:29:54 +01:00
snipe 28f293fdc1 Merge remote-tracking branch 'origin/develop' 2025-07-24 13:07:09 +01:00
snipe b3e7619adc Merge remote-tracking branch 'origin/develop'
Signed-off-by: snipe <snipe@snipe.net>

# Conflicts:
#	config/version.php
2025-07-23 16:11:20 +01:00
snipe 6e56d56137 Merge remote-tracking branch 'origin/develop' 2025-07-23 15:06:25 +01:00
snipe 2528f6a07b Merge remote-tracking branch 'origin/develop' 2025-07-23 14:56:49 +01:00
snipe 423d07c919 Merge remote-tracking branch 'origin/develop' 2025-07-23 12:41:20 +01:00
snipe cc608de4bf Merge remote-tracking branch 'origin/develop' 2025-07-23 12:28:35 +01:00
snipe f999a68608 Merge remote-tracking branch 'origin/develop' 2025-07-22 20:28:53 +01:00
snipe db78a9f18f Merge remote-tracking branch 'origin/develop' 2025-07-22 15:25:51 +01:00
snipe 816039f48e Merge remote-tracking branch 'origin/develop' 2025-07-22 15:18:50 +01:00
snipe ae240bae6d Updated prod CSS
Signed-off-by: snipe <snipe@snipe.net>
2025-07-22 15:14:42 +01:00
snipe 9e30c69e6d Merge remote-tracking branch 'origin/develop'
Signed-off-by: snipe <snipe@snipe.net>

# Conflicts:
#	public/css/build/app.css
#	public/css/build/overrides.css
#	public/css/dist/all.css
#	public/mix-manifest.json
2025-07-22 15:14:32 +01:00
snipe 43c7de9049 Updated prod assets
Signed-off-by: snipe <snipe@snipe.net>
2025-07-22 14:38:04 +01:00
snipe 7e51c5db81 Merge remote-tracking branch 'origin/develop'
Signed-off-by: snipe <snipe@snipe.net>

# Conflicts:
#	public/css/build/app.css
#	public/css/build/overrides.css
#	public/css/dist/all.css
#	public/mix-manifest.json
2025-07-22 14:34:10 +01:00
snipe 0ee3c45e7b Merge remote-tracking branch 'origin/develop' 2025-07-22 13:39:54 +01:00
snipe 981e69929c Merge remote-tracking branch 'origin/develop' 2025-07-21 12:36:44 +01:00
Oliver Cox 553ab8851a Fix #17431: EULA not displaying on asset acceptance page
Changed two instances of === to ==, as this was causing a comparison to fail and preventing EULAs from being displayed on asset acceptance pages as expected.
2025-07-20 23:00:18 +01:00
snipe 1eae5d12fc Merge remote-tracking branch 'origin/develop' 2025-07-18 17:56:20 +01:00
snipe 8863208333 Merge remote-tracking branch 'origin/develop' 2025-07-16 17:35:55 +01:00
snipe 5f38a74a72 Merge remote-tracking branch 'origin/develop' 2025-07-16 17:02:29 +01:00
snipe fe15dacb1f Merge remote-tracking branch 'origin/develop' 2025-07-16 16:54:30 +01:00
snipe c2d44cf2f2 Merge remote-tracking branch 'origin/develop' 2025-07-16 12:25:14 +01:00
snipe 7f1bdb6f34 Merge remote-tracking branch 'origin/develop' 2025-07-15 10:58:58 +01:00
snipe b0305e12d2 Merge remote-tracking branch 'origin/develop' 2025-07-10 13:11:10 +01:00
snipe 58f76b5c99 Merge remote-tracking branch 'origin/develop' 2025-07-09 21:01:24 +01:00
snipe 7c4ee632cf Merge remote-tracking branch 'origin/develop' 2025-07-09 20:58:17 +01:00
snipe b6b0f716eb Merge remote-tracking branch 'origin/develop' 2025-07-09 20:22:25 +01:00
snipe bd0e04ed15 Merge remote-tracking branch 'origin/develop' 2025-07-09 15:48:17 +01:00
snipe 8599981d44 Merge remote-tracking branch 'origin/develop' 2025-07-09 15:46:53 +01:00
snipe 6fc6e95c67 Merge remote-tracking branch 'origin/develop' 2025-07-08 22:02:34 +01:00
snipe 43b585bde8 Merge remote-tracking branch 'origin/develop' 2025-07-08 21:59:58 +01:00
snipe 710f89291f Merge remote-tracking branch 'origin/develop'
Signed-off-by: snipe <snipe@snipe.net>

# Conflicts:
#	config/version.php
2025-07-08 21:27:06 +01:00
snipe 4c6249eb9e Merge remote-tracking branch 'origin/develop' 2025-07-07 22:09:45 +01:00
snipe 016900bad8 Merge remote-tracking branch 'origin/develop'
Signed-off-by: snipe <snipe@snipe.net>

# Conflicts:
#	config/version.php
2025-07-07 21:54:04 +01:00
snipe 2e8ae33761 Merge remote-tracking branch 'origin/develop' 2025-07-07 20:58:36 +01:00
snipe 0d325060da Merge remote-tracking branch 'origin/develop' 2025-07-07 17:06:24 +01:00
snipe 1a6e98e18f Merge remote-tracking branch 'origin/develop' 2025-07-07 16:24:04 +01:00
snipe 97e34595f6 Merge remote-tracking branch 'origin/develop' 2025-07-07 16:00:10 +01:00
snipe a179d5234b Merge remote-tracking branch 'origin/develop' 2025-07-07 14:43:28 +01:00
snipe 64c6121fdb Merge remote-tracking branch 'origin/develop' 2025-07-07 14:00:55 +01:00
snipe 08d8954a85 Merge remote-tracking branch 'origin/develop' 2025-07-07 14:00:03 +01:00
snipe 4f20955d0d Merge remote-tracking branch 'origin/develop' 2025-07-07 13:46:03 +01:00
snipe 3a703c8bcf Merge remote-tracking branch 'origin/develop' 2025-07-07 13:35:07 +01:00
snipe ccbffa086b Merge remote-tracking branch 'origin/develop' 2025-07-07 11:36:33 +01:00
snipe 07ee4be840 Merge remote-tracking branch 'origin/develop' 2025-07-02 18:38:12 +01:00
snipe 4cc9b2d312 Merge remote-tracking branch 'origin/develop' 2025-07-02 17:21:39 +01:00
snipe 24dddae1d1 Merge remote-tracking branch 'origin/develop' 2025-07-02 11:57:57 +01:00
snipe ad0165d085 Merge remote-tracking branch 'origin/develop' 2025-07-02 11:44:30 +01:00
snipe 39dc38c5d1 Merge remote-tracking branch 'origin/develop' 2025-07-01 23:32:43 +01:00
snipe 046ce19dbb Merge remote-tracking branch 'origin/develop'
Signed-off-by: snipe <snipe@snipe.net>

# Conflicts:
#	config/version.php
2025-06-30 11:46:24 +01:00
snipe 33263f5a93 Merge remote-tracking branch 'origin/develop' 2025-06-27 13:52:09 +01:00
snipe 8ef8e76300 Merge remote-tracking branch 'origin/develop' 2025-06-27 12:48:54 +01:00
snipe 73cfdae9e7 Merge remote-tracking branch 'origin/develop' 2025-06-25 15:00:46 +01:00
snipe 54a3e41281 Merge remote-tracking branch 'origin/develop' 2025-06-25 14:58:46 +01:00
snipe d59ba6da84 Merge remote-tracking branch 'origin/develop' 2025-06-25 13:11:39 +01:00
snipe 1b28b06934 Merge remote-tracking branch 'origin/develop' 2025-06-25 11:04:15 +01:00
snipe ff3e69a56c Merge remote-tracking branch 'origin/develop' 2025-06-23 20:51:24 +01:00
snipe 6b975a5fb4 Merge remote-tracking branch 'origin/develop' 2025-06-23 16:41:42 +01:00
snipe 3a02b15124 Merge remote-tracking branch 'origin/develop' 2025-06-23 12:38:40 +01:00
snipe 5f73d81935 Merge remote-tracking branch 'origin/develop' 2025-06-22 20:14:59 +01:00
snipe 002b5c0f6f Merge remote-tracking branch 'origin/develop' 2025-06-22 20:07:52 +01:00
snipe 8086842570 Merge remote-tracking branch 'origin/develop' 2025-06-22 19:42:03 +01:00
snipe 51f2d5a664 Merge remote-tracking branch 'origin/develop' 2025-06-22 19:30:42 +01:00
snipe b74b76de75 Merge remote-tracking branch 'origin/develop' 2025-06-17 18:17:10 +01:00
snipe a1b1498106 Merge remote-tracking branch 'origin/develop' 2025-06-17 17:51:37 +01:00
snipe 1158851ea7 Merge remote-tracking branch 'origin/develop' 2025-06-17 15:57:12 +01:00
snipe e1ab9e959e Merge remote-tracking branch 'origin/develop' 2025-06-17 13:03:27 +01:00
snipe 2bbac3ae9d Merge remote-tracking branch 'origin/develop' 2025-06-17 12:38:52 +01:00
snipe e889b1d5e5 Merge remote-tracking branch 'origin/develop' 2025-06-17 11:42:00 +01:00
snipe 233bf856f4 Merge remote-tracking branch 'origin/develop' 2025-06-17 11:39:12 +01:00
snipe bca843e06c Merge remote-tracking branch 'origin/develop' 2025-06-16 20:32:40 +01:00
snipe 30a79a1278 Merge remote-tracking branch 'origin/develop'
Signed-off-by: snipe <snipe@snipe.net>

# Conflicts:
#	config/version.php
2025-06-16 14:45:53 +01:00
snipe 0f92dee2c4 Merge remote-tracking branch 'origin/develop' 2025-06-15 03:41:23 +01:00
snipe f04efede15 Merge remote-tracking branch 'origin/develop' 2025-06-15 02:59:47 +01:00
snipe f0dfdf6720 Merge remote-tracking branch 'origin/develop' 2025-06-14 23:56:06 +01:00
snipe e26d731382 Merge remote-tracking branch 'origin/develop' 2025-06-14 23:08:48 +01:00
snipe d684d3e559 Merge remote-tracking branch 'origin/develop' 2025-06-14 22:22:54 +01:00
snipe 47c54cb998 Merge remote-tracking branch 'origin/develop' 2025-06-14 17:45:44 +01:00
snipe 592cb2b3ec Merge remote-tracking branch 'origin/develop' 2025-06-14 17:08:11 +01:00
snipe f5a7871a2e Merge remote-tracking branch 'origin/develop' 2025-06-14 16:44:48 +01:00
snipe ec411fa0db Merge remote-tracking branch 'origin/develop' 2025-06-14 12:17:43 +01:00
snipe a850a9bb83 Merge remote-tracking branch 'origin/develop' 2025-06-12 21:34:59 +01:00
snipe 479b7a3f94 Merge remote-tracking branch 'origin/develop' 2025-06-11 10:32:49 +01:00
snipe f7cfee77c9 Merge remote-tracking branch 'origin/develop' 2025-06-11 10:20:22 +01:00
snipe 65a8126a13 Merge remote-tracking branch 'origin/develop' 2025-06-09 13:40:44 +01:00
snipe a39bc102d5 Merge remote-tracking branch 'origin/develop' 2025-06-08 15:30:32 +01:00
snipe 81d930c4d2 Merge remote-tracking branch 'origin/develop' 2025-06-08 15:19:19 +01:00
snipe 6839623061 Merge remote-tracking branch 'origin/develop' 2025-06-06 17:03:37 +01:00
snipe 7de2809d42 Merge remote-tracking branch 'origin/develop'
Signed-off-by: snipe <snipe@snipe.net>

# Conflicts:
#	public/js/dist/bootstrap-table.js
#	public/mix-manifest.json
2025-06-06 14:05:47 +01:00
snipe 98ec6b6886 Merge remote-tracking branch 'origin/develop' 2025-06-06 12:48:54 +01:00
snipe 04827f00cc Merge remote-tracking branch 'origin/develop' 2025-06-06 11:54:10 +01:00
snipe 660bfc6578 Merge remote-tracking branch 'origin/develop' 2025-06-06 08:31:09 +01:00
snipe 1152cd5537 Merge remote-tracking branch 'origin/develop' 2025-06-06 08:26:52 +01:00
snipe f30e8497b2 Merge remote-tracking branch 'origin/develop' 2025-06-04 16:17:26 +01:00
snipe 06495bc45d Merge remote-tracking branch 'origin/develop' 2025-06-04 12:13:30 +01:00
snipe 26067916b3 Merge remote-tracking branch 'origin/develop' 2025-06-04 11:49:03 +01:00
snipe c36ee4852b Merge remote-tracking branch 'origin/develop' 2025-06-04 10:40:56 +01:00
snipe 2cb992ad44 Merge remote-tracking branch 'origin/develop' 2025-06-04 08:43:52 +01:00
snipe 083b7be6c0 Make version number match tagged version :(
Signed-off-by: snipe <snipe@snipe.net>
2025-06-03 11:03:33 +01:00
snipe e24854558f Merge remote-tracking branch 'origin/develop'
Signed-off-by: snipe <snipe@snipe.net>

# Conflicts:
#	config/version.php
2025-06-03 11:03:05 +01:00
snipe e4314cf426 Merge remote-tracking branch 'origin/develop' 2025-06-03 06:07:20 +01:00
snipe 4106e4e45c Merge remote-tracking branch 'origin/develop' 2025-06-02 22:29:09 +01:00
snipe 05f143db2b Merge remote-tracking branch 'origin/develop'
Signed-off-by: snipe <snipe@snipe.net>

# Conflicts:
#	config/version.php
2025-06-02 18:15:54 +01:00
snipe 64aeaeeeea Merge remote-tracking branch 'origin/develop' 2025-06-02 17:29:52 +01:00
snipe 61db37ab0d Merge remote-tracking branch 'origin/develop' 2025-06-02 15:28:08 +01:00
snipe f9c4d921e7 Merge remote-tracking branch 'origin/develop' 2025-06-02 15:07:15 +01:00
snipe ca099df573 Merge remote-tracking branch 'origin/develop' 2025-06-02 15:04:00 +01:00
snipe 28b584b8bc Merge remote-tracking branch 'origin/develop' 2025-06-02 02:08:19 +01:00
snipe 70449e694d Merge remote-tracking branch 'origin/develop' 2025-05-29 22:18:50 +01:00
snipe 8395ea552d Merge remote-tracking branch 'origin/develop' 2025-05-29 16:17:58 +01:00
snipe dc66452633 Merge remote-tracking branch 'origin/develop' 2025-05-29 13:32:41 +01:00
snipe 53ce44ac91 Merge remote-tracking branch 'origin/develop' 2025-05-29 12:38:40 +01:00
snipe c7c3243bbc Merge remote-tracking branch 'origin/develop' 2025-05-29 12:35:21 +01:00
snipe 8bdd77d33d Merge remote-tracking branch 'origin/develop' 2025-05-29 12:24:51 +01:00
snipe acd7d0db3a Merge remote-tracking branch 'origin/develop' 2025-05-29 12:09:08 +01:00
snipe 2bfadb8a3c Merge remote-tracking branch 'origin/develop' 2025-05-28 15:21:34 +01:00
snipe 0912e4af7b Merge remote-tracking branch 'origin/develop' 2025-05-26 13:17:38 +01:00
snipe 5aa5c48018 Merge remote-tracking branch 'origin/develop' 2025-05-23 19:37:42 +01:00
snipe 8cdd998f79 Merge remote-tracking branch 'origin/develop' 2025-05-23 17:35:08 +01:00
snipe 050d4d6b25 Merge remote-tracking branch 'origin/develop' 2025-05-23 14:51:48 +01:00
snipe 366cd11238 Merge remote-tracking branch 'origin/develop' 2025-05-23 14:31:10 +01:00
snipe 58d6443331 Merge remote-tracking branch 'origin/develop'
Signed-off-by: snipe <snipe@snipe.net>

# Conflicts:
#	config/version.php
2025-05-23 13:27:44 +01:00
snipe 101b8afb56 Merge remote-tracking branch 'origin/develop' 2025-05-23 13:07:47 +01:00
snipe 5df5c47945 Merge remote-tracking branch 'origin/develop'
Signed-off-by: snipe <snipe@snipe.net>

# Conflicts:
#	config/version.php
2025-05-23 10:43:58 +01:00
snipe a04740ba86 Merge remote-tracking branch 'origin/develop' 2025-05-23 10:42:44 +01:00
snipe 425ad93ac5 Merge remote-tracking branch 'origin/develop' 2025-05-23 10:17:10 +01:00
snipe 8a44144c20 Merge pull request #16954 from grokability/develop
Merge dev into master
2025-05-16 11:16:14 +02:00
snipe ee82c70582 Merge remote-tracking branch 'origin/develop' 2025-05-15 18:32:05 +02:00
snipe c87e8e606b Merge remote-tracking branch 'origin/develop' 2025-05-15 18:02:47 +02:00
snipe 37a50dd953 Merge remote-tracking branch 'origin/develop'
Signed-off-by: snipe <snipe@snipe.net>

# Conflicts:
#	config/version.php
2025-05-15 17:51:54 +02:00
snipe a2669a3084 Removed temp code
Signed-off-by: snipe <snipe@snipe.net>
2025-05-15 17:31:16 +02:00
snipe 77da22f4dd Print errors if they exist (temp)
Signed-off-by: snipe <snipe@snipe.net>
2025-05-15 17:26:04 +02:00
snipe 7830ffe202 Temp echo errors
Signed-off-by: snipe <snipe@snipe.net>
2025-05-15 17:24:08 +02:00
snipe 1c9e20d59f Merge remote-tracking branch 'origin/develop' 2025-05-15 17:10:57 +02:00
snipe 320edac286 Merge remote-tracking branch 'origin/develop' 2025-05-14 17:39:30 +02:00
snipe d49878371d Merge remote-tracking branch 'origin/develop' 2025-05-14 16:23:38 +02:00
snipe d2575a5d9b Add @JassonCordones as a contributor 2025-05-14 15:03:04 +02:00
Marcus Moore ea6cf72580 Formatting 2025-05-14 15:03:04 +02:00
Marcus Moore 2118155b37 Fix bug in getImageUrl method 2025-05-14 15:03:04 +02:00
Marcus Moore ba4f5bb71f Add test for existing functionality 2025-05-14 15:03:04 +02:00
Marcus Moore d5a74a5a8b Remove unneeded div 2025-05-14 15:03:04 +02:00
Marcus Moore 23be1df360 Remove the replaced locales form macro 2025-05-14 15:03:04 +02:00
Marcus Moore b5c1a1da4c Replace Form::locales on user setup 2025-05-14 15:03:04 +02:00
Marcus Moore c11e784f51 Replace Form::locales on bulk edit users page 2025-05-14 15:03:04 +02:00
Marcus Moore 06f51c8f9c Replace Form::locales on user edit page 2025-05-14 15:03:04 +02:00
Marcus Moore 181bcbbda6 Replace Form::locales on localization page 2025-05-14 15:03:04 +02:00
Marcus Moore d008ead6a4 Fix input name 2025-05-14 15:03:04 +02:00
Marcus Moore 75924be958 Introduce locale select component and make replacement on profile page 2025-05-14 15:03:04 +02:00
snipe b1a6e3f8a2 Merge pull request #16930 from JassonCordones/master
fix typo in snipeit.sh
2025-05-14 15:01:41 +02:00
snipe 06712a6041 Merge remote-tracking branch 'origin/develop' 2025-05-14 13:42:51 +02:00
snipe 62b16339a9 Merge remote-tracking branch 'origin/develop' 2025-05-13 20:44:34 +02:00
Jasson 9a2f1a36ba fix typo in snipeit.sh
fix redirect output to stderr
2025-05-13 14:31:37 -04:00
snipe 95cc4d3a73 Merge remote-tracking branch 'origin/develop' 2025-05-09 21:16:58 +01:00
snipe 497eeeb2e0 Merge remote-tracking branch 'origin/develop' 2025-05-09 19:29:01 +01:00
snipe 4be21ca249 Merge remote-tracking branch 'origin/develop' 2025-05-09 18:03:38 +01:00
snipe e8598e214e Merge remote-tracking branch 'origin/develop' 2025-05-09 17:23:22 +01:00
snipe 54b1d65e3c Merge remote-tracking branch 'origin/develop' 2025-05-09 14:46:37 +01:00
snipe f7648496d3 Merge remote-tracking branch 'origin/develop' 2025-05-08 16:26:02 +01:00
snipe 59a57c7197 Merge remote-tracking branch 'origin/develop' 2025-05-08 15:43:53 +01:00
snipe 5659b26827 Merge remote-tracking branch 'origin/develop' 2025-05-08 15:22:43 +01:00
snipe ee4443aaf0 Merge remote-tracking branch 'origin/develop' 2025-05-08 15:09:26 +01:00
snipe 839dcad358 Merge remote-tracking branch 'origin/develop'
Signed-off-by: snipe <snipe@snipe.net>

# Conflicts:
#	config/version.php
#	public/css/dist/skins/_all-skins.css
#	public/css/dist/skins/_all-skins.min.css
#	public/css/dist/skins/skin-black-dark.css
#	public/css/dist/skins/skin-black-dark.min.css
#	public/css/dist/skins/skin-blue-dark.css
#	public/css/dist/skins/skin-blue-dark.min.css
#	public/css/dist/skins/skin-green-dark.css
#	public/css/dist/skins/skin-green-dark.min.css
#	public/css/dist/skins/skin-orange-dark.css
#	public/css/dist/skins/skin-orange-dark.min.css
#	public/css/dist/skins/skin-purple-dark.css
#	public/css/dist/skins/skin-purple-dark.min.css
#	public/css/dist/skins/skin-red-dark.css
#	public/css/dist/skins/skin-red-dark.min.css
#	public/css/dist/skins/skin-yellow-dark.css
#	public/css/dist/skins/skin-yellow-dark.min.css
#	public/mix-manifest.json
2025-05-07 11:41:31 +01:00
snipe d67933ab49 Merge remote-tracking branch 'origin/develop'
Signed-off-by: snipe <snipe@snipe.net>

# Conflicts:
#	.all-contributorsrc
#	CONTRIBUTORS.md
2025-05-06 16:46:41 +01:00
Godfrey M 0eb3f6b952 set max to 5 2025-05-05 14:42:06 +01:00
Godfrey M 68b0f80fce fix input max, and help block position 2025-05-05 14:42:06 +01:00
Godfrey M 93489529a3 adds Field offset option to labels 2025-05-05 14:42:06 +01:00
snipe 511be74e74 Add @chfsx as a contributor 2025-05-05 14:42:06 +01:00
Fabian Schmid bdee067803 [FIX] set upload-limit 2025-05-05 14:42:06 +01:00
snipe 32156cace3 Merge pull request #16847 from realchrisolin/issue16214
add barcode support for Avery 3490
2025-05-05 14:40:54 +01:00
snipe 30688114be Merge remote-tracking branch 'origin/develop' 2025-05-05 14:04:52 +01:00
snipe 34088bcc17 Merge remote-tracking branch 'origin/develop'
Signed-off-by: snipe <snipe@snipe.net>

# Conflicts:
#	config/version.php
2025-05-05 11:17:01 +01:00
Calvin Schwartz 07835766cc adds support for Avery 3490 2025-05-01 21:11:42 -04:00
Brady Wetherington 251851ec6a Try to get Docker images to build for both architectures 2025-04-30 18:00:39 +01:00
snipe 049a669186 Merge remote-tracking branch 'origin/develop' 2025-04-30 16:46:16 +01:00
snipe d29f13bae9 Merge remote-tracking branch 'origin/develop' 2025-04-30 16:26:38 +01:00
snipe c758355df9 Merge remote-tracking branch 'origin/develop' 2025-04-30 16:14:34 +01:00
snipe 79d97a83af Merge remote-tracking branch 'origin/develop' 2025-04-30 15:48:38 +01:00
snipe 85bd47c240 Merge remote-tracking branch 'origin/develop' 2025-04-30 15:35:10 +01:00
snipe 473ead9616 Merge remote-tracking branch 'origin/develop' 2025-04-30 13:57:27 +01:00
snipe cf2850933c Merge remote-tracking branch 'origin/develop' 2025-04-30 10:19:43 +01:00
snipe ff2564c57a Merge remote-tracking branch 'origin/develop' 2025-04-30 10:12:05 +01:00
snipe 91d3848246 Merge remote-tracking branch 'origin/develop'
Signed-off-by: snipe <snipe@snipe.net>

# Conflicts:
#	config/version.php
2025-04-29 23:17:51 +01:00
snipe c031f0b45e Merge remote-tracking branch 'origin/develop'
Signed-off-by: snipe <snipe@snipe.net>

# Conflicts:
#	public/css/dist/skins/_all-skins.css
#	public/css/dist/skins/_all-skins.min.css
#	public/css/dist/skins/skin-blue-dark.css
#	public/css/dist/skins/skin-blue-dark.min.css
#	public/css/dist/skins/skin-green-dark.css
#	public/css/dist/skins/skin-green-dark.min.css
#	public/css/dist/skins/skin-orange-dark.css
#	public/css/dist/skins/skin-orange-dark.min.css
#	public/css/dist/skins/skin-purple-dark.css
#	public/css/dist/skins/skin-purple-dark.min.css
#	public/css/dist/skins/skin-red-dark.css
#	public/css/dist/skins/skin-red-dark.min.css
#	public/css/dist/skins/skin-yellow-dark.css
#	public/css/dist/skins/skin-yellow-dark.min.css
#	public/mix-manifest.json
2025-04-29 20:38:41 +01:00
snipe fdbb9568ae Merge remote-tracking branch 'origin/develop'
Signed-off-by: snipe <snipe@snipe.net>

# Conflicts:
#	config/version.php
#	public/css/build/app.css
#	public/css/build/overrides.css
#	public/css/dist/all.css
#	public/mix-manifest.json
2025-04-29 12:39:31 +01:00
snipe d817883459 Merge remote-tracking branch 'origin/develop' 2025-04-29 10:25:42 +01:00
snipe 12255979ac Merge remote-tracking branch 'origin/develop'
Signed-off-by: snipe <snipe@snipe.net>

# Conflicts:
#	public/css/build/app.css
#	public/css/dist/all.css
#	public/mix-manifest.json
2025-04-29 10:22:21 +01:00
snipe 366b61850b Merge remote-tracking branch 'origin/develop' 2025-04-26 17:54:02 +01:00
snipe 89be6bd183 Merge remote-tracking branch 'origin/develop' 2025-04-24 14:06:00 +01:00
snipe e120331a2c Merge remote-tracking branch 'origin/develop' 2025-04-24 12:16:53 +01:00
snipe cb8a212d96 Merge remote-tracking branch 'origin/develop' 2025-04-23 21:57:20 +01:00
snipe 7aec431ac5 Merge remote-tracking branch 'origin/develop'
Signed-off-by: snipe <snipe@snipe.net>
2025-04-23 21:30:16 +01:00
snipe d19681dea1 Merge remote-tracking branch 'origin/develop'
Signed-off-by: snipe <snipe@snipe.net>
2025-04-23 21:05:38 +01:00
snipe bf2299daf8 Merge remote-tracking branch 'origin/develop' 2025-04-22 17:51:48 +01:00
snipe 164930d0dd Merge remote-tracking branch 'origin/develop' 2025-04-22 16:35:23 +01:00
snipe 387dbac809 Merge remote-tracking branch 'origin/develop' 2025-04-22 14:36:14 +01:00
snipe 3b661e5a99 Merge remote-tracking branch 'origin/develop' 2025-04-22 12:39:35 +01:00
snipe 90c1c0e655 Merge remote-tracking branch 'origin/develop' 2025-04-22 11:42:49 +01:00
snipe 21d8e7695b Merge remote-tracking branch 'origin/develop' 2025-04-21 20:19:54 +01:00
snipe 1acc452cfe Merge remote-tracking branch 'origin/develop' 2025-04-21 14:59:26 +01:00
snipe 1375e1feee Merge remote-tracking branch 'origin/develop' 2025-04-21 12:21:08 +01:00
snipe 2187adf59a Merge remote-tracking branch 'origin/develop'
Signed-off-by: snipe <snipe@snipe.net>
2025-04-19 15:34:58 +01:00
snipe 0dcb315d9d Merge remote-tracking branch 'origin/develop' 2025-04-18 00:56:26 +01:00
snipe 327ccbd0c9 Merge remote-tracking branch 'origin/develop' 2025-04-18 00:37:11 +01:00
snipe f571d400e6 Merge remote-tracking branch 'origin/develop' 2025-04-17 23:29:12 +01:00
snipe 293aa52335 Merge remote-tracking branch 'origin/develop' 2025-04-17 23:13:04 +01:00
snipe ca178ae9a7 Merge remote-tracking branch 'origin/develop' 2025-04-17 22:48:35 +01:00
snipe d0c810e418 Merge remote-tracking branch 'origin/develop' 2025-04-17 16:42:37 +01:00
snipe d496d2caeb Merge remote-tracking branch 'origin/develop' 2025-04-17 11:59:24 +01:00
snipe e70b75c350 Merge remote-tracking branch 'origin/develop' 2025-04-17 01:00:34 +01:00
snipe a50befeda5 Merge remote-tracking branch 'origin/develop' 2025-04-16 20:16:18 +01:00
snipe e2616e8039 Merge remote-tracking branch 'origin/develop' 2025-04-16 15:52:18 +01:00
snipe 904266debe Merge remote-tracking branch 'origin/develop' 2025-04-16 09:47:18 +01:00
snipe 72d5783795 Merge remote-tracking branch 'origin/develop' 2025-04-16 09:19:05 +01:00
snipe d699fb1473 Merge remote-tracking branch 'origin/develop'
Signed-off-by: snipe <snipe@snipe.net>
2025-04-15 20:46:43 +01:00
snipe fab1a6c33a Merge remote-tracking branch 'origin/develop' 2025-04-15 20:30:02 +01:00
snipe be73c30194 Merge remote-tracking branch 'origin/develop'
Signed-off-by: snipe <snipe@snipe.net>

# Conflicts:
#	public/css/build/app.css
#	public/css/build/overrides.css
#	public/css/dist/all.css
#	public/js/dist/bootstrap-table.js
#	public/mix-manifest.json
2025-04-15 20:01:20 +01:00
snipe 451646fe4f Prod assets
Signed-off-by: snipe <snipe@snipe.net>
2025-04-15 19:42:26 +01:00
snipe decc919991 Merge remote-tracking branch 'origin/develop' 2025-04-15 19:33:23 +01:00
snipe e0b4005921 Merge remote-tracking branch 'origin/develop' 2025-04-15 16:48:17 +01:00
snipe 3ef36e7534 Merge remote-tracking branch 'origin/develop' 2025-04-14 11:02:06 +01:00
snipe 1949e1e1e9 Merge remote-tracking branch 'origin/develop' 2025-04-14 09:26:25 +01:00
snipe 3358382358 Comment out location scoping option for now
Signed-off-by: snipe <snipe@snipe.net>
2025-04-09 21:44:38 +01:00
snipe 3eca3ecd75 Merge remote-tracking branch 'origin/develop' 2025-04-09 21:31:41 +01:00
snipe 140c6b91b0 Merge remote-tracking branch 'origin/develop'
Signed-off-by: snipe <snipe@snipe.net>

# Conflicts:
#	public/css/build/app.css
#	public/css/build/overrides.css
#	public/css/dist/all.css
#	public/mix-manifest.json
2025-04-09 02:40:28 +01:00
snipe a5315ec240 Merge remote-tracking branch 'origin/develop' 2025-04-08 08:32:25 +01:00
snipe 93f1656e0b Merge remote-tracking branch 'origin/develop' 2025-04-08 06:51:21 +01:00
snipe f1d006c236 Merge remote-tracking branch 'origin/develop'
Signed-off-by: snipe <snipe@snipe.net>

# Conflicts:
#	public/css/build/app.css
#	public/css/build/overrides.css
#	public/css/dist/all.css
#	public/mix-manifest.json
2025-04-08 05:58:51 +01:00
snipe b0b5a96694 Merge remote-tracking branch 'origin/develop' 2025-04-07 13:54:23 +01:00
snipe 7dbe9a85f4 Merge remote-tracking branch 'origin/develop' 2025-04-05 21:02:33 +01:00
snipe d2c39528d5 Merge remote-tracking branch 'origin/develop' 2025-04-05 15:44:22 +01:00
snipe 0420543c94 Merge remote-tracking branch 'origin/develop'
Signed-off-by: snipe <snipe@snipe.net>

# Conflicts:
#	public/css/build/app.css
#	public/css/build/overrides.css
#	public/css/dist/all.css
#	public/mix-manifest.json
2025-04-05 14:11:07 +01:00
snipe aae0db902b Merge remote-tracking branch 'origin/develop' 2025-04-03 15:41:08 +01:00
snipe 88dae7cef7 Merge remote-tracking branch 'origin/develop'
Signed-off-by: snipe <snipe@snipe.net>

# Conflicts:
#	public/css/build/app.css
#	public/css/build/overrides.css
#	public/css/dist/all.css
#	public/mix-manifest.json
2025-04-03 15:28:10 +01:00
snipe e5cb17e934 Merge remote-tracking branch 'origin/develop' 2025-04-03 10:16:18 +01:00
snipe 9d609805f2 Merge remote-tracking branch 'origin/develop' 2025-04-02 18:33:48 +01:00
snipe e2b9ca8254 Merge remote-tracking branch 'origin/develop' 2025-04-02 14:03:22 +01:00
snipe e16a2fe8af Merge remote-tracking branch 'origin/develop' 2025-04-02 13:51:09 +01:00
snipe 22d61a533d Merge remote-tracking branch 'origin/develop'
Signed-off-by: snipe <snipe@snipe.net>

# Conflicts:
#	config/version.php
2025-04-02 12:50:35 +01:00
snipe af408bb45f Merge remote-tracking branch 'origin/develop' 2025-04-01 21:33:07 +01:00
snipe 24bfbc06f0 Merge remote-tracking branch 'origin/develop' 2025-04-01 19:40:03 +01:00
snipe 5eb9f353b5 Merge remote-tracking branch 'origin/develop'
Signed-off-by: snipe <snipe@snipe.net>

# Conflicts:
#	public/css/dist/all.css
#	public/css/dist/bootstrap-table.css
#	public/js/dist/bootstrap-table.js
#	public/mix-manifest.json
2025-04-01 11:25:33 +01:00
snipe 473ce15f47 Merge pull request #16526 from snipe/develop
Merge #16486  and #16519 into master
2025-03-19 15:31:50 -01:00
snipe eb9cfbaed6 Merge pull request #16498 from snipe/develop
Merge develop into master
2025-03-12 23:23:44 +00:00
snipe faeb037ff9 Merge remote-tracking branch 'origin/develop'
Signed-off-by: snipe <snipe@snipe.net>

# Conflicts:
#	public/css/build/app.css
#	public/css/build/overrides.css
#	public/css/dist/all.css
#	public/js/build/app.js
#	public/js/dist/all.js
#	public/mix-manifest.json
2025-03-12 21:26:34 +00:00
snipe 07602f697d Merge remote-tracking branch 'origin/develop' 2025-03-12 18:13:22 +00:00
snipe 11abb0fdb1 Merge remote-tracking branch 'origin/develop' 2025-03-11 22:13:34 +00:00
snipe deeb2fa543 Merge remote-tracking branch 'origin/develop' 2025-03-11 21:14:12 +00:00
snipe ef8d5ff11e Merge remote-tracking branch 'origin/develop' 2025-03-06 12:06:10 +00:00
snipe 91f3e07b83 Merge remote-tracking branch 'origin/develop'
Signed-off-by: snipe <snipe@snipe.net>

# Conflicts:
#	config/version.php
2025-03-05 17:05:28 +00:00
snipe c29bdbdacb Merge remote-tracking branch 'origin/develop'
Signed-off-by: snipe <snipe@snipe.net>

# Conflicts:
#	public/css/dist/skins/_all-skins.css
#	public/css/dist/skins/_all-skins.min.css
#	public/css/dist/skins/skin-blue.css
#	public/css/dist/skins/skin-blue.min.css
#	public/mix-manifest.json
2025-03-05 13:46:29 +00:00
snipe a20d104d2f Merge remote-tracking branch 'origin/develop' 2025-03-05 11:59:47 +00:00
snipe a61dd8ac17 Merge remote-tracking branch 'origin/develop' 2025-03-05 10:52:42 +00:00
snipe 7ee9a690ea Merge remote-tracking branch 'origin/develop' 2025-03-05 01:12:22 +00:00
snipe 5ba94c6c41 Merge remote-tracking branch 'origin/develop' 2025-03-05 00:12:09 +00:00
snipe 9fa855c837 Prod assets
Signed-off-by: snipe <snipe@snipe.net>
2025-03-04 23:30:45 +00:00
snipe 9251007574 Merge remote-tracking branch 'origin/develop' 2025-03-04 23:29:31 +00:00
snipe cc73b984cb Merge remote-tracking branch 'origin/develop' 2025-03-04 21:13:43 +00:00
snipe 548ef97c32 Merge remote-tracking branch 'origin/develop'
Signed-off-by: snipe <snipe@snipe.net>

# Conflicts:
#	config/version.php
2025-03-04 19:57:33 +00:00
snipe ed8a486726 Merge remote-tracking branch 'origin/develop' 2025-03-04 19:54:08 +00:00
snipe 1ab0911fc8 Merge remote-tracking branch 'origin/develop' 2025-03-04 19:52:16 +00:00
snipe bdbaea7294 Merge remote-tracking branch 'origin/develop' 2025-03-04 19:43:28 +00:00
snipe 5cfd1f6fb2 Merge remote-tracking branch 'origin/develop' 2025-03-04 17:16:26 +00:00
snipe 5eda67381f Merge remote-tracking branch 'origin/develop' 2025-03-04 17:07:13 +00:00
snipe 2c8b8bfaf2 Merge remote-tracking branch 'origin/develop' 2025-03-04 17:05:55 +00:00
snipe 8f3159751a Merge remote-tracking branch 'origin/develop' 2025-03-04 17:01:07 +00:00
snipe 4b05e55b29 Merge remote-tracking branch 'origin/develop' 2025-03-04 15:56:05 +00:00
snipe 3d3c13fcd0 Merge remote-tracking branch 'origin/develop' 2025-03-04 15:38:58 +00:00
snipe 88e1d8a8cf Merge remote-tracking branch 'origin/develop' 2025-03-04 15:28:53 +00:00
snipe e007db34e2 Merge remote-tracking branch 'origin/develop' 2025-03-03 22:12:26 +00:00
snipe f9f06d2c02 Merge remote-tracking branch 'origin/develop' 2025-02-27 19:08:45 +00:00
snipe 234f7d00c8 Merge remote-tracking branch 'origin/develop' 2025-02-27 16:18:18 +00:00
snipe 9924553da5 Merge remote-tracking branch 'origin/develop' 2025-02-27 15:45:57 +00:00
snipe df38d7e3ed Merge remote-tracking branch 'origin/develop'
Signed-off-by: snipe <snipe@snipe.net>

# Conflicts:
#	config/version.php
2025-02-27 12:22:30 +00:00
snipe 44dd061619 Merge remote-tracking branch 'origin/develop' 2025-02-26 20:55:57 +00:00
snipe 7603a932b1 Merge remote-tracking branch 'origin/develop' 2025-02-26 20:29:42 +00:00
snipe 138e7acc13 Merge remote-tracking branch 'origin/develop' 2025-02-26 12:47:54 +00:00
snipe e863d3e7e5 Merge remote-tracking branch 'origin/develop' 2025-02-26 12:02:00 +00:00
snipe c8e401f5ed Merge remote-tracking branch 'origin/develop' 2025-02-26 11:59:53 +00:00
snipe 3ba20a8e28 Merge remote-tracking branch 'origin/develop' 2025-02-26 11:39:10 +00:00
snipe ebae63752f Merge remote-tracking branch 'origin/develop' 2025-02-26 10:25:18 +00:00
snipe 8bc73901cf Merge remote-tracking branch 'origin/develop' 2025-02-26 08:25:35 +00:00
snipe b4f70d9244 Merge remote-tracking branch 'origin/develop' 2025-02-26 07:16:59 +00:00
snipe 21e9f2bba3 Merge remote-tracking branch 'origin/develop' 2025-02-26 07:11:22 +00:00
snipe 881f4e3d6a Merge remote-tracking branch 'origin/develop' 2025-02-25 14:43:57 +00:00
snipe b141945add Updated branch
Signed-off-by: snipe <snipe@snipe.net>
2025-02-25 12:18:52 +00:00
1260 changed files with 17667 additions and 152946 deletions
+27
View File
@@ -4207,6 +4207,33 @@
"contributions": [
"code"
]
},
{
"login": "strobelm",
"name": "Michael Strobel",
"avatar_url": "https://avatars.githubusercontent.com/u/14185442?v=4",
"profile": "https://strobelm.de",
"contributions": [
"code"
]
},
{
"login": "nickwest",
"name": "Nicky West",
"avatar_url": "https://avatars.githubusercontent.com/u/634790?v=4",
"profile": "http://nickwest.me",
"contributions": [
"code"
]
},
{
"login": "akaspeh1",
"name": "akaspeh1",
"avatar_url": "https://avatars.githubusercontent.com/u/1347327?v=4",
"profile": "https://github.com/akaspeh1",
"contributions": [
"code"
]
}
]
}
+7 -1
View File
@@ -193,11 +193,17 @@ LDAP_TIME_LIM=600
IMPORT_TIME_LIMIT=600
IMPORT_MEMORY_LIMIT=500M
REPORT_TIME_LIMIT=12000
REQUIRE_SAML=false
API_THROTTLE_PER_MINUTE=120
CSV_ESCAPE_FORMULAS=true
LIVEWIRE_URL_PREFIX=null
# --------------------------------------------
# OPTIONAL: SAML SETTINGS
# --------------------------------------------
REQUIRE_SAML=false
SAML_KEY_SIZE=2048
# --------------------------------------------
# OPTIONAL: HASHING
# --------------------------------------------
+1 -1
View File
@@ -26,7 +26,7 @@ jobs:
language: [ 'javascript' ]
steps:
- name: Checkout repository
uses: actions/checkout@v4
uses: actions/checkout@v5
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
+1 -1
View File
@@ -32,7 +32,7 @@ jobs:
steps:
# Checkout the repository to the GitHub Actions runner
- name: Checkout code
uses: actions/checkout@v4
uses: actions/checkout@v5
# Execute Codacy Analysis CLI and generate a SARIF output with the security issues identified during the analysis
- name: Run Codacy Analysis CLI
+1 -1
View File
@@ -9,7 +9,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
uses: actions/checkout@v5
- name: Crowdin push
uses: crowdin/github-action@v2
+1 -1
View File
@@ -42,7 +42,7 @@ jobs:
steps:
# https://github.com/actions/checkout
- name: Checkout codebase
uses: actions/checkout@v4
uses: actions/checkout@v5
# https://github.com/docker/setup-buildx-action
- name: Setup Docker Buildx
+1 -1
View File
@@ -42,7 +42,7 @@ jobs:
steps:
# https://github.com/actions/checkout
- name: Checkout codebase
uses: actions/checkout@v4
uses: actions/checkout@v5
# https://github.com/docker/setup-buildx-action
- name: Setup Docker Buildx
+1 -1
View File
@@ -11,7 +11,7 @@ jobs:
dockerHubDescription:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v5
- name: Docker Hub Description
uses: grokability/dockerhub-description@7ea9d275c7cdbe2b676a093a0308c50665e3b8b4
+1 -1
View File
@@ -37,7 +37,7 @@ jobs:
php-version: "${{ matrix.php-version }}"
coverage: none
- uses: actions/checkout@v4
- uses: actions/checkout@v5
- name: Get Composer Cache Directory
id: composer-cache
+1 -1
View File
@@ -34,7 +34,7 @@ jobs:
php-version: "${{ matrix.php-version }}"
coverage: none
- uses: actions/checkout@v4
- uses: actions/checkout@v5
- name: Get Composer Cache Directory
id: composer-cache
+1 -1
View File
@@ -25,7 +25,7 @@ jobs:
php-version: "${{ matrix.php-version }}"
coverage: none
- uses: actions/checkout@v4
- uses: actions/checkout@v5
- name: Get Composer Cache Directory
id: composer-cache
+1 -1
View File
@@ -68,7 +68,7 @@ Thanks goes to all of these wonderful people ([emoji key](https://github.com/ken
| [<img src="https://avatars.githubusercontent.com/u/181059?v=4" width="110px;"/><br /><sub>Juan Font</sub>](https://github.com/juanfont)<br />[💻](https://github.com/snipe/snipe-it/commits?author=juanfont "Code") | [<img src="https://avatars.githubusercontent.com/u/13137708?v=4" width="110px;"/><br /><sub>Juho Taipale</sub>](https://github.com/juhotaipale)<br />[💻](https://github.com/snipe/snipe-it/commits?author=juhotaipale "Code") | [<img src="https://avatars.githubusercontent.com/u/1007419?v=4" width="110px;"/><br /><sub>Korvin Szanto</sub>](https://github.com/KorvinSzanto)<br />[💻](https://github.com/snipe/snipe-it/commits?author=KorvinSzanto "Code") | [<img src="https://avatars.githubusercontent.com/u/8513053?v=4" width="110px;"/><br /><sub>Lewis Foster</sub>](https://lewisfoster.foo/)<br />[💻](https://github.com/snipe/snipe-it/commits?author=sniff122 "Code") | [<img src="https://avatars.githubusercontent.com/u/33877541?v=4" width="110px;"/><br /><sub>Logan Swartzendruber</sub>](https://github.com/loganswartz)<br />[💻](https://github.com/snipe/snipe-it/commits?author=loganswartz "Code") | [<img src="https://avatars.githubusercontent.com/u/1156208?v=4" width="110px;"/><br /><sub>Lorenzo P.</sub>](https://github.com/lopezio)<br />[💻](https://github.com/snipe/snipe-it/commits?author=lopezio "Code") | [<img src="https://avatars.githubusercontent.com/u/33946590?v=4" width="110px;"/><br /><sub>Lukas Jung</sub>](https://github.com/m4us1ne)<br />[💻](https://github.com/snipe/snipe-it/commits?author=m4us1ne "Code") |
| [<img src="https://avatars.githubusercontent.com/u/10965027?v=4" width="110px;"/><br /><sub>Ellie</sub>](https://leafedfox.xyz/)<br />[💻](https://github.com/snipe/snipe-it/commits?author=LeafedFox "Code") | [<img src="https://avatars.githubusercontent.com/u/20960555?v=4" width="110px;"/><br /><sub>GA Stamper</sub>](https://github.com/gastamper)<br />[💻](https://github.com/snipe/snipe-it/commits?author=gastamper "Code") | [<img src="https://avatars.githubusercontent.com/u/206553556?v=4" width="110px;"/><br /><sub>Guillaume Lefranc</sub>](https://github.com/gl-pup)<br />[💻](https://github.com/snipe/snipe-it/commits?author=gl-pup "Code") | [<img src="https://avatars.githubusercontent.com/u/733892?v=4" width="110px;"/><br /><sub>Hajo Möller</sub>](https://github.com/dasjoe)<br />[💻](https://github.com/snipe/snipe-it/commits?author=dasjoe "Code") | [<img src="https://avatars.githubusercontent.com/u/3420063?v=4" width="110px;"/><br /><sub>Istvan Basa</sub>](https://github.com/pottom)<br />[💻](https://github.com/snipe/snipe-it/commits?author=pottom "Code") | [<img src="https://avatars.githubusercontent.com/u/810824?v=4" width="110px;"/><br /><sub>JJ Asghar</sub>](https://jjasghar.github.io/)<br />[💻](https://github.com/snipe/snipe-it/commits?author=jjasghar "Code") | [<img src="https://avatars.githubusercontent.com/u/40404495?v=4" width="110px;"/><br /><sub>James E. Msenga</sub>](https://github.com/JemCdo)<br />[💻](https://github.com/snipe/snipe-it/commits?author=JemCdo "Code") |
| [<img src="https://avatars.githubusercontent.com/u/6865786?v=4" width="110px;"/><br /><sub>Jan Felix Wiebe</sub>](https://github.com/jfwiebe)<br />[💻](https://github.com/snipe/snipe-it/commits?author=jfwiebe "Code") | [<img src="https://avatars.githubusercontent.com/u/43412008?v=4" width="110px;"/><br /><sub>Jo Drexl</sub>](https://www.nfon.com/)<br />[💻](https://github.com/snipe/snipe-it/commits?author=drexljo "Code") | [<img src="https://avatars.githubusercontent.com/u/4807843?v=4" width="110px;"/><br /><sub>Austin Sasko</sub>](https://github.com/austinsasko)<br />[💻](https://github.com/snipe/snipe-it/commits?author=austinsasko "Code") | [<img src="https://avatars.githubusercontent.com/u/4875039?v=4" width="110px;"/><br /><sub>Jasson</sub>](http://jassoncordones.github.io)<br />[💻](https://github.com/snipe/snipe-it/commits?author=JassonCordones "Code") | [<img src="https://avatars.githubusercontent.com/u/76069640?v=4" width="110px;"/><br /><sub>Okean</sub>](https://github.com/Tinyblargon)<br />[💻](https://github.com/snipe/snipe-it/commits?author=Tinyblargon "Code") | [<img src="https://avatars.githubusercontent.com/u/6515064?v=4" width="110px;"/><br /><sub>Alejandro Medrano</sub>](https://www.lst.tfo.upm.es/alejandro-medrano/)<br />[💻](https://github.com/snipe/snipe-it/commits?author=amedranogil "Code") | [<img src="https://avatars.githubusercontent.com/u/58696401?v=4" width="110px;"/><br /><sub>Lukas Kraic</sub>](https://github.com/lukaskraic)<br />[💻](https://github.com/snipe/snipe-it/commits?author=lukaskraic "Code") |
| [<img src="https://avatars.githubusercontent.com/u/1571724?v=4" width="110px;"/><br /><sub>Герхард PICCORO Lenz McKAY </sub>](https://github-readme-stats.vercel.app/api?username=mckaygerhard)<br />[💻](https://github.com/snipe/snipe-it/commits?author=mckaygerhard "Code") | [<img src="https://avatars.githubusercontent.com/u/15015119?v=4" width="110px;"/><br /><sub>Johannes Pollitt</sub>](https://github.com/FlorestanII)<br />[💻](https://github.com/snipe/snipe-it/commits?author=FlorestanII "Code") |
| [<img src="https://avatars.githubusercontent.com/u/1571724?v=4" width="110px;"/><br /><sub>Герхард PICCORO Lenz McKAY </sub>](https://github-readme-stats.vercel.app/api?username=mckaygerhard)<br />[💻](https://github.com/snipe/snipe-it/commits?author=mckaygerhard "Code") | [<img src="https://avatars.githubusercontent.com/u/15015119?v=4" width="110px;"/><br /><sub>Johannes Pollitt</sub>](https://github.com/FlorestanII)<br />[💻](https://github.com/snipe/snipe-it/commits?author=FlorestanII "Code") | [<img src="https://avatars.githubusercontent.com/u/14185442?v=4" width="110px;"/><br /><sub>Michael Strobel</sub>](https://strobelm.de)<br />[💻](https://github.com/snipe/snipe-it/commits?author=strobelm "Code") | [<img src="https://avatars.githubusercontent.com/u/634790?v=4" width="110px;"/><br /><sub>Nicky West</sub>](http://nickwest.me)<br />[💻](https://github.com/snipe/snipe-it/commits?author=nickwest "Code") | [<img src="https://avatars.githubusercontent.com/u/1347327?v=4" width="110px;"/><br /><sub>akaspeh1</sub>](https://github.com/akaspeh1)<br />[💻](https://github.com/snipe/snipe-it/commits?author=akaspeh1 "Code") |
<!-- ALL-CONTRIBUTORS-LIST:END -->
This project follows the [all-contributors](https://github.com/kentcdodds/all-contributors) specification. Contributions of any kind welcome!
+21
View File
@@ -55,6 +55,8 @@ class LdapSync extends Command
ini_set('max_execution_time', env('LDAP_TIME_LIM', 600)); //600 seconds = 10 minutes
ini_set('memory_limit', env('LDAP_MEM_LIM', '500M'));
// Map the LDAP attributes to the Snipe-IT user fields.
$ldap_map = [
"username" => Setting::getSettings()->ldap_username_field,
"last_name" => Setting::getSettings()->ldap_lname_field,
@@ -63,11 +65,17 @@ class LdapSync extends Command
"emp_num" => Setting::getSettings()->ldap_emp_num,
"email" => Setting::getSettings()->ldap_email,
"phone" => Setting::getSettings()->ldap_phone_field,
"mobile" => Setting::getSettings()->ldap_mobile,
"jobtitle" => Setting::getSettings()->ldap_jobtitle,
"address" => Setting::getSettings()->ldap_address,
"city" => Setting::getSettings()->ldap_city,
"state" => Setting::getSettings()->ldap_state,
"zip" => Setting::getSettings()->ldap_zip,
"country" => Setting::getSettings()->ldap_country,
"location" => Setting::getSettings()->ldap_location,
"dept" => Setting::getSettings()->ldap_dept,
"manager" => Setting::getSettings()->ldap_manager,
"display_name" => Setting::getSettings()->ldap_display_name,
];
$ldap_default_group = Setting::getSettings()->ldap_default_group;
@@ -234,9 +242,11 @@ class LdapSync extends Command
}
// Assign the mapped LDAP attributes for each user to the Snipe-IT user fields
for ($i = 0; $i < $results['count']; $i++) {
$item = [];
$item['username'] = $results[$i][$ldap_map["username"]][0] ?? '';
$item['display_name'] = $results[$i][$ldap_map["display_name"]][0] ?? '';
$item['employee_number'] = $results[$i][$ldap_map["emp_num"]][0] ?? '';
$item['lastname'] = $results[$i][$ldap_map["last_name"]][0] ?? '';
$item['firstname'] = $results[$i][$ldap_map["first_name"]][0] ?? '';
@@ -244,8 +254,13 @@ class LdapSync extends Command
$item['ldap_location_override'] = $results[$i]['ldap_location_override'] ?? '';
$item['location_id'] = $results[$i]['location_id'] ?? '';
$item['telephone'] = $results[$i][$ldap_map["phone"]][0] ?? '';
$item['mobile'] = $results[$i][$ldap_map["mobile"]][0] ?? '';
$item['jobtitle'] = $results[$i][$ldap_map["jobtitle"]][0] ?? '';
$item['address'] = $results[$i][$ldap_map["address"]][0] ?? '';
$item['city'] = $results[$i][$ldap_map["city"]][0] ?? '';
$item['state'] = $results[$i][$ldap_map["state"]][0] ?? '';
$item['country'] = $results[$i][$ldap_map["country"]][0] ?? '';
$item['zip'] = $results[$i][$ldap_map["zip"]][0] ?? '';
$item['department'] = $results[$i][$ldap_map["dept"]][0] ?? '';
$item['manager'] = $results[$i][$ldap_map["manager"]][0] ?? '';
$item['location'] = $results[$i][$ldap_map["location"]][0] ?? '';
@@ -278,6 +293,9 @@ class LdapSync extends Command
if($ldap_map["username"] != null){
$user->username = $item['username'];
}
if($ldap_map["display_name"] != null){
$user->display_name = $item['display_name'];
}
if($ldap_map["last_name"] != null){
$user->last_name = $item['lastname'];
}
@@ -293,6 +311,9 @@ class LdapSync extends Command
if($ldap_map["phone"] != null){
$user->phone = $item['telephone'];
}
if($ldap_map["mobile"] != null){
$user->mobile = $item['mobile'];
}
if($ldap_map["jobtitle"] != null){
$user->jobtitle = $item['jobtitle'];
}
+165 -55
View File
@@ -6,6 +6,7 @@ use Illuminate\Console\Command;
use App\Models\Setting;
use Exception;
use Illuminate\Support\Facades\Crypt;
use App\Models\Ldap;
/**
* Check if a given ip is in a network
@@ -160,7 +161,15 @@ class LdapTroubleshooter extends Command
$output[] = "-x";
$output[] = "-b ".escapeshellarg($settings->ldap_basedn);
$output[] = "-D ".escapeshellarg($settings->ldap_uname);
$output[] = "-w ".escapeshellarg(Crypt::Decrypt($settings->ldap_pword));
try {
$w = Crypt::Decrypt($settings->ldap_pword);
} catch (\Exception $e) {
$this->warn("Could not decrypt password. This usually means an LDAP password was not set or the APP_KEY was changed since the LDAP pasword was last saved. Aborting.");
exit(0);
}
$output[] = "-w ". escapeshellarg($w);
$output[] = escapeshellarg(parenthesized_filter($settings->ldap_filter));
if($settings->ldap_tls) {
$this->line("# adding STARTTLS option");
@@ -171,6 +180,23 @@ class LdapTroubleshooter extends Command
$this->line(implode(" \\\n",$output));
exit(0);
}
//PHP Version check for warning
$php_version = phpversion();
list($major, $minor, $patch) = explode('.', $php_version);
if (
$major < 8 ||
($major == 8 && $minor < 3) ||
($major == 8 && $minor == 3 && $patch < 21) ||
($major == 8 && $minor == 4 && $patch < 7)
) {
$this->warn("PHP Version: $php_version WARNING - Versions before 8.3.21 or 8.4.7 will return INCONSISTENT results!");
if (!$this->confirm("Are you sure you wish to continue?")) {
$this->warn("ABORTING");
exit(-1);
}
}
if(!$this->option('force')) {
$confirmation = $this->confirm('WARNING: This command will make several attempts to connect to your LDAP server. Are you sure this is ok?');
if(!$confirmation) {
@@ -179,7 +205,7 @@ class LdapTroubleshooter extends Command
}
}
//$this->line(print_r($settings,true));
$this->info("STAGE 1: Checking settings");
$this->line("STAGE 1: Checking settings");
if(!$settings->ldap_enabled) {
$this->error("WARNING: Snipe-IT's LDAP setting is not turned on. (That may be OK if you're still trying to figure out settings)");
}
@@ -210,32 +236,40 @@ class LdapTroubleshooter extends Command
$this->info("Determined LDAP hostname to be: ".$parsed['host']);
}
$this->info("Performing DNS lookup of: ".$parsed['host']);
$ips = dns_get_record($parsed['host']);
$raw_ips = [];
//$this->info("Host IP is: ".print_r($ips,true));
if (inet_pton($parsed['host']) !== false) {
$this->line($parsed['host'] . " already looks like an address; skipping DNS lookup");
$raw_ips[] = $parsed['host'];
} else {
$this->line("Performing DNS lookup of: " . $parsed['host']);
$ips = dns_get_record($parsed['host']);
if(!$ips || count($ips) == 0) {
$this->error("ERROR: DNS lookup of host: ".$parsed['host']." has failed. ABORTING.");
exit(-1);
}
$this->debugout("IP's? ".print_r($ips,true));
foreach($ips as $ip) {
if(!isset($ip['ip'])) {
continue;
//$this->info("Host IP is: ".print_r($ips,true));
if (!$ips || count($ips) == 0) {
$this->error("ERROR: DNS lookup of host: " . $parsed['host'] . " has failed. ABORTING.");
exit(-1);
}
$raw_ips[]=$ip['ip'];
if($ip['ip'] == "127.0.0.1") {
$this->debugout("IP's? " . print_r($ips, true));
foreach ($ips as $ip) {
if (!isset($ip['ip'])) {
continue;
}
$raw_ips[] = $ip['ip'];
}
}
foreach ($raw_ips as $ip) {
if ($ip == "127.0.0.1") {
$this->error("WARNING: Using the localhost IP as the LDAP server. This is usually wrong");
}
if(ip_in_range($ip['ip'],'10.0.0.0/8') || ip_in_range($ip['ip'],'192.168.0.0/16') || ip_in_range($ip['ip'], '172.16.0.0/12')) {
if (ip_in_range($ip, '10.0.0.0/8') || ip_in_range($ip, '192.168.0.0/16') || ip_in_range($ip, '172.16.0.0/12')) {
$this->error("WARNING: Using an RFC1918 Private address for LDAP server. This may be correct, but it can be a problem if your Snipe-IT instance is not hosted on your private network");
}
}
$this->info("STAGE 2: Checking basic network connectivity");
$ports = [389,636];
$this->line("STAGE 2: Checking basic network connectivity");
$ports = [636, 389];
if(@$parsed['port'] && !in_array($parsed['port'],$ports)) {
$ports[] = $parsed['port'];
}
@@ -246,7 +280,7 @@ class LdapTroubleshooter extends Command
$errstr = '';
$timeout = 30.0;
$result = '';
$this->info("Attempting to connect to port: ".$port." - may take up to $timeout seconds");
$this->line("Attempting to connect to port: " . $port . " - may take up to $timeout seconds");
try {
$result = fsockopen($parsed['host'], $port, $errno, $errstr, 30.0);
} catch(Exception $e) {
@@ -265,9 +299,9 @@ class LdapTroubleshooter extends Command
exit(-1);
}
$this->info("STAGE 3: Determine encryption algorithm, if any");
$this->line("STAGE 3: Determine encryption algorithm, if any");
$ldap_urls = [];
$ldap_urls = []; // [url, cert-check?, start_tls?]
$pretty_ldap_urls = [];
foreach($open_ports as $port) {
$this->line("Trying TLS first for port $port");
@@ -275,35 +309,46 @@ class LdapTroubleshooter extends Command
if($this->test_anonymous_bind($ldap_url)) {
$this->info("Anonymous bind succesful to $ldap_url!");
$ldap_urls[] = [ $ldap_url, true, false ];
$pretty_ldap_urls[] = [ $ldap_url, "YES", "no" ];
$pretty_ldap_urls[] = [$ldap_url, "enabled", "n/a (no)"];
continue; // TODO - lots of copypasta in these if(test_anonymous_bind()) routines...
} else {
$this->error("WARNING: Failed to bind to $ldap_url - trying without certificate checks.");
}
if($this->test_anonymous_bind($ldap_url, false)) {
$this->info("Anonymous bind succesful to $ldap_url with certifcate-checks disabled");
$ldap_urls[] = [ $ldap_url, false, false ];
$pretty_ldap_urls[] = [ $ldap_url, "no", "no" ];
$this->info("Anonymous bind successful to $ldap_url with certificate-checks disabled");
$ldap_urls[] = [$ldap_url, false, false];
$pretty_ldap_urls[] = [$ldap_url, "DISABLED", "n/a (no)"];
continue;
} else {
$this->error("WARNING: Failed to bind to $ldap_url with certificate checks disabled. Trying unencrypted with STARTTLS");
}
// now switching to ldap:// URL's from ldaps://
$ldap_url = "ldap://".$parsed['host'].":$port";
if($this->test_anonymous_bind($ldap_url, true, true)) {
$this->info("Plain connection to $ldap_url with STARTTLS succesful!");
$ldap_urls[] = [ $ldap_url, true, true ];
$pretty_ldap_urls[] = [ $ldap_url, "YES", "YES" ];
$pretty_ldap_urls[] = [$ldap_url, "enabled", "STARTTLS ENABLED"];
continue;
} else {
$this->error("WARNING: Failed to bind to $ldap_url with STARTTLS enabled. Trying without STARTTLS");
$this->error("WARNING: Failed to bind to $ldap_url with STARTTLS enabled. Trying without certificate checks.");
}
if ($this->test_anonymous_bind($ldap_url, false, true)) {
$this->info("Plain connection to $ldap_url with STARTTLS and cert checks *disabled* successful!");
$ldap_urls[] = [$ldap_url, false, true];
$pretty_ldap_urls[] = [$ldap_url, "DISABLED", "STARTTLS ENABLED"];
continue;
} else {
$this->error("WARNING: Failed to bind to $ldap_url with STARTTLS enabled, and cert checks disabled. Trying without STARTTLS");
}
if($this->test_anonymous_bind($ldap_url)) {
$this->info("Plain connection to $ldap_url succesful!");
$ldap_urls[] = [ $ldap_url, true, false ];
$pretty_ldap_urls[] = [ $ldap_url, "YES", "no" ];
$pretty_ldap_urls[] = [$ldap_url, "n/a", "starttls disabled"];
continue;
} else {
$this->error("WARNING: Failed to bind to $ldap_url. Giving up on port $port");
@@ -313,23 +358,29 @@ class LdapTroubleshooter extends Command
$this->debugout(print_r($ldap_urls,true));
if(count($ldap_urls) > 0 ) {
$this->info("Found working LDAP URL's: ");
$this->debugout("Found working LDAP URL's: ");
foreach($ldap_urls as $ldap_url) { // TODO maybe do this as a $this->table() instead?
$this->info("LDAP URL: ".$ldap_url[0]);
$this->info($ldap_url[0]. ($ldap_url[1] ? " certificate checks enabled" : " certificate checks disabled"). ($ldap_url[2] ? " STARTTLS Enabled ": " STARTTLS Disabled"));
$this->debugout("LDAP URL: " . $ldap_url[0]);
$this->debugout($ldap_url[0] . ($ldap_url[1] ? " certificate checks enabled" : " certificate checks disabled") . ($ldap_url[2] ? " STARTTLS Enabled " : " STARTTLS Disabled"));
}
$this->table(["URL", "Cert Checks Enabled?", "STARTTLS Enabled?"],$pretty_ldap_urls);
$this->table(["URL", "Cert Checks?", "STARTTLS?"], $pretty_ldap_urls);
} else {
$this->error("ERROR - no valid LDAP URL's available - ABORTING");
exit(1);
}
$this->info("STAGE 4: Test Administrative Bind for LDAP Sync");
$this->line("STAGE 4: Test Administrative Bind for LDAP Sync");
foreach($ldap_urls AS $ldap_url) {
$this->test_authed_bind($ldap_url[0], $ldap_url[1], $ldap_url[2], $settings->ldap_uname, Crypt::decrypt($settings->ldap_pword));
try {
$w = Crypt::Decrypt($settings->ldap_pword);
} catch (\Exception $e) {
$this->warn("Could not decrypt password. This usually means an LDAP password was not set or the APP_KEY was changed since the LDAP pasword was last saved. Aborting.");
exit(0);
}
$this->test_authed_bind($ldap_url[0], $ldap_url[1], $ldap_url[2], $settings->ldap_uname, $w);
}
$this->info("STAGE 5: Test BaseDN");
$this->line("STAGE 5: Test BaseDN");
//grab all LDAP_ constants and fill up a reversed array mapping from weird LDAP dotted-strings to (Constant Name)
$all_defined_constants = get_defined_constants();
$ldap_constants = [];
@@ -341,16 +392,23 @@ class LdapTroubleshooter extends Command
$this->debugout("LDAP constants are: ".print_r($ldap_constants,true));
foreach($ldap_urls AS $ldap_url) {
if($this->test_informational_bind($ldap_url[0],$ldap_url[1],$ldap_url[2],$settings->ldap_uname,Crypt::decrypt($settings->ldap_pword),$settings)) {
try {
$w = Crypt::Decrypt($settings->ldap_pword);
} catch (\Exception $e) {
$this->warn("Could not decrypt password. This usually means an LDAP password was not set or the APP_KEY was changed since the LDAP pasword was last saved. Aborting.");
exit(0);
}
if($this->test_informational_bind($ldap_url[0],$ldap_url[1],$ldap_url[2],$settings->ldap_uname,$w,$settings)) {
$this->info("Success getting informational bind!");
} else {
$this->error("Unable to get information from bind.");
}
}
$this->info("STAGE 6: Test LDAP Login to Snipe-IT");
$this->line("STAGE 6: Test LDAP Login to Snipe-IT");
foreach($ldap_urls AS $ldap_url) {
$this->info("Starting auth to ".$ldap_url[0]);
$this->line("Starting auth to " . $ldap_url[0]);
while(true) {
$with_tls = $ldap_url[1] ? "with": "without";
$with_startssl = $ldap_url[2] ? "using": "not using";
@@ -359,7 +417,12 @@ class LdapTroubleshooter extends Command
}
$username = $this->ask("Username");
$password = $this->secret("Password");
$this->test_authed_bind($ldap_url[0], $ldap_url[1], $ldap_url[2], $username, $password); // FIXME - should do some other stuff here, maybe with the concatenating or something? maybe? and/or should put up some results?
$results = $this->test_authed_bind($ldap_url[0], $ldap_url[1], $ldap_url[2], $username, $password); // FIXME - should do some other stuff here, maybe with the concatenating or something? maybe? and/or should put up some results?
if ($results) {
$this->info("Success authenticating with " . $username);
} else {
$this->error("Unable to authenticate with " . $username);
}
}
}
@@ -368,14 +431,17 @@ class LdapTroubleshooter extends Command
public function connect_to_ldap($ldap_url, $check_cert, $start_tls)
{
if ($check_cert) {
$this->line("we *ARE* checking certs");
Ldap::ignoreCertificates(false);
} else {
$this->line("we are IGNORING certs");
Ldap::ignoreCertificates(true);
}
$lconn = ldap_connect($ldap_url);
ldap_set_option($lconn, LDAP_OPT_PROTOCOL_VERSION, 3); // should we 'test' different protocol versions here? Does anyone even use anything other than LDAPv3?
// no - it's formally deprecated: https://tools.ietf.org/html/rfc3494
if(!$check_cert) {
putenv('LDAPTLS_REQCERT=never'); // This is horrible; is this *really* the only way to do it?
} else {
putenv('LDAPTLS_REQCERT'); // have to very explicitly and manually *UN* set the env var here to ensure it works
}
if($this->settings->ldap_client_tls_cert && $this->settings->ldap_client_tls_key) {
// client-side TLS certificate support for LDAP (Google Secure LDAP)
putenv('LDAPTLS_CERT=storage/ldap_client_tls.cert');
@@ -404,9 +470,10 @@ class LdapTroubleshooter extends Command
return $this->timed_boolean_execute(function () use ($ldap_url, $check_cert , $start_tls) {
try {
$lconn = $this->connect_to_ldap($ldap_url, $check_cert, $start_tls);
$this->info("gonna try to bind now, this can take a while if we mess it up");
$this->line("Attempting to bind now, this can take a while if we mess it up");
$bind_results = ldap_bind($lconn);
$this->info("Bind results are: ".$bind_results." which translate into boolean: ".(bool)$bind_results);
$this->line("Bind results are: " . $bind_results . " which translate into boolean: " . (bool)$bind_results);
ldap_close($lconn);
return (bool)$bind_results;
} catch (Exception $e) {
$this->error("WARNING: Exception caught during bind - ".$e->getMessage());
@@ -421,6 +488,7 @@ class LdapTroubleshooter extends Command
try {
$lconn = $this->connect_to_ldap($ldap_url, $check_cert, $start_tls);
$bind_results = ldap_bind($lconn, $username, $password);
ldap_close($lconn);
if(!$bind_results) {
$this->error("WARNING: Failed to bind to $ldap_url as $username");
return false;
@@ -446,22 +514,62 @@ class LdapTroubleshooter extends Command
return false;
}
$this->info("SUCCESS - Able to bind to $ldap_url as $username");
$result = ldap_read($conn, '', '(objectClass=*)'/* , ['supportedControl']*/);
$results = ldap_get_entries($conn, $result);
$cleaned_results = $this->ldap_results_cleaner($results);
$this->line(print_r($cleaned_results,true));
//okay, great - now how do we display those results? I have no idea.
$cleaned_results = [];
try {
// This _may_ only work for Active Directory?
$result = ldap_read($conn, '', '(objectClass=*)'/* , ['supportedControl']*/);
$results = ldap_get_entries($conn, $result);
$cleaned_results = $this->ldap_results_cleaner($results);
//$this->line(print_r($cleaned_results,true));
$default_naming_contexts = $cleaned_results[0]['namingcontexts'];
$this->info("Default Naming Contexts:");
$this->info(implode(", ", $default_naming_contexts));
//okay, great - now how do we display those results? I have no idea.
} catch (\Exception $e) {
$this->error("Unable to get base naming contexts - here's what we *did* get:");
$this->line(print_r($cleaned_results, true));
}
// I don't see why this throws an Exception for Google LDAP, but I guess we ought to try and catch it?
$this->comment("I guess we're trying to do the ldap search here, but sometimes it takes too long?");
$this->debugout("I guess we're trying to do the ldap search here, but sometimes it takes too long?");
$this->debugout("Base DN is: ".$settings->ldap_basedn." and filter is: ".parenthesized_filter($settings->ldap_filter));
$search_results = ldap_search($conn, $settings->ldap_basedn, parenthesized_filter($settings->ldap_filter));
$entries = ldap_get_entries($conn, $search_results);
$this->info("Printing first 10 results: ");
for($i=0;$i<10;$i++) {
$this->info($search_results[$i]);
$pretty_data = array_slice($this->ldap_results_cleaner($entries), 0, 10);
//print_r($data);
$headers = [];
foreach ($pretty_data as $row) {
//populate headers
foreach ($row as $key => $value) {
//skip objectsid and objectguid because it junks up output
if ($key == "objectsid" || $key == "objectguid") {
continue;
}
if (!in_array($key, $headers)) {
$headers[] = $key;
}
}
}
$table = [];
//repeat again to populate table
foreach ($pretty_data as $row) {
$newrow = [];
foreach ($headers as $header) {
if (is_array(@$row[$header])) {
$newrow[] = "[" . implode(", ", $row[$header]) . "]";
} else {
$newrow[] = @$row[$header];
}
}
$table[] = $newrow;
}
$this->table($headers, $table);
} catch (\Exception $e) {
$this->error("WARNING: Exception caught during Authed bind to $username - ".$e->getMessage());
return false;
} finally {
ldap_close($conn);
}
});
}
@@ -477,7 +585,7 @@ class LdapTroubleshooter extends Command
{
if(!(function_exists('pcntl_sigtimedwait') && function_exists('posix_getpid') && function_exists('pcntl_fork') && function_exists('posix_kill') && function_exists('pcntl_wifsignaled'))) {
// POSIX functions needed for forking aren't present, just run the function inline (ignoring timeout)
$this->info('WARNING: Unable to execute POSIX fork() commands, timeout may not be respected');
$this->line('WARNING: Unable to execute POSIX fork() commands, timeout may not be respected');
return $function();
} else {
$parent_pid = posix_getpid();
@@ -514,4 +622,6 @@ class LdapTroubleshooter extends Command
}
}
}
@@ -77,7 +77,7 @@ class SendAcceptanceReminder extends Command
if(!$email){
$no_email_list[] = [
'id' => $acceptance->assignedTo?->id,
'name' => $acceptance->assignedTo?->present()->fullName(),
'name' => $acceptance->assignedTo?->display_name,
];
} else {
$count++;
@@ -248,15 +248,15 @@ class AcceptanceController extends Controller
// Add the attachment for the signing user into the $data array
$data['file'] = $pdf_filename;
$locale = $assigned_user->locale;
try {
$assigned_user->notify(new AcceptanceAssetAcceptedToUserNotification($data));
$assigned_user->notify((new AcceptanceAssetAcceptedToUserNotification($data))->locale($locale));
} catch (\Exception $e) {
Log::warning($e);
}
}
try {
$acceptance->notify(new AcceptanceAssetAcceptedNotification($data));
$acceptance->notify((new AcceptanceAssetAcceptedNotification($data))->locale(Setting::getSettings()->locale));
} catch (\Exception $e) {
Log::warning($e);
}
@@ -610,7 +610,7 @@ class AssetsController extends Controller
$asset->use_text = $asset->present()->fullName;
if (($asset->checkedOutToUser()) && ($asset->assigned)) {
$asset->use_text .= ' → ' . $asset->assigned->getFullNameAttribute();
$asset->use_text .= ' → ' . $asset->assigned->display_name;
}
@@ -230,13 +230,13 @@ class ConsumablesController extends Controller
'avatar' => ($consumable_assignment->user) ? e($consumable_assignment->user->present()->gravatar) : '',
'user' => ($consumable_assignment->user) ? [
'id' => (int) $consumable_assignment->user->id,
'name'=> e($consumable_assignment->user->present()->fullName()),
'name'=> e($consumable_assignment->user->display_name),
] : null,
'created_at' => Helper::getFormattedDateObject($consumable_assignment->created_at, 'datetime'),
'note' => ($consumable_assignment->note) ? e($consumable_assignment->note) : null,
'created_by' => ($consumable_assignment->adminuser) ? [
'id' => (int) $consumable_assignment->adminuser->id,
'name'=> e($consumable_assignment->adminuser->present()->fullName()),
'name'=> e($consumable_assignment->adminuser->display_name),
] : null,
];
}
@@ -195,7 +195,7 @@ class ImportController extends Controller
// Run a backup immediately before processing
if ($request->get('run-backup')) {
Log::debug('Backup manually requested via importer');
Artisan::call('snipeit:backup', ['--filename' => 'pre-import-backup-'.date('Y-m-d-H:i:s')]);
Artisan::call('snipeit:backup', ['--filename' => 'pre-import-backup-'.date('Y-m-d-H-i-s')]);
} else {
Log::debug('NO BACKUP requested via importer');
}
@@ -0,0 +1,95 @@
<?php
namespace App\Http\Controllers\Api;
use App\Helpers\Helper;
use App\Http\Controllers\Controller;
use App\Models\Actionlog;
use App\Models\Asset;
use Illuminate\Database\Eloquent\ModelNotFoundException;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Log;
/**
* This class controls all API actions related to notes for
* the Snipe-IT Asset Management application.
*/
class NotesController extends Controller
{
/**
* Retrieve a list of manual notes (action logs) for a given asset.
*
* Checks authorization to view assets, attempts to find the asset by ID,
* and fetches related action log entries of type 'note added', including
* user information for each note. Returns a JSON response with the notes or errors.
*
* @param \Illuminate\Http\Request $request The incoming HTTP request.
* @param Asset $asset The ID of the asset whose notes to retrieve.
* @return \Illuminate\Http\JsonResponse
*/
public function index(Asset $asset): JsonResponse
{
$this->authorize('view', $asset);
// Get the manual notes for the asset
$notes = ActionLog::with('user:id,username')
->where('item_type', Asset::class)
->where('item_id', $asset->id)
->where('action_type', 'note added')
->orderBy('created_at', 'desc')
->get(['id', 'created_at', 'note', 'created_by', 'item_id', 'item_type', 'action_type', 'target_id', 'target_type']);
$notesArray = $notes->map(function ($note) {
return [
'id' => $note->id,
'created_at' => $note->created_at,
'note' => $note->note,
'created_by' => $note->created_by,
'username' => $note->user?->username, // adding the username
'item_id' => $note->item_id,
'item_type' => $note->item_type,
'action_type' => $note->action_type,
];
});
// Return a success response
return response()->json(Helper::formatStandardApiResponse('success', ['notes' => $notesArray, 'asset_id' => $asset->id]));
}
/**
* Store a manual note on a specified asset and log the action.
*
* Checks authorization for updating assets, validates the presence of the 'note',
* attempts to find the asset by ID, and creates a new ActionLog entry if successful.
* Returns JSON responses indicating success or failure with appropriate HTTP status codes.
*
* @param \Illuminate\Http\Request $request The incoming HTTP request containing the 'note'.
* @param Asset $asset The ID of the asset to attach the note to.
* @return \Illuminate\Http\JsonResponse
*/
public function store(Request $request, Asset $asset): JsonResponse
{
$this->authorize('update', $asset);
if ($request->input('note', '') == '') {
return response()->json(Helper::formatStandardApiResponse('error', null, trans('validation.required', ['attribute' => 'note'])), 422);
}
// Create the note
$logaction = new ActionLog();
$logaction->item_type = get_class($asset);
$logaction->created_by = Auth::id();
$logaction->item_id = $asset->id;
$logaction->note = $request->input('note', '');
if ($logaction->logaction('note added')) {
// Return a success response
return response()->json(Helper::formatStandardApiResponse('success', ['note' => $logaction->note, 'item_id' => $asset->id], trans('general.note_added')));
}
// Return an error response if something went wrong
return response()->json(Helper::formatStandardApiResponse('error', null, 'Something went wrong'), 500);
}
}
@@ -3,7 +3,6 @@
namespace App\Http\Controllers\Api;
use App\Helpers\Helper;
use App\Helpers\StorageHelper;
use App\Http\Transformers\DatatablesTransformer;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
@@ -51,10 +50,22 @@ class SettingsController extends Controller
})->slice(0, 10)->map(function ($item) use ($settings) {
return (object) [
'username' => $item[$settings['ldap_username_field']][0] ?? null,
'display_name' => $item[$settings['ldap_display_name']][0] ?? null,
'employee_number' => $item[$settings['ldap_emp_num']][0] ?? null,
'lastname' => $item[$settings['ldap_lname_field']][0] ?? null,
'firstname' => $item[$settings['ldap_fname_field']][0] ?? null,
'email' => $item[$settings['ldap_email']][0] ?? null,
'phone' => $item[$settings['ldap_phone_field']][0] ?? null,
'mobile' => $item[$settings['ldap_mobile']][0] ?? null,
'jobtitle' => $item[$settings['ldap_jobtitle']][0] ?? null,
'department' => $item[$settings['ldap_department']][0] ?? null,
'manager' => $item[$settings['ldap_manager']][0] ?? null,
'address' => $item[$settings['ldap_address']][0] ?? null,
'city' => $item[$settings['ldap_city']][0] ?? null,
'state' => $item[$settings['ldap_state']][0] ?? null,
'zip' => $item[$settings['ldap_zip']][0] ?? null,
'country' => $item[$settings['ldap_country']][0] ?? null,
'location' => $item[$settings['ldap_location']][0] ?? null,
];
});
if ($users->count() > 0) {
@@ -78,7 +89,7 @@ class SettingsController extends Controller
}
} catch (\Exception $e) {
Log::debug('Connection failed but we cannot debug it any further on our end.');
return response()->json(['message' => $e->getMessage()], 500);
return response()->json(['message' => $e->getMessage()], 400);
}
+26 -6
View File
@@ -20,6 +20,7 @@ use App\Models\Consumable;
use App\Models\License;
use App\Models\User;
use App\Notifications\CurrentInventory;
use App\Notifications\WelcomeNotification;
use Illuminate\Support\Facades\Artisan;
use Illuminate\Support\Facades\Auth;
use Illuminate\Database\Eloquent\Builder;
@@ -64,6 +65,7 @@ class UsersController extends Controller
'users.jobtitle',
'users.last_login',
'users.last_name',
'users.display_name',
'users.locale',
'users.location_id',
'users.manager_id',
@@ -154,6 +156,10 @@ class UsersController extends Controller
$users = $users->where('users.last_name', '=', $request->input('last_name'));
}
if ($request->filled('display_name')) {
$users = $users->where('users.display_name', '=', $request->input('display_name'));
}
if ($request->filled('employee_num')) {
$users = $users->where('users.employee_num', '=', $request->input('employee_num'));
}
@@ -284,6 +290,7 @@ class UsersController extends Controller
[
'last_name',
'first_name',
'display_name',
'email',
'jobtitle',
'username',
@@ -355,6 +362,7 @@ class UsersController extends Controller
'users.employee_num',
'users.first_name',
'users.last_name',
'users.display_name',
'users.gravatar',
'users.avatar',
'users.email',
@@ -365,20 +373,17 @@ class UsersController extends Controller
$users = $users->where(function ($query) use ($request) {
$query->SimpleNameSearch($request->get('search'))
->orWhere('username', 'LIKE', '%'.$request->get('search').'%')
->orWhere('display_name', 'LIKE', '%'.$request->get('search').'%')
->orWhere('email', 'LIKE', '%'.$request->get('search').'%')
->orWhere('employee_num', 'LIKE', '%'.$request->get('search').'%');
});
}
$users = $users->orderBy('last_name', 'asc')->orderBy('first_name', 'asc');
$users = $users->orderBy('display_name', 'asc')->orderBy('last_name', 'asc')->orderBy('first_name', 'asc');
$users = $users->paginate(50);
foreach ($users as $user) {
$name_str = '';
if ($user->last_name != '') {
$name_str .= $user->last_name.', ';
}
$name_str .= $user->first_name;
$name_str = $user->display_name;
if ($user->username != '') {
$name_str .= ' ('.$user->username.')';
@@ -433,6 +438,17 @@ class UsersController extends Controller
app('App\Http\Requests\ImageUploadRequest')->handleImages($user, 600, 'image', 'avatars', 'avatar');
if ($user->save()) {
if (($user->activated == '1') && ($user->email != '') && ($request->input('send_welcome') == '1')) {
try {
$user->notify(new WelcomeNotification($user));
} catch (\Exception $e) {
Log::warning('Could not send welcome notification for user: ' . $e->getMessage());
}
}
if ($request->filled('groups')) {
$user->groups()->sync($request->input('groups'));
} else {
@@ -511,6 +527,10 @@ class UsersController extends Controller
$user->username = $request->input('username');
}
if ($request->filled('display_name')) {
$user->display_name = $request->input('display_name');
}
if ($request->filled('email')) {
$user->email = $request->input('email');
}
@@ -797,7 +797,7 @@ class AssetsController extends Controller
'item_id' => $asset->id,
'item_type' => Asset::class,
'created_by' => auth()->id(),
'note' => 'Checkout imported by '.auth()->user()->present()->fullName().' from history importer',
'note' => 'Checkout imported by '.auth()->user()->display_name.' from history importer',
'target_id' => $item[$asset_tag][$batch_counter]['user_id'],
'target_type' => User::class,
'created_at' => $item[$asset_tag][$batch_counter]['checkout_date'],
@@ -825,7 +825,7 @@ class AssetsController extends Controller
'item_id' => $item[$asset_tag][$batch_counter]['asset_id'],
'item_type' => Asset::class,
'created_by' => auth()->id(),
'note' => 'Checkin imported by '.auth()->user()->present()->fullName().' from history importer',
'note' => 'Checkin imported by '.auth()->user()->display_name.' from history importer',
'target_id' => null,
'created_at' => $checkin_date,
'action_type' => 'checkin',
@@ -364,7 +364,7 @@ class LicensesController extends Controller
$license->order_number,
$license->free_seat_count,
$license->seats,
($license->adminuser ? $license->adminuser->present()->fullName() : trans('admin/reports/general.deleted_user')),
($license->adminuser ? $license->adminuser->display_name : trans('admin/reports/general.deleted_user')),
$license->depreciation ? $license->depreciation->name: '',
$license->updated_at,
$license->deleted_at,
+3 -3
View File
@@ -275,7 +275,7 @@ class ReportsController extends Controller
if ($actionlog->target) {
if ($actionlog->targetType() == 'user') {
$target_name = $actionlog->target->getFullNameAttribute();
$target_name = $actionlog->target->display_name;
} else {
$target_name = $actionlog->target->getDisplayNameAttribute();
}
@@ -289,7 +289,7 @@ class ReportsController extends Controller
$row = [
$actionlog->created_at,
($actionlog->adminuser) ? e($actionlog->adminuser->getFullNameAttribute()) : '',
($actionlog->adminuser) ? e($actionlog->adminuser->display_name) : '',
$actionlog->present()->actionType(),
e($actionlog->itemType()),
($actionlog->itemType() == 'user') ? $actionlog->filename : $item_name,
@@ -856,7 +856,7 @@ class ReportsController extends Controller
}
if ($request->filled('assigned_to')) {
$row[] = ($asset->checkedOutToUser() && $asset->assigned) ? $asset->assigned->getFullNameAttribute() : ($asset->assigned ? $asset->assigned->display_name : '');
$row[] = ($asset->checkedOutToUser() && $asset->assigned) ?? $asset->assigned->display_name;
$row[] = ($asset->checkedOutToUser() && $asset->assigned) ? 'user' : $asset->assignedType();
}
@@ -873,6 +873,7 @@ class SettingsController extends Controller
$setting->ldap_default_group = $request->input('ldap_default_group');
$setting->ldap_filter = $request->input('ldap_filter');
$setting->ldap_username_field = $request->input('ldap_username_field');
$setting->ldap_display_name = $request->input('ldap_display_name');
$setting->ldap_lname_field = $request->input('ldap_lname_field');
$setting->ldap_fname_field = $request->input('ldap_fname_field');
$setting->ldap_auth_filter_query = $request->input('ldap_auth_filter_query');
@@ -889,7 +890,12 @@ class SettingsController extends Controller
$setting->ldap_pw_sync = $request->input('ldap_pw_sync', '0');
$setting->custom_forgot_pass_url = $request->input('custom_forgot_pass_url');
$setting->ldap_phone_field = $request->input('ldap_phone');
$setting->ldap_mobile = $request->input('ldap_mobile');
$setting->ldap_jobtitle = $request->input('ldap_jobtitle');
$setting->ldap_address = $request->input('ldap_address');
$setting->ldap_city = $request->input('ldap_city');
$setting->ldap_state = $request->input('ldap_state');
$setting->ldap_zip = $request->input('ldap_zip');
$setting->ldap_country = $request->input('ldap_country');
$setting->ldap_location = $request->input('ldap_location');
$setting->ldap_dept = $request->input('ldap_dept');
+19 -3
View File
@@ -13,7 +13,9 @@ use App\Models\Company;
use App\Models\Group;
use App\Models\Setting;
use App\Models\User;
use App\Notifications\WelcomeNotification;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Password;
use Symfony\Component\HttpFoundation\StreamedResponse;
use App\Notifications\CurrentInventory;
@@ -88,6 +90,7 @@ class UsersController extends Controller
//Username, email, and password need to be handled specially because the need to respect config values on an edit.
$user->email = trim($request->input('email'));
$user->username = trim($request->input('username'));
$user->display_name = $request->input('display_name');
if ($request->filled('password')) {
$user->password = bcrypt($request->input('password'));
}
@@ -127,7 +130,7 @@ class UsersController extends Controller
// we have to invoke the form request here to handle image uploads
app(ImageUploadRequest::class)->handleImages($user, 600, 'avatar', 'avatars', 'avatar');
if($request->get('redirect_option') === 'back'){
if ($request->get('redirect_option') === 'back'){
session()->put(['redirect_option' => 'index']);
} else {
session()->put(['redirect_option' => $request->get('redirect_option')]);
@@ -135,6 +138,18 @@ class UsersController extends Controller
if ($user->save()) {
if (($user->activated == '1') && ($user->email != '') && ($request->input('send_welcome') == '1')) {
try {
$user->notify(new WelcomeNotification($user));
} catch (\Exception $e) {
Log::warning('Could not send welcome notification for user: ' . $e->getMessage());
}
}
if ($request->filled('groups')) {
$user->groups()->sync($request->input('groups'));
} else {
@@ -240,6 +255,7 @@ class UsersController extends Controller
$user->first_name = $request->input('first_name');
$user->last_name = $request->input('last_name');
$user->display_name = $request->input('display_name');
$user->two_factor_optin = $request->input('two_factor_optin') ?: 0;
$user->locale = $request->input('locale');
$user->employee_num = $request->input('employee_num');
@@ -562,10 +578,10 @@ class UsersController extends Controller
$user->employee_num,
$user->first_name,
$user->last_name,
$user->present()->fullName(),
$user->display_name,
$user->username,
$user->email,
($user->manager) ? $user->manager->present()->fullName() : '',
($user->manager) ? $user->manager->display_name : '',
($user->userloc) ? $user->userloc->name : '',
($user->department) ? $user->department->name : '',
$user->assets->count(),
@@ -185,7 +185,7 @@ class ViewAssetsController extends Controller
$logaction->target_type = User::class;
$data['item_quantity'] = $request->has('request-quantity') ? e($request->input('request-quantity')) : 1;
$data['requested_by'] = $user->present()->fullName();
$data['requested_by'] = $user->display_name;
$data['item'] = $item;
$data['item_type'] = $itemType;
$data['target'] = auth()->user();
+1 -1
View File
@@ -109,7 +109,7 @@ class SettingsSamlRequest extends FormRequest
];
$pkey = openssl_pkey_new([
'private_key_bits' => 2048,
'private_key_bits' => config('app.saml_key_size'),
'private_key_type' => OPENSSL_KEYTYPE_RSA,
]);
@@ -44,7 +44,7 @@ class AccessoriesTransformer
'checkouts_count' => $accessory->checkouts_count,
'created_by' => ($accessory->adminuser) ? [
'id' => (int) $accessory->adminuser->id,
'name'=> e($accessory->adminuser->present()->fullName()),
'name'=> e($accessory->adminuser->display_name),
] : null,
'created_at' => Helper::getFormattedDateObject($accessory->created_at, 'datetime'),
'updated_at' => Helper::getFormattedDateObject($accessory->updated_at, 'datetime'),
@@ -150,7 +150,7 @@ class ActionlogsTransformer
'item' => ($actionlog->item) ? [
'id' => (int) $actionlog->item->id,
'name' => ($actionlog->itemType()=='user') ? e($actionlog->item->getFullNameAttribute()) : e($actionlog->item->getDisplayNameAttribute()),
'name' => e($actionlog->item->display_name) ?? null,
'type' => e($actionlog->itemType()),
'serial' =>e($actionlog->item->serial) ? e($actionlog->item->serial) : null
] : null,
@@ -165,19 +165,19 @@ class ActionlogsTransformer
'action_type' => $actionlog->present()->actionType(),
'admin' => ($actionlog->adminuser) ? [
'id' => (int) $actionlog->adminuser->id,
'name' => e($actionlog->adminuser->getFullNameAttribute()),
'name' => e($actionlog->adminuser->display_name),
'first_name'=> e($actionlog->adminuser->first_name),
'last_name'=> e($actionlog->adminuser->last_name)
] : null,
'created_by' => ($actionlog->adminuser) ? [
'id' => (int) $actionlog->adminuser->id,
'name' => e($actionlog->adminuser->getFullNameAttribute()),
'name' => e($actionlog->adminuser->display_name),
'first_name'=> e($actionlog->adminuser->first_name),
'last_name'=> e($actionlog->adminuser->last_name)
] : null,
'target' => ($actionlog->target) ? [
'id' => (int) $actionlog->target->id,
'name' => ($actionlog->targetType()=='user') ? e($actionlog->target->getFullNameAttribute()) : e($actionlog->target->getDisplayNameAttribute()),
'name' => ($actionlog->target->display_name) ?? null,
'type' => e($actionlog->targetType()),
] : null,
@@ -68,7 +68,7 @@ class AssetModelsTransformer
'notes' => Helper::parseEscapedMarkedownInline($assetmodel->notes),
'created_by' => ($assetmodel->adminuser) ? [
'id' => (int) $assetmodel->adminuser->id,
'name'=> e($assetmodel->adminuser->present()->fullName()),
'name'=> e($assetmodel->adminuser->display_name),
] : null,
'created_at' => Helper::getFormattedDateObject($assetmodel->created_at, 'datetime'),
'updated_at' => Helper::getFormattedDateObject($assetmodel->updated_at, 'datetime'),
+2 -2
View File
@@ -91,7 +91,7 @@ class AssetsTransformer
'warranty_expires' => ($asset->warranty_months > 0) ? Helper::getFormattedDateObject($asset->warranty_expires, 'date') : null,
'created_by' => ($asset->adminuser) ? [
'id' => (int) $asset->adminuser->id,
'name'=> e($asset->adminuser->present()->fullName()),
'name'=> e($asset->adminuser->display_name),
] : null,
'created_at' => Helper::getFormattedDateObject($asset->created_at, 'datetime'),
'updated_at' => Helper::getFormattedDateObject($asset->updated_at, 'datetime'),
@@ -287,7 +287,7 @@ class AssetsTransformer
'id' => (int) $asset->id,
'image' => ($asset->getImageUrl()) ? $asset->getImageUrl() : null,
'type' => 'asset',
'name' => e($asset->present()->fullName()),
'name' => e($asset->display_name),
'model' => ($asset->model) ? e($asset->model->name) : null,
'model_number' => (($asset->model) && ($asset->model->model_number)) ? e($asset->model->model_number) : null,
'asset_tag' => e($asset->asset_tag),
@@ -64,7 +64,7 @@ class CategoriesTransformer
'licenses_count' => (int) $category->licenses_count,
'created_by' => ($category->adminuser) ? [
'id' => (int) $category->adminuser->id,
'name'=> e($category->adminuser->present()->fullName()),
'name'=> e($category->adminuser->display_name),
] : null,
'notes' => Helper::parseEscapedMarkedownInline($category->notes),
'created_at' => Helper::getFormattedDateObject($category->created_at, 'datetime'),
@@ -38,7 +38,7 @@ class CompaniesTransformer
'users_count' => (int) $company->users_count,
'created_by' => ($company->adminuser) ? [
'id' => (int) $company->adminuser->id,
'name'=> e($company->adminuser->present()->fullName()),
'name'=> e($company->adminuser->display_name),
] : null,
'notes' => Helper::parseEscapedMarkedownInline($company->notes),
'created_at' => Helper::getFormattedDateObject($company->created_at, 'datetime'),
@@ -51,7 +51,7 @@ class ComponentsTransformer
'notes' => ($component->notes) ? Helper::parseEscapedMarkedownInline($component->notes) : null,
'created_by' => ($component->adminuser) ? [
'id' => (int) $component->adminuser->id,
'name'=> e($component->adminuser->present()->fullName()),
'name'=> e($component->adminuser->display_name),
] : null,
'created_at' => Helper::getFormattedDateObject($component->created_at, 'datetime'),
'updated_at' => Helper::getFormattedDateObject($component->updated_at, 'datetime'),
@@ -42,7 +42,7 @@ class ConsumablesTransformer
'notes' => ($consumable->notes) ? Helper::parseEscapedMarkedownInline($consumable->notes) : null,
'created_by' => ($consumable->adminuser) ? [
'id' => (int) $consumable->adminuser->id,
'name'=> e($consumable->adminuser->present()->fullName()),
'name'=> e($consumable->adminuser->display_name),
] : null,
'created_at' => Helper::getFormattedDateObject($consumable->created_at, 'datetime'),
'updated_at' => Helper::getFormattedDateObject($consumable->updated_at, 'datetime'),
@@ -35,7 +35,7 @@ class DepartmentsTransformer
] : null,
'manager' => ($department->manager) ? [
'id' => (int) $department->manager->id,
'name' => e($department->manager->getFullNameAttribute()),
'name' => e($department->manager->display_name),
'first_name'=> e($department->manager->first_name),
'last_name'=> e($department->manager->last_name),
] : null,
@@ -33,7 +33,7 @@ class DepreciationsTransformer
'licenses_count' => ($depreciation->licenses_count > 0) ? (int) $depreciation->licenses_count : 0,
'created_by' => ($depreciation->adminuser) ? [
'id' => (int) $depreciation->adminuser->id,
'name'=> e($depreciation->adminuser->present()->fullName()),
'name'=> e($depreciation->adminuser->display_name),
] : null,
'created_at' => Helper::getFormattedDateObject($depreciation->created_at, 'datetime'),
'updated_at' => Helper::getFormattedDateObject($depreciation->updated_at, 'datetime')
+1 -1
View File
@@ -29,7 +29,7 @@ class GroupsTransformer
'notes' => Helper::parseEscapedMarkedownInline($group->notes),
'created_by' => ($group->adminuser) ? [
'id' => (int) $group->adminuser->id,
'name'=> e($group->adminuser->present()->fullName()),
'name'=> e($group->adminuser->display_name),
] : null,
'created_at' => Helper::getFormattedDateObject($group->created_at, 'datetime'),
'updated_at' => Helper::getFormattedDateObject($group->updated_at, 'datetime'),
@@ -48,7 +48,7 @@ class LicensesTransformer
'category' => ($license->category) ? ['id' => (int) $license->category->id, 'name'=> e($license->category->name)] : null,
'created_by' => ($license->adminuser) ? [
'id' => (int) $license->adminuser->id,
'name'=> e($license->adminuser->present()->fullName()),
'name'=> e($license->adminuser->display_name),
] : null,
'created_at' => Helper::getFormattedDateObject($license->created_at, 'datetime'),
'updated_at' => Helper::getFormattedDateObject($license->updated_at, 'datetime'),
@@ -73,11 +73,11 @@ class MaintenancesTransformer
'completion_date' => Helper::getFormattedDateObject($assetmaintenance->completion_date, 'date'),
'user_id' => ($assetmaintenance->adminuser) ? [
'id' => $assetmaintenance->adminuser->id,
'name'=> e($assetmaintenance->adminuser->present()->fullName())
'name'=> e($assetmaintenance->adminuser->display_name)
] : null, // legacy to not change the shape of the API
'created_by' => ($assetmaintenance->adminuser) ? [
'id' => (int) $assetmaintenance->adminuser->id,
'name'=> e($assetmaintenance->adminuser->present()->fullName()),
'name'=> e($assetmaintenance->adminuser->display_name),
] : null,
'created_at' => Helper::getFormattedDateObject($assetmaintenance->created_at, 'datetime'),
'updated_at' => Helper::getFormattedDateObject($assetmaintenance->updated_at, 'datetime'),
@@ -40,7 +40,7 @@ class ManufacturersTransformer
'notes' => Helper::parseEscapedMarkedownInline($manufacturer->notes),
'created_by' => ($manufacturer->adminuser) ? [
'id' => (int) $manufacturer->adminuser->id,
'name'=> e($manufacturer->adminuser->present()->fullName()),
'name'=> e($manufacturer->adminuser->display_name),
] : null,
'created_at' => Helper::getFormattedDateObject($manufacturer->created_at, 'datetime'),
'updated_at' => Helper::getFormattedDateObject($manufacturer->updated_at, 'datetime'),
@@ -34,7 +34,7 @@ class PredefinedKitsTransformer
'name' => e($kit->name),
'created_by' => ($kit->adminuser) ? [
'id' => (int) $kit->adminuser->id,
'name'=> e($kit->adminuser->present()->fullName()),
'name'=> e($kit->adminuser->display_name),
] : null,
'created_at' => Helper::getFormattedDateObject($kit->created_at, 'datetime'),
'updated_at' => Helper::getFormattedDateObject($kit->updated_at, 'datetime'),
+1 -1
View File
@@ -26,7 +26,7 @@ class ProfileTransformer
'id' => (int) $file->id,
'icon' => Helper::filetype_icon($file->filename),
'item' => ($file->item) ? [
'name' => ($file->itemType()=='user') ? e($file->item->getFullNameAttribute()) : e($file->item->getDisplayNameAttribute()),
'name' => ($file->itemType()=='user') ? e($file->item->display_name) : e($file->item->getDisplayNameAttribute()),
'type' => e($file->itemType()),
] : null,
'filename' => e($file->filename),
@@ -32,7 +32,7 @@ class StatuslabelsTransformer
'notes' => e($statuslabel->notes),
'created_by' => ($statuslabel->adminuser) ? [
'id' => (int) $statuslabel->adminuser->id,
'name'=> e($statuslabel->adminuser->present()->fullName()),
'name'=> e($statuslabel->adminuser->display_name),
] : null,
'created_at' => Helper::getFormattedDateObject($statuslabel->created_at, 'datetime'),
'updated_at' => Helper::getFormattedDateObject($statuslabel->updated_at, 'datetime'),
+9 -7
View File
@@ -31,16 +31,17 @@ class UsersTransformer
$array = [
'id' => (int) $user->id,
'avatar' => e($user->present()->gravatar) ?? null,
'name' => e($user->getFullNameAttribute()),
'first_name' => e($user->first_name),
'last_name' => e($user->last_name),
'username' => e($user->username),
'name' => e($user->getFullNameAttribute()) ?? null,
'first_name' => e($user->first_name) ?? null,
'last_name' => e($user->last_name) ?? null,
'display_name' => e($user->getRawOriginal('display_name')) ?? null,
'username' => e($user->username) ?? null,
'remote' => ($user->remote == '1') ? true : false,
'locale' => ($user->locale) ? e($user->locale) : null,
'employee_num' => ($user->employee_num) ? e($user->employee_num) : null,
'manager' => ($user->manager) ? [
'id' => (int) $user->manager->id,
'name'=> e($user->manager->first_name).' '.e($user->manager->last_name),
'name'=> e($user->manager->display_name),
] : null,
'jobtitle' => ($user->jobtitle) ? e($user->jobtitle) : null,
'vip' => ($user->vip == '1') ? true : false,
@@ -59,7 +60,7 @@ class UsersTransformer
] : null,
'department_manager' => ($user->department?->manager) ? [
'id' => (int) $user->department->manager->id,
'name'=> e($user->department->manager->full_name),
'name'=> e($user->department->manager->display_name),
] : null,
'location' => ($user->userloc) ? [
'id' => (int) $user->userloc->id,
@@ -82,7 +83,7 @@ class UsersTransformer
'company' => ($user->company) ? ['id' => (int) $user->company->id, 'name'=> e($user->company->name)] : null,
'created_by' => ($user->createdBy) ? [
'id' => (int) $user->createdBy->id,
'name'=> e($user->createdBy->present()->fullName),
'name'=> e($user->createdBy->display_name),
] : null,
'created_at' => Helper::getFormattedDateObject($user->created_at, 'datetime'),
'updated_at' => Helper::getFormattedDateObject($user->updated_at, 'datetime'),
@@ -138,6 +139,7 @@ class UsersTransformer
'first_name' => e($user->first_name),
'last_name' => e($user->last_name),
'username' => e($user->username),
'display_name' => e($user->display_name),
'created_by' => $user->adminuser ? [
'id' => (int) $user->adminuser->id,
'name'=> e($user->adminuser->present()->fullName),
+3
View File
@@ -72,6 +72,7 @@ abstract class Importer
'termination_date' => 'termination date',
'warranty_months' => 'warranty',
'full_name' => 'full name',
'display_name' => 'display name',
'email' => 'email',
'username' => 'username',
'address' => 'address',
@@ -299,6 +300,7 @@ abstract class Importer
'full_name' => $this->findCsvMatch($row, 'full_name'),
'first_name' => $this->findCsvMatch($row, 'first_name'),
'last_name' => $this->findCsvMatch($row, 'last_name'),
'display_name' => $this->findCsvMatch($row, 'display_name'),
'email' => $this->findCsvMatch($row, 'email'),
'manager_id'=> '',
'department_id' => '',
@@ -369,6 +371,7 @@ abstract class Importer
$user->first_name = $user_array['first_name'];
$user->last_name = $user_array['last_name'];
$user->username = $user_array['username'];
$user->display_name = $user_array['display_name'] ?? null;
$user->email = $user_array['email'];
$user->manager_id = $user_array['manager_id'] ?? null;
$user->department_id = $user_array['department_id'] ?? null;
+18 -18
View File
@@ -27,7 +27,7 @@ class ManufacturerImporter extends ItemImporter
}
/**
* Create a supplier if a duplicate does not exist.
* Create a manufacturer if a duplicate does not exist.
* @todo Investigate how this should interact with Importer::createManufacturerIfNotExists
*
* @author A. Gianotto
@@ -39,16 +39,16 @@ class ManufacturerImporter extends ItemImporter
$editingManufacturer = false;
$supplier = Manufacturer::where('name', '=', $this->findCsvMatch($row, 'name'))->first();
$manufacturer = Manufacturer::where('name', '=', $this->findCsvMatch($row, 'name'))->first();
if ($this->findCsvMatch($row, 'id')!='') {
// Override supplier if an ID was given
\Log::debug('Finding supplier by ID: '.$this->findCsvMatch($row, 'id'));
$supplier = Manufacturer::find($this->findCsvMatch($row, 'id'));
// Override manufacturer if an ID was given
\Log::debug('Finding manufacturer by ID: '.$this->findCsvMatch($row, 'id'));
$manufacturer = Manufacturer::find($this->findCsvMatch($row, 'id'));
}
if ($supplier) {
if ($manufacturer) {
if (! $this->updating) {
$this->log('A matching Manufacturer '.$this->item['name'].' already exists');
return;
@@ -58,8 +58,8 @@ class ManufacturerImporter extends ItemImporter
$editingManufacturer = true;
} else {
$this->log('No Matching Manufacturer, Create a new one');
$supplier = new Manufacturer;
$supplier->created_by = auth()->id();
$manufacturer = new Manufacturer;
$manufacturer->created_by = auth()->id();
}
// Pull the records from the CSV to determine their values
@@ -79,21 +79,21 @@ class ManufacturerImporter extends ItemImporter
if ($editingManufacturer) {
Log::debug('Updating existing supplier');
$supplier->update($this->sanitizeItemForUpdating($supplier));
Log::debug('Updating existing manufacturer');
$manufacturer->update($this->sanitizeItemForUpdating($manufacturer));
} else {
Log::debug('Creating supplier');
$supplier->fill($this->sanitizeItemForStoring($supplier));
Log::debug('Creating manufacturer');
$manufacturer->fill($this->sanitizeItemForStoring($manufacturer));
}
if ($supplier->save()) {
$this->log('Manufacturer '.$supplier->name.' created or updated from CSV import');
return $supplier;
if ($manufacturer->save()) {
$this->log('Manufacturer '.$manufacturer->name.' created or updated from CSV import');
return $manufacturer;
} else {
Log::debug($supplier->getErrors());
$this->logError($supplier, 'Manufacturer "'.$this->item['name'].'"');
return $supplier->errors;
Log::debug($manufacturer->getErrors());
$this->logError($manufacturer, 'Manufacturer "'.$this->item['name'].'"');
return $manufacturer->errors;
}
+1
View File
@@ -47,6 +47,7 @@ class UserImporter extends ItemImporter
// Pull the records from the CSV to determine their values
$this->item['id'] = trim($this->findCsvMatch($row, 'id'));
$this->item['username'] = trim($this->findCsvMatch($row, 'username'));
$this->item['display_name'] = trim($this->findCsvMatch($row, 'display_name'));
$this->item['first_name'] = trim($this->findCsvMatch($row, 'first_name'));
$this->item['last_name'] = trim($this->findCsvMatch($row, 'last_name'));
$this->item['email'] = trim($this->findCsvMatch($row, 'email'));
+4 -2
View File
@@ -96,7 +96,8 @@ class CheckoutableListener
if (!empty($to)) {
try {
Mail::to(array_flatten($to))->cc(array_flatten($cc))->send($mailable);
Mail::to(array_flatten($to))->send($mailable->locale($notifiable->locale));
Mail::to(array_flatten($cc))->send($mailable->locale(Setting::getSettings()->locale));
Log::info('Checkout Mail sent to checkout target');
} catch (ClientException $e) {
Log::debug("Exception caught during checkout email: " . $e->getMessage());
@@ -180,7 +181,8 @@ class CheckoutableListener
try {
if (!empty($to)) {
Mail::to(array_flatten($to))->cc(array_flatten($cc))->send($mailable);
Mail::to(array_flatten($to))->send($mailable->locale($notifiable->locale));
Mail::to(array_flatten($cc))->send($mailable->locale(Setting::getSettings()->locale));
Log::info('Checkin Mail sent to CC addresses');
}
} catch (ClientException $e) {
+8
View File
@@ -339,6 +339,7 @@ class Importer extends Component
'start_date' => trans('general.start_date'),
'state' => trans('general.state'),
'username' => trans('admin/users/table.username'),
'display_name' => trans('admin/users/table.display_name'),
'vip' => trans('general.importer.vip'),
'website' => trans('general.website'),
'zip' => trans('general.zip'),
@@ -485,6 +486,13 @@ class Importer extends Component
'username',
trans('general.importer.checked_out_to_username'),
],
'display_name' =>
[
'display name',
'displayName',
'display',
trans('admin/users/table.display_name'),
],
'first_name' =>
[
'first name',
+36 -2
View File
@@ -3,6 +3,8 @@
namespace App\Mail;
use App\Models\Accessory;
use App\Models\Asset;
use App\Models\Location;
use App\Models\Setting;
use App\Models\User;
use Illuminate\Bus\Queueable;
@@ -41,7 +43,7 @@ class CheckoutAccessoryMail extends Mailable
return new Envelope(
from: $from,
subject: (trans('mail.Accessory_Checkout_Notification')),
subject: trans('mail.Accessory_Checkout_Notification'),
);
}
@@ -54,6 +56,17 @@ class CheckoutAccessoryMail extends Mailable
$eula = $this->item->getEula();
$req_accept = $this->item->requireAcceptance();
$accept_url = is_null($this->acceptance) ? null : route('account.accept.item', $this->acceptance);
$name = null;
if($this->target instanceof User){
$name = $this->target->display_name;
}
else if($this->target instanceof Asset){
$name = $this->target->assignedto?->display_name;
}
else if($this->target instanceof Location){
$name = $this->target->manager->name;
}
return new Content(
markdown: 'mail.markdown.checkout-accessory',
@@ -61,14 +74,35 @@ class CheckoutAccessoryMail extends Mailable
'item' => $this->item,
'admin' => $this->admin,
'note' => $this->note,
'target' => $this->target,
'target' => $name,
'eula' => $eula,
'req_accept' => $req_accept,
'accept_url' => $accept_url,
'checkout_qty' => $this->checkout_qty,
'introduction_line' => $this->introductionLine(),
],
);
}
private function introductionLine(): string
{
if ($this->target instanceof Location) {
return trans('mail.new_item_checked_location', ['location' => $this->target->name ]);
}
if ($this->requiresAcceptance()) {
return trans('mail.new_item_checked_with_acceptance');
}
if (!$this->requiresAcceptance()) {
return trans('mail.new_item_checked');
}
// we shouldn't get here but let's send a default message just in case
return trans('new_item_checked');
}
private function requiresAcceptance(): int|bool
{
return method_exists($this->item, 'requireAcceptance') ? $this->item->requireAcceptance() : 0;
}
/**
* Get the attachments for the message.
+16 -9
View File
@@ -4,6 +4,7 @@ namespace App\Mail;
use App\Helpers\Helper;
use App\Models\Asset;
use App\Models\Location;
use App\Models\Setting;
use App\Models\User;
use Illuminate\Bus\Queueable;
@@ -36,14 +37,6 @@ class CheckoutAssetMail extends Mailable
$this->settings = Setting::getSettings();
$this->target = $checkedOutTo;
// Location is a target option, but there are no emails currently associated with locations.
if($this->target instanceof User){
$this->target = $this->target->present()?->fullName();
}
else if($this->target instanceof Asset){
$this->target = $this->target->assignedto?->present()?->fullName();
}
$this->last_checkout = '';
$this->expected_checkin = '';
@@ -85,6 +78,17 @@ class CheckoutAssetMail extends Mailable
$eula = method_exists($this->item, 'getEula') ? $this->item->getEula() : '';
$req_accept = $this->requiresAcceptance();
$fields = [];
$name = null;
if($this->target instanceof User){
$name = $this->target->display_name;
}
else if($this->target instanceof Asset){
$name = $this->target->assignedto?->display_name;
}
else if($this->target instanceof Location){
$name = $this->target->manager->name;
}
// Check if the item has custom fields associated with it
if (($this->item->model) && ($this->item->model->fieldset)) {
@@ -100,7 +104,7 @@ class CheckoutAssetMail extends Mailable
'admin' => $this->admin,
'status' => $this->item->assetstatus?->name,
'note' => $this->note,
'target' => $this->target,
'target' => $name,
'fields' => $fields,
'eula' => $eula,
'req_accept' => $req_accept,
@@ -133,6 +137,9 @@ class CheckoutAssetMail extends Mailable
private function introductionLine(): string
{
if ($this->firstTimeSending && $this->target instanceof Location) {
return trans('mail.new_item_checked_location', ['location' => $this->target->name ]);
}
if ($this->firstTimeSending && $this->requiresAcceptance()) {
return trans('mail.new_item_checked_with_acceptance');
}
+2 -2
View File
@@ -31,10 +31,10 @@ class CheckoutLicenseMail extends Mailable
$this->target = $checkedOutTo;
if($this->target instanceof User){
$this->target = $this->target->present()?->fullName();
$this->target = $this->target->display_name;
}
elseif($this->target instanceof Asset){
$this->target = $this->target->assignedto?->present()?->fullName();
$this->target = $this->target->display_name;
}
}
+2 -2
View File
@@ -1031,9 +1031,9 @@ class Asset extends Depreciable
{
if (($this->model) && ($this->model->category)) {
if (($this->model->category->eula_text) && ($this->model->category->use_default_eula === 0)) {
if (($this->model->category->eula_text) && ($this->model->category->use_default_eula == 0)) {
return Helper::parseEscapedMarkedown($this->model->category->eula_text);
} elseif ($this->model->category->use_default_eula === 1) {
} elseif ($this->model->category->use_default_eula == 1) {
return Helper::parseEscapedMarkedown(Setting::getSettings()->default_eula_text);
} else {
+12
View File
@@ -32,7 +32,19 @@ class CheckoutAcceptance extends Model
return array_filter($recipients);
}
public function getCheckoutableItemTypeAttribute(): string
{
$type = $this->checkoutable_type;
return match ($type) {
Asset::class => trans('general.asset'),
LicenseSeat::class => trans('general.license'),
Accessory::class => trans('general.accessory'),
Component::class => trans('general.component'),
Consumable::class => trans('general.consumable'),
default => class_basename($type),
};
}
/**
* The resource that was is out
*
+2 -2
View File
@@ -30,10 +30,10 @@ class FieldOption
if ($asset->relationLoaded('assignedTo')) {
// If the "assignedTo" relationship was eager loaded then the way to get the
// relationship changes from $asset->assignedTo to $asset->assigned.
return $asset->assigned ? $asset->assigned->present()->fullName() : null;
return $asset->assigned ? $asset->assigned->display_name : null;
}
return $asset->assignedTo ? $asset->assignedTo->present()->fullName() : null;
return $asset->assignedTo ? $asset->assignedTo->display_name : null;
}
// Handle Laravel's stupid Carbon datetime casting
+110
View File
@@ -0,0 +1,110 @@
<?php
namespace App\Models\Labels\Sheets\Avery;
use App\Helpers\Helper;
use App\Models\Labels\RectangleSheet;
abstract class L6009 extends RectangleSheet
{
private const PAPER_FORMAT = 'A4';
private const PAPER_ORIENTATION = 'P';
/* Data in pt from Word Template */
private const COLUMN1_X = 31.70;
private const COLUMN2_X = 167.92;
private const ROW1_Y = 53.00;
private const ROW2_Y = 112.8;
private const LABEL_W = 122.24;
private const LABEL_H = 66.5;
private float $pageWidth;
private float $pageHeight;
private float $pageMarginLeft;
private float $pageMarginTop;
private float $columnSpacing;
private float $rowSpacing;
private float $labelWidth;
private float $labelHeight;
public function __construct()
{
$paperSize = static::fromFormat(self::PAPER_FORMAT, self::PAPER_ORIENTATION, $this->getUnit(), 0);
$this->pageWidth = $paperSize->width;
$this->pageHeight = $paperSize->height;
$this->pageMarginLeft = Helper::convertUnit(self::COLUMN1_X, 'pt', $this->getUnit());
$this->pageMarginTop = Helper::convertUnit(self::ROW1_Y, 'pt', $this->getUnit());
$columnSpacingPt = self::COLUMN2_X - self::COLUMN1_X - self::LABEL_W;
$this->columnSpacing = Helper::convertUnit($columnSpacingPt, 'pt', $this->getUnit());
$rowSpacingPt = self::ROW2_Y - self::ROW1_Y - self::LABEL_H;
$this->rowSpacing = Helper::convertUnit($rowSpacingPt, 'pt', $this->getUnit());
$this->labelWidth = Helper::convertUnit(self::LABEL_W, 'pt', $this->getUnit());
$this->labelHeight = Helper::convertUnit(self::LABEL_H, 'pt', $this->getUnit());
}
public function getPageWidth()
{
return $this->pageWidth;
}
public function getPageHeight()
{
return $this->pageHeight;
}
public function getPageMarginTop()
{
return $this->pageMarginTop;
}
public function getPageMarginBottom()
{
return $this->pageMarginTop;
}
public function getPageMarginLeft()
{
return $this->pageMarginLeft;
}
public function getPageMarginRight()
{
return $this->pageMarginLeft;
}
public function getColumns()
{
return 4;
}
public function getRows()
{
return 12;
}
public function getLabelColumnSpacing()
{
return $this->columnSpacing;
}
public function getLabelRowSpacing()
{
return $this->rowSpacing;
}
public function getLabelWidth()
{
return $this->labelWidth;
}
public function getLabelHeight()
{
return $this->labelHeight;
}
public function getLabelBorder()
{
return 0;
}
}
?>
+121
View File
@@ -0,0 +1,121 @@
<?php
namespace App\Models\Labels\Sheets\Avery;
class L6009_A extends L6009
{
private const BARCODE_MARGIN = 1.80;
private const TAG_SIZE = 4.80;
private const TITLE_SIZE = 3.00;
private const TITLE_MARGIN = 1.80;
private const LABEL_SIZE = 2.8;
private const LABEL_MARGIN = - 0.45;
private const FIELD_SIZE = 3.80;
private const FIELD_MARGIN = 0.20;
public function getUnit()
{
return 'mm';
}
public function getLabelMarginTop()
{
return 0.06;
}
public function getLabelMarginBottom()
{
return 0.06;
}
public function getLabelMarginLeft()
{
return 0.06;
}
public function getLabelMarginRight()
{
return 0.06;
}
public function getSupportAssetTag()
{
return true;
}
public function getSupport1DBarcode()
{
return false;
}
public function getSupport2DBarcode()
{
return true;
}
public function getSupportFields()
{
return 4;
}
public function getSupportLogo()
{
return false;
}
public function getSupportTitle()
{
return true;
}
public function preparePDF($pdf)
{
}
public function write($pdf, $record)
{
$pa = $this->getLabelPrintableArea();
$currentX = $pa->x1;
$currentY = $pa->y1;
$usableWidth = $pa->w;
$usableHeight = $pa->h;
if ($record->has('title')) {
static::writeText(
$pdf, $record->get('title'),
$pa->x1, $pa->y1,
'freesans', '', self::TITLE_SIZE, 'C',
$pa->w, self::TITLE_SIZE, true, 0
);
}
$currentY += self::TITLE_SIZE + self::TITLE_MARGIN;
$usableHeight -= self::TITLE_SIZE + self::TITLE_MARGIN;
$barcodeSize = $usableHeight;
if ($record->has('barcode2d')) {
static::write2DBarcode(
$pdf, $record->get('barcode2d')->content, $record->get('barcode2d')->type,
$currentX, $currentY,
$barcodeSize, $barcodeSize
);
$currentX += $barcodeSize + self::BARCODE_MARGIN;
$usableWidth -= $barcodeSize + self::BARCODE_MARGIN;
}
foreach ($record->get('fields') as $field) {
static::writeText(
$pdf, $field['label'],
$currentX, $currentY,
'freesans', '', self::LABEL_SIZE, 'L',
$usableWidth, self::LABEL_SIZE, true, 0
);
$currentY += self::LABEL_SIZE + self::LABEL_MARGIN;
static::writeText(
$pdf, $field['value'],
$currentX, $currentY,
'freemono', 'B', self::FIELD_SIZE, 'L',
$usableWidth, self::FIELD_SIZE, true, 0, 0.01
);
$currentY += self::FIELD_SIZE + self::FIELD_MARGIN;
}
}
}
?>
+30 -4
View File
@@ -27,6 +27,35 @@ use Illuminate\Support\Facades\Crypt;
class Ldap extends Model
{
public static function ignoreCertificates(bool $ignore_cert = true)
{
if (defined('LDAP_OPT_X_TLS_REQUIRE_CERT') && defined('LDAP_OPT_X_TLS_NEVER')) {
// TODO - we are currently, as a 'safety', doing *both* the following 'new-style' ldap_set_option calls,
// as well as "falling-through" to the 'old-style' putenv() calls.
//
// I *suspect* we can eventually remove the putenv() calls, but I'm just a little nervous about that.
// According to the PHP docs, the LDAP_OPT_X_TLS_REQUIRE_CERT constant has been available since PHP 7.0.
// We're currently using PHP versions way, way later than that (v8.2-v8.4 as of this writing). So it's
// unlikely that these constants wouldn't be defined - unless you didn't have LDAP support in the first
// place. But if that were to happen, I would hope we would've detected that long, long ago, rather than at
// this point.
if ($ignore_cert) {
if (ldap_set_option(null, LDAP_OPT_X_TLS_REQUIRE_CERT, LDAP_OPT_X_TLS_NEVER)) {
//return true;
}
} else {
if (ldap_set_option(null, LDAP_OPT_X_TLS_REQUIRE_CERT, LDAP_OPT_X_TLS_DEMAND)) {
//return true;
}
}
}
if ($ignore_cert) {
return putenv('LDAPTLS_REQCERT=never');
} else {
return putenv('LDAPTLS_REQCERT');
}
}
/**
* Makes a connection to LDAP using the settings in Admin > Settings.
*
@@ -43,15 +72,12 @@ class Ldap extends Model
// If we are ignoring the SSL cert we need to setup the environment variable
// before we create the connection
if ($ldap_server_cert_ignore == '1') {
putenv('LDAPTLS_REQCERT=never');
}
self::ignoreCertificates((bool)$ldap_server_cert_ignore);
// If the user specifies where CA Certs are, make sure to use them
if (env('LDAPTLS_CACERT')) {
putenv('LDAPTLS_CACERT='.env('LDAPTLS_CACERT'));
}
$connection = @ldap_connect($ldap_host);
if (! $connection) {
+8 -3
View File
@@ -3,6 +3,7 @@
namespace App\Models;
use App\Helpers\Helper;
use Illuminate\Database\Eloquent\Casts\Attribute;
use Illuminate\Database\Eloquent\Model;
class SnipeModel extends Model
@@ -155,9 +156,13 @@ class SnipeModel extends Model
$this->attributes['status_id'] = $value;
}
//
public function getDisplayNameAttribute()
protected function displayName(): Attribute
{
return $this->name;
return Attribute:: make(
get: fn(mixed $value) => $this->name,
);
}
}
+8 -16
View File
@@ -34,6 +34,7 @@ class SnipeSCIMConfig extends \ArieTimmerman\Laravel\SCIMServer\SCIMConfig
'validations' => [
$user_prefix . 'userName' => 'required',
$user_prefix . 'displayName' => 'nullable|string',
$user_prefix . 'name.givenName' => 'required',
$user_prefix . 'name.familyName' => 'nullable|string',
$user_prefix . 'externalId' => 'nullable|string',
@@ -121,7 +122,7 @@ class SnipeSCIMConfig extends \ArieTimmerman\Laravel\SCIMServer\SCIMConfig
'honorificSuffix' => null
],
'displayName' => null,
'displayName' => AttributeMapping::eloquent("display_name"),
'nickName' => null,
'profileUrl' => null,
'title' => AttributeMapping::eloquent('jobtitle'),
@@ -153,21 +154,12 @@ class SnipeSCIMConfig extends \ArieTimmerman\Laravel\SCIMServer\SCIMConfig
"primary" => AttributeMapping::constant(true)->ignoreWrite()
]],
// Mobile and work phone numbers
'phoneNumbers' => [
[
"value" => AttributeMapping::eloquent("phone"),
"display" => null,
"type" => AttributeMapping::constant("work")->ignoreWrite(),
"primary" => AttributeMapping::constant(true)->ignoreWrite(),
],
[
"value" => AttributeMapping::eloquent("mobile"),
"display" => null,
"type" => AttributeMapping::constant("mobile")->ignoreWrite(),
"primary" => AttributeMapping::constant(false)->ignoreWrite()
]
],
'phoneNumbers' => [[
"value" => AttributeMapping::eloquent("phone"),
"display" => null,
"type" => AttributeMapping::constant("work")->ignoreWrite(),
"primary" => AttributeMapping::constant(true)->ignoreWrite()
]],
'ims' => [[
"value" => null,
+24 -6
View File
@@ -64,6 +64,7 @@ class User extends SnipeModel implements AuthenticatableContract, AuthorizableCo
'first_name',
'jobtitle',
'last_name',
'display_name',
'ldap_import',
'locale',
'location_id',
@@ -103,6 +104,8 @@ class User extends SnipeModel implements AuthenticatableContract, AuthorizableCo
protected $rules = [
'first_name' => 'required|string|min:1|max:191',
'last_name' => 'nullable|string|max:191',
'display_name' => 'nullable|string|max:191',
'username' => 'required|string|min:1|unique_undeleted|max:191',
'email' => 'email|nullable|max:191',
'password' => 'required|min:8',
@@ -113,9 +116,9 @@ class User extends SnipeModel implements AuthenticatableContract, AuthorizableCo
'start_date' => 'nullable|date_format:Y-m-d',
'end_date' => 'nullable|date_format:Y-m-d|after_or_equal:start_date',
'autoassign_licenses' => 'boolean',
'address' => 'max:191|nullable',
'city' => 'max:191|nullable',
'state' => 'min:2|max:191|nullable',
'address' => 'nullable|string|max:191',
'city' => 'nullable|string|max:191',
'state' => 'nullable|string|max:191',
'country' => 'min:2|max:191|nullable',
'zip' => 'max:10|nullable',
'vip' => 'boolean',
@@ -132,15 +135,16 @@ class User extends SnipeModel implements AuthenticatableContract, AuthorizableCo
'address',
'city',
'country',
'display_name',
'email',
'employee_num',
'first_name',
'jobtitle',
'last_name',
'locale',
'mobile',
'notes',
'phone',
'mobile',
'state',
'username',
'website',
@@ -157,7 +161,7 @@ class User extends SnipeModel implements AuthenticatableContract, AuthorizableCo
'department' => ['name'],
'groups' => ['name'],
'company' => ['name'],
'manager' => ['first_name', 'last_name', 'username'],
'manager' => ['first_name', 'last_name', 'username', 'display_name'],
];
@@ -196,8 +200,20 @@ class User extends SnipeModel implements AuthenticatableContract, AuthorizableCo
});
}
/**
* This overrides the SnipeModel displayName accessor to return the full name if display_name is not set
* @see SnipeModel::displayName()
* @return Attribute
*/
public function isAvatarExternal()
protected function displayName(): Attribute
{
return Attribute:: make(
get: fn(mixed $value) => $value ?? $this->getFullNameAttribute(),
);
}
public function isAvatarExternal() : bool
{
// Check if it's a google avatar or some external avatar
if (Str::startsWith($this->avatar, ['http://', 'https://'])) {
@@ -859,6 +875,7 @@ class User extends SnipeModel implements AuthenticatableContract, AuthorizableCo
{
return $query->where('first_name', 'LIKE', '%' . $search . '%')
->orWhere('last_name', 'LIKE', '%' . $search . '%')
->orWhere('display_name', 'LIKE', '%' . $search . '%')
->orWhereMultipleColumns(
[
'users.first_name',
@@ -1068,6 +1085,7 @@ class User extends SnipeModel implements AuthenticatableContract, AuthorizableCo
->orWhere('users.jobtitle', 'LIKE', '%' . $search . '%')
->orWhere('users.employee_num', 'LIKE', '%' . $search . '%')
->orWhere('users.username', 'LIKE', '%' . $search . '%')
->orWhere('users.display_name', 'LIKE', '%' . $search . '%')
->orwhereRaw('CONCAT(users.first_name," ",users.last_name) LIKE \''.$search.'%\'');
}
+9 -9
View File
@@ -57,14 +57,14 @@ use NotificationChannels\MicrosoftTeams\MicrosoftTeamsMessage;
$channel = ($this->settings->webhook_channel) ? $this->settings->webhook_channel : '';
return (new SlackMessage)
->success()
->content(class_basename(get_class($this->params['item'])).' Audited')
->content(class_basename(get_class($this->params['item'])).' '.trans('general.audited'))
->from(($this->settings->webhook_botname) ? $this->settings->webhook_botname : 'Snipe-Bot')
->to($channel)
->attachment(function ($attachment) {
$item = $this->params['item'];
$admin_user = $this->params['admin'];
$fields = [
'By' => '<'.$admin_user->present()->viewUrl().'|'.$admin_user->present()->fullName().'>',
'By' => '<'.$admin_user->present()->viewUrl().'|'.$admin_user->display_name.'>',
];
array_key_exists('note', $this->params) && $fields['Notes'] = $this->params['note'];
array_key_exists('location', $this->params) && $fields['Location'] = $this->params['location'];
@@ -76,22 +76,22 @@ use NotificationChannels\MicrosoftTeams\MicrosoftTeamsMessage;
public static function toMicrosoftTeams($params)
{
$item = $params['item'];
$admin_user = $params['admin'];
$note = $params['note'];
$location = $params['location'];
$item = $params['item'] ?? null;
$admin_user = $params['admin'] ?? null;
$note = $params['note'] ?? '';
$location = $params['location'] ?? '';
$setting = Setting::getSettings();
if(!Str::contains($setting->webhook_endpoint, 'workflows')) {
return MicrosoftTeamsMessage::create()
->to($setting->webhook_endpoint)
->type('success')
->title(class_basename(get_class($params['item'])) . ' Audited')
->title(class_basename(get_class($params['item'])) .' '.trans('general.audited'))
->addStartGroupToSection('activityText')
->fact(trans('mail.asset'), $item)
->fact(trans('general.administrator'), $admin_user->present()->viewUrl() . '|' . $admin_user->present()->fullName());
->fact(trans('general.administrator'), $admin_user->present()->viewUrl() . '|' . $admin_user->display_name);
}
$message = class_basename(get_class($params['item'])) . ' Audited By '.$admin_user->present()->fullName();
$message = class_basename(get_class($params['item'])) . ' Audited By '.$admin_user->display_name;
$details = [
trans('mail.asset') => htmlspecialchars_decode($item->present()->name),
trans('mail.notes') => $note ?: '',
@@ -73,8 +73,8 @@ class CheckinAccessoryNotification extends Notification
$channel = ($this->settings->webhook_channel) ? $this->settings->webhook_channel : '';
$fields = [
trans('general.from') => '<'.$target->present()->viewUrl().'|'.$target->present()->fullName().'>',
trans('general.by') => '<'.$admin->present()->viewUrl().'|'.$admin->present()->fullName().'>',
trans('general.from') => '<'.$target->present()->viewUrl().'|'.$target->display_name.'>',
trans('general.by') => '<'.$admin->present()->viewUrl().'|'.$admin->display_name.'>',
];
if ($item->location) {
@@ -109,7 +109,7 @@ class CheckinAccessoryNotification extends Notification
->addStartGroupToSection('activityText')
->fact(htmlspecialchars_decode($item->present()->name), '', 'activityTitle')
->fact(trans('mail.checked_into'), $item->location->name ? $item->location->name : '')
->fact(trans('mail.Accessory_Checkin_Notification')." by ", $admin->present()->fullName())
->fact(trans('mail.Accessory_Checkin_Notification')." by ", $admin->display_name)
->fact(trans('admin/consumables/general.remaining'), $item->numRemaining())
->fact(trans('mail.notes'), $note ?: '');
}
@@ -118,7 +118,7 @@ class CheckinAccessoryNotification extends Notification
$details = [
trans('mail.accessory_name') => htmlspecialchars_decode($item->present()->name),
trans('mail.checked_into') => $item->location->name ? $item->location->name : '',
trans('mail.Accessory_Checkin_Notification'). ' by' => $admin->present()->fullName(),
trans('mail.Accessory_Checkin_Notification'). ' by' => $admin->display_name,
trans('admin/consumables/general.remaining')=> $item->numRemaining(),
trans('mail.notes') => $note ?: '',
];
@@ -78,7 +78,7 @@ class CheckinAssetNotification extends Notification
$channel = ($this->settings->webhook_channel) ? $this->settings->webhook_channel : '';
$fields = [
trans('general.administrator') => '<'.$admin->present()->viewUrl().'|'.$admin->present()->fullName().'>',
trans('general.administrator') => '<'.$admin->present()->viewUrl().'|'.$admin->display_name.'>',
trans('general.status') => $item->assetstatus?->name,
trans('general.location') => ($item->location) ? $item->location->name : '',
];
@@ -116,7 +116,7 @@ class CheckinAssetNotification extends Notification
->addStartGroupToSection('activityText')
->fact(htmlspecialchars_decode($item->present()->name), '', 'activityText')
->fact(trans('mail.checked_into'), ($item->location) ? $item->location->name : '')
->fact(trans('mail.Asset_Checkin_Notification') . " by ", $admin->present()->fullName())
->fact(trans('mail.Asset_Checkin_Notification') . " by ", $admin->display_name)
->fact(trans('admin/hardware/form.status'), $item->assetstatus?->name)
->fact(trans('mail.notes'), $note ?: '');
}
@@ -126,7 +126,7 @@ class CheckinAssetNotification extends Notification
$details = [
trans('mail.asset') => htmlspecialchars_decode($item->present()->name),
trans('mail.checked_into') => ($item->location) ? $item->location->name : '',
trans('mail.Asset_Checkin_Notification')." by " => $admin->present()->fullName(),
trans('mail.Asset_Checkin_Notification')." by " => $admin->display_name,
trans('admin/hardware/form.status') => $item->assetstatus?->name,
trans('mail.notes') => $note ?: '',
];
@@ -76,8 +76,8 @@ class CheckinComponentNotification extends Notification
if ($admin) {
$fields = [
trans('general.from') => '<'.$target->present()->viewUrl().'|'.$target->present()->fullName().'>',
trans('general.by') => '<'.$admin->present()->viewUrl().'|'.$admin->present()->fullName().'>',
trans('general.from') => '<'.$target->present()->viewUrl().'|'.$target->display_name.'>',
trans('general.by') => '<'.$admin->present()->viewUrl().'|'.$admin->display_name.'>',
];
if ($item->location) {
@@ -90,7 +90,7 @@ class CheckinComponentNotification extends Notification
} else {
$fields = [
'To' => '<'.$target->present()->viewUrl().'|'.$target->present()->fullName().'>',
'To' => '<'.$target->present()->viewUrl().'|'.$target->display_name.'>',
'By' => 'CLI tool',
];
}
@@ -119,16 +119,16 @@ class CheckinComponentNotification extends Notification
->title(trans('mail.Component_checkin_notification'))
->addStartGroupToSection('activityText')
->fact(htmlspecialchars_decode($item->present()->name), '', 'header')
->fact(trans('mail.Component_checkin_notification')." by ", $admin->present()->fullName() ?: 'CLI tool')
->fact(trans('mail.checkedin_from'), $target->present()->fullName())
->fact(trans('mail.Component_checkin_notification')." by ", $admin->display_name ?: 'CLI tool')
->fact(trans('mail.checkedin_from'), $target->display_name)
->fact(trans('admin/consumables/general.remaining'), $item->numRemaining())
->fact(trans('mail.notes'), $note ?: '');
}
$message = trans('mail.Component_checkin_notification');
$details = [
trans('mail.checkedin_from')=> $target->present()->fullName(),
trans('mail.Component_checkin_notification')." by " => $admin->present()->fullName() ?: 'CLI tool',
trans('mail.checkedin_from')=> $target->display_name,
trans('mail.Component_checkin_notification')." by " => $admin->display_name ?: 'CLI tool',
trans('admin/consumables/general.remaining') => $item->numRemaining(),
trans('mail.notes') => $note ?: '',
];
@@ -153,7 +153,7 @@ class CheckinComponentNotification extends Notification
Section::create(
KeyValue::create(
trans('mail.checkedin_from') ?: '',
$target->present()->fullName() ?: '',
$target->display_name ?: '',
trans('admin/consumables/general.remaining').': '.$item->numRemaining(),
)
->onClick(route('components.show', $item->id))
@@ -77,8 +77,8 @@ class CheckinLicenseSeatNotification extends Notification
if ($admin) {
$fields = [
trans('general.from') => '<'.$target->present()->viewUrl().'|'.$target->present()->fullName().'>',
trans('general.by') => '<'.$admin->present()->viewUrl().'|'.$admin->present()->fullName().'>',
trans('general.from') => '<'.$target->present()->viewUrl().'|'.$target->display_name.'>',
trans('general.by') => '<'.$admin->present()->viewUrl().'|'.$admin->display_name.'>',
];
if ($item->location) {
@@ -91,7 +91,7 @@ class CheckinLicenseSeatNotification extends Notification
} else {
$fields = [
'To' => '<'.$target->present()->viewUrl().'|'.$target->present()->fullName().'>',
'To' => '<'.$target->present()->viewUrl().'|'.$target->display_name.'>',
'By' => 'CLI tool',
];
}
@@ -120,17 +120,17 @@ class CheckinLicenseSeatNotification extends Notification
->title(trans('mail.License_Checkin_Notification'))
->addStartGroupToSection('activityText')
->fact(htmlspecialchars_decode($item->present()->name), '', 'header')
->fact(trans('mail.License_Checkin_Notification')." by ", $admin->present()->fullName() ?: 'CLI tool')
->fact(trans('mail.checkedin_from'), $target->present()->fullName())
->fact(trans('mail.License_Checkin_Notification')." by ", $admin->display_name ?: 'CLI tool')
->fact(trans('mail.checkedin_from'), $target->display_name)
->fact(trans('admin/consumables/general.remaining'), $item->availCount()->count())
->fact(trans('mail.notes'), $note ?: '');
}
$message = trans('mail.License_Checkin_Notification');
$details = [
trans('mail.checkedin_from')=> $target->present()->fullName(),
trans('mail.checkedin_from')=> $target->display_name,
trans('mail.license_for') => htmlspecialchars_decode($item->present()->name),
trans('mail.License_Checkin_Notification')." by " => $admin->present()->fullName() ?: 'CLI tool',
trans('mail.License_Checkin_Notification')." by " => $admin->display_name ?: 'CLI tool',
trans('admin/consumables/general.remaining') => $item->availCount()->count(),
trans('mail.notes') => $note ?: '',
];
@@ -155,7 +155,7 @@ class CheckinLicenseSeatNotification extends Notification
Section::create(
KeyValue::create(
trans('mail.checkedin_from') ?: '',
$target->present()->fullName() ?: '',
$target->display_name ?: '',
trans('admin/consumables/general.remaining').': '.$item->availCount()->count(),
)
->onClick(route('licenses.show', $item->id))
@@ -100,8 +100,8 @@ class CheckoutAccessoryNotification extends Notification
$channel = ($this->settings->webhook_channel) ? $this->settings->webhook_channel : '';
$fields = [
trans('general.to') => '<'.$target->present()->viewUrl().'|'.$target->present()->fullName().'>',
trans('general.by') => '<'.$admin->present()->viewUrl().'|'.$admin->present()->fullName().'>',
trans('general.to') => '<'.$target->present()->viewUrl().'|'.$target->display_name.'>',
trans('general.by') => '<'.$admin->present()->viewUrl().'|'.$admin->display_name.'>',
];
if ($item->location) {
@@ -140,7 +140,7 @@ class CheckoutAccessoryNotification extends Notification
->fact(trans('mail.assigned_to'), $target->present()->name)
->fact(trans('general.qty'), $this->checkout_qty)
->fact(trans('mail.checkedout_from'), $item->location->name ? $item->location->name : '')
->fact(trans('mail.Accessory_Checkout_Notification') . " by ", $admin->present()->fullName())
->fact(trans('mail.Accessory_Checkout_Notification') . " by ", $admin->display_name)
->fact(trans('admin/consumables/general.remaining'), $item->numRemaining())
->fact(trans('mail.notes'), $note ?: '');
}
@@ -151,7 +151,7 @@ class CheckoutAccessoryNotification extends Notification
trans('mail.accessory_name') => htmlspecialchars_decode($item->present()->name),
trans('general.qty') => $this->checkout_qty,
trans('mail.checkedout_from') => $item->location->name ? $item->location->name : '',
trans('mail.Accessory_Checkout_Notification'). ' by' => $admin->present()->fullName(),
trans('mail.Accessory_Checkout_Notification'). ' by' => $admin->display_name,
trans('admin/consumables/general.remaining')=> $item->numRemaining(),
trans('mail.notes') => $note ?: '',
];
@@ -93,8 +93,8 @@ class CheckoutAssetNotification extends Notification
$channel = ($this->settings->webhook_channel) ? $this->settings->webhook_channel : '';
$fields = [
trans('general.to') => '<'.$target->present()->viewUrl().'|'.$target->present()->fullName().'>',
trans('general.by') => '<'.$admin->present()->viewUrl().'|'.$admin->present()->fullName().'>',
trans('general.to') => '<'.$target->present()->viewUrl().'|'.$target->display_name.'>',
trans('general.by') => '<'.$admin->present()->viewUrl().'|'.$admin->display_name.'>',
];
if ($item->location) {
@@ -135,7 +135,7 @@ class CheckoutAssetNotification extends Notification
->addStartGroupToSection('activityText')
->fact(trans('mail.assigned_to'), $target->present()->name)
->fact(htmlspecialchars_decode($item->present()->name), '', 'activityText')
->fact(trans('mail.Asset_Checkout_Notification') . " by ", $admin->present()->fullName())
->fact(trans('mail.Asset_Checkout_Notification') . " by ", $admin->display_name)
->fact(trans('mail.notes'), $note ?: '');
}
@@ -143,7 +143,7 @@ class CheckoutAssetNotification extends Notification
$details = [
trans('mail.assigned_to') => $target->present()->name,
trans('mail.asset') => htmlspecialchars_decode($item->present()->name),
trans('mail.Asset_Checkout_Notification'). ' by' => $admin->present()->fullName(),
trans('mail.Asset_Checkout_Notification'). ' by' => $admin->display_name,
trans('mail.notes') => $note ?: '',
];
return array($message, $details);
@@ -80,8 +80,8 @@ class CheckoutComponentNotification extends Notification
$channel = ($this->settings->webhook_channel) ? $this->settings->webhook_channel : '';
$fields = [
trans('general.to') => '<'.$target->present()->viewUrl().'|'.$target->present()->fullName().'>',
trans('general.by') => '<'.$admin->present()->viewUrl().'|'.$admin->present()->fullName().'>',
trans('general.to') => '<'.$target->present()->viewUrl().'|'.$target->display_name.'>',
trans('general.by') => '<'.$admin->present()->viewUrl().'|'.$admin->display_name.'>',
];
if ($item->location) {
@@ -117,17 +117,17 @@ class CheckoutComponentNotification extends Notification
->title(trans('mail.Component_checkout_notification'))
->addStartGroupToSection('activityText')
->fact(htmlspecialchars_decode($item->present()->name), '', 'activityTitle')
->fact(trans('mail.Component_checkout_notification')." by ", $admin->present()->fullName())
->fact(trans('mail.assigned_to'), $target->present()->fullName())
->fact(trans('mail.Component_checkout_notification')." by ", $admin->display_name)
->fact(trans('mail.assigned_to'), $target->display_name)
->fact(trans('admin/consumables/general.remaining'), $item->numRemaining())
->fact(trans('mail.notes'), $note ?: '');
}
$message = trans('mail.Component_checkout_notification');
$details = [
trans('mail.assigned_to') => $target->present()->fullName(),
trans('mail.assigned_to') => $target->display_name,
trans('mail.item') => htmlspecialchars_decode($item->present()->name),
trans('mail.Component_checkout_notification').' by' => $admin->present()->fullName(),
trans('mail.Component_checkout_notification').' by' => $admin->display_name,
trans('admin/consumables/general.remaining') => $item->numRemaining(),
trans('mail.notes') => $note ?: '',
];
@@ -152,7 +152,7 @@ class CheckoutComponentNotification extends Notification
Section::create(
KeyValue::create(
trans('mail.assigned_to') ?: '',
$target->present()->fullName() ?: '',
$target->display_name ?: '',
trans('admin/consumables/general.remaining').': '.$item->numRemaining(),
)
->onClick(route('api.assets.show', $target->id))
@@ -80,8 +80,8 @@ class CheckoutConsumableNotification extends Notification
$channel = ($this->settings->webhook_channel) ? $this->settings->webhook_channel : '';
$fields = [
trans('general.to') => '<'.$target->present()->viewUrl().'|'.$target->present()->fullName().'>',
trans('general.by') => '<'.$admin->present()->viewUrl().'|'.$admin->present()->fullName().'>',
trans('general.to') => '<'.$target->present()->viewUrl().'|'.$target->display_name.'>',
trans('general.by') => '<'.$admin->present()->viewUrl().'|'.$admin->display_name.'>',
];
if ($item->location) {
@@ -117,17 +117,17 @@ class CheckoutConsumableNotification extends Notification
->title(trans('mail.Consumable_checkout_notification'))
->addStartGroupToSection('activityText')
->fact(htmlspecialchars_decode($item->present()->name), '', 'activityTitle')
->fact(trans('mail.Consumable_checkout_notification')." by ", $admin->present()->fullName())
->fact(trans('mail.assigned_to'), $target->present()->fullName())
->fact(trans('mail.Consumable_checkout_notification')." by ", $admin->display_name)
->fact(trans('mail.assigned_to'), $target->display_name)
->fact(trans('admin/consumables/general.remaining'), $item->numRemaining())
->fact(trans('mail.notes'), $note ?: '');
}
$message = trans('mail.Consumable_checkout_notification');
$details = [
trans('mail.assigned_to') => $target->present()->fullName(),
trans('mail.assigned_to') => $target->display_name,
trans('mail.item') => htmlspecialchars_decode($item->present()->name),
trans('mail.Consumable_checkout_notification').' by' => $admin->present()->fullName(),
trans('mail.Consumable_checkout_notification').' by' => $admin->display_name,
trans('admin/consumables/general.remaining') => $item->numRemaining(),
trans('mail.notes') => $note ?: '',
];
@@ -152,7 +152,7 @@ class CheckoutConsumableNotification extends Notification
Section::create(
KeyValue::create(
trans('mail.assigned_to') ?: '',
$target->present()->fullName() ?: '',
$target->display_name ?: '',
trans('admin/consumables/general.remaining').': '.$item->numRemaining(),
)
->onClick(route('users.show', $target->id))
@@ -78,8 +78,8 @@ class CheckoutLicenseSeatNotification extends Notification
$channel = ($this->settings->webhook_channel) ? $this->settings->webhook_channel : '';
$fields = [
trans('general.to') => '<'.$target->present()->viewUrl().'|'.$target->present()->fullName().'>',
trans('general.by') => '<'.$admin->present()->viewUrl().'|'.$admin->present()->fullName().'>',
trans('general.to') => '<'.$target->present()->viewUrl().'|'.$target->display_name.'>',
trans('general.by') => '<'.$admin->present()->viewUrl().'|'.$admin->display_name.'>',
];
if ($item->location) {
@@ -115,17 +115,17 @@ class CheckoutLicenseSeatNotification extends Notification
->title(trans('mail.License_Checkout_Notification'))
->addStartGroupToSection('activityText')
->fact(htmlspecialchars_decode($item->present()->name), '', 'activityTitle')
->fact(trans('mail.License_Checkout_Notification')." by ", $admin->present()->fullName())
->fact(trans('mail.assigned_to'), $target->present()->fullName())
->fact(trans('mail.License_Checkout_Notification')." by ", $admin->display_name)
->fact(trans('mail.assigned_to'), $target->display_name)
->fact(trans('admin/consumables/general.remaining'), $item->availCount()->count())
->fact(trans('mail.notes'), $note ?: '');
}
$message = trans('mail.License_Checkout_Notification');
$details = [
trans('mail.assigned_to') => $target->present()->fullName(),
trans('mail.assigned_to') => $target->display_name,
trans('mail.license_for') => htmlspecialchars_decode($item->present()->name),
trans('mail.License_Checkout_Notification').' by' => $admin->present()->fullName(),
trans('mail.License_Checkout_Notification').' by' => $admin->display_name,
trans('admin/consumables/general.remaining') => $item->availCount()->count(),
trans('mail.notes') => $note ?: '',
];
@@ -79,7 +79,7 @@ class RequestAssetCancelation extends Notification
$fields = [
'QTY' => $qty,
'Canceled By' => '<'.$target->present()->viewUrl().'|'.$target->present()->fullName().'>',
'Canceled By' => '<'.$target->present()->viewUrl().'|'.$target->display_name.'>',
];
if (($this->expected_checkin) && ($this->expected_checkin != '')) {
@@ -78,7 +78,7 @@ class RequestAssetNotification extends Notification
$fields = [
'QTY' => $qty,
'Requested By' => '<'.$target->present()->viewUrl().'|'.$target->present()->fullName().'>',
'Requested By' => '<'.$target->present()->viewUrl().'|'.$target->display_name.'>',
];
return (new SlackMessage)
+26 -5
View File
@@ -3,6 +3,7 @@
namespace App\Presenters;
use App\Models\SnipeModel;
use Illuminate\Database\Eloquent\Casts\Attribute;
abstract class Presenter
{
@@ -69,10 +70,30 @@ abstract class Presenter
return '';
}
public function name()
{
return $this->model->name;
}
// public function name()
// {
// return $this->model->name;
// }
//
// public function display_name()
// {
// return $this->model->display_name;
// }
// protected function displayName(): Attribute
// {
// // This override should only kick in if the model has a display_name prope
// if ($this->getRawOriginal('display_name')) {
// return Attribute:: make (
// get: fn(mixed $value) => 'Poop:'.$this->display_name
// );
// }
//
// return Attribute:: make(
// get: fn(mixed $value) => 'Fart: '.$this->name,
// );
// }
public function __get($property)
{
@@ -80,7 +101,7 @@ abstract class Presenter
return $this->{$property}();
}
return e($this->model->{$property});
return $this->model->{$property};
}
public function __call($method, $args)
+25 -13
View File
@@ -79,6 +79,14 @@ class UserPresenter extends Presenter
'visible' => false,
'formatter' => 'usersLinkFormatter',
],
[
'field' => 'display_name',
'searchable' => true,
'sortable' => true,
'switchable' => false,
'title' => trans('admin/users/table.display_name'),
'visible' => true,
],
[
'field' => 'jobtitle',
'searchable' => true,
@@ -191,6 +199,7 @@ class UserPresenter extends Presenter
'visible' => true,
'formatter' => 'usernameRoleLinkFormatter',
],
[
'field' => 'employee_num',
'searchable' => true,
@@ -447,20 +456,23 @@ class UserPresenter extends Presenter
*
* @return string
*/
public function fullName()
{
return html_entity_decode($this->first_name.' '.$this->last_name, ENT_QUOTES | ENT_XML1, 'UTF-8');
}
// public function fullName()
// {
// if ($this->display_name) {
// return 'kjdfh'.html_entity_decode($this->display_name, ENT_QUOTES | ENT_XML1, 'UTF-8');
// }
// return 'roieuoe'.html_entity_decode($this->first_name.' '.$this->last_name, ENT_QUOTES | ENT_XML1, 'UTF-8');
// }
/**
* Standard accessor.
* @TODO Remove presenter::fullName() entirely?
* @return string
*/
public function name()
{
return $this->fullName();
}
// /**
// * Standard accessor.
// * @TODO Remove presenter::fullName() entirely?
// * @return string
// */
// public function name()
// {
// return $this->fullName();
// }
+3 -3
View File
@@ -74,12 +74,12 @@ class BreadcrumbsServiceProvider extends ServiceProvider
Breadcrumbs::for('hardware.show', fn (Trail $trail, Asset $asset) =>
$trail->parent('hardware.index', route('hardware.index'))
->push($asset->present()->fullName(), route('hardware.show', $asset))
->push($asset->display_name, route('hardware.show', $asset))
);
Breadcrumbs::for('hardware.edit', fn (Trail $trail, Asset $asset) =>
$trail->parent('hardware.index', route('hardware.index'))
->push($asset->present()->fullName(), route('hardware.show', $asset))
->push($asset->display_name, route('hardware.show', $asset))
->push(trans('admin/hardware/general.edit'))
);
@@ -579,7 +579,7 @@ class BreadcrumbsServiceProvider extends ServiceProvider
Breadcrumbs::for('users.show', fn (Trail $trail, User $user) =>
$trail->parent('users.index', route('users.index'))
->push($user->getFullNameAttribute() ?? 'Missing Username!', route('users.show', $user))
->push($user->display_name ?? 'Missing Username!', route('users.show', $user))
);
Breadcrumbs::for('users.edit', fn (Trail $trail, User $user) =>
+18 -1
View File
@@ -207,7 +207,7 @@ return [
/*
|--------------------------------------------------------------------------
| Require SAML Login
| Require SAML Login
|--------------------------------------------------------------------------
|
| Disable the ability to login via form login, and disables the 'nosaml'
@@ -220,6 +220,23 @@ return [
'require_saml' => env('REQUIRE_SAML', false),
/*
|--------------------------------------------------------------------------
| SAML KEYS
|--------------------------------------------------------------------------
|
| This is the size of the keys used by openssl_pkey_new for SAML authentication.
| The default is 2048 bits, but this can be changed to 3072 or 4096 bits
| for higher security. Note that this will increase the time it takes to
| generate the keys, so it is not recommended to set this to a very high value
| unless you have a specific need for it.
|
| The European Commission now requires at least 3072-bit keys for new SAML certificates
| @link https://github.com/grokability/snipe-it/issues/17386
*/
'saml_key_size' => env('SAML_KEY_SIZE', 2048),
/*
|--------------------------------------------------------------------------
+6 -6
View File
@@ -1,10 +1,10 @@
<?php
return array (
'app_version' => 'v8.2.2-pre',
'full_app_version' => 'v8.2.2-pre - build 19319-ga36afbcb2',
'build_version' => '19319',
'app_version' => 'v8.3.0',
'full_app_version' => 'v8.3.0 - build 19559-g0ba8f5cc5',
'build_version' => '19559',
'prerelease_version' => '',
'hash_version' => 'ga36afbcb2',
'full_hash' => 'v8.2.2-pre-249-ga36afbcb2',
'branch' => 'develop',
'hash_version' => 'g0ba8f5cc5',
'full_hash' => 'v8.3.0-489-g0ba8f5cc5',
'branch' => 'master',
);
+22
View File
@@ -84,6 +84,28 @@ class ActionlogFactory extends Factory
});
}
/**
* This sets up an ActionLog representing a manually added note tied to an Asset,
* with an optional User as the creator. If no User is provided, one is generated.
*
* @param User|null $user Optional user to associate as the creator of the note.
* @return \Illuminate\Database\Eloquent\Factories\Factory<ActionLog>
*/
public function assetNote(?User $user=null)
{
return $this
->state(function () use ($user) {
return [
'action_type' => 'note added',
'item_type' => Asset::class,
'target_type' => 'asset',
'note' => 'Factory-generated manual note',
'created_by' => $user?->id ?? User::factory(),
];
})
->for($user ?? User::factory(), 'user');
}
public function licenseCheckoutToUser()
{
return $this->state(function () {
+2 -1
View File
@@ -28,8 +28,9 @@ class UserFactory extends Factory
'email' => $this->faker->safeEmail(),
'employee_num' => $this->faker->numberBetween(3500, 35050),
'first_name' => $this->faker->firstName(),
'jobtitle' => $this->faker->jobTitle(),
'last_name' => $this->faker->lastName(),
'display_name' => null,
'jobtitle' => $this->faker->jobTitle(),
'locale' => 'en-US',
'notes' => 'Created by DB seeder',
'password' => '$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi', // password
@@ -0,0 +1,32 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::table('users', function (Blueprint $table) {
if (!Schema::hasColumn('users', 'display_name')) {
$table->text('display_name')->after('last_name')->nullable()->default(null);
}
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('users', function (Blueprint $table) {
if (Schema::hasColumn('users', 'display_name')) {
$table->dropColumn('display_name');
}
});
}
};
@@ -0,0 +1,82 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::table('settings', function (Blueprint $table) {
if (!Schema::hasColumn('settings', 'ldap_display_name')) {
$table->string('ldap_display_name', 191)->after('ldap_fname_field')->nullable()->default(null);
}
if (!Schema::hasColumn('settings', 'ldap_zip')) {
$table->string('ldap_zip', 191)->after('ldap_manager')->nullable()->default(null);
}
if (!Schema::hasColumn('settings', 'ldap_state')) {
$table->string('ldap_state', 191)->after('ldap_manager')->nullable()->default(null);
}
if (!Schema::hasColumn('settings', 'ldap_city')) {
$table->string('ldap_city', 191)->after('ldap_manager')->nullable()->default(null);
}
if (!Schema::hasColumn('settings', 'ldap_address')) {
$table->string('ldap_address', 191)->after('ldap_manager')->nullable()->default(null);
}
if (!Schema::hasColumn('settings', 'ldap_mobile')) {
$table->string('ldap_mobile', 191)->after('ldap_phone_field')->nullable()->default(null);
}
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('settings', function (Blueprint $table) {
if (Schema::hasColumn('settings', 'ldap_display_name')) {
$table->dropColumn('ldap_display_name');
}
});
Schema::table('settings', function (Blueprint $table) {
if (Schema::hasColumn('settings', 'ldap_zip')) {
$table->dropColumn('ldap_zip');
}
});
Schema::table('settings', function (Blueprint $table) {
if (Schema::hasColumn('settings', 'ldap_address')) {
$table->dropColumn('ldap_address');
}
});
Schema::table('settings', function (Blueprint $table) {
if (Schema::hasColumn('settings', 'ldap_city')) {
$table->dropColumn('ldap_city');
}
});
Schema::table('settings', function (Blueprint $table) {
if (Schema::hasColumn('settings', 'ldap_state')) {
$table->dropColumn('ldap_state');
}
});
Schema::table('settings', function (Blueprint $table) {
if (Schema::hasColumn('settings', 'ldap_mobile')) {
$table->dropColumn('ldap_mobile');
}
});
}
};
@@ -0,0 +1,28 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::table('models', function (Blueprint $table) {
$table->index(['created_at']);
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('models', function (Blueprint $table) {
$table->dropIndex(['created_at']);
});
}
};
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+1 -1490
View File
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+6 -24401
View File
File diff suppressed because one or more lines are too long
+1 -390
View File
File diff suppressed because one or more lines are too long
+1 -135
View File
@@ -1,135 +1 @@
#signature-pad {
padding-top: 250px;
margin: auto;
}
.m-signature-pad {
position: relative;
font-size: 10px;
width: 100%;
height: 300px;
border: 1px solid #e8e8e8;
background-color: #fff;
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.27), 0 0 40px rgba(0, 0, 0, 0.08) inset;
border-radius: 4px;
}
.m-signature-pad:before, .m-signature-pad:after {
position: absolute;
z-index: -1;
content: "";
width: 40%;
height: 10px;
left: 20px;
bottom: 10px;
background: transparent;
-webkit-transform: skew(-3deg) rotate(-3deg);
-moz-transform: skew(-3deg) rotate(-3deg);
-ms-transform: skew(-3deg) rotate(-3deg);
-o-transform: skew(-3deg) rotate(-3deg);
transform: skew(-3deg) rotate(-3deg);
box-shadow: 0 8px 12px rgba(0, 0, 0, 0.4);
}
.m-signature-pad:after {
left: auto;
right: 20px;
-webkit-transform: skew(3deg) rotate(3deg);
-moz-transform: skew(3deg) rotate(3deg);
-ms-transform: skew(3deg) rotate(3deg);
-o-transform: skew(3deg) rotate(3deg);
transform: skew(3deg) rotate(3deg);
}
.m-signature-pad--body {
position: absolute;
top: 20px;
bottom: 60px;
border: 1px solid #f4f4f4;
background-color: white;
}
.m-signature-pad--body
canvas {
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
border-radius: 4px;
box-shadow: 0 0 5px rgba(0, 0, 0, 0.02) inset;
}
.m-signature-pad--footer {
position: absolute;
left: 20px;
right: 20px;
bottom: 20px;
height: 40px;
}
.m-signature-pad--footer
.description {
color: #C3C3C3;
text-align: center;
font-size: 1.2em;
margin-top: 1.8em;
}
.m-signature-pad--footer
.button {
position: absolute;
bottom: 0;
}
.m-signature-pad--footer
.button.clear {
left: 0;
}
.m-signature-pad--footer
.button.save {
right: 0;
}
@media screen and (max-width: 1024px) {
.m-signature-pad {
top: 0;
left: 0;
right: 0;
bottom: 0;
width: auto;
height: auto;
min-width: 250px;
min-height: 140px;
margin: 5%;
}
}
@media screen and (min-device-width: 768px) and (max-device-width: 1024px) {
.m-signature-pad {
margin: 10%;
}
}
@media screen and (max-height: 320px) {
.m-signature-pad--body {
left: 0;
right: 0;
top: 0;
bottom: 32px;
}
.m-signature-pad--footer {
left: 20px;
right: 20px;
bottom: 4px;
height: 28px;
}
.m-signature-pad--footer
.description {
font-size: 1em;
margin-top: 1em;
}
}
#signature-pad{padding-top:250px;margin:auto}.m-signature-pad{position:relative;font-size:10px;width:100%;height:300px;border:1px solid #e8e8e8;background-color:#fff;box-shadow:0 1px 4px rgba(0,0,0,.27),0 0 40px rgba(0,0,0,.08) inset;border-radius:4px}.m-signature-pad:after,.m-signature-pad:before{position:absolute;z-index:-1;content:"";width:40%;height:10px;left:20px;bottom:10px;background:0 0;-webkit-transform:skew(-3deg) rotate(-3deg);-moz-transform:skew(-3deg) rotate(-3deg);-ms-transform:skew(-3deg) rotate(-3deg);-o-transform:skew(-3deg) rotate(-3deg);transform:skew(-3deg) rotate(-3deg);box-shadow:0 8px 12px rgba(0,0,0,.4)}.m-signature-pad:after{left:auto;right:20px;-webkit-transform:skew(3deg) rotate(3deg);-moz-transform:skew(3deg) rotate(3deg);-ms-transform:skew(3deg) rotate(3deg);-o-transform:skew(3deg) rotate(3deg);transform:skew(3deg) rotate(3deg)}.m-signature-pad--body{position:absolute;top:20px;bottom:60px;border:1px solid #f4f4f4;background-color:#fff}.m-signature-pad--body canvas{position:absolute;left:0;top:0;width:100%;height:100%;border-radius:4px;box-shadow:0 0 5px rgba(0,0,0,.02) inset}.m-signature-pad--footer{position:absolute;left:20px;right:20px;bottom:20px;height:40px}.m-signature-pad--footer .description{color:#c3c3c3;text-align:center;font-size:1.2em;margin-top:1.8em}.m-signature-pad--footer .button{position:absolute;bottom:0}.m-signature-pad--footer .button.clear{left:0}.m-signature-pad--footer .button.save{right:0}@media screen and (max-width:1024px){.m-signature-pad{top:0;left:0;right:0;bottom:0;width:auto;height:auto;min-width:250px;min-height:140px;margin:5%}}@media screen and (min-device-width:768px) and (max-device-width:1024px){.m-signature-pad{margin:10%}}@media screen and (max-height:320px){.m-signature-pad--body{left:0;right:0;top:0;bottom:32px}.m-signature-pad--footer{left:20px;right:20px;bottom:4px;height:28px}.m-signature-pad--footer .description{font-size:1em;margin-top:1em}}
+1 -5473
View File
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long

Some files were not shown because too many files have changed in this diff Show More