Compare commits

..

1286 Commits

Author SHA1 Message Date
snipe
42c8de5620 Merge branch 'develop'
# Conflicts:
#	config/version.php
2018-02-21 04:44:48 -08:00
snipe
ba4f63bca3 Bumped version 2018-02-21 04:43:52 -08:00
snipe
4ed2ef6298 Merge branch 'develop' 2018-02-21 04:42:03 -08:00
snipe
d28c2af7de Fixed bootstrap table issue if per page was set to 10 2018-02-21 04:41:44 -08:00
snipe
1e8c32fbdb Fixed - missing table prefix for location parent search 2018-02-21 04:33:47 -08:00
snipe
97bd87773c Merge branch 'develop'
# Conflicts:
#	config/version.php
2018-02-21 02:40:23 -08:00
snipe
b560828173 Bumped hash 2018-02-21 02:18:14 -08:00
snipe
0d7a43ab38 Fixed orderby parent location name 2018-02-21 02:17:18 -08:00
snipe
7865fbea7e Merge branch 'develop'
# Conflicts:
#	config/version.php
2018-02-21 01:27:11 -08:00
snipe
5fcbf9091e Bumped version 2018-02-21 01:23:19 -08:00
snipe
fedd2b638c Merge branch 'develop' 2018-02-21 01:20:48 -08:00
snipe
22f44e342f Fixed incorrect next audit date if asset override 2018-02-21 01:18:21 -08:00
snipe
f7eb013935 Reverse order on activity report 2018-02-20 15:42:44 -08:00
snipe
1c28f893e7 Fixed #5027 - remove link to non-existant reports page 2018-02-20 14:44:29 -08:00
snipe
195dfd752d Updated translations 2018-02-20 14:41:12 -08:00
snipe
cc788d3b62 Added Slovenian 2018-02-20 14:37:22 -08:00
snipe
e54021e7be Added Venzuelan spanish 2018-02-20 14:37:12 -08:00
snipe
918db39eba Merge branch 'develop' 2018-02-19 18:06:58 -08:00
snipe
213fe2ecea Fixed #5044 - incorrect env values for SSL DB paths 2018-02-19 18:03:50 -08:00
snipe
6e70352d0b Merge branch 'develop'
# Conflicts:
#	config/version.php
2018-02-17 01:05:20 -08:00
snipe
d2403cdadb Added image preview for uploads 2018-02-17 00:51:22 -08:00
snipe
9a4f5e0ba8 Bumped hash 2018-02-16 22:10:06 -08:00
snipe
502e4d672a Use image upload partial in asset edit/create 2018-02-16 22:08:49 -08:00
snipe
99205bf72e Merge branch 'develop' 2018-02-16 21:39:15 -08:00
snipe
b3d673b0aa Fixed #5037 - use line breaks in notes in table view 2018-02-16 21:38:56 -08:00
snipe
baf51eb430 Merge branch 'develop' 2018-02-16 21:19:03 -08:00
snipe
d8fc50c351 Fixed #5033 - use PHP’s max filesize for image uploads 2018-02-16 21:17:41 -08:00
snipe
ba5057181e Check for model in asset view 2018-02-16 18:04:11 -08:00
snipe
4c4dee0bf1 Use dropifexists for rollback 2018-02-16 17:45:40 -08:00
snipe
589c3a2be3 Fixed #4668 - wrong gate on manufacturer save 2018-02-16 17:45:27 -08:00
snipe
991f182f89 Added drop table to migration 2018-02-16 15:36:33 -08:00
snipe
f44b03f5a9 Updated sticky table header extenion 2018-02-16 15:36:21 -08:00
snipe
5fd50040d3 Fixed weird migration 2018-02-16 15:31:47 -08:00
snipe
5302108556 Update to master 2018-02-16 13:27:03 -08:00
snipe
592c62de75 Merge branch 'develop'
# Conflicts:
#	README.md
#	config/version.php
2018-02-16 13:26:53 -08:00
snipe
27c1bc0271 Bumped hash 2018-02-16 13:24:47 -08:00
snipe
3744a68daf Features/better table options (#5018)
* Added CSS for table toolbar

* Use maintenances API for table listings

* NIcer layout for allowed_columns in maintenances API

* Fixed #5014 - bootstrap cookie issues

* Fixed #5015 - bug when saving settings

* Refactored datatable code to use data attributes

* Updated dashboard with new table code

* Added - Order by group user count

* Updated groups to use new table attributes

* New license listing table code

* More bootstrap table implementations

* More BS table refactoring

* Improved bootstrap assigned assets

* New bootstrap for reports

* Misc BS fixes

* FIxed small issue with asset history display

* Removed multisort option

* JS refactor
2018-02-16 13:22:55 -08:00
dl1l
c209b7bb5d Update edit.blade.php (#5019) 2018-02-15 14:59:54 -08:00
snipe
f04493c1ab Added firstname_lastname as possible username format 2018-02-13 20:31:51 -08:00
snipe
62edf14893 Refactored method to generate usernames from full names 2018-02-13 20:31:11 -08:00
snipe
0d11e32523 Fixed issue where group with no permissions would crash view page 2018-02-13 17:14:30 -08:00
snipe
5484b06df8 Fixed #4923 - invalid check for location object in Ldap Sync 2018-02-13 17:06:42 -08:00
snipe
9f3116e4e3 Added - Deep linking in Bootstrap tabs 2018-02-13 17:04:50 -08:00
snipe
f144d671ff Fixed #4988 - incorrect variable name in asset checkout API method 2018-02-12 19:13:33 -08:00
snipe
b294635e17 Updated packages 2018-02-08 09:29:12 -08:00
snipe
36234cc0e8 Add @seanmcilvenna as a contributor 2018-02-08 09:29:12 -08:00
snipe
5c87003196 Added code triage badge 2018-02-08 09:29:12 -08:00
Sean McIlvenna
cc5d36f8be Addng "Category" column to "view assets" and re-organizing columns (#4970) 2018-02-05 17:36:35 -06:00
README Bot
1359a4f88a Add CodeTriage badge to snipe/snipe-it (#4968)
Adds a badge showing the number of people helping this repo on CodeTriage.

[![Open Source Helpers](https://www.codetriage.com/snipe/snipe-it/badges/users.svg)](https://www.codetriage.com/snipe/snipe-it)

## What is CodeTriage?

CodeTriage is an Open Source app that is designed to make contributing to Open Source projects easier. It works by sending subscribers a few open issues in their inbox. If subscribers get busy, there is an algorithm that backs off issue load so they do not get overwhelmed

[Read more about the CodeTriage project](https://www.codetriage.com/what).

## Why am I getting this PR?

Your project was picked by the human, @schneems. They selected it from the projects submitted to https://www.codetriage.com and hand edited the PR. How did your project get added to [CodeTriage](https://www.codetriage.com/what)? Roughly 4 months ago, [@imjennyli](https://github.com/imjennyli) added this project to CodeTriage in order to start contributing. Since then, 8 people have subscribed to help this repo.

## What does adding a badge accomplish?

Adding a badge invites people to help contribute to your project. It also lets developers know that others are invested in the longterm success and maintainability of the project.

You can see an example of a CodeTriage badge on these popular OSS READMEs:

- [![](https://www.codetriage.com/rails/rails/badges/users.svg)](https://www.codetriage.com/rails/rails) https://github.com/rails/rails
- [![](https://www.codetriage.com/crystal-lang/crystal/badges/users.svg)](https://www.codetriage.com/crystal-lang/crystal) https://github.com/crystal-lang/crystal

## Have a question or comment?

While I am a bot, this PR was manually reviewed and monitored by a human - @schneems. My job is writing commit messages and handling PR logistics.

If you have any questions, you can reply back to this PR and they will be answered by @schneems. If you do not want a badge right now, no worries, close the PR, you will not hear from me again.

Thanks for making your project Open Source! Any feedback is greatly appreciated.
2018-02-05 15:22:52 -06:00
snipe
1e1362bdbc Merge branch 'develop' 2018-02-02 09:42:50 -06:00
snipe
813106efd3 Default to only changing default location in bulk edit 2018-02-02 09:42:34 -06:00
snipe
08d129c2ea Fixed #4951 - updating asset location in bulk edit 2018-02-02 09:36:40 -06:00
snipe
8491e57258 Merge branch 'develop' 2018-02-02 09:32:00 -06:00
snipe
d86fb098a8 Fixed sort ordering on dashboard 2018-02-02 09:31:43 -06:00
snipe
e21f8e46d4 Merge branch 'develop' 2018-02-01 17:18:16 -06:00
snipe
b3a6ec2804 Fixed #4938 - default sort order 2018-02-01 17:17:56 -06:00
snipe
0034938c04 Merge branch 'develop'
# Conflicts:
#	config/version.php
2018-02-01 16:32:13 -06:00
snipe
d2587337e4 Fixed #4952 - ignore show_archived setting when drilling down into specific ID 2018-02-01 16:31:32 -06:00
snipe
8b2045523d Bumped hash 2018-02-01 15:55:33 -06:00
snipe
e7e10c24be Add departments to usr export 2018-02-01 15:54:49 -06:00
snipe
f06852f48d Merge branch 'develop' 2018-01-25 13:17:11 -06:00
snipe
2f9fff7130 Do not try to show depreciation report if no depreciations are set up 2018-01-25 13:16:49 -06:00
snipe
0b788f64f7 Merge branch 'develop'
# Conflicts:
#	config/version.php
2018-01-25 11:07:18 -08:00
snipe
facf1d42f7 Sigh. 2018-01-25 11:06:37 -08:00
snipe
e77aae703b Bumped hash 2018-01-25 11:03:45 -08:00
snipe
76f52dd89b Fixed #4872 - Check for assigned in depreciation table 2018-01-25 11:02:46 -08:00
snipe
0e980f7229 Hotfix: Disabling the event dispatcher broke model validation. (#4912) (#4915)
* Hotfix: Disabling the event dispatcher broke model validation.

This resulted in invalid data being imported.  Reenable the event dispatcher for now--this causes double logs, but at least validates properly.

* Actually disable the event dispatcher.

* Sign in where necessary to fix the importer unit test.  This catches the issues found manually in 4912
2018-01-25 10:29:06 -08:00
Daniel Meltzer
2f5d550df6 Hotfix: Disabling the event dispatcher broke model validation. (#4912)
* Hotfix: Disabling the event dispatcher broke model validation.

This resulted in invalid data being imported.  Reenable the event dispatcher for now--this causes double logs, but at least validates properly.

* Actually disable the event dispatcher.

* Sign in where necessary to fix the importer unit test.  This catches the issues found manually in 4912
2018-01-25 10:10:56 -08:00
snipe
3acf5f76fe Merge branch 'develop' 2018-01-25 03:35:30 -08:00
snipe
4be8ae7f3d Fuckery. 2018-01-25 03:34:52 -08:00
snipe
029dd43ecd Merge branch 'develop' 2018-01-25 03:01:35 -08:00
snipe
cf8feb37e1 Fixed crash if no model associated
This should never be triggered. Bad data is getting in somehow.
2018-01-25 03:00:54 -08:00
snipe
648531f4cc Merge branch 'develop' 2018-01-25 00:26:17 -08:00
snipe
11505d5d06 Fix crash if no asset model
(This should never happen, but shouldn’t crash if/when it does)
2018-01-25 00:25:43 -08:00
snipe
1d04897b32 Order by default location 2018-01-24 14:27:12 -08:00
snipe
eddcc0fbbd Fixed cookie issue on hardware 2018-01-24 14:23:19 -08:00
snipe
bd80a77b78 Added default location to asset listing 2018-01-24 14:23:12 -08:00
snipe
edc30a31c1 Merge branch 'develop'
# Conflicts:
#	config/version.php
2018-01-24 11:02:46 -08:00
snipe
f5636f325d Bumped hash 2018-01-24 11:01:51 -08:00
snipe
426bf3803b Merge branch 'develop' 2018-01-24 11:00:40 -08:00
snipe
739d3c72b7 Fixed #4902 - include last name in checkin email 2018-01-24 10:59:34 -08:00
snipe
60c38a0c47 Added setting to choose what appears in model select list - Fixes #4879 2018-01-24 10:43:46 -08:00
snipe
9566fbd3cd Fixed borked down() migrations 2018-01-24 10:41:49 -08:00
Anh DAO-DUY
e41ee1bcf8 Fix upload images problem with Docker (#4906)
Some folders were missing in this script file (Docker installation).
Missing folders caused errors while uploading some images.
2018-01-24 09:13:03 -08:00
Tim Bishop
bc14f225af Only use location currency if it's actually set. (#4904)
This changes the depreciation report to only use the currency on a
location if it's actually set to something. Previously, if an asset had
a location it would use the currency even if it was blank rather than
falling back to the default.
2018-01-24 08:55:51 -08:00
snipe
07148c1503 Merge branch 'develop'
# Conflicts:
#	config/version.php
2018-01-24 08:29:25 -08:00
snipe
fcb5eea951 Bumped hash 2018-01-24 08:28:53 -08:00
snipe
7a4bf26733 Merge branch 'develop' 2018-01-24 08:25:36 -08:00
snipe
2c2910d1dd Handle shitty edge cases where an asset has no model without crashing 2018-01-24 08:16:05 -08:00
snipe
1dae7a2fe4 Fixed #3636 - removed thread_id (we don’t use this anymore) 2018-01-24 08:00:28 -08:00
snipe
e19ab329bd Add @tdb as a contributor 2018-01-24 07:13:24 -08:00
snipe
922cb90cb3 Add @CronKz as a contributor 2018-01-24 07:12:59 -08:00
snipe
765295136a Added - ability to add custom footer text, hide user’s manual/support links 2018-01-24 07:02:30 -08:00
snipe
7579333ad3 Disallow LDAP settings if in demo mode 2018-01-24 05:50:31 -08:00
snipe
543ea28b72 Added qty to asset components - fixed #4876 2018-01-24 05:25:01 -08:00
snipe
fefd6d60f6 Fixed #4899 - sorting in user history 2018-01-24 04:48:00 -08:00
snipe
a7b8b4bf55 Added: ability to change actual location from bulk edit assets 2018-01-24 04:38:25 -08:00
snipe
7cafa194c1 Fix for counts 2018-01-24 04:26:15 -08:00
snipe
b37f78dbbf Fixed #4858 - wrong params for id count 2018-01-24 04:24:45 -08:00
snipe
e20cd42cc2 More parse error fixes 2018-01-24 03:42:49 -08:00
snipe
7b99f81f72 Fixed parse error on hardware blade 2018-01-24 03:38:29 -08:00
snipe
f1bbdc9e59 Revert PR #4845 2018-01-24 03:32:45 -08:00
Richard Hofman
5219fb63a1 Add --base_dn option to LdapSync command. (#4888) 2018-01-23 18:15:36 -08:00
CronKz
dcc379c3fa Adding missing translations. (#4896) 2018-01-23 18:13:55 -08:00
vcordes79
0fb8dc3418 check if user is allowed to view assets (#4845) 2018-01-23 18:10:05 -08:00
vcordes79
f4e9d245d0 Status labels (#4895)
* fix statuslabels

* fix statuslabels
2018-01-23 18:08:54 -08:00
snipe
c75a2051ff Hide mfg button if no permissions to create 2018-01-22 14:02:23 -08:00
CronKz
691ec164b1 Added Translations (#4880) 2018-01-22 13:14:52 -08:00
vcordes79
7b596c750d API for (dis)associating fields with fieldsets (#4881)
* start work on fields in fieldset api

* revert CustomFieldsetsController

* fieldset associate / disassociate api

* fix variable names and payload

* fix variable name
2018-01-22 13:14:04 -08:00
Tim Bishop
b346556caa Allow manager_id to be fillable. (#4882)
The API UsersController accepts manager_id, but calls the following:

$user->fill($request->all());

This results in manager_id being ignored. I can't see any problem with
allowing a user's manager to be modified using the API, so this change
allows it.
2018-01-22 13:12:02 -08:00
snipe
93ec7068df Removed a few additional unused badges 2018-01-20 08:54:49 -08:00
snipe
5f65f993a0 Small refactor for AssetPresenter method 2018-01-20 08:52:50 -08:00
snipe
a9441521a4 Small refactor for Setting method 2018-01-20 08:52:50 -08:00
snipe
2dede67ae9 Removed unusued badges 2018-01-20 08:52:49 -08:00
Daniel Meltzer
6bf17e7d47 Reset the item between rows of import to avoid stale data. (#4868) 2018-01-20 08:40:01 -08:00
snipe
a3240da707 Merge branch 'develop'
# Conflicts:
#	config/version.php
2018-01-20 07:47:54 -08:00
snipe
a28fee1ff4 Bumped hash 2018-01-20 07:47:07 -08:00
snipe
57e5af2f69 Removed console logging from JS 2018-01-20 07:42:48 -08:00
snipe
8d3a214475 Merge branch 'develop'
# Conflicts:
#	config/version.php
2018-01-20 04:56:36 -08:00
snipe
58eedce6fe Updated language files 2018-01-20 04:53:04 -08:00
snipe
f91704a372 Added Ukrianian to language dropdown 2018-01-20 04:49:40 -08:00
snipe
f53c68e040 Bumped hash 2018-01-20 04:40:26 -08:00
snipe
99e55f84f0 Fixed misc UI permissions elements 2018-01-20 04:39:31 -08:00
snipe
798ea75f3d Merge branch 'develop'
# Conflicts:
#	config/version.php
2018-01-20 04:00:26 -08:00
snipe
913e6a5709 Bumped hash 2018-01-20 03:59:42 -08:00
snipe
34f6d5ab45 Fixed #4671 - corrected component checkin gate 2018-01-20 03:58:59 -08:00
snipe
86c0194e9a Fixed #4628 and #4590 - Illegal mix of collations for operation error when searching on some languages 2018-01-20 03:08:27 -08:00
Brady Wetherington
dfb2b9b569 Major overhaul for modals, and a fix for #4820 (#4866)
Changes how the various modals work, and allows for specifying
category_type when inline-creating categories.
2018-01-20 00:42:29 -08:00
snipe
7fae380ab6 Fixed #4300 - Fix for illegal character type in action log 2018-01-20 00:27:45 -08:00
snipe
4ca8272efc Merge branch 'develop' 2018-01-20 00:21:03 -08:00
snipe
5d4bbc393e Fixed #4837 - link phone numbers 2018-01-20 00:20:45 -08:00
snipe
984275ff05 Merge branch 'develop' 2018-01-19 23:47:54 -08:00
snipe
e6f70f2ab7 Fixed #4821 - add username to user selection dropdown 2018-01-19 23:47:37 -08:00
snipe
f7de252f67 Wrong branch. :( 2018-01-19 23:46:42 -08:00
snipe
532b299c40 Fixed #4821 - add username to user selection dropdown 2018-01-19 23:46:12 -08:00
snipe
5dcc63dc74 Merge branch 'develop' 2018-01-19 20:49:20 -08:00
snipe
6eb8acf319 Swich to panel box for dashboard message 2018-01-19 20:49:02 -08:00
snipe
862251ab36 Change label to stale 2018-01-19 20:45:25 -08:00
snipe
95a9742571 Fixed #4768 - adds dashboard message option to settings 2018-01-19 20:43:55 -08:00
snipe
81d0921782 Merge branch 'develop' 2018-01-19 19:18:43 -08:00
snipe
0fa556da1d Exempt ready for dev and bounty tags from stale collection 2018-01-19 19:16:35 -08:00
snipe
05bc238c9a Merge branch 'develop' 2018-01-19 18:17:38 -08:00
snipe
782813ab49 Check for valid category before checking acceptance 2018-01-19 18:17:23 -08:00
snipe
cbca126d9d Merge branch 'develop'
# Conflicts:
#	config/version.php
2018-01-19 17:53:15 -08:00
snipe
a9ffe8d210 Bumped hash 2018-01-19 17:52:40 -08:00
snipe
c242abb42e Added Company policy to fix company deletion issue 2018-01-19 17:51:28 -08:00
snipe
2c722ffc4f Fixed issue template with correct path to storage logs 2018-01-19 16:31:01 -08:00
snipe
484c47cef8 Added stale.yml to auto-close stale issues 2018-01-19 16:23:28 -08:00
snipe
f38dc37152 Merge branch 'develop'
# Conflicts:
#	config/version.php
2018-01-17 19:31:09 -08:00
snipe
6133f09056 Bumped hash 2018-01-17 19:30:31 -08:00
snipe
2a959edeba Added - Setting to allow archived assets in List All 2018-01-17 19:18:48 -08:00
snipe
8995d689b8 Fixed #4817 - [BREAKING API CHANGE] - changed user API response from firstname, lastname to first_name, last_name 2018-01-17 13:25:11 -08:00
snipe
f08bec6c78 Merge branch 'develop' 2018-01-17 13:12:58 -08:00
snipe
d920d91786 Fixed #4593 - do not require model_id to update asset custom fields via API 2018-01-17 13:12:32 -08:00
snipe
e35b3745eb Merge branch 'develop'
# Conflicts:
#	config/version.php
2018-01-17 12:41:51 -08:00
snipe
e8252d9468 Bumped hash 2018-01-17 12:41:11 -08:00
snipe
8fff6a1a06 Update asset location based on user checkout in bulk checkout 2018-01-17 12:39:49 -08:00
snipe
0eff821928 Merge branch 'develop'
# Conflicts:
#	config/version.php
2018-01-17 12:12:33 -08:00
snipe
9e605e0f79 Bumped hash 2018-01-17 12:11:39 -08:00
snipe
8fb991110e Fixed #4652 - asset not correctly checking out to user on creation 2018-01-17 12:10:28 -08:00
snipe
b383ebee48 Add @fordster78 as a contributor 2018-01-17 10:59:00 -08:00
fordster78
138313dcb9 Setup changes (#4813)
* Add Asset Tag settings to Setup

* Add Locale Settings to Setup

* Add multiple company support to setup

* Changed the locale label name from 'site_name' to locale
Added default value for language to 'en' and multiple companies support
to 0 (false)
Switched out the old Input facade to the preferred $request->input
method for the setup page.
2018-01-17 10:58:03 -08:00
snipe
f254958db9 Check if db_column foield already exists 2018-01-17 06:48:14 -08:00
snipe
09eff88679 Merge branch 'develop' 2018-01-17 06:28:11 -08:00
snipe
24b356dba4 Fixed typos in default blade that cause components to not show up for non-superadmins 2018-01-17 06:27:23 -08:00
snipe
91bca5fcba Fixed #4844 - use input value for ids in user bulk edit 2018-01-17 06:15:52 -08:00
vcordes79
96a469db36 allow changing user activated field via api (#4843) 2018-01-17 05:38:10 -08:00
snipe
9ab05e7037 Add @vcordes79 as a contributor 2018-01-17 05:36:15 -08:00
vcordes79
52a99faf68 fix phone number update in api (#4842) 2018-01-17 05:33:55 -08:00
vcordes79
94cf1f8741 Fixes #4829 - add fields api (#4840)
* add fields api

* change route names
2018-01-17 05:31:57 -08:00
snipe
e2a8f9b790 Merge branch 'develop' 2018-01-17 03:27:03 -08:00
snipe
409f5cc4fd Added - display asset model category on hardware view page 2018-01-16 16:26:24 -08:00
snipe
3b5e4c44eb Fixed depreciation report not showing assigned to 2018-01-16 07:46:34 -08:00
snipe
69a7ea63e2 Pass nopages to dashboard stuff 2018-01-16 07:37:20 -08:00
snipe
aac379daeb If nopages is passed, hide page numbers
This seems weird since we’re checking for a negative, but there are only a few spots where we wouldn’t want page numbers, namely the dashboard sruff
2018-01-16 07:37:06 -08:00
snipe
1d3472b5c4 Truncate the checkout_requests field on seed 2018-01-16 07:36:14 -08:00
snipe
66a590b774 Account for user’s that have been deleted in the requested list 2018-01-16 07:36:03 -08:00
snipe
dc4472e9e9 Misc export table fixes 2018-01-15 21:03:46 -08:00
snipe
6bfd428c2e Use real status label names, even if deployed 2018-01-15 21:03:26 -08:00
snipe
f4623bd277 Add user group membership to user view page 2018-01-15 20:31:10 -08:00
snipe
1f04d7aafd Merge branch 'develop'
# Conflicts:
#	config/version.php
2018-01-11 15:27:17 -08:00
snipe
78efeec368 Bumped hash 2018-01-11 15:24:37 -08:00
snipe
5b15a2fc0a Merge branch 'develop' 2018-01-11 15:23:27 -08:00
snipe
68f1fa0340 Added - ability to sort by asset count in models 2018-01-11 15:21:51 -08:00
snipe
9293f17707 Moved search scope lower to fix weird (possible Laravel) bug w/prepared statements 2018-01-11 15:17:34 -08:00
snipe
a4b32e2328 Improved - use presenters on model detail 2018-01-11 15:17:10 -08:00
snipe
d109ca30e2 Improved - allow searching on most detail views with additional tables 2018-01-11 15:16:53 -08:00
snipe
3b4a651dd9 Allow counts in mfg sorting 2018-01-11 15:16:23 -08:00
snipe
a4ac53e2e9 Improved - Using presenters for column headers in location detail 2018-01-11 15:16:09 -08:00
snipe
cf1b5a7685 Added- sort by count in manufacturer listing 2018-01-11 15:13:32 -08:00
snipe
0789eb8b07 Improved - using presenters for column headers in manufacturer detail 2018-01-11 15:12:48 -08:00
snipe
7f674fdd35 Require implicit search 2018-01-11 13:18:06 -08:00
snipe
500aa37e3c Fixed switchable attributes on table headers 2018-01-11 13:17:55 -08:00
snipe
efe668d26d Merge branch 'develop'
# Conflicts:
#	config/version.php
2018-01-10 22:59:02 -08:00
snipe
90db97b980 Merge branch 'features/fixes_4792_ajax_tables_on_license_view' into develop 2018-01-10 22:57:44 -08:00
snipe
bc3d27fac6 Bumped hash 2018-01-10 22:57:22 -08:00
snipe
55b9f1207d Updated bootstrap tables 2018-01-10 22:53:54 -08:00
snipe
2bbb6001a8 Added location to seats transformer 2018-01-10 20:36:27 -08:00
snipe
af7b7664c5 Added license seat location method 2018-01-10 20:34:44 -08:00
snipe
c31362655c Refactored BS tables include for clearer separation of simple v not simple 2018-01-10 20:34:36 -08:00
snipe
c6a956382f Fixed #4784 - cookie not always being set correctly for ajax tables 2018-01-10 20:04:41 -08:00
snipe
bab0bda174 Added custom formatter for license seats (WIP) 2018-01-10 18:58:55 -08:00
snipe
bb52a8417c Switch view code to AJAX table 2018-01-10 18:58:41 -08:00
snipe
e3d7be23cb Added new seats controller method 2018-01-10 18:47:57 -08:00
snipe
3d5545494e Added new seats transformer 2018-01-10 18:47:40 -08:00
snipe
7f1a535b30 Added new seats API route 2018-01-10 18:47:27 -08:00
snipe
254234b0dc Fixed #4787 - don’t try to display category if it is invalid
This shouldn’t be needed, but in case data got weird (manual editing, etc)
2018-01-10 06:33:59 -08:00
snipe
3566f37981 Merge branch 'develop' 2018-01-10 06:25:06 -08:00
snipe
e6259eb6e1 Fixed #4774 - show assets assigned to assets in asset view
Todo: Fix text search on the asset to asset tab. It’s currently broken so I’ve disabled it.
2018-01-10 05:44:11 -08:00
snipe
eeb3d1eb42 Use language strings for tab text 2018-01-10 05:42:34 -08:00
snipe
79295f6434 Use dataTableLayout for table 2018-01-10 05:33:45 -08:00
snipe
285e4e2e52 Allow bulk language update in user edit 2018-01-10 05:33:26 -08:00
snipe
5587b64d64 Fixed #4770 - broken licenses, etc on company view, added users and components 2018-01-10 03:52:21 -08:00
snipe
f0f2a5aa67 Workaround for #4784 - make changes tab always visible
Not sure why the cookie isn’t cookie-ing
2018-01-10 01:56:24 -08:00
Brady Wetherington
061317866b Changes to Models in the asset-edit screen maintain chosen values (#4781)
Fixed for #2195
2018-01-09 23:45:20 -08:00
snipe
65ffc01583 Merge branch 'develop' 2018-01-09 20:19:50 -08:00
snipe
f5f7a63a23 Production assets 2018-01-09 20:19:04 -08:00
snipe
b6a7fd1cec Run production assets - because modern web development. Sigh. 2018-01-09 20:18:49 -08:00
snipe
6245f92e16 Merge branch 'develop' 2018-01-09 20:12:44 -08:00
snipe
0abab2107c Fixed #4779 - show selected filename on filepicker 2018-01-09 20:12:07 -08:00
snipe
afc7116260 Fixed #4778 - added notes to asset model view 2018-01-09 20:00:06 -08:00
Geoff Young
0b3d2b46e0 Add attributes to delete asset file button (#4336)
This adds attributes to the delete file buttons on the View Asset page.
The attributes will fill the confirmation modal that prompts users
before deleting. They also activate a tooltip on the button.
2018-01-03 17:25:50 -08:00
Brandon Daniel Bailey
f786e07179 Allow auto increment through the API (#4690)
* Allow auto incrementing asset_id from the API when the setting is enabled

* Cleaned up the if else statement

* Added prefix to the orWhereRaw which causes a database error if the configuration uses a prefix

* Auto incrementing through the API
2018-01-03 17:24:32 -08:00
Daniel Meltzer
b2469bb34f Fix double create log on import. (#4706)
* Fix double create log on import.

* Fix code error causing component importer to implode.

* More component importer oldities
2018-01-03 17:22:02 -08:00
Brandon Daniel Bailey
b721bfcc84 Added prefix to the orWhereRaw which causes a database error if the configuration uses a prefix (#4703) 2017-12-28 20:09:36 -08:00
Daniel Meltzer
f16ce09a7a Importer again (#4702)
* If a user id is provided in the name column of an import, we should assume that it is a user id and check out to it.

* Fix build of vue files.  The location is public/js/build, not public/build

* Ensure a status type is set before allowing submission of an import.

Also expand the status text label to change color based on success/failure.

Fixes #4658

* Use right key to lookup emails when importing users.  Fixes 4619.

* Import serial for components, and make unique matches based on the serial as well as the name.  Fixes #4569

* Set the location_id when importing an item properly.

This moves as well to using the Asset::checkout() method, which should consolidate the logic into a useful spot.
Fixes #4563 (I think)

* Production assets.

* Case insensitive field map guessing and repopulate when changingin import type.
2017-12-28 20:08:45 -08:00
snipe
bbe9df306b Merge branch 'develop' 2017-12-26 17:33:06 -08:00
snipe
1bd7392531 Account for audits on deleted assets 2017-12-26 17:32:45 -08:00
snipe
2002dfca17 Merge branch 'develop' 2017-12-26 17:13:49 -08:00
snipe
38c2ecbd0c Fixed migration use 2017-12-26 17:13:26 -08:00
snipe
ce97faa8d4 Merge branch 'develop' 2017-12-26 17:11:40 -08:00
snipe
31ca4bff8c Break audit date denorm migrations into two separate migrations 2017-12-26 17:11:08 -08:00
snipe
6f9033b2fd Merge branch 'develop' 2017-12-26 16:49:42 -08:00
snipe
8864f81402 Fixed manufacturer error on printable user page
Manufacturer is not required for accessories, so need to account for that
2017-12-26 16:49:01 -08:00
snipe
71ba1af647 Fixed button class on asset view 2017-12-26 16:48:28 -08:00
snipe
b894a4c19a Merge branch 'develop' 2017-12-20 12:36:45 -08:00
snipe
c3a44f25fd Fixed #4663 - duplicate manufacturer name in selectlist 2017-12-20 12:32:55 -08:00
snipe
1f36e7997f Bumped version 2017-12-20 03:31:43 -08:00
snipe
33b5c26da5 Bumped hashcount 2017-12-19 22:16:31 -08:00
snipe
e5a7e6619f Merge branch 'develop' 2017-12-19 22:15:51 -08:00
snipe
d2e2c1c05f Stub and 404 registration routes 2017-12-19 22:14:51 -08:00
snipe
557b8b0ded Merge branch 'develop' 2017-12-19 20:57:46 -08:00
snipe
37d4cf3afb Fixed #4647 - requestable model button not clickable 2017-12-19 20:48:26 -08:00
snipe
b716db225f Added “new” buttons for manufacturer and category in asset model creation 2017-12-19 20:30:46 -08:00
snipe
fbe093705d Fixed #4640 - add username to user detail 2017-12-19 13:42:34 -08:00
snipe
db278e9109 Merge branch 'develop' 2017-12-19 00:48:44 -08:00
snipe
88798435f6 Fixed inefficient query for inventory alerts 2017-12-19 00:32:39 -08:00
snipe
6220f0d8a5 Merge branch 'develop'
# Conflicts:
#	config/version.php
2017-12-15 18:57:21 -08:00
snipe
30716b349b Bumped dev hash 2017-12-15 18:55:56 -08:00
snipe
7a8c8233a2 Fixes #4639 2017-12-15 18:54:38 -08:00
snipe
7a2abcca33 Merge branch 'develop' 2017-12-14 13:00:46 -08:00
Ryan
9a40e5e651 return an error from ldap_search (#4623)
This will return the error from the ldap_search ran in Models/Ldap.php instead of throwing an exception. Users seem to commonly be getting an Exception because of invalid search filters. This will better inform them of that issue without requiring them to enable DEBUG.
2017-12-14 12:57:43 -08:00
snipe
893bcd0533 Merge branch 'develop' 2017-12-12 21:14:41 -08:00
snipe
f1a911d305 Fixed ambiguous query on non-super admins with FCS 2017-12-12 21:14:12 -08:00
snipe
8e8d9118e9 Merge branch 'develop' 2017-12-12 16:35:45 -08:00
snipe
9c108873e9 Trying 5.4.35 2017-12-12 16:32:45 -08:00
snipe
6fe5d00e9b Testing laravel 5.4.3 for PHP7.2 bug 2017-12-12 16:23:30 -08:00
snipe
a85d5cfe92 Merge branch 'develop' 2017-12-12 12:58:52 -08:00
snipe
6b257cc287 Concat search for full name 2017-12-12 12:52:10 -08:00
snipe
2952497a60 Removed bower components directory
We use npm/webpack now
2017-12-12 11:42:26 -08:00
snipe
9018af4f1d Bumped hash 2017-12-12 10:45:20 -08:00
snipe
5204e84703 Merge branch 'develop'
# Conflicts:
#	config/version.php
2017-12-12 09:25:45 -08:00
snipe
55eaea0110 Derp. 2017-12-12 09:25:06 -08:00
snipe
671a125c62 Bumped hash 2017-12-12 09:24:40 -08:00
snipe
eb827cdbe6 Merge branch 'develop' 2017-12-12 09:21:17 -08:00
snipe
5504dd435f Updated transslations 2017-12-12 09:20:57 -08:00
snipe
608bb1b5b1 Fixed #3416 - bulk delete asset models 2017-12-12 09:10:05 -08:00
snipe
88b64034e8 Fixed #3416 - bulk delete asset models 2017-12-12 09:03:37 -08:00
snipe
694c6f3ec6 Merge branch 'develop' 2017-12-12 07:22:30 -08:00
snipe
1d82f80e73 Improved - used “checked out to” string in asset model listing to reflect new polymorphic options 2017-12-12 07:20:06 -08:00
snipe
e21fa37254 Added - bulk actions to model asset listings 2017-12-12 07:15:51 -08:00
snipe
1ef44721f5 Improved - disallow delete if not elgible in UI 2017-12-12 07:03:31 -08:00
snipe
528630a8d3 Improvement - make asset, etc totals in company listing sortable 2017-12-12 07:03:09 -08:00
snipe
856a760d89 Improved - disallow deleting manufactureres if there are associated items
This is enforced on the backend - UI imorovement only
2017-12-12 06:52:50 -08:00
snipe
9179b6d9c4 Improved - disallow delete through the GUI if asset model has assets associated
(We prevent this on the backend anyway, but this makes for nicer UI)
2017-12-12 06:49:04 -08:00
snipe
4ce91a4f5d Fixed namespace gate for components - related to #4282 2017-12-12 06:26:37 -08:00
snipe
aff93d8f2b Fixed #4589 - Licence deployed to asset issue 2017-12-12 05:43:06 -08:00
snipe
e4ab4024c5 Added - changelog searchable in history tab 2017-12-12 05:10:13 -08:00
snipe
612f23f6e0 Added #2893 - track changes on asset edits 2017-12-12 04:59:28 -08:00
snipe
1d543f83d4 Added line spacing between unstyled lists 2017-12-12 04:31:53 -08:00
snipe
88ca852dcf Cleaned up asset observer 2017-12-12 03:40:04 -08:00
snipe
9fe2a7f81d Removed duplicate log entry on asset creation 2017-12-12 03:39:55 -08:00
snipe
a988011f0c Merge branch 'develop'
# Conflicts:
#	config/version.php
2017-12-12 03:07:43 -08:00
snipe
c816870083 De-norm last audit date so we can display it in the asset listing 2017-12-12 03:03:43 -08:00
snipe
c5c46b7283 Removed duplicate deleted logaction
This is handled via observers now
2017-12-12 02:32:45 -08:00
snipe
8bb8306f80 Added restored string 2017-12-12 02:31:46 -08:00
snipe
d91e8bfee5 Fixed select2 on setup 2017-12-12 02:31:36 -08:00
snipe
2b3e5c8800 Moved “deleted” alert banner higher on page 2017-12-12 02:31:26 -08:00
snipe
5b00a8ae33 Use specific company_id column name in user search 2017-12-11 22:50:55 -08:00
snipe
5ee6e7f94b Fixed #4613 - Added table prefix to user search DB raw 2017-12-11 22:31:07 -08:00
snipe
f90271dae5 Aaaaand one more for #2810. Sigh. 2017-12-08 14:33:12 -08:00
snipe
e1423bd9d9 One more fix for #2810 2017-12-08 14:02:27 -08:00
snipe
557714e7b7 Fixed #2810 - checkin fix for licenses 2017-12-08 13:19:10 -08:00
snipe
3df62a200f Fixed manufacturer gates 2017-12-08 13:16:37 -08:00
snipe
a65ea639ed Added comments to SnipePermissionsPolicy for clarity 2017-12-07 21:00:09 -08:00
snipe
defed52caa Fixed #4596 - manufacturer gate 2017-12-07 20:59:55 -08:00
snipe
035f7a5292 Formatted version 2017-12-07 19:24:03 -08:00
snipe
0ea3100896 Bumped hash 2017-12-07 19:23:34 -08:00
snipe
2e0c2bd190 Add @Gelob as a contributor 2017-12-07 19:20:08 -08:00
snipe
ceca76b344 Merge branch 'develop' 2017-12-07 13:21:45 -08:00
snipe
a062769672 Check for array key before checking selected state
This is necessary for pre-created groups that don’t have all keys present
2017-12-07 13:21:30 -08:00
Ryan
af6a794ae9 fix typo (#4585) 2017-12-06 20:51:37 -08:00
snipe
f4ac087c83 Fixed policy namespace 2017-12-06 14:49:52 -08:00
snipe
4898dd8e23 Use ImageUploadRequest $request on user profile update 2017-12-06 14:42:14 -08:00
snipe
a090b6a9d2 Use ImageUploadRequest 2017-12-06 14:38:01 -08:00
snipe
023910472c Fixes #2415 - only allow gif, png jpg, svg image uploads 2017-12-06 14:33:52 -08:00
snipe
25bf10b125 Merge branch 'develop' 2017-12-06 11:19:45 -08:00
snipe
dfb0c09c51 Fixed #4581 - renamed print method 2017-12-06 11:17:42 -08:00
snipe
41c8d6302a Merge branch 'develop' 2017-12-05 18:17:32 -08:00
snipe
83547e3fed Prepopulate ther groups array on create 2017-12-05 18:17:11 -08:00
snipe
0d92ffc7ed Merge branch 'develop' 2017-12-05 18:13:08 -08:00
snipe
3d0525bc51 Removed debugging info 2017-12-05 18:11:59 -08:00
snipe
808cd0f728 Nicer groups permission edit UI 2017-12-05 18:11:06 -08:00
snipe
f5b3df697c Better select/unselect all javascript for permissions 2017-12-05 18:10:35 -08:00
snipe
29a36b5d1c Do not allow null id on group edit 2017-12-05 16:49:26 -08:00
snipe
ec131a7416 Updated account licenses 2017-12-05 16:27:02 -08:00
snipe
3da49ceb60 Standardize hidden key format 2017-12-05 16:26:39 -08:00
snipe
a19cef07bf Check for gate on license key display 2017-12-05 16:26:23 -08:00
snipe
c39e6d7006 Fixed #4576 - licence checkout gate 2017-12-05 15:04:10 -08:00
snipe
60f6895919 Remove version from asset table to persist column selections 2017-12-05 14:50:38 -08:00
snipe
bfa4812482 Exclude company on filter 2017-12-05 14:23:46 -08:00
snipe
a083cdba18 Merge branch 'develop' 2017-12-05 14:04:55 -08:00
snipe
438f484d68 Removed duplicate purchase cost column 2017-12-05 14:03:08 -08:00
snipe
f95d780fcf Include purchase cost column if depreciation is selected 2017-12-05 14:02:43 -08:00
snipe
79fe092c81 Merge branch 'develop'
# Conflicts:
#	config/version.php
2017-12-05 13:20:39 -08:00
snipe
027f6a7c12 Bumped hash 2017-12-05 13:18:52 -08:00
snipe
76fe2af0af Fixed #4444 - Added EOL back into asset lsiting and custom report 2017-12-05 13:03:11 -08:00
snipe
e490185533 Fixed EOL in custom report 2017-12-05 12:54:19 -08:00
snipe
deba4d2b81 Added consumables tio printable output 2017-12-05 12:37:42 -08:00
snipe
a8cc29f062 Added #2562 - print view of all assigned inventory 2017-12-05 12:34:16 -08:00
snipe
c9e6a75ea8 Make sure there is a valid status label associated withthe asset when checking if deployable 2017-12-05 11:28:48 -08:00
snipe
7efa7ec03f Starter print template for all assets assigned to a user 2017-12-05 01:55:24 -08:00
snipe
9eef7a94ab Fixed #4557 - added missing fields in components/consumables list view 2017-12-05 00:40:30 -08:00
snipe
244eceadec Merge branch 'develop'
# Conflicts:
#	config/version.php
2017-12-04 23:51:53 -08:00
snipe
28fdbdd5d8 Bumped version 2017-12-04 23:50:45 -08:00
Brady Wetherington
4584990cc3 Cleaner re-implementation of loop-detection for asset-assigned-assets (#4553)
* Cleaner re-implementation of loop-detection for asset-assigned-assets

* Get rid of the other static and pass it along recursively too.
2017-12-04 23:00:55 -08:00
snipe
4f3c932bb1 Merge branch 'develop' 2017-12-04 20:45:46 -08:00
snipe
d7f2bceea2 Fixed incorrect property on supplier 2017-12-04 20:45:20 -08:00
snipe
18c1b2b477 Merge branch 'develop' 2017-12-04 20:43:24 -08:00
snipe
174e3e720a Fixed #4521 - profile location not selected
This is kind of a janky way to handle this - I created a new dropdown select, instead of adding even more convoluted code to the partial. The reasoon for this is because there may be situations where $user is passed in *addition* to $item, and we don’t want to erroneously use that location if we’re not supposed to be.
2017-12-04 20:30:57 -08:00
snipe
fdaa279930 Fixed #4548 - add cateory to model dropdown 2017-12-04 20:19:30 -08:00
snipe
a4323a0308 Fixed #4559 - min width for checkin/checkout buttons 2017-12-04 19:57:15 -08:00
snipe
ec4bed436c Fixed #4565 - show manufacturer in models selectlist 2017-12-04 19:52:18 -08:00
snipe
636c558fe6 Fixed #4566 - search by purchase_date 2017-12-04 15:26:40 -08:00
snipe
29873f9c22 Merge branch 'develop' 2017-12-01 21:58:23 -08:00
snipe
912ee20f3c Better supplier/location flow for suppliers/locations without data 2017-12-01 21:58:00 -08:00
snipe
9f10080243 Fixed parsed error 2017-12-01 21:13:18 -08:00
snipe
b3c386663f Merge branch 'develop'
# Conflicts:
#	config/version.php
2017-12-01 21:11:33 -08:00
snipe
f2d25ff777 Added device image to supplier 2017-12-01 21:06:36 -08:00
snipe
dec9d959db Added additional user/asset fields to location view 2017-12-01 21:06:16 -08:00
snipe
2aafdb1400 Bumped version 2017-12-01 20:49:04 -08:00
snipe
c6b02cdc02 Location layout tweaks 2017-12-01 20:35:15 -08:00
snipe
f0c825a9b3 Improved suppliers view (use ajax tables) 2017-12-01 20:29:51 -08:00
snipe
79c035da11 Added map alt tag 2017-12-01 20:29:04 -08:00
snipe
9deafd771e Fixed bad suppliers error route 2017-12-01 20:28:37 -08:00
snipe
cbc09f3a12 Fixes #4508 - adds image to location view (and google map, if address and API key exist) 2017-12-01 19:12:35 -08:00
snipe
22c4d79cfb Fixed #4345 - Disallow future date for checkin date, disallow past date for expected checkin 2017-12-01 17:52:56 -08:00
snipe
71b9a15c9c Moved User menu down 2017-12-01 17:50:01 -08:00
snipe
db328e1ce5 Fixed granular hash resetting cookie 2017-12-01 17:49:44 -08:00
snipe
8b4c85d69a Removed verbose logging 2017-12-01 16:56:50 -08:00
snipe
78a51d3675 Additional fixes, improvements for custom report 2017-12-01 16:51:38 -08:00
snipe
a5bcf53146 Pass $required variable to display requiredness 2017-12-01 16:51:22 -08:00
snipe
9f97b4aefd Added created_at status, and manufacturer filter to custom report 2017-12-01 16:50:56 -08:00
snipe
62468199af Wider column for checkboxes 2017-12-01 16:50:16 -08:00
snipe
c220315cb0 Check if item is set before trying to look up selected 2017-12-01 16:49:51 -08:00
snipe
5a3233da37 Grr. 2017-12-01 14:54:18 -08:00
snipe
80109071a2 Fixed version number 2017-12-01 14:54:02 -08:00
snipe
c43bb670d2 Bumped hash 2017-12-01 14:50:46 -08:00
snipe
14874d8e8a Fixes #4495 - missing field in Download CSV, added filter options on custom report 2017-12-01 14:47:52 -08:00
snipe
ff793f1cb5 Added variable to determine if “new” modal button should be displayed 2017-12-01 14:37:11 -08:00
snipe
500f6d7baf Set requiredness of select2 ajax fields 2017-12-01 14:36:27 -08:00
snipe
ee9a229c0e Added datepicker range CSS 2017-12-01 14:26:01 -08:00
snipe
8140bdaa88 Fixed repeated header issue in asset export 2017-12-01 14:25:32 -08:00
snipe
5979a18852 Merge branch 'develop'
# Conflicts:
#	config/version.php
2017-11-30 16:43:59 -08:00
snipe
5efb803b60 Auto-bumped hash/version 2017-11-30 16:41:06 -08:00
snipe
fd4a8edae9 Fixed incorrect glyphs for users/locations 2017-11-30 16:40:58 -08:00
snipe
e9fdf06bf6 Improved display of asset status and meta status 2017-11-30 16:40:37 -08:00
snipe
0a5b72e71e Fixed #4517 - order number not visible if no purchase cost given on asset view 2017-11-30 16:39:59 -08:00
snipe
51168e8e10 Auto-bumped hash/version 2017-11-30 13:40:36 -08:00
snipe
cefdca3d22 Fixed incorrect has vs input 2017-11-30 13:40:26 -08:00
snipe
cc5eee1890 Auto-bumped hash/version 2017-11-30 13:32:12 -08:00
snipe
d3864db5e1 Switched to use $request from Input:: facade 2017-11-30 13:32:00 -08:00
snipe
ece8ae3adc Fixed #4542 and #4482 - default asset location not updating on biulk edit 2017-11-30 13:31:46 -08:00
snipe
e25829c759 Removed extra debug logging 2017-11-30 13:30:20 -08:00
snipe
92afd5f232 Removed debugging console code 2017-11-30 11:48:59 -08:00
snipe
b934d2e504 Merge branch 'develop'
# Conflicts:
#	config/version.php
2017-11-27 22:19:24 -08:00
snipe
8cf70e7e20 Auto-bumped hash/version 2017-11-27 22:10:54 -08:00
snipe
cdfd720c65 Fixed custom fields edit behavior with cutom format always selected 2017-11-27 22:10:46 -08:00
snipe
c0f791cf13 Sigh. 2017-11-27 21:35:06 -08:00
snipe
290cf79778 Auto-bumped hash/version 2017-11-27 21:25:21 -08:00
snipe
8af1481749 Auto-bumped hash/version 2017-11-27 21:20:38 -08:00
snipe
d8f404096c Added spacing in js 2017-11-27 21:20:31 -08:00
snipe
ea2f7617df Validate checkout_to_type on asset checkout 2017-11-27 21:20:12 -08:00
snipe
b6c258bb12 Redirect to back on bad checkout 2017-11-27 21:19:50 -08:00
snipe
804b49cefb Make sure the asset is available for checkout before displaying the checkout screen 2017-11-27 21:18:29 -08:00
snipe
305b0d8edb Fixed #4522 - properly check for valid target, throw error otherwise 2017-11-27 21:17:58 -08:00
snipe
05996019e5 Use asset checkout request in API 2017-11-27 21:17:16 -08:00
snipe
31a967e072 Use general order_number string to mean order number 2017-11-27 21:16:51 -08:00
snipe
0b56ebf291 Fixed radio button selector to provide correct default value in checkout 2017-11-27 21:16:25 -08:00
snipe
fcc87b3219 Merge branch 'develop'
# Conflicts:
#	config/version.php
2017-11-24 11:27:54 -08:00
snipe
82fca0c72d Auto-bumped hash/version 2017-11-24 11:25:57 -08:00
snipe
51661b0a21 Fixed #4190 - Added artisan command to regenerate asset tags 2017-11-24 11:25:51 -08:00
snipe
e8670fe591 Merge branch 'develop' of github.com:snipe/snipe-it into develop 2017-11-24 10:53:20 -08:00
Daniel Meltzer
bee1dfc4a6 More importer fixes (#4516)
* The default locale of en does not include dollar sign in default currency.  Assume if there is no currency symbol set that the dollar sign is a good thing to look for in parsefloat.

* Fix for 4485.  Serial not serial_number

Also fix bug where updating with a csv that does not include custom field columns should not overwrite current values.

* Rename serial_number to serial in default imports to avoid needing to map weirdly.

* Add Test for 4359.  Not reproducable at current though
2017-11-24 10:42:11 -08:00
snipe
83c8449aca Auto-bumped hash/version 2017-11-22 18:43:18 -08:00
snipe
9dba1bb3e5 Merge branch 'develop'
# Conflicts:
#	config/version.php
2017-11-22 18:43:15 -08:00
snipe
76e3398d44 Auto-bumped hash/version 2017-11-22 18:42:33 -08:00
snipe
a7e12931fa Check that assigned is an object in reports controller 2017-11-22 18:42:17 -08:00
snipe
ba04c64567 Auto-bumped hash/version 2017-11-22 18:34:03 -08:00
snipe
8c8352ecc6 Merge branch 'develop'
# Conflicts:
#	config/version.php
2017-11-22 18:33:56 -08:00
snipe
64b670033d Auto-bumped hash/version 2017-11-22 18:30:45 -08:00
snipe
b9d102a5fb Truncate the fieldset table and pivot table on seed as well 2017-11-22 15:57:05 -08:00
snipe
77076e02e8 Fixed - mark supplier as requried in maintenance 2017-11-22 15:22:44 -08:00
snipe
c6a761a5ad Fixed - supplier is not required on asset creation/edit 2017-11-22 15:20:46 -08:00
snipe
6f3a90c48b Check that the assigned data is valid 2017-11-22 15:07:34 -08:00
snipe
8f160a8590 Fixed CSV asset export missing checked out to info 2017-11-22 13:05:48 -08:00
snipe
2278d5bfd8 Fixed restore permission to assets API disable delete/checkin/checkout on deleted assets 2017-11-22 10:35:24 -08:00
snipe
66ac147c9e Auto-bumped hash/version 2017-11-22 07:32:40 -08:00
snipe
05e0d15ae4 Auto-bumped hash/version 2017-11-22 07:31:50 -08:00
snipe
8562f018ed Fixed - conflicting error when a user and asset were both checked out 2017-11-22 07:31:38 -08:00
snipe
0cbdcce3ea Production asset manifest 2017-11-22 07:07:33 -08:00
snipe
980be65193 Added ability to turn items on/off in checkout-selector 2017-11-22 07:07:18 -08:00
snipe
3aaaea37e4 Added - sync locations artican call after seed 2017-11-22 06:21:56 -08:00
snipe
964c594c4c Added ItemFormatter for acrtivity report 2017-11-22 06:21:06 -08:00
snipe
9430c4bf43 Added sanity checks in BS tables formatter 2017-11-22 06:20:51 -08:00
snipe
538757317b Fixed #4411 - broken activity report if purge didn’t remove relationship entries 2017-11-22 06:20:28 -08:00
snipe
fe986f7c51 Auto-bumped hash/version 2017-11-21 22:45:10 -08:00
snipe
09105871d9 Auto-bumped hash/version 2017-11-21 22:43:33 -08:00
snipe
e84a6059f4 Merge branch 'develop' 2017-11-21 22:43:00 -08:00
snipe
09f20873df Auto-bumped hash/version 2017-11-21 22:35:05 -08:00
snipe
2adc1e8ba9 Auto-bumped hash/version 2017-11-21 22:35:04 -08:00
snipe
4a6c18532b Auto-bumped hash/version 2017-11-21 22:35:02 -08:00
snipe
921f882680 Auto-bumped hash/version 2017-11-21 22:35:01 -08:00
snipe
f79e5add58 Auto-bumped hash/version 2017-11-21 22:34:59 -08:00
snipe
d98d06377e Fixed #4098 - autolink URL and email addresses in listing 2017-11-21 22:34:53 -08:00
snipe
22fdd05314 Add UTF charset 2017-11-21 22:34:07 -08:00
snipe
8c15a4e0c6 Auto-bumped hash/version 2017-11-21 21:00:07 -08:00
snipe
9250b45e6e Auto-bumped hash/version 2017-11-21 21:00:05 -08:00
snipe
3a1de3d2a5 Auto-bumped hash/version 2017-11-21 21:00:02 -08:00
snipe
b59dd11304 Auto-bumped hash/version 2017-11-21 21:00:00 -08:00
snipe
b6222abb7c Auto-bumped hash/version 2017-11-21 20:59:58 -08:00
snipe
dcf8e4f5ef Auto-bumped hash/version 2017-11-21 20:59:54 -08:00
snipe
f195073ac3 Auto-bumped hash/version 2017-11-21 20:59:52 -08:00
snipe
452a9d6725 Auto-bumped hash/version 2017-11-21 20:59:50 -08:00
snipe
1d74ddc547 Auto-bumped hash/version 2017-11-21 20:59:45 -08:00
snipe
932b589a14 Auto-bumped hash/version 2017-11-21 20:59:43 -08:00
snipe
671e514785 Auto-bumped hash/version 2017-11-21 20:59:41 -08:00
snipe
1e2ebdb69c Auto-bumped hash/version 2017-11-21 20:59:39 -08:00
snipe
148751d927 Auto-bumped hash/version 2017-11-21 20:59:37 -08:00
snipe
efecdfaea0 Auto-bumped hash/version 2017-11-21 20:59:35 -08:00
snipe
ab9c84a6b6 Auto-bumped hash/version 2017-11-21 20:59:33 -08:00
snipe
8711bc0dbd Added comments for toggle checkout-to JS 2017-11-21 20:55:57 -08:00
snipe
0adebd1ec8 Add sorting and additional category types to dashboard categories
BREAKING CHANGE: Category type now reports as `category_type`, instead of `type`
2017-11-21 20:33:30 -08:00
snipe
43c1e893c0 Fixed #4494 - use audit settings for asset audit pre-populaton 2017-11-21 20:13:51 -08:00
snipe
7ce63e653b Auto-bumped hash/version 2017-11-21 19:39:53 -08:00
snipe
e5129a8b98 Removed next_version 2017-11-21 19:39:33 -08:00
snipe
a922c1a298 Auto-bumped hash/version 2017-11-21 19:38:29 -08:00
snipe
f4aa812d96 Changed twitter handle to @snipeitapp 2017-11-21 19:02:15 -08:00
snipe
0c9e41e1fa Updated versioning script to handle githooks better 2017-11-21 19:01:47 -08:00
snipe
1d6320a88f Merge branch 'develop' 2017-11-21 16:26:41 -08:00
snipe
4696e799ed Fixes #4491 and #4483 - handle pre-selected asset on checkout, better checkout-to selection UI (#4501)
* Added form checkout selector partial

* Stupid stash

* Added radio button checkout selector javascript

* New compiled production assets

* Added $style override in form partials for select2 ajax lists

* Added checkout-to radio button selector

TODO: Fix for accessibility - currently cannot tab-select this radio button

* Added new checkout-to selector to hardware edit

* Added new checkout-to selector to asset checkout form

* Refactored postCheckout to use radio button submission

This defaults to user checkout if nothing is passed for some reason

* Better visual feedback on whether or not an asset is deployable in edit screen
2017-11-21 15:58:31 -08:00
snipe
2e08a91c53 Merge branch 'develop' 2017-11-20 21:48:57 -08:00
snipe
4fd35573ad Bumped version 2017-11-20 21:20:34 -08:00
snipe
caf2cdbf6f Merge branch 'develop' 2017-11-20 20:51:22 -08:00
snipe
c0293a7c1c Add @uknzaeinozpas as a contributor 2017-11-20 19:39:04 -08:00
snipe
17405f5de1 Fixed #4413 - Next license seat not bering assigned correctly 2017-11-20 19:21:05 -08:00
snipe
bfefa10462 Add @TheVakman as a contributor 2017-11-20 18:54:43 -08:00
snipe
55a140045b Fixed upgrade language 2017-11-16 16:50:16 -08:00
snipe
897bd2c56e Fixed location sorting location instead of rtd 2017-11-16 16:49:48 -08:00
snipe
7321c5937f Fixed #4440 - allow username search in asset dropdown 2017-11-16 16:49:16 -08:00
snipe
98700cab8b Merge branch 'develop' 2017-11-16 14:14:49 -08:00
snipe
3d07635820 Fixed sort by model in asset listing 2017-11-16 14:14:30 -08:00
snipe
59b18a6ada Merge branch 'develop' 2017-11-16 13:49:05 -08:00
snipe
ce525c1985 Fixed #4471 - removed gate for categories selectlist 2017-11-16 13:48:38 -08:00
snipe
a0d163a3c4 Merge branch 'develop' 2017-11-16 11:41:18 -08:00
snipe
faab971931 Improved - removed 500 pixel width on 2FA dropdown 2017-11-16 11:09:42 -08:00
snipe
38eb16dfea Fixed #4408 - requestable assets not working 2017-11-16 11:09:24 -08:00
snipe
4494456cad Merge branch 'develop' 2017-11-15 15:51:50 -08:00
snipe
876dde1280 Fixed #4428 - updated translations 2017-11-15 15:31:34 -08:00
snipe
17ee904828 Fixed #4450 - added MAIL_REPLYTO_ADDR to docker.env 2017-11-15 14:48:45 -08:00
snipe
4f1b58cd35 Merge branch 'develop' 2017-11-15 14:27:47 -08:00
snipe
edcd3afc3e Fixes #4457 - use un-escaped CSS for custom CSS styles
We are already escaping the CSS in the show_custom_css() method
2017-11-15 14:27:21 -08:00
snipe
e433b0f9d8 Merge branch 'develop'
# Conflicts:
#	config/version.php
2017-11-14 16:50:05 -08:00
snipe
f137e516a6 Bumped version 2017-11-14 16:49:18 -08:00
snipe
ba38b841cb Constrain accessory by category ID if one is passed 2017-11-14 16:47:21 -08:00
snipe
f7c6697a69 Merge branch 'develop' 2017-11-14 01:32:43 -08:00
snipe
498fc3762d Fixed #4437 - pagination for maintenances 2017-11-14 01:32:25 -08:00
snipe
eb24eb1fff Merge branch 'develop' 2017-11-14 00:04:27 -08:00
snipe
3e5e6ba99a Use table alias for models join in search/order by models 2017-11-14 00:04:03 -08:00
snipe
0396267388 Fixed #4412 - use select2 ajax list for asset maintenances 2017-11-12 17:22:16 -08:00
snipe
4577ba39d7 Merge branch 'develop' 2017-11-10 15:56:34 -08:00
snipe
7eef1b4bcf Fixed #4418 - order models by name asc in selectlist 2017-11-10 15:56:14 -08:00
snipe
578da128e9 Merge branch 'develop' 2017-11-09 18:59:25 -08:00
snipe
bb4d49690f Add purchase date to dates array so it’s treated as a Carbon date 2017-11-09 18:59:05 -08:00
snipe
7eb94d16a1 Merge branch 'develop' 2017-11-09 14:42:19 -08:00
snipe
65bd33c274 Make sure the user isn’t deleted before trying to display the name 2017-11-09 14:42:03 -08:00
snipe
0f7aa21a59 Merge branch 'develop' 2017-11-09 13:41:17 -08:00
snipe
ee0814716a Only format ecpected checkin date if one exists 2017-11-09 13:40:55 -08:00
snipe
f56e1768b6 Merge branch 'develop' 2017-11-09 13:28:12 -08:00
snipe
012afe99e2 Set purchase date to date type 2017-11-09 13:27:58 -08:00
snipe
0c02b6d24e Use —no-dev flag in upgrade 2017-11-09 13:25:44 -08:00
snipe
2f34336f2b Merge branch 'develop' 2017-11-09 11:18:21 -08:00
snipe
afe6f43a1b Exclude manufacturer on filter sort 2017-11-09 11:18:04 -08:00
snipe
738e33b165 Merge branch 'develop' 2017-11-09 11:06:50 -08:00
snipe
566fd4d2e1 Only format purchase date if one exists 2017-11-09 11:06:37 -08:00
snipe
c61887da21 Merge branch 'develop'
# Conflicts:
#	upgrade.php
2017-11-09 10:52:46 -08:00
snipe
6852b74317 Removed gates from selectlist method 2017-11-09 10:51:55 -08:00
snipe
4c266fdcf4 Merge branch 'develop' of github.com:snipe/snipe-it into develop 2017-11-08 20:28:23 -08:00
snipe
c26a2f8291 Patching #4402 into develop 2017-11-08 20:28:18 -08:00
uknzaeinozpas
a994e54726 Update upgrade.php (#4402)
posix_* are not supported on Windows platform
2017-11-08 20:13:35 -08:00
madd15
172c7c75a8 Fixed #4374 - Add option to display company names to labels (#4405)
* Migration - Labels Display Company Name setting

* Add Company Name to Labels

Add company name if it is turned on in settings and asset has a valid company

* Add Company Name checkbox to Label settings

* Add Company Name Lang

* Add display company name to postLabels

* Revert Add Company Name Lang

* Fix display company name in postLabels

* Change tinyInt to boolean for display company name

* Simplify checking for company and getting the name

* Change to square brackets for array notation

* Move divs inside if statements on optional fields
2017-11-08 20:05:39 -08:00
snipe
487fd17ce3 Fixed ambiguous query when selecting by model_id 2017-11-08 20:03:26 -08:00
snipe
65353fa422 Nicer styling for purchase cost in edit form
Made it more consistent with the warranty months foeld below it
2017-11-08 18:06:51 -08:00
snipe
4f4920615c Format expected checkin as Y-m-d in form 2017-11-08 18:06:14 -08:00
snipe
c162c02304 Force expected checkin to be formatted as a date (not datetime) since it’s a date field in the DB 2017-11-08 18:03:47 -08:00
snipe
1bb1480f67 Added a comment around protected dates so we know wtf 2017-11-08 18:03:27 -08:00
snipe
8dceacc2b4 Merge branch 'develop' 2017-11-08 17:09:19 -08:00
snipe
ffae537400 Check that the models are valid being trying to return a value in the ajax partials 2017-11-08 17:07:57 -08:00
snipe
5ce7882bf5 Merge branch 'develop' of github.com:snipe/snipe-it into develop 2017-11-08 17:01:50 -08:00
snipe
b36594f508 Check that the company is valid in select ajax 2017-11-08 17:01:46 -08:00
madd15
59c9c22a59 Small UI Changes (#4404)
* Small ui change to settings nav

* Remove min-height

Removed min-height from Assets by Status

* Add min-height to box-body
2017-11-08 13:12:03 -08:00
snipe
9097681c13 Changed log fomrat in example env to single 2017-11-08 11:08:11 -08:00
snipe
567f741d95 Merge branch 'develop' 2017-11-08 10:59:29 -08:00
snipe
9b1fb90519 Change default log type back to single 2017-11-08 10:58:56 -08:00
snipe
b567ffdcfe Fixed #2855 - checkin for components 2017-11-08 06:06:05 -08:00
snipe
9d44607b8f Added UI fade out when bootstrap alerts are dismissed 2017-11-08 03:13:18 -08:00
snipe
35ee52212f Added ability to disable the alert icon in the top menu 2017-11-08 03:08:17 -08:00
snipe
e9e32fdb00 Merge branch 'develop' of github.com:snipe/snipe-it into develop 2017-11-08 02:46:40 -08:00
snipe
6c130ce8ac Apply patch #4354 2017-11-08 02:46:33 -08:00
Sorvani
dd7db0de93 Moved firewall commands from CentOS 7 to a routine and called form both CentOS 7 and Fedora. (#4366) 2017-11-08 02:37:34 -08:00
snipe
70efac8fa7 Production js 2017-11-08 02:24:34 -08:00
snipe
6e2556eefd Production assets 2017-11-08 02:24:06 -08:00
snipe
fb6a545cc6 Slightly nicer styling 2017-11-08 02:11:33 -08:00
snipe
e5c1e41966 Nicer icheck for user menu 2017-11-08 01:52:35 -08:00
snipe
61617a2629 Slightly less fugly groups permission styling 2017-11-08 01:19:20 -08:00
snipe
a3e80882c1 Better error handling for qr codes on invalid assets 2017-11-08 01:04:14 -08:00
snipe
31980c55de Merge branch 'develop'
# Conflicts:
#	config/version.php
2017-11-08 00:58:16 -08:00
snipe
d1022e8ff7 Fixed #4390 - results couldn’t be loaded error
The baseUrl in the javascript routes is already appending a trailing slash, so don’t prepend a slash in front of api call
2017-11-08 00:57:43 -08:00
snipe
e6ff447ee8 Bumped hash 2017-11-07 23:12:59 -08:00
snipe
1123272ae8 Bumped hash 2017-11-07 23:12:10 -08:00
snipe
74aa562a3b Merge branch 'develop' 2017-11-07 23:10:49 -08:00
snipe
74773ac912 Fixed incorrect policy reference in consumables listing 2017-11-07 23:05:29 -08:00
snipe
9764d2ad24 Removed commented code 2017-11-07 22:25:32 -08:00
snipe
d03b8c6528 Error handling for when log ID has no match on asset accept 2017-11-07 22:25:24 -08:00
snipe
99a355145e Removed empty comments 2017-11-07 22:24:57 -08:00
snipe
7233e2dded Merge branch 'develop' 2017-11-07 18:21:47 -08:00
snipe
eed50112d5 Better fallback for local that won’t break migrations 2017-11-07 18:18:27 -08:00
snipe
5aee5a3f3d Update location on checkout, error if bad target 2017-11-07 17:37:08 -08:00
snipe
f21c7ba312 Merge branch 'develop' 2017-11-07 11:28:41 -08:00
snipe
9d7455f022 Fixed handling deleting old images better 2017-11-07 11:28:13 -08:00
snipe
b748e7ed5e Fixed transformers to use new singleton upload urls 2017-11-07 11:11:47 -08:00
snipe
84a717c6ad Fixed deleted ordering scope 2017-11-07 11:06:38 -08:00
snipe
a202e1657c Fixed path for singletons 2017-11-06 21:58:28 -08:00
snipe
30ec919048 Remove AWS package
We unfortunately can’t use it right now because it requires a symlink from the storage/app directory. Until we have a better way of checking for configuration issues and/or automatically handling that symlink creation, we’re pulling it for now, since it’s not used anywhere.
2017-11-06 21:45:31 -08:00
snipe
4ae4083b7b Removed unused $matches variable 2017-11-06 21:26:30 -08:00
snipe
dec9ac1ac8 Fixed lowercase false 2017-11-06 21:25:40 -08:00
snipe
8776d28d3b Remove fastclick from package.json
We’re not using it anymore because of conflicts with select2. Select2 is more important for our UX than fastclick is.
2017-11-06 21:22:18 -08:00
snipe
231dea0ebc Break out service providers by responsibility 2017-11-06 21:17:17 -08:00
snipe
cceeb5c8a2 Disable Fastclick - conflicts with Select2, per #4392 2017-11-06 21:16:20 -08:00
snipe
579334b5fc Fixed - name should always be required in custom fields 2017-11-06 20:05:40 -08:00
snipe
3a82fbe714 Switch to rollbar’s official package 2017-11-06 20:04:50 -08:00
snipe
143071fa0c Merge branch 'develop' 2017-11-06 17:18:18 -08:00
snipe
0589652edb Fixed #4392 - select2 + fastclick incompatibility
This is a workaround fix - should upgrade both to latest after testing extensively
2017-11-06 17:17:48 -08:00
snipe
b772d8e527 Fix for IIS+ Chrome not showing webfonts
Thanks, @BrettFagerlund!
2017-11-06 16:51:46 -08:00
snipe
b96d4dcf1f Don’t show ANY in custom regex field if empty 2017-11-06 16:43:27 -08:00
snipe
dc32e4bdb0 Fixed form request ffor custom fields 2017-11-06 16:42:37 -08:00
snipe
43f2a530f5 Merge branch 'develop' 2017-11-06 12:39:00 -08:00
snipe
6ece593629 Fixed #4381 - asset uploads 2017-11-06 12:38:31 -08:00
snipe
33de0ec8a9 Merge branch 'develop' 2017-11-06 12:19:48 -08:00
snipe
8e17714c12 Fixed #4384 - bulk checkout of assets 2017-11-06 12:19:22 -08:00
snipe
32fc052c3b Fixed #4391 - companies now listing correct assets 2017-11-06 12:01:54 -08:00
snipe
17febca466 Merge branch 'develop' 2017-11-06 10:55:42 -08:00
snipe
8572a9771b Only return location name if find is valid 2017-11-06 10:55:20 -08:00
snipe
3ea294c0e6 Merge branch 'develop' 2017-11-06 10:45:14 -08:00
snipe
2b3b2e3197 Removed presenter references in custom report 2017-11-06 10:44:57 -08:00
snipe
a9d9234fb3 One more fix for custom reports 2017-11-06 10:44:18 -08:00
snipe
a11d9b84a4 Merge branch 'develop' 2017-11-06 10:42:48 -08:00
snipe
936ff707c7 Fixed custom report bug if assignedTo has no value 2017-11-06 10:42:34 -08:00
snipe
def69b1aaa Merge branch 'develop' 2017-11-06 10:30:42 -08:00
snipe
4818e1b8ca Fixed sorting for filtered items by location 2017-11-06 10:26:09 -08:00
snipe
623f21e51f Merge branch 'develop' 2017-11-04 18:21:09 -07:00
snipe
bd524ff2f3 Removed buggy migration code switched to artisan command 2017-11-04 18:20:41 -07:00
snipe
04ab522ee3 Fixes #4236 - validate the regex custom validation (#4380)
* More helpful text on how the custom validator works

* Clarified language of custom format, fixed regex example

* Fixed regex example in placeholder

* Added comments to custom fields

* Added regex validation string

* Added valid_regex validator in format requirements

* Removed useles comments

* Fixes #4236 - validate the regex custom validation
2017-11-04 17:06:14 -07:00
snipe
f672b14468 Ignore deleted assets and check for valid location in artisan command 2017-11-04 16:20:31 -07:00
snipe
b0973de1a6 Merge branch 'develop' 2017-11-04 01:24:23 -07:00
snipe
fe06ef10f1 Set the items array variable for no results 2017-11-04 01:23:50 -07:00
snipe
14ca690441 Merge branch 'develop' 2017-11-04 01:11:41 -07:00
snipe
2de0a3669e Check that there is a valid array before unshifting 2017-11-04 01:11:11 -07:00
snipe
c7c63e8432 Merge branch 'develop' 2017-11-04 00:49:19 -07:00
snipe
adf6afbb43 Moved delay back to 250 on ajax menus 2017-11-04 00:48:54 -07:00
snipe
69b90fb65e Merge branch 'develop' 2017-11-04 00:46:22 -07:00
snipe
97ea68b15c Updated translations 2017-11-04 00:45:50 -07:00
snipe
badc763c06 Bumped version 2017-11-04 00:32:33 -07:00
snipe
b6a14d2c9c Production assets 2017-11-04 00:20:06 -07:00
snipe
d59dd0f636 Reduced rate limit from 250 to 100 2017-11-04 00:20:00 -07:00
snipe
d68d95a915 Fixed - Added a “clear selection” option to select2 ajax lists 2017-11-04 00:19:16 -07:00
snipe
15d4344efb Comments in the JS 2017-11-04 00:15:23 -07:00
snipe
dc10f18188 Merge branch 'develop' 2017-11-03 21:53:13 -07:00
snipe
2522bfee9c Only return mnon-archived assets by location 2017-11-03 21:46:11 -07:00
snipe
d7f8615964 Fixed query for location ID 2017-11-03 20:10:36 -07:00
snipe
88dff754b1 Fixed swapped asset total headings 2017-11-03 20:10:16 -07:00
snipe
ecd21074fb Commented out erroneous fixme 2017-11-03 20:10:05 -07:00
snipe
12caa48390 Uncommented info output 2017-11-03 19:42:54 -07:00
snipe
cc7be5f947 Added location to checkout in API 2017-11-03 19:42:45 -07:00
snipe
5b489e003d Set the location_id on save/update to rtd if one is given 2017-11-03 19:41:26 -07:00
snipe
8c1f4b006e Removed comment 2017-11-03 19:40:55 -07:00
snipe
3a52c19428 Updated fieldname in Locations transformer and API 2017-11-03 19:40:40 -07:00
snipe
279ad6d80a Updasted fieldname in locations table 2017-11-03 19:40:04 -07:00
snipe
b786791401 Added location to checkout method 2017-11-03 19:39:48 -07:00
snipe
1c12b6e13b Added artisan command to sync locations 2017-11-03 19:00:36 -07:00
snipe
c06539dee3 Update the location ID if there is an rtd_location given 2017-11-03 17:36:18 -07:00
snipe
3b9544d1f3 Remove commented code 2017-11-03 17:35:46 -07:00
snipe
da9bb07041 Add a default legacy cipher of rijndael-256 2017-11-03 16:27:03 -07:00
snipe
5d9b9ad590 Merge branch 'develop' 2017-11-03 15:05:07 -07:00
snipe
f95502ae35 Fixed search by model on adsvanced search for assets 2017-11-03 15:04:21 -07:00
snipe
877daba096 Merge branch 'develop' 2017-11-03 14:59:38 -07:00
snipe
b3b8ab493e Switch to the reply_to address 2017-11-03 14:58:49 -07:00
snipe
1859c8f5ab Reply to seems to be overwritten 2017-11-03 14:55:03 -07:00
snipe
87ba042b2d Fixed manager name subquery on user search
Self-joins in Laravel make baby jesus cry :(
2017-11-03 14:47:31 -07:00
snipe
6fb0ef908d Fixed issue sorting when viewing users by department 2017-11-03 14:29:04 -07:00
snipe
c4a30cc646 Merge branch 'develop' 2017-11-03 13:29:33 -07:00
snipe
cf56f70b3a Added table alias for sorting 2017-11-03 13:28:57 -07:00
snipe
f84e6a34cc Merge branch 'develop' 2017-11-03 13:04:18 -07:00
snipe
85360a7c7f Removed gates on selectlists
They can’t access the API directly unless they have been granted API accesses anyway
2017-11-03 13:03:57 -07:00
snipe
9e0b3afa91 Merge branch 'develop' 2017-11-03 12:48:17 -07:00
snipe
416455fe01 Fixes weird manager_id validation
This is a shit fix - need to find out what’s happening here.
2017-11-03 12:48:00 -07:00
snipe
53a1511cac No idea why this is needed, but… 2017-11-03 12:20:11 -07:00
snipe
733921f1f9 Added optional required parameter 2017-11-03 12:17:41 -07:00
snipe
3ecaa99990 Fixed only undeployed assets in checkout to list 2017-11-03 11:33:36 -07:00
Kasey
ab9729c39a fix to availCount() (licenseSeatRelation) (#4378)
`license_seats`.`user_id` represents an overall "owner" of the license
2017-11-03 09:51:15 -07:00
snipe
104cc2bf11 Make sure the seat hasn’t been deleted 2017-11-02 21:07:59 -07:00
snipe
1659c3f1a6 Fixed inconsistent color type on checkin/checkout 2017-11-02 20:42:07 -07:00
snipe
caa8ec3178 Fixed checkout on license view page 2017-11-02 20:23:17 -07:00
snipe
0c794c103b Return an integer value for free seats if null 2017-11-02 20:23:04 -07:00
snipe
53175d5035 Fixed sorting issue on company/manufacturer/supplier 2017-11-02 20:01:39 -07:00
snipe
0bd09f9c46 Added sorting on available and total seats 2017-11-02 19:37:30 -07:00
snipe
27d795508d Fixed n+1 query, changed checkout behavior to just ask for a license ID
We’re offloading the freeSeat() to the checkout page now
2017-11-02 19:16:09 -07:00
snipe
368ac5b85d First stab at handling the n+1 issue on licenses 2017-11-02 18:20:42 -07:00
snipe
d5635f32e5 Merge branch 'develop' 2017-11-02 17:23:14 -07:00
snipe
f47075c180 Removed depreciation from Licenses transformer 2017-11-02 17:18:53 -07:00
snipe
0a5e4b9b7b Fixed inconsistent required field indicator 2017-11-02 17:13:06 -07:00
snipe
85624205b4 Updated Lang::get to trans 2017-11-02 17:12:51 -07:00
snipe
2330e5ee57 Merge branch 'develop' 2017-11-02 16:20:48 -07:00
snipe
c9c5ce6ee0 Return Deleted User if the user is invalid for some reason 2017-11-02 16:20:01 -07:00
snipe
fc3a59d193 Merge branch 'develop' 2017-11-02 13:47:52 -07:00
snipe
950519be5d Added a few more table aliases for ordering complex results 2017-11-02 13:47:37 -07:00
snipe
e64cf8b320 Merge branch 'develop' 2017-11-02 13:01:28 -07:00
snipe
87affa40ed Fixes filtering on status label 2017-11-02 13:01:09 -07:00
snipe
513a1b1e3b Bumped version 2017-11-02 12:52:44 -07:00
snipe
cf09908c60 Merge branch 'develop' 2017-11-02 12:50:56 -07:00
snipe
d21c92f91b Changed assetloc to location 2017-11-02 12:50:34 -07:00
snipe
ffd93c59d6 Merge branch 'develop' 2017-11-02 11:26:13 -07:00
snipe
01bb4bf64a Bumped version 2017-11-02 11:24:01 -07:00
snipe
28a4293a0b Fixed #4370 - user’s listing flashing then no results 2017-11-02 11:19:34 -07:00
snipe
f095f1807c Eager load userloc 2017-11-02 11:06:15 -07:00
snipe
e08911ab8f Removed nonce for now
There is a dependency in a package where we can’t edit the script tags to add the nonce
2017-11-02 10:57:05 -07:00
snipe
ca6dc5c2b5 Eager load user location 2017-11-02 10:56:36 -07:00
snipe
27875c2dac Improved to use trans() facade instead of lang 2017-11-02 10:27:53 -07:00
snipe
6f886d3d6e Merge branch 'develop' 2017-11-02 08:44:40 -07:00
snipe
fd74e4308b Don’t show request if the user or the asset/model has been deleted 2017-11-02 08:11:04 -07:00
snipe
3695e118f4 Fixed erroneous call to assets.category in filter scope 2017-11-02 08:06:10 -07:00
snipe
f43692938b Fixed slug call in asset models image 2017-11-02 08:02:51 -07:00
snipe
6008eec205 Merge branch 'develop' 2017-11-02 04:37:27 -07:00
snipe
3343cf16dd Bumped version 2017-11-02 04:37:08 -07:00
snipe
48207fc695 Added model number in box header 2017-11-02 04:36:04 -07:00
snipe
3dae464c34 Added nicer formatting for model details 2017-11-02 04:33:53 -07:00
snipe
0c524e0830 Use model image if it’s a requestable model 2017-11-02 04:29:05 -07:00
snipe
da56a253bc Added checkout requests method 2017-11-02 04:21:57 -07:00
snipe
a844d5b018 Added pagination, nicer formatting for requested assets 2017-11-02 04:17:14 -07:00
snipe
ba9bb470eb Added imageSrc presenter to assets 2017-11-02 04:15:24 -07:00
snipe
41452450b3 Added imageSrc presenter 2017-11-02 04:15:09 -07:00
snipe
a9e5ad0df1 Added link to requested assets in sidenav 2017-11-02 03:12:12 -07:00
snipe
0e2f4f3cfb Added requested route back in 2017-11-02 03:11:09 -07:00
snipe
3bc9d3f3f1 Merge branch 'develop' 2017-11-01 23:47:36 -07:00
snipe
81ca0ac91d Added better styling for user upload 2017-11-01 23:46:21 -07:00
snipe
3ca5d39c66 Hide upload button if app is locked 2017-11-01 23:44:31 -07:00
snipe
4f008e118f Fixed search string on suppliers selectlist 2017-11-01 21:55:17 -07:00
snipe
e11f9313f0 Fixed #4360 - better output if backup fails 2017-11-01 14:12:18 -07:00
snipe
d379c6b61f Merge branch 'develop' 2017-11-01 13:28:19 -07:00
snipe
d36e8cfbd2 Dashbpoard pie fixes 2017-11-01 13:27:59 -07:00
snipe
4cdcbc97ee Fixed varname issue on old image delete for manufacturers 2017-11-01 13:10:56 -07:00
snipe
ba516ac9af Merge branch 'develop' 2017-11-01 11:11:32 -07:00
snipe
feb2f5b076 Fixed #4356 - removed reference to old assetloc 2017-10-31 18:20:03 -07:00
snipe
b5f1e10b45 Merge branch 'develop' 2017-10-31 11:50:47 -07:00
snipe
a1eac967a7 Few more migration fixes 2017-10-31 08:57:57 -07:00
snipe
6186c324b5 Misc assetLoc error checks 2017-10-31 08:47:40 -07:00
snipe
772785f9b5 Few more fixes for big ugly location migration 2017-10-31 08:39:53 -07:00
snipe
2f6c0cee59 Merge branch 'develop' 2017-10-31 07:46:36 -07:00
snipe
e56f1ee6fd Fix for anomolies where asigned_type is not null but asigned_to is 2017-10-31 07:33:43 -07:00
snipe
37868cd70e Added warranty and expiration to list view 2017-10-31 07:05:15 -07:00
snipe
32b2f77ad9 Fixed issue where we tried to call the audit log even if the asset wasn’t valid 2017-10-31 05:41:06 -07:00
snipe
472a5b9f69 Removed extra log on API asset create 2017-10-31 05:38:52 -07:00
snipe
121e158f39 Change method name from userloc to location
This needs to be changed in more places though
2017-10-31 05:22:57 -07:00
snipe
f4e7bfc28d Null custom field if field exists but is empty 2017-10-31 05:22:21 -07:00
snipe
0089f73686 Moved trait to single line 2017-10-31 05:21:55 -07:00
snipe
0f4c05c5d0 Remove commented code 2017-10-31 05:02:46 -07:00
snipe
379274deff Check for multiple variable (for bulk checkout) 2017-10-31 04:48:40 -07:00
snipe
dbf5fec7b0 Fixed language string 2017-10-31 04:48:09 -07:00
snipe
4bb546a882 Pull assigned asets preview into its own blade for re-use 2017-10-31 04:47:59 -07:00
snipe
7f1b7be416 Rolling back prepending models to sort 2017-10-30 21:26:25 -07:00
snipe
02720f225c Fixed sorting issue in asset models when ordering by manufacturer 2017-10-30 20:51:01 -07:00
snipe
e44e573a3c Fixed requestable assets reference to assetloc 2017-10-30 19:40:35 -07:00
snipe
546c3e50fa Fixed updating the assigned assets location if user’s location changes 2017-10-30 19:33:52 -07:00
snipe
7f1b962e56 Improved use of de-normed locations fields 2017-10-30 19:21:35 -07:00
snipe
4eee7f8d97 Added address for users - fixes #4323 2017-10-30 18:57:00 -07:00
snipe
0fd0e3a8b4 Returns null for order number if it’s blank 2017-10-28 15:53:22 -07:00
snipe
1076ec96be Bumped version 2017-10-28 15:46:02 -07:00
snipe
3b498efee1 Fixes indefined item in user select blade 2017-10-28 15:42:55 -07:00
snipe
9687a78981 Fixed a few inconsistencies in the API results (null vs empty string) 2017-10-28 15:17:36 -07:00
snipe
2244a4b3cf Fix peresenter for assigned 2017-10-28 15:17:09 -07:00
snipe
f3f84f1a8c Production assets 2017-10-28 11:22:38 -07:00
snipe
41994c95e0 Bumped version 2017-10-28 11:22:27 -07:00
snipe
39c68214e9 More ajax menu fixes 2017-10-28 11:17:52 -07:00
snipe
9c94e70917 Merge branch 'develop' of github.com:snipe/snipe-it into develop 2017-10-28 09:21:49 -07:00
snipe
6a3716a06d Added new ajax dropdown menus for components, consumables, etc editing/creating 2017-10-28 09:21:39 -07:00
Sorvani
feccc55c54 Added support for Fedora to the installer. (#4332) 2017-10-28 09:17:19 -07:00
snipe
fe70792cbd Bumped hash 2017-10-28 08:41:34 -07:00
snipe
95b6e0d2d8 Fixed assetloc to location 2017-10-28 08:40:27 -07:00
snipe
5d890fb139 Added more defaults for selected values 2017-10-28 08:38:19 -07:00
snipe
cd2816b1c7 Suppliers ajax menu API route 2017-10-28 08:38:00 -07:00
snipe
2172e6cc25 Added suppliers ajax list 2017-10-28 08:37:47 -07:00
snipe
04130a568c Fixes check for help_text 2017-10-28 07:41:13 -07:00
snipe
108ac79442 Added update to asset location id on checkout/checkin 2017-10-28 07:38:36 -07:00
snipe
3d7fd5cf04 Fixed references to assetLoc in hardware view 2017-10-28 07:29:32 -07:00
snipe
5737de2e22 Added help text to location partial 2017-10-28 07:29:14 -07:00
snipe
1e21cef218 Set max page size to 500 2017-10-28 07:29:03 -07:00
snipe
ad7a2da9bd Add help text that explains location override 2017-10-28 07:28:49 -07:00
snipe
bd48ae96c2 Update location on checkin if one is given 2017-10-28 07:28:35 -07:00
snipe
0f5e0dcd4f Added nobr for nicer formatting of bs tables status and deployed to 2017-10-28 07:12:47 -07:00
snipe
c37fa44f72 Use ther morphto assigned 2017-10-28 07:12:22 -07:00
snipe
daaf98783f Fixes status display in listing 2017-10-28 07:11:06 -07:00
snipe
1399ebb133 Nicer formatting on 503 2017-10-28 07:01:45 -07:00
snipe
03f6211582 Make notes null if empty 2017-10-28 07:01:06 -07:00
snipe
20bcc73000 Don’t emit to logs on this migration, otherwise we’ll flood the actionlogs 2017-10-28 06:33:15 -07:00
snipe
0058f02e82 Closure wasn’t working, go traditional 2017-10-28 06:23:04 -07:00
snipe
25b8c4438e Check for asset before attempting to cite mismatch 2017-10-28 06:20:44 -07:00
snipe
4f1747023a Seed with demo images 2017-10-28 05:46:43 -07:00
snipe
46fb5c9d40 Remove die() from migration 2017-10-28 03:54:06 -07:00
snipe
52f10232a1 Merge branch 'features/flatten-locations' into develop 2017-10-28 03:50:32 -07:00
snipe
5278dac2b0 Eager loading assignedTo - I have no idea why this works 2017-10-28 03:50:02 -07:00
snipe
890012f6c4 Update references to assetloc to location 2017-10-28 02:58:38 -07:00
snipe
3991f79115 Use new location method for hardware view 2017-10-28 02:37:59 -07:00
snipe
0a114c7daf Log instead of echoing 2017-10-28 02:32:05 -07:00
snipe
3064b3f80e Updated availableForCheckout() method to be clearer 2017-10-28 02:31:54 -07:00
snipe
df430a2263 Removed assignedTo eager load for now - it’s not working 2017-10-28 02:31:36 -07:00
snipe
277e49468b Added deleted at to API 2017-10-28 02:31:13 -07:00
snipe
f687c8db24 Fix custom field seeder to drop old columns 2017-10-28 02:11:10 -07:00
snipe
c616041876 Use form selector 2017-10-28 01:51:10 -07:00
snipe
d76f858dcd Try eager loading assignedTo 2017-10-28 01:50:58 -07:00
snipe
7a543fa6d5 Use new location method on asset API 2017-10-28 01:49:13 -07:00
snipe
49afd325a9 Add more data from seeders to check for 1001 queries 2017-10-28 01:48:50 -07:00
snipe
ce5ccc31f0 Added location method, fixed assetLoc 2017-10-28 01:48:27 -07:00
snipe
c70db75de9 Migration to add location_id de-normed data 2017-10-28 01:47:59 -07:00
snipe
7b76bbfd68 Update seeders with more locations 2017-10-28 01:03:16 -07:00
snipe
cfd1925625 Nicer display of notifications on checkout 2017-10-28 01:00:26 -07:00
snipe
e8b4bdf6f4 Added location_id to assets table to denorm 2017-10-27 20:35:34 -07:00
snipe
7e0c33d535 Speed up user factory by only bcrypting once 2017-10-27 20:35:13 -07:00
tiagom62
24211cb674 Setup firewall rules on CentOS 7. (#4329) 2017-10-27 18:27:44 -07:00
snipe
2d758be0e1 Merge branch 'develop' of github.com:snipe/snipe-it into develop 2017-10-27 18:01:46 -07:00
snipe
f49ecbdb61 Code cleanup 2017-10-27 18:01:42 -07:00
Daniel Meltzer
3cea12565b Add missing policies (#4330)
* Add Authorizable trait and interface to our user model so we have access to User::can/User::cant.  We should take a look at where else our user model has diverged from Larvel since it was created...

* Policy cleanup/fixes.

This commit adds policies for the missing backend/"settings" areas.  The
permissions were implemented a while back but the policies did not, so
authorizing actions was failing.

In addition, this condenses a lot of code in the policies into base
classes.  Most of the files were identical except for table names, so we
move all of the checks into a base class and override the table name in
each policy.

* Use a better name and permission for the check in the default layout.
2017-10-27 18:01:11 -07:00
snipe
b1ac024725 Refined upload code 2017-10-27 17:40:10 -07:00
snipe
ec68bd7842 Small refactoring for code quality 2017-10-27 17:38:11 -07:00
snipe
a224904ade Removed uncessary code
This is already handled in the env
2017-10-27 17:00:33 -07:00
snipe
cb3b294baa Clesned up status label model for code quality 2017-10-26 22:54:07 -07:00
snipe
0788347990 Cleaned up status label method 2017-10-26 22:49:57 -07:00
snipe
7496a902bd Removed unused getDataView controller method
This is all API based now
2017-10-26 22:39:41 -07:00
snipe
f2d04be8fe Remove unused methods in Settings API controller (for now) 2017-10-26 22:35:01 -07:00
snipe
f2499fc7d2 Removed else condition on custom fields API for code quality 2017-10-26 22:33:40 -07:00
snipe
00d910ddbc Added manufacturers and categories select lists 2017-10-26 22:09:08 -07:00
snipe
c6d191bcba Merge branch 'develop' of github.com:snipe/snipe-it into develop 2017-10-26 21:52:04 -07:00
snipe
f13836eb55 Use select2 partials 2017-10-26 21:52:00 -07:00
snipe
76c4c19b3e Fixed small issues with select2 partials 2017-10-26 21:51:53 -07:00
snipe
1d212b59bd Added model select2 partial 2017-10-26 21:51:27 -07:00
snipe
1174d37c20 Added model selectlist route 2017-10-26 21:51:09 -07:00
snipe
6bcb55a129 Slight tweak to model name presenter 2017-10-26 21:50:39 -07:00
snipe
a99e09e5e3 Removed extra with() calls, since we load those up via the select2 lists now 2017-10-26 21:50:27 -07:00
snipe
7d11cb0748 Added selectlist transformer for select2 API calls 2017-10-26 21:50:01 -07:00
snipe
9c29ee9c6d Fixed datepicker in asset checkout 2017-10-26 19:51:29 -07:00
snipe
bdb95e4e3d Added companies ajax select2 endpoint 2017-10-26 16:37:41 -07:00
snipe
1fa6228fb7 Add @techincolor as a contributor 2017-10-26 16:32:32 -07:00
Danielle
8b535c1806 Default DB_HOST 127.0.0.1 instead of localhost (#4324) 2017-10-26 16:30:48 -07:00
snipe
b71d0ab484 Fixed order number and warranty bug in importer 2017-10-26 16:13:35 -07:00
snipe
ea07517ad5 Added more ajax select2 boxes to checkouts, remove helper ->with() methods 2017-10-26 03:43:28 -07:00
snipe
82690e1fd7 Integrate ajax select2 menus in all asset checkouts 2017-10-26 02:28:17 -07:00
snipe
75b527ab59 Features/image uploads (#4320)
* Locations API support for image

* Added manufacturers API support for image

* Added manufacturers API support for image

* Added image support for locations add/update

* Added manufacturer image upload support to controller

* General image string

* Added blade support for image uploads/delete image

* Added $request support (from Input::)

* Added image support in API transformers

* Added image to Manufacturers presenter for data table

* Migration to create image fields

* Ignore the contents of the new image directories

* Create new image upload directories

* Created components/consumables uploads directory

* Fixed missing textSearch scope from companies

* Added ignore for companies uploads directory

* Added blade support for image upload

* Fixed path to upload directory on edit

* Added company image upport to transformers, controllers

* Added image support for categories

* Added support for images in Departments

* Added support for image in Consumables

* Added image support for components
2017-10-25 22:35:58 -07:00
snipe
b083541723 Fixed docblock copypasta 2017-10-25 20:23:59 -07:00
snipe
6dbb598616 Merge branch 'develop' 2017-10-25 20:18:24 -07:00
snipe
e8d938e188 Bumped hash 2017-10-25 20:18:06 -07:00
snipe
f7c92f61e1 Merge branch 'develop' 2017-10-25 20:16:16 -07:00
snipe
4f80eac467 Prod assets 2017-10-25 20:15:34 -07:00
snipe
0e5af78cf1 New route for menu state saving 2017-10-25 20:15:30 -07:00
snipe
0d34cc704a Added controller for state-saver for sidenav 2017-10-25 20:10:59 -07:00
snipe
d4bb4d2edd Added state-save for open/cloed sidenav 2017-10-25 20:10:41 -07:00
snipe
d008334f2d Fixed #2857 - better CSS for requestable assets page when no results 2017-10-25 20:07:10 -07:00
snipe
109ea82cb9 Merge branch 'develop' 2017-10-25 18:17:38 -07:00
snipe
e8847753f4 Fixed importer using previous row’s custom field 2017-10-25 18:16:28 -07:00
snipe
7dad71d2b6 Fixed smaller button for import/cancel 2017-10-25 18:14:22 -07:00
snipe
db5968f95a Fixed larger button size 2017-10-25 18:13:55 -07:00
snipe
d97a1edeb4 Moved style sheet call back into page content 2017-10-25 18:13:41 -07:00
snipe
3dd39a46be Fixed large font size on importer 2017-10-25 18:13:21 -07:00
snipe
dc9a908de7 Fixing laravel mix() fuckery, hopefully for the last time 2017-10-25 18:13:03 -07:00
snipe
687cf44d3d Use inline style for logo 2017-10-25 16:15:50 -07:00
snipe
e054504669 lol whoops 2017-10-25 16:08:29 -07:00
snipe
e1ad28aa20 Mix fuckery 2017-10-25 16:05:39 -07:00
snipe
87992b7f71 More mix() fuckery 2017-10-25 16:05:18 -07:00
snipe
32478f1a10 Fixed #4310 - logo not scaling correctly without text 2017-10-25 15:47:06 -07:00
snipe
abc722b9c0 Fix path to overrides 2017-10-25 15:43:57 -07:00
snipe
49ebf4a314 Removed old build dir 2017-10-25 15:04:37 -07:00
snipe
c503729a9a Removed build vue 2017-10-25 15:03:04 -07:00
snipe
0b7864b09c Fixed model number not saving in modal 2017-10-25 13:17:35 -07:00
snipe
ede16eec3c Fixed #4308 - checkin and delete from user page 2017-10-25 11:11:32 -07:00
snipe
21c1ca2336 Bumped hash 2017-10-24 19:26:21 -07:00
snipe
a305b1ea2d Merge branch 'develop' of github.com:snipe/snipe-it into develop 2017-10-24 19:24:39 -07:00
snipe
17d58d9cc5 Added snazzy rich user selection menu
TODO:
- Abstract this out so it can be used by other select2 menus
- Write a select2 transformer to standardize output
2017-10-24 19:24:35 -07:00
snipe
c605984db0 Added nicer table formatting for “assets checked out to this user” table 2017-10-24 19:21:53 -07:00
snipe
d678a0ebff Switched to using JS routes for better subdirectory support, removed debugging console logs 2017-10-24 19:20:00 -07:00
snipe
e0fe383815 Removed debug message in SaveUserRequest 2017-10-24 19:18:53 -07:00
snipe
7140efc561 Use the transformers, Luke 2017-10-24 19:18:20 -07:00
snipe
99be54fd96 Fixed success message on saving new user 2017-10-24 19:17:30 -07:00
snipe
35da7906cc Fix standardized exception formatter for correct payload 2017-10-24 17:57:49 -07:00
snipe
680ad676ca Remove debugging 2017-10-24 17:10:42 -07:00
snipe
4628c15813 Fixed typo in comments 2017-10-24 16:57:04 -07:00
snipe
8a9960f830 Fixed missing break that would override password requirement 2017-10-24 16:56:46 -07:00
snipe
2b45433255 Removed copypasta commented out seeder code 2017-10-24 16:55:59 -07:00
snipe
715da63581 Check that model name exists before trying to display it
I don’t know why this would ever trigger, but a user in Gitter complained earlier today, so… ¯\_(ツ)_/¯
2017-10-24 16:53:46 -07:00
Brady Wetherington
ad32bae62f Fix to bad relation definition in Location. (#4306) 2017-10-24 16:52:45 -07:00
snipe
bbda0dc3b4 Always return an avatar, and set a fun default 2017-10-24 13:02:30 -07:00
snipe
dc805dd9b1 Added user avatars to listing 2017-10-24 09:51:07 -07:00
snipe
167cd4e4a0 Merge branch 'develop' 2017-10-24 05:25:52 -07:00
snipe
8d68bb7a57 Sticky headers for bootstrap tables 2017-10-24 05:22:26 -07:00
snipe
7d64ab3158 Fixes #4294 - pass correct group ID for group user listings 2017-10-24 04:39:47 -07:00
snipe
a41d603e0f Merge branch 'develop' 2017-10-23 21:17:43 -07:00
snipe
c18220069d Bumped version 2017-10-23 21:17:23 -07:00
snipe
fbf516284c One more time… 2017-10-23 21:13:39 -07:00
snipe
3db25dca7a Downgrade doctrine for php5.6 2017-10-23 20:54:52 -07:00
snipe
47c7061af5 Merge branch 'develop' 2017-10-23 20:11:01 -07:00
snipe
3799ab87ed Fixed search query for default sorting 2017-10-23 20:10:37 -07:00
snipe
6232a1f941 Merge branch 'develop' 2017-10-23 19:51:29 -07:00
snipe
f5ce580593 Bumped version 2017-10-23 19:51:14 -07:00
snipe
3afa5f7cda Merge branch 'develop' 2017-10-23 19:50:09 -07:00
snipe
17b271918f Fix date picker for custom fields 2017-10-23 19:47:43 -07:00
snipe
3922569d7f Merge branch 'develop' 2017-10-23 19:14:13 -07:00
Nicolai Essig
3a302fe2d7 ref #2737 prevent assets with "rtd_location_id" null values to be removed on location sort (#4283) 2017-10-23 18:28:06 -07:00
snipe
249f86bb21 Merge branch 'develop' 2017-10-23 17:50:58 -07:00
snipe
0951a756cc Updated passport to 3.0
Re: https://stackoverflow.com/a/45029309/200021
via @robertpearce
2017-10-23 17:35:31 -07:00
snipe
fc644925ea Fixes #4291 - adds phone to user listing 2017-10-23 14:21:51 -07:00
snipe
59c0b63ad0 Merge branch 'develop' 2017-10-20 20:22:42 -07:00
snipe
c0f8b3773c Temp fix for markdown stuff 2017-10-20 20:22:14 -07:00
snipe
fd210c6439 Fixes #4267 - email notifications showing model name as number 2017-10-20 18:58:11 -07:00
snipe
f7e23cf7c8 Fixes #4272 - adds serial to assigned assets view 2017-10-20 18:51:14 -07:00
snipe
387351d7ed Merge branch 'master' of github.com:snipe/snipe-it 2017-10-20 17:44:35 -07:00
snipe
6438d30afc Merge branch 'develop' 2017-10-20 17:44:28 -07:00
snipe
b4e1d37b16 Merge branch 'develop' of github.com:snipe/snipe-it into develop 2017-10-20 17:44:04 -07:00
Brady Wetherington
8ac57d0121 Need to prefix status_id with assets. for uniqueness (#4279) 2017-10-20 17:37:46 -07:00
Kasey
d3b51715dc adding --force to php artistan snipeit:legacy-recrypt (#4232) 2017-10-20 17:21:21 -07:00
snipe
b215924b1a Merge branch 'develop' of github.com:snipe/snipe-it into develop 2017-10-20 17:18:13 -07:00
Brady Wetherington
25d3d66880 Add performance-improving indexes (#4278) 2017-10-20 17:17:11 -07:00
Brady Wetherington
189574377a Add 'where' clause to hasManyThrough relationship. (#4276) 2017-10-20 16:58:39 -07:00
snipe
341ddec9d8 Adds built-in mail notification vendor templates 2017-10-20 16:52:12 -07:00
Nicolai Essig
abcce78944 use translation for "All" in sidebar menu (#4268) 2017-10-20 00:20:33 -07:00
snipe
22e13cd4d2 Allow sorting on asset counts, disable delete button if the user has items checked out to them 2017-10-19 17:15:21 -07:00
snipe
5c105b52b6 Merge branch 'develop' 2017-10-19 16:45:22 -07:00
snipe
f757da1a98 Bumped hash 2017-10-19 16:45:04 -07:00
snipe
c1f8db37d9 Added note about saving before testing LDAP 2017-10-19 16:35:59 -07:00
snipe
cfc215a013 Merge branch 'develop' 2017-10-19 16:28:26 -07:00
snipe
4215a3257b Fixes #1044 - adds suppliers and image to accessories (#4266)
* Ignore accesories uploads

* API: Allow searching accessories by supplier id

* Adds suppliers and image upload to accessories

* Allow sorting by counts for suppliers

* Validate supplier image uploads

* Remove purchase_date from protected accessory array, it was converting it to datetime in datepicker
2017-10-19 16:25:24 -07:00
snipe
1f247ff541 Don’t let the user checkout an asset to itself
(We should consolidate that AssetCheckoutRequest for the API)
2017-10-19 15:51:55 -07:00
snipe
2fc46746e2 Adds translation string placeholders for new LDAP functionality 2017-10-19 12:22:54 -07:00
snipe
e185dc68af Fixes #4240 - allows admins to use custom password reset URL 2017-10-19 12:22:27 -07:00
snipe
54000ff69f Allows sorting by number of assets, etc in category 2017-10-19 11:48:09 -07:00
snipe
f6a38e848a Allows sorting by whether or not the category requires acceptance 2017-10-19 11:44:42 -07:00
snipe
7e8d670f81 Disable delete buttons if there are assets, etc 2017-10-19 11:41:35 -07:00
snipe
287b150b7f Show disabled delete button if thing can’t be deleted 2017-10-19 11:29:58 -07:00
snipe
b379656d55 Adds more consistent visual display of status label types 2017-10-19 11:06:55 -07:00
snipe
2e11a983c8 Nicer card display of status type explanations 2017-10-19 10:52:30 -07:00
snipe
a9753eb646 Include asset count in status labels overview 2017-10-19 10:48:15 -07:00
snipe
707c4db881 API: Check there are no assets associated before allowing delete 2017-10-19 10:39:08 -07:00
snipe
d1de34394e Removed stupid count method 2017-10-19 10:37:30 -07:00
snipe
e5719441bc Merge branch 'develop' 2017-10-19 08:36:05 -07:00
snipe
7153013fb0 Fake sending the test email if the app is in demo mode 2017-10-19 08:33:46 -07:00
snipe
55500f77fb Merge branch 'develop' 2017-10-19 08:20:44 -07:00
snipe
2b826c3adc Merge branch 'features/mail_test_button' into develop 2017-10-19 08:19:24 -07:00
snipe
cd193ce8bb Fixes #4036 - adds test email button to general settings 2017-10-19 08:18:56 -07:00
snipe
cb50142ba3 Update @thakilla as a contributor 2017-10-19 06:16:03 -07:00
snipe
81aaed92ce Change default session name 2017-10-19 06:08:58 -07:00
Nicolai Essig
4bc551db82 ref #4042 scale barcode with label size (#4258) 2017-10-19 06:08:01 -07:00
snipe
471d665408 Add @thakilla as a contributor 2017-10-19 06:07:42 -07:00
Robin Temme
068308ef56 Change changepassword menu icon to fixed width (#4262) 2017-10-19 06:04:02 -07:00
Nicolai Essig
1e65c7bf9a load custom css also on login page (#4260) 2017-10-19 06:01:41 -07:00
snipe
ae567c08db Fixes incorrect language reference for consumables on checkout if consumable doesn’t exist 2017-10-19 03:44:01 -07:00
snipe
0d25a4868a Merge branch 'develop' 2017-10-19 03:37:52 -07:00
snipe
13586be6b0 Fixed load error if license is invalid 2017-10-19 03:37:27 -07:00
snipe
44c649c3c8 Fixes #4256 - double encoding on user bulk checkin and delete blade 2017-10-19 03:17:55 -07:00
snipe
1a7bfb75fa Merge branch 'develop' 2017-10-19 02:22:39 -07:00
snipe
2b803a6a6c Fixes #4257 - use admin url when editing groups 2017-10-19 02:22:05 -07:00
snipe
92e4bdc02e Merge branch 'develop' 2017-10-19 02:09:06 -07:00
snipe
4d3d19ca2b Fixes older route reference in consumables 2017-10-19 02:07:31 -07:00
snipe
9c06912efd Small tweaks to prevent Chrome autofill 2017-10-19 01:59:13 -07:00
snipe
c5893b4445 Fixes #4249 - display deployed location in listing 2017-10-19 01:30:40 -07:00
snipe
b90933bb8b Fixes #4139 - fixed route for deleting file 2017-10-19 01:11:24 -07:00
snipe
fe9a90854d Adds d.m.Y as date format, per #2423 2017-10-18 10:30:25 -07:00
snipe
3b012f2827 Some advanced search query tweaks 2017-10-18 10:07:35 -07:00
snipe
e31dadc99a Merge branch 'develop' 2017-10-18 09:28:00 -07:00
snipe
5519e2d4ae Fixes custom fields sorting on asset listings
I need a silkwood shower :(
2017-10-18 09:27:34 -07:00
snipe
6285a8b5b2 Merge branch 'develop' 2017-10-18 08:54:35 -07:00
snipe
a3139c6fc6 Fix accessories route for invalid accessory ID 2017-10-18 08:53:25 -07:00
snipe
389ba9059f Merge branch 'develop' 2017-10-18 08:45:22 -07:00
snipe
c0e50be03e Duh. Helps if you actually assign the array first. 2017-10-18 08:45:05 -07:00
snipe
447833c996 Only try to process model bulk editing if at least one model was selected 2017-10-18 08:15:54 -07:00
snipe
809e310565 Recrypt the LDAP password properly
Older installs should add a line to their .env:

`LEGACY_CIPHER=rijndael-256`
2017-10-18 08:15:23 -07:00
snipe
38dd03b5ad Merge branch 'develop' 2017-10-18 07:16:19 -07:00
snipe
68f6385eba Fixes 500 in bulk checkout if no asset is selected 2017-10-18 07:15:16 -07:00
snipe
bd376a4992 Possible fix for #4227 2017-10-18 07:02:18 -07:00
snipe
97f65ceac0 Merge branch 'develop' 2017-10-18 06:25:01 -07:00
snipe
9e39abcc32 Merge branch 'develop' of github.com:snipe/snipe-it into develop 2017-10-18 06:24:41 -07:00
snipe
5cd2857d5d Use footer sumformatter for cost totals 2017-10-18 06:24:36 -07:00
snipe
585fcfb7d4 Use maintenances report API to populate the maintenances report 2017-10-18 05:47:47 -07:00
snipe
d9135a8aac Disallow deleting suppliers with associated assets, licenses or maintenances 2017-10-18 05:47:20 -07:00
snipe
081a64223a Add @TonisOrmisson as a contributor 2017-10-18 05:45:14 -07:00
Tõnis Ormisson
a4eeff01f0 FIXED upgrade Recrypt not working with changed cipher (#4245)
* FIX legacy cipher change

* FIX Recrypt Custom fields column names

* FIX ReCrypt Clean un-needed code
2017-10-18 05:43:54 -07:00
snipe
eedbe468ac Fix licenses not saving supplier id on edit 2017-10-18 05:43:15 -07:00
snipe
463d9513e2 Merge branch 'develop' 2017-10-18 04:49:16 -07:00
snipe
ed4aa7dec2 Account for deleted suppliers in asset maintenances report
This should all be reworked via the API though anyway
2017-10-18 04:48:52 -07:00
snipe
d6bbe15a76 Added upload state back to log test 2017-10-18 04:04:05 -07:00
snipe
ea0a0a4a69 Merge branch 'develop' 2017-10-18 02:35:43 -07:00
snipe
34442362ca Fixes bad route for new groups 2017-10-18 02:35:30 -07:00
snipe
b846bb20c6 Merge branch 'develop' 2017-10-18 01:23:01 -07:00
snipe
ab3f5f4f4d Bumped version 2017-10-18 01:21:50 -07:00
snipe
ea63ced2bd Fixes table alias bug in complex queries for Laravel 2017-10-18 01:21:08 -07:00
snipe
6bd49bfb72 Fixes #4191 - user search 2017-10-18 01:20:50 -07:00
snipe
b80d3ce50d Hopefully fixes #4218 2017-10-18 00:36:52 -07:00
snipe
c069829b33 Fixes #906 - groups view 2017-10-17 21:43:57 -07:00
Geoff Young
665a113ed8 Update account history query (#4237)
This will limit the action_log records displayed when a user is viewing
their own assets and history since both target_type and target_id must
be set for a where condition to be added to the history query.
2017-10-17 20:39:49 -07:00
snipe
aa7091d962 Fixes #4226 - adds log_max_files to app config and sample env 2017-10-17 20:04:07 -07:00
snipe
ceff6a9617 Merge branch 'develop' 2017-10-17 19:27:31 -07:00
snipe
c01850fc73 Corrected Italian to Irish in language selector 2017-10-17 19:19:46 -07:00
snipe
4c04dc7b84 Merge branch 'develop' 2017-10-17 18:55:49 -07:00
snipe
c0103cd878 Bumped version 2017-10-17 18:55:30 -07:00
snipe
1f1d9d5461 Merge branch 'develop' 2017-10-17 18:53:21 -07:00
snipe
c776fa4f7b Updated language strings 2017-10-17 18:52:20 -07:00
snipe
dc91d10395 More possible fixes for #4210 2017-10-17 17:35:48 -07:00
snipe
4df10ad26c Merge branch 'develop' 2017-10-17 17:19:15 -07:00
snipe
668a88bc86 Add autocomplete=off to settings forms for #4210 2017-10-17 17:18:17 -07:00
snipe
d6e0012818 Merge branch 'develop' 2017-10-17 17:05:38 -07:00
snipe
1d5fb52bfc Fix for LDAP where location ou is not null but blank 2017-10-17 16:59:50 -07:00
snipe
8efb02a0ee Merge branch 'develop' 2017-10-17 16:23:59 -07:00
snipe
dea42db18b Reversed order of withTrashed for deleted asset QR codes 2017-10-17 16:21:50 -07:00
snipe
78d5d3947f Merge branch 'develop' 2017-10-17 16:18:14 -07:00
snipe
a1f5e11517 Fix for broken QR code on deleted assets 2017-10-17 16:01:53 -07:00
snipe
99ad096a8a Added a space next to crowdin badge 2017-10-17 15:26:16 -07:00
snipe
65b4ffeed9 Higher res crowdin badge 2017-10-17 15:25:34 -07:00
snipe
0dac88816a Merge branch 'develop' of github.com:snipe/snipe-it into develop
# Conflicts:
#	README.md
2017-10-17 15:20:53 -07:00
snipe
f7626404b7 Add @BlueHatbRit as a contributor 2017-10-17 15:18:27 -07:00
Elliot Blackburn
78f4b08398 Change zenhub markdown shield to higher res (#4235)
The zenhub badge was fuzzy as it was a low resolution for retina display. It's now using a new shield which falls in line with some of the others (img.shield.io).
2017-10-17 15:16:49 -07:00
snipe
160fd1c86a Added setting to let admin decide whether footer text should link back to site 2017-10-17 13:54:03 -07:00
snipe
6ce01487c5 Merge branch 'develop' 2017-10-17 13:31:43 -07:00
snipe
b46cbac911 Fixes #4230 - adds model name and manufacturer to emails 2017-10-17 13:30:32 -07:00
snipe
e9c3d6bfb7 Full text search fixes - addresses laravel bug :( 2017-10-17 12:48:18 -07:00
snipe
9e9a5b7a53 Changed checkin/checkout buttons to different colors for easier visibility 2017-10-17 11:32:09 -07:00
snipe
e7fe91c9d4 Depreciation view 2017-10-17 11:20:05 -07:00
snipe
6d130326aa Merge branch 'develop' 2017-10-16 21:28:23 -07:00
snipe
02db0f9f9d Handle deleted assets in maintenance 2017-10-16 21:28:05 -07:00
snipe
e0668b7507 Handle references to suppliers that have been deleted 2017-10-16 21:19:06 -07:00
snipe
1376f246dc Merge branch 'develop' 2017-10-16 20:38:19 -07:00
snipe
113c55d905 Hopefully fixes #4150 2017-10-16 20:34:31 -07:00
snipe
9cc25bcfd0 Hopefully fixes #4150 2017-10-16 20:34:22 -07:00
snipe
81d3f78263 Production assets 2017-10-16 20:12:42 -07:00
snipe
66596b0b09 Production assets 2017-10-16 20:12:22 -07:00
snipe
7455b1019a Hacky possible fix for subdir issues 2017-10-16 20:12:11 -07:00
snipe
37df934e97 Fixes #4220 - allow nullable for completion date 2017-10-16 18:32:48 -07:00
snipe
6517a95d45 Check if there are any custom fields before trying to loop through them 2017-10-16 15:29:19 -07:00
snipe
4b84a0c916 Tidying some of the LDAP UDN logic 2017-10-16 15:29:06 -07:00
snipe
0f0a61e477 Merge branch 'develop' 2017-10-16 10:10:29 -07:00
snipe
f64382aa00 Nicer error display in LDAP tests 2017-10-16 10:10:11 -07:00
snipe
1743417ec9 Merge branch 'develop' 2017-10-16 09:38:26 -07:00
snipe
c61bed52c8 Removed danger class 2017-10-16 09:38:09 -07:00
snipe
edf75865dc Merge branch 'develop' 2017-10-16 09:27:01 -07:00
snipe
176a26e6c3 Bumped version 2017-10-16 09:26:44 -07:00
snipe
10a4d7e849 Merge branch 'develop' 2017-10-16 09:09:53 -07:00
snipe
cbe008d52f Fix assetLoc to assetloc because reasons? 2017-10-16 09:08:08 -07:00
snipe
aeb5152789 Removed extranneous class for danger text 2017-10-16 09:04:38 -07:00
snipe
938490df16 Merge branch 'develop' 2017-10-16 09:01:09 -07:00
snipe
45c2af80a3 More LDAP testing US refinements 2017-10-16 09:00:51 -07:00
snipe
892c1b04fd Merge branch 'develop' 2017-10-16 07:07:35 -07:00
snipe
1fbf3753bc More small LDAP test improvements 2017-10-16 07:07:21 -07:00
snipe
5ead5a94e3 Merge branch 'develop' 2017-10-16 06:47:01 -07:00
snipe
bcf435f625 Try for better error reporting on LDAP fail
Sorry for all the commits on this - my local LDAP isn’t working and I can’t figure out why, so no easy way to test locally
2017-10-16 06:46:33 -07:00
snipe
8638c46b1d Merge branch 'develop' 2017-10-16 06:40:15 -07:00
snipe
b107280b7b Slightly nicer UI for LDAP login test 2017-10-16 06:39:36 -07:00
snipe
1a60c20117 Merge branch 'develop' 2017-10-16 06:34:23 -07:00
snipe
f1a6926ad9 LDAP test login 2017-10-16 06:34:04 -07:00
snipe
c27a7f09bd Merge branch 'develop' 2017-10-16 05:55:27 -07:00
snipe
ba7b9d8168 Removed stray foo 2017-10-16 05:54:33 -07:00
snipe
5b070ee32f Merge branch 'develop' 2017-10-16 05:52:52 -07:00
snipe
59a126c47c Small tweaks to LDAP test 2017-10-16 05:52:18 -07:00
snipe
322e62418e Merge branch 'develop' 2017-10-16 05:23:26 -07:00
snipe
a98d94ccdc Pass token to LDAPtest 2017-10-16 05:22:37 -07:00
snipe
5addcb517f Merge branch 'develop' 2017-10-16 05:01:37 -07:00
snipe
56cbc005ae Fixes expected checkins name in console kernel 2017-10-16 05:01:15 -07:00
Daniel Meltzer
22e9246031 Fix more old routes. Should fix #4216 (#4217) 2017-10-15 23:32:40 -07:00
snipe
c0b39701cc Fixes #4170 - asset maintenance type not showing 2017-10-14 16:17:14 -07:00
madd15
e2bac62e36 Fix #4205 (#4213)
* Fixing various UI items

* Revert css change

* Dashboard icon CSS up 4px
2017-10-14 00:14:22 -07:00
snipe
c12a23b84a Merge branch 'develop' 2017-10-11 15:37:01 -07:00
snipe
fa95f6d836 Another attempt for #4165 2017-10-11 15:36:47 -07:00
snipe
280e8c7ed1 Revert "Another attempt for #4165"
This reverts commit 7617fda978.
2017-10-11 15:34:30 -07:00
snipe
7617fda978 Another attempt for #4165
(This is terrible and needs to be refactored.)
2017-10-11 15:33:53 -07:00
snipe
af69f7636b Merge branch 'develop' 2017-10-11 14:44:37 -07:00
snipe
6d4574130f Clearer indication of whether or not the user will be emailed a eula 2017-10-11 14:44:25 -07:00
snipe
485b6397d0 Possible (crummy temp) fix for #4165 2017-10-11 14:42:11 -07:00
snipe
93990327de Hopefully fixes #4163 2017-10-11 14:18:08 -07:00
madd15
4ee7765403 Change Save buttons to Checkout and add Cancel (#4202)
Bringing components and consumables checkout page inline with other
checkout pages
2017-10-11 13:29:22 -07:00
snipe
bdbad067b4 Merge branch 'develop' 2017-10-11 13:10:46 -07:00
snipe
13a716310c Bumped hash 2017-10-11 13:10:29 -07:00
snipe
d0c77c228b Merge branch 'develop' 2017-10-11 13:09:30 -07:00
snipe
36cbffa183 Fixes bug where custom fields would not store new name in custom fields table on edit 2017-10-11 13:09:10 -07:00
snipe
5edf9e143f Merge branch 'develop' 2017-10-11 12:46:42 -07:00
snipe
b6a1e0d12f Call migrate before passport install 2017-10-11 12:42:31 -07:00
snipe
2fda3a2d26 Merge branch 'develop' 2017-10-11 12:29:48 -07:00
snipe
f56eb16941 More specific order by clause for drilling down on order number 2017-10-11 12:29:08 -07:00
snipe
c15c082fb4 Merge branch 'develop' 2017-10-11 01:31:59 -07:00
snipe
64e7ab3a12 Fixes #4182 - empty names for assets when checking out to asset 2017-10-11 01:31:37 -07:00
snipe
afbd6c811b Merge branch 'develop' 2017-10-10 23:38:45 -07:00
snipe
f64c02ce12 Fix for ambiguous query on models 2017-10-10 23:12:16 -07:00
snipe
a0d8aa77d3 Merge branch 'develop' 2017-10-10 22:59:50 -07:00
snipe
bed7b29417 Fixes group search 2017-10-10 22:59:32 -07:00
tiagom62
40ed86bfe0 Sudo isnt available on every distro. (#4194) 2017-10-10 22:02:47 -07:00
snipe
33497c9811 Merge branch 'develop' 2017-10-10 12:48:05 -07:00
snipe
52a8597813 Fixes #4136 2017-10-10 12:44:28 -07:00
snipe
eeb07f73e5 Added Redis vairables to example env 2017-10-09 15:44:08 -07:00
Alex Markessinis
57422c9135 Added Redis support. (#4146)
* Fix forgotten password missing route (???)

* Fixes #4056 - check for assets before deleting user

* added predis/predis dependency to composer.json to support redis based cache/queue/session/broadcast
2017-10-09 15:39:20 -07:00
Richard Hofman
adca7cb0c5 Fix LDAP location sync issue in #3993 (#4181)
* Ensure locations with the most specific OUs take precedence during user assignment.

* Save 'ldap_ou' Location attribute during creation.
2017-10-09 13:06:47 -07:00
Richard Schwab
059f8f5bc9 Remove dead macro code (#4164)
The barcode_types macro existed twice in the code, the second occurrence overriding the first one.
This commit removes the first occurrence which is essentially dead code.
2017-10-09 13:06:05 -07:00
tiagom62
c676e9d794 Fix progress spinner. (#4178) 2017-10-09 13:04:48 -07:00
Daniel Meltzer
e9f10dd74e Maybe Fix #4052. Missed an absolute URL. (#4187) 2017-10-09 13:04:38 -07:00
snipe
e29d878d4f Remove unused method arguments 2017-10-07 15:09:50 -07:00
snipe
d4e3ea1412 Derp 2017-10-07 15:07:31 -07:00
snipe
c5462c5f1f Not sure why this isn’t working… commenting it out for now 2017-10-07 14:52:00 -07:00
snipe
d1328c3ba9 Merge branch 'develop' of github.com:snipe/snipe-it into develop 2017-10-07 14:49:54 -07:00
snipe
8c406e8e55 Additional auth policies 2017-10-07 14:49:47 -07:00
snipe
6e33f36595 Set snipe-logo as default 2017-10-07 14:49:36 -07:00
tiagom62
48277606de Support Debian 8 installs. Shellchecked. More cleanup. (#4174) 2017-10-07 12:45:25 -07:00
snipe
d7c9fcc8df Small manufacturer display tweaks on license view to make text clearer, link phone 2017-10-07 08:27:56 -07:00
snipe
508576544b Merge branch 'develop' 2017-10-07 08:17:58 -07:00
snipe
9f2fc21649 I guess we don’t need to manually create the license seats 2017-10-07 08:17:38 -07:00
snipe
11f99a963a Removed extra comma in demo warning 2017-10-07 08:03:08 -07:00
snipe
27ab0271a1 Merge branch 'develop' 2017-10-07 08:00:11 -07:00
snipe
f858b2858d Add language about the demo resetting daily to en files 2017-10-07 07:59:57 -07:00
snipe
e2809f7bd0 Merge branch 'develop' 2017-10-07 07:45:58 -07:00
snipe
f468b37f36 Bumped hash 2017-10-07 07:45:43 -07:00
snipe
0b3d3de30f Merge branch 'develop' 2017-10-07 07:44:30 -07:00
snipe
907b909223 Fixed language on settings page 2017-10-07 07:44:08 -07:00
snipe
9dc79f7165 Demo Settings reset artisan command
We’ll set this as a cron job to reset the language back to english
2017-10-07 07:43:57 -07:00
snipe
324d44dbac Small accessory factory tweaks 2017-10-07 07:24:15 -07:00
snipe
7a0e695ea0 Merge branch 'develop' 2017-10-07 07:17:05 -07:00
snipe
a69a939034 Small barcode tweaks 2017-10-07 07:15:28 -07:00
snipe
ed8efbe759 Add dateFormatter to components view 2017-10-07 06:57:02 -07:00
snipe
834c6ad8f9 Removed extra space 2017-10-07 06:56:47 -07:00
snipe
2ce48fbc7e Use components transformer in API method 2017-10-07 06:56:39 -07:00
snipe
5d18937e94 Standardized component API output 2017-10-07 06:56:18 -07:00
snipe
b3186ba5ea Removed old getDataTable methods
These are no longer used because of the API
2017-10-07 06:56:02 -07:00
snipe
f51dc9a1c4 Use recent date range for factory 2017-10-07 06:17:39 -07:00
snipe
f3f9920bd3 Added Crucial as a manufacturer in factory 2017-10-07 06:17:18 -07:00
snipe
ea6140e786 Components factory and seeder 2017-10-07 06:16:53 -07:00
snipe
05c4d6dead Make HDD into HDD/SSD for factory 2017-10-07 06:16:36 -07:00
snipe
e2c6f36c70 Use recent date range for factory 2017-10-07 06:16:21 -07:00
snipe
21b1ecb6b3 Only checkout RTD assets 2017-10-07 06:16:06 -07:00
snipe
a62cf358ee More realistic prices for factories 2017-10-07 05:52:44 -07:00
snipe
20c429b600 Add some archived and pending assets too 2017-10-07 05:52:26 -07:00
snipe
38e25a388c lol whoops 2017-10-07 05:34:13 -07:00
snipe
2c6cedd62c Removed unused factories 2017-10-07 05:32:59 -07:00
snipe
9b0cca4a37 Added licensed to name, email to licenses factory 2017-10-07 05:32:39 -07:00
snipe
f6d198a39c Added back in some unused asset stuff for tests 2017-10-07 05:32:22 -07:00
snipe
d12fc6b13c Add depreciation ID to model factories 2017-10-07 05:32:00 -07:00
snipe
a12c7c83d4 Req acceptance on laptop category 2017-10-07 05:31:46 -07:00
snipe
affd4035c3 Added displays to seeders 2017-10-07 05:31:32 -07:00
snipe
ecfe1a5442 Depreciations factory 2017-10-07 05:30:53 -07:00
snipe
e9c77198d7 Fix duplicate call to licenses seeder 2017-10-07 04:54:16 -07:00
snipe
20be670648 Fixed ids for license 2017-10-07 04:43:55 -07:00
snipe
a03207e5b4 Show license notes 2017-10-07 04:42:53 -07:00
snipe
6555b3a49d No location id in licenses? 2017-10-07 04:36:23 -07:00
snipe
61a634bc1a No idea why this worked locally before, but… 2017-10-07 04:34:51 -07:00
snipe
00696a3668 Commented out slow users factories right now - will revert when finished 2017-10-07 04:26:37 -07:00
snipe
e20271791b Removed unused factories for now
Need to add these back, once the correct logic is applied
2017-10-07 04:26:21 -07:00
snipe
86b9fdbffe License and actionlog seeder tweaks 2017-10-07 04:25:35 -07:00
snipe
7e728094a1 User seeders 2017-10-07 03:41:46 -07:00
snipe
f865c621ef Removed commented code 2017-10-07 03:41:40 -07:00
snipe
e2f4685a55 Added notes back to list view 2017-10-07 03:36:50 -07:00
snipe
2148ea94bb Additional model seeders 2017-10-07 03:19:46 -07:00
snipe
1d2787250b Reference IDs 2017-10-07 03:19:27 -07:00
snipe
7f02ff12cf Asset seeder 2017-10-07 03:19:17 -07:00
snipe
65341a5d8a Added ID reference numbers 2017-10-07 03:19:07 -07:00
snipe
1608edbb28 Added ID reference numbers 2017-10-07 03:18:57 -07:00
snipe
776da1dea4 Add Dept seeder to db seeder 2017-10-07 03:18:46 -07:00
snipe
a6b3e4bbb1 Department seeder/factory 2017-10-07 03:18:36 -07:00
snipe
3b2ecda243 Consumables factory/seeder 2017-10-07 02:46:04 -07:00
snipe
57cbb5c5ce Removed unused factories 2017-10-07 02:45:54 -07:00
snipe
7b27d32121 Added ID numbers 2017-10-07 02:45:36 -07:00
snipe
ccfba324ee Indenting 2017-10-07 02:45:28 -07:00
snipe
9f55a76fcf Added avery 2017-10-07 02:45:21 -07:00
snipe
8fdddc310f More rigid seeders for more realistic data 2017-10-07 02:27:02 -07:00
snipe
064a4ebe33 Ability to skip deleting/generating new users
This will behave unpredictably if there is not a user id 1
2017-10-07 00:02:37 -07:00
snipe
4981077cb1 Merge branch 'develop' 2017-10-06 22:59:01 -07:00
tiagom62
fbea1c0823 Code dedupe, general cleanup and added a verbose option for debugging. (#4173) 2017-10-06 22:58:41 -07:00
snipe
a84da88114 Demo seeder 2017-10-06 22:58:00 -07:00
snipe
282b3b5b0a Remove catch-all “deployed” from pie chart 2017-10-06 18:41:10 -07:00
snipe
130a99c46f Merge branch 'develop' 2017-10-06 18:15:31 -07:00
snipe
df4cb7d351 Don’t reload the page if the API returns a 500 2017-10-06 18:15:13 -07:00
snipe
1dcff8d463 Remove eager loading on pie
This was causing memory issues for large asset sets
2017-10-06 18:15:01 -07:00
snipe
ae4ba6176d Merge branch 'develop' 2017-10-06 17:04:06 -07:00
snipe
e461c25428 Apply model image fix to update method 2017-10-06 17:03:51 -07:00
snipe
ea4bfdc51d Merge branch 'develop' 2017-10-06 16:57:51 -07:00
snipe
554ea8bb95 Fixed asset model image validation 2017-10-06 16:56:43 -07:00
Richard Hofman
f2be409914 LDAP sync improvements and DB query fix. (#4148)
* Set 'ldap_ou' Location field to NULL when an empty string is submitted.

* Consolidate LDAP user import logic in LdapSync.php.
2017-10-06 16:15:14 -07:00
snipe
3fc1bbea73 Apply PR changes to master. Again? 2017-10-06 14:28:19 -07:00
snipe
a97f7d2277 Merge branch 'develop' 2017-10-06 14:27:46 -07:00
snipe
af70cdaeac Adds email address to CoC 2017-10-06 13:44:39 -07:00
snipe
8919c3b52a Merge branch 'develop'
# Conflicts:
#	snipeit.sh
2017-10-05 23:14:13 -07:00
snipe
f580e20bc3 Fixed custom fields filter for advanced search 2017-10-05 23:09:02 -07:00
snipe
a054cec7c9 Supress output if no title is given
This should never happen, but….
2017-10-05 22:51:33 -07:00
tiagom62
1ad7bbdd0c Support configuring smtp settings (#4161)
* Able to configure smtp settings. General cleanup.

* Check if sudo is available.
2017-10-05 21:27:00 -07:00
snipe
cfe6759825 Merge branch 'develop' 2017-10-05 00:41:30 -07:00
snipe
10c13baf2b Add @GeoffYoung as a contributor 2017-10-05 00:40:32 -07:00
snipe
9fe4e11874 Merge branch 'develop'
# Conflicts:
#	snipeit.sh
2017-10-05 00:37:16 -07:00
snipe
f6d8642799 Fix $search variable to $search_var for new filter 2017-10-05 00:35:37 -07:00
snipe
adddc5324b Add @imjennyli as a contributor 2017-10-05 00:34:50 -07:00
snipe
f442b70ae7 Apply PR #4133 to develop 2017-10-05 00:02:14 -07:00
madd15
7b10213b3a Small UI Tweaks to Accessories (#4149)
* Small UI Change

Changing Save button for Checkout button and adding Cancel button

* Small UI Change

Move buttons to match checkout page and remove extra save button
2017-10-04 23:28:13 -07:00
tiagom62
ddc79b9070 Support Ubuntu and Debian installs. (#4133)
* Ubuntu related fixes.

* Further cleanup.

* Support Debian 9 install. More cleanup.
2017-10-04 23:19:38 -07:00
Jenny Li
5e9b04b0f5 update broken link to contributor docs (#4123) 2017-10-04 23:19:19 -07:00
snipe
2562eb2aeb Merge branch 'develop' 2017-10-03 21:23:46 -07:00
snipe
85da30894b Bumped version 2017-10-03 21:23:27 -07:00
snipe
bf344e9322 Merge branch 'develop' 2017-10-03 21:03:19 -07:00
snipe
f66e222f3d Fixes #4132 - associated accessory users 2017-10-03 21:03:00 -07:00
snipe
fb180d74a1 Merge branch 'develop' 2017-10-03 18:12:47 -07:00
snipe
eaf55f5e79 Hide table toolbar id models are deleted 2017-10-03 18:12:30 -07:00
snipe
8edb586576 Merge branch 'develop' 2017-10-03 18:06:59 -07:00
snipe
32b01b8f38 Toggle button deleted/not for models 2017-10-03 18:06:41 -07:00
snipe
340386f282 Merge branch 'develop' 2017-10-03 17:55:21 -07:00
snipe
6dd4282f1f Fixes #4130 - show deleted asset models 2017-10-03 17:53:08 -07:00
snipe
3f44987799 Small logo size tweaks 2017-10-03 14:15:03 -07:00
snipe
b4fec068d0 Use asset url for favicon on login blade 2017-10-03 13:44:50 -07:00
snipe
512632ce60 Make the export button contextual for requested status 2017-10-03 12:50:18 -07:00
snipe
58a9b0d3e8 Normalized route name 2017-10-03 12:50:01 -07:00
snipe
fcb1283a14 Added missing deployed page title 2017-10-03 12:49:53 -07:00
snipe
54671af7f0 Small export assets fix 2017-10-03 11:49:41 -07:00
snipe
aedabb0920 Merge branch 'develop' 2017-10-03 11:29:06 -07:00
snipe
aaf4acef83 Merge branch 'develop' of github.com:snipe/snipe-it into develop 2017-10-03 11:28:45 -07:00
snipe
8e73cacf4e Fixes custom report to include assigned to names, etc 2017-10-03 10:38:28 -07:00
Daniel Meltzer
b4b2daebbd Fix Importer tests. (#4122) 2017-10-03 09:14:04 -07:00
snipe
3e2c18cb4d Merge branch 'develop' 2017-10-03 08:47:57 -07:00
snipe
c721fdd793 Merge branch 'develop' of github.com:snipe/snipe-it into develop 2017-10-03 08:46:25 -07:00
Daniel Meltzer
d119372ff0 Fix License Import. (#4121)
The license name is not unique, so keying by license alone was causing issues.  Match using name + serial instead.
2017-10-03 08:46:06 -07:00
snipe
c8bed867da Export PDF as landscape 2017-10-03 07:32:18 -07:00
snipe
3a470ce789 Only report exceptions we want to see 2017-10-03 07:28:00 -07:00
snipe
f9105719a8 Merge branch 'develop' 2017-10-03 05:16:11 -07:00
snipe
d303cbd7cb Bumped version 2017-10-03 05:15:52 -07:00
snipe
96c09e7264 Merge branch 'develop' 2017-10-03 02:05:47 -07:00
snipe
ef19bc7c16 Workaround to fix #4117
This shouldn’t be necessary, but it looks like some folks missed the migration that drops the FK for company_id
2017-10-03 02:05:22 -07:00
snipe
aa8472971d Merge branch 'develop' 2017-10-02 21:58:17 -07:00
snipe
78257d5ca6 Merge branch 'develop' 2017-10-02 21:55:25 -07:00
tiagom62
655484b1da General cleanup and get ubuntu install working. (#4118) 2017-10-02 21:37:04 -07:00
snipe
ac8185339d Removed linebreaks 2017-10-02 20:32:42 -07:00
snipe
a021ce011b Correct argv 2017-10-02 20:31:43 -07:00
snipe
3687cbfdb3 Added rollbar support 2017-10-02 20:27:45 -07:00
snipe
594135fd70 Upgrade script improvements 2017-10-02 20:11:07 -07:00
snipe
2542b9cf59 Merge branch 'develop' 2017-10-02 17:21:36 -07:00
snipe
8a7abba427 Slash url 2017-10-02 17:21:18 -07:00
snipe
3775649c8a Merge branch 'develop' 2017-10-02 17:19:59 -07:00
snipe
9df648b428 Fix Session path 2017-10-02 17:19:22 -07:00
snipe
11a1efdbbc Merge branch 'develop' 2017-10-02 16:56:12 -07:00
snipe
a65c2f305e Set polict to same-origin in example env 2017-10-02 16:47:19 -07:00
snipe
50777f5c1d Merge branch 'develop' 2017-10-02 16:39:11 -07:00
snipe
ff38cdd09b Comment out the nullable middleware until we have a chance to check all model validators 2017-10-02 16:36:43 -07:00
snipe
9420913d25 Set referrer policy to same origin - should fix a lot of weird validation redirects 2017-10-02 16:35:57 -07:00
snipe
59225701b5 Redirect to previous after login 2017-10-02 16:00:42 -07:00
snipe
6aa5d4d58c Merge branch 'develop' 2017-10-02 15:27:33 -07:00
snipe
cd2e137fcc Bumped version 2017-10-02 15:27:18 -07:00
snipe
0b968e1d6b Merge branch 'develop' 2017-10-02 13:31:08 -07:00
snipe
7a27fda083 Update example env with CSP default 2017-10-02 13:29:42 -07:00
snipe
aab635154a Default to turning CSP off until we can fix vue/CSP issues 2017-10-02 13:29:14 -07:00
snipe
e389f67629 Merge branch 'develop' 2017-10-02 13:09:17 -07:00
Geoff Young
169dc779fd Fix box title in Label settings view (#4111) 2017-10-02 13:00:32 -07:00
tiagom62
26423c5c02 Fix various installer issues. (#4096)
* Various installer fixes.

* CentOS 6 related fixes.
2017-10-02 12:59:53 -07:00
snipe
862543428b Fix named route for license checkin 2017-10-02 12:58:17 -07:00
snipe
d28e882f5d Fixed form close tag 2017-10-02 12:57:01 -07:00
snipe
e26d038589 Fixed license checkin form UI 2017-10-01 15:08:32 -07:00
snipe
afc8133acf URL nullable validation isn’t working in Laravel 5.4? 2017-10-01 14:40:13 -07:00
snipe
abe19a6311 Merge branch 'develop' of github.com:snipe/snipe-it into develop 2017-10-01 14:33:02 -07:00
snipe
07359c76ad Fixes #4094 - more nullables 2017-10-01 14:32:47 -07:00
Daniel Meltzer
a2453be573 Pass urls to passport vue components to make work in subdirectories. (#4090) 2017-10-01 13:59:07 -07:00
Daniel Meltzer
c2616412c0 Add laravel routes to javascript (#4092)
* Add laravel routes to javascript

This will clean up a lot of passing of urls.  Adds a route() helper and
everything...

This commit also moves the customfield fetching to only be fetched once
and shared with each file, rather than once for each file.

* Try to fix travis unit test things.

* Downgrade doctrine/inflector for php5

* Attempt to occasional seeder issues on travis if the asset does not generate validatable data.

* Update sql dump for functional tests.

* Try to fix api tests.
2017-10-01 12:59:55 -07:00
Daniel Meltzer
23ca2d9a0b Minor fixes (#4091)
* Fix old urls.

Still had some /admin/ urls floating around, which was causing bad
redirects in some instances.  Should fix #4085

* The modal seems to be confusing license upload. be more explicit in the route we redirect to.

* Fix #4039.  Use proper methods for location assets.

This also fixes a bunch of n+1 issues in the transformer.  Also: curious
to know what Location::assets() does, because it doesn't do what I want
it to :)
2017-10-01 12:57:04 -07:00
snipe
0bb186ad3b Prod manifest 2017-09-29 19:43:33 -07:00
snipe
b7abd8328a Prod asset build 2017-09-29 19:43:18 -07:00
snipe
ad2821b4ab Merge branch 'develop' 2017-09-29 17:57:48 -07:00
snipe
7d5b08446a Missing colon in status explanations 2017-09-29 17:52:43 -07:00
snipe
ba793355cb Nullable crap. Again. 2017-09-29 17:50:52 -07:00
Daniel Meltzer
655ca78633 Adjust the import controller to return a url to the process path to enable processing an uploaded file without refresh. (#4080) 2017-09-29 17:49:35 -07:00
snipe
f00dcb57cf Merge branch 'develop' 2017-09-29 17:39:09 -07:00
snipe
1e52fb546c Merge branch 'develop' of github.com:snipe/snipe-it into develop 2017-09-29 17:32:25 -07:00
snipe
24cad588bd Added preceding icons in polymorphic formatter 2017-09-29 17:32:16 -07:00
Daniel Meltzer
bbffde47f7 Remove conditional related to no longer existant testrun option. (#4079) 2017-09-29 17:31:39 -07:00
snipe
be7598b279 Fixes all assets showing as unassigned in license checkout 2017-09-29 17:14:38 -07:00
snipe
1a7e3fbb4b Merge branch 'develop' of github.com:snipe/snipe-it into develop 2017-09-29 17:05:32 -07:00
Daniel Meltzer
e8a0c44e93 Update some composer dependencies to try to fix everything breaking in subdirectories. Attempts to fix #4052, it seems to help here. (#4078) 2017-09-29 17:05:20 -07:00
snipe
fe644c76c5 Better explanations of how status label metas work 2017-09-29 17:03:21 -07:00
snipe
9301c56a77 Fixes #4069 - include request handler 2017-09-29 16:17:35 -07:00
snipe
e37503c734 Fixes #4075 - this is janky and should be revisited 2017-09-29 16:09:24 -07:00
snipe
6bc3f194ec Merge branch 'develop' 2017-09-29 15:59:40 -07:00
snipe
878bde67ac Few more issue template tweaks 2017-09-29 15:59:04 -07:00
snipe
314d6fa4c5 Expanded issue template 2017-09-29 15:55:58 -07:00
snipe
43ff66e4d9 More UI tweaking for meta statuses 2017-09-29 15:24:33 -07:00
snipe
2ea91266c0 Init lightbox 2017-09-29 14:26:00 -07:00
snipe
a0bd9bce39 Commented out security headers - might req apache module 2017-09-29 14:00:05 -07:00
snipe
5223ec1dbb Clearer status listing in the sidenav 2017-09-29 12:13:15 -07:00
snipe
4eda2a2f96 *ahem* 2017-09-29 12:03:12 -07:00
snipe
fe1975067a Hopefully clearer status label meta info 2017-09-29 12:03:02 -07:00
snipe
b9e79c27a8 Added nonce to basic blade 2017-09-29 05:49:26 -07:00
snipe
b8ed6a53b6 For #3998 - Added nonce to all.js 2017-09-29 04:53:24 -07:00
snipe
efd71f8bfe For #3998 - Disable CSP if debug=true
To avoid all the nonce hell from debugbar
2017-09-29 04:53:09 -07:00
snipe
05a8ba9a8e Fix weird url if license checkout fails 2017-09-29 04:37:33 -07:00
snipe
9ce2d1f560 Merge branch 'csp-middleware' into develop 2017-09-29 04:14:33 -07:00
snipe
5a1225a8bf Merge branch 'develop' 2017-09-29 03:48:37 -07:00
snipe
c6069b905b Bumped version 2017-09-29 03:47:50 -07:00
snipe
2e76620cf8 More specific required check 2017-09-29 03:44:23 -07:00
snipe
a4b30279ee Fixes #4067 - Make unrequired custom fields nullable 2017-09-29 03:30:13 -07:00
snipe
db59d4b2c4 Merge branch 'develop' 2017-09-29 02:08:06 -07:00
snipe
faf3802971 Fixes #4011 - do not send email to user on license checkout 2017-09-29 02:00:49 -07:00
snipe
7fe2a1f802 Fixes #4051 - use delete method for deleting user files 2017-09-29 01:48:16 -07:00
snipe
3d57d1bd1d Merge branch 'develop' 2017-09-29 01:30:30 -07:00
snipe
ba8bcce8eb Hopefully fixes #4020 2017-09-29 01:21:08 -07:00
snipe
8247a73182 Merge branch 'develop' 2017-09-28 22:22:37 -07:00
snipe
aab409dec2 Fixes #4061 - bulk checkout error 2017-09-28 22:22:21 -07:00
snipe
70a9b7bf05 Merge branch 'develop' 2017-09-28 21:21:01 -07:00
snipe
d9824a0454 Bumped version 2017-09-28 21:20:37 -07:00
snipe
e759a249bd Merge branch 'develop' 2017-09-28 21:18:39 -07:00
snipe
42c2a66946 Small UI tweaks for accessories 2017-09-28 21:18:16 -07:00
snipe
4d32f2b337 Fixes #4059 - accessories view 2017-09-28 21:18:00 -07:00
snipe
0e29744ec2 Don’t try to send an email if the user doesn’t have an email address 2017-09-28 20:57:33 -07:00
snipe
51236a2ad9 Fixes #4056 - check for assets before deleting user 2017-09-28 19:57:52 -07:00
snipe
9b6726a630 Fixes #4056 - check for assets before deleting user 2017-09-28 19:57:03 -07:00
snipe
cbdd05144a Merge branch 'develop' 2017-09-28 19:50:34 -07:00
snipe
46d87849f4 Added content security middleware 2017-09-28 19:45:15 -07:00
snipe
507f1f196c Added integrity hashes 2017-09-28 18:46:16 -07:00
snipe
b60febeea2 Removed space in XSS header because safari was getting angry 2017-09-28 18:45:54 -07:00
snipe
b3e0d8f675 Disallow / in robots 2017-09-28 17:47:48 -07:00
snipe
9b84a0d516 *eyeroll* 2017-09-28 17:34:47 -07:00
snipe
adac5ac544 Check for valid asset 2017-09-28 17:32:37 -07:00
snipe
1775995f26 Is this space necessary? Getting weird results from netsparker 2017-09-28 17:25:04 -07:00
snipe
df4700b411 Merge branch 'develop' 2017-09-28 17:17:03 -07:00
snipe
26a7701cda Added referrer-policy header 2017-09-28 17:12:58 -07:00
snipe
a34085f1d9 Added mode=block to XSSProtect header 2017-09-28 16:28:27 -07:00
snipe
8e682c715e Merge branch 'develop' 2017-09-28 16:07:04 -07:00
snipe
915c19ebda Merge branch 'develop' of github.com:snipe/snipe-it into develop 2017-09-28 16:03:41 -07:00
snipe
7fded367c4 Adds rel="noopener" to footer links 2017-09-28 16:03:36 -07:00
Daniel Meltzer
0a4743210c Pass urls to vue. Should fix subdirectory issues. (#4054) 2017-09-28 16:03:04 -07:00
Daniel Meltzer
af19e5d976 Fix old route (#4053)
Looks like we missed in the v4 port.  Fixes the unrelated issue in #4052
2017-09-28 16:02:50 -07:00
snipe
3d7277398c Fixes #4057 - sig file in lightbox 2017-09-28 15:13:05 -07:00
snipe
a7ad48a02a Make fields nullable for licenses 2017-09-27 22:11:20 -07:00
snipe
469a3fc608 Merge branch 'develop' 2017-09-27 17:48:32 -07:00
snipe
0fb4ff77f4 Restoring older SnipeModel attribute setters
In case needed by API - needs investigation
2017-09-27 16:39:20 -07:00
snipe
ac83dba2bb Fixes #4034 - save login note 2017-09-27 16:35:54 -07:00
snipe
979ecf961d Added back button to oauth page 2017-09-27 16:33:51 -07:00
snipe
13dcdf41b8 Fixes #4045 - missing back button 2017-09-27 16:32:37 -07:00
snipe
fc96fa756e Fix redirect default on password reset 2017-09-27 16:23:21 -07:00
snipe
ea9a502152 Added empty regsitration controller
When using the default Laravel auth routes, it expects a registration controller, even though we don’t have a concept of registration. This blank controller just prevents route caching from throwing errors.
2017-09-27 16:23:01 -07:00
snipe
d844734b6c Use named login route 2017-09-27 16:22:02 -07:00
snipe
ec8a3d2e56 Fixes #4027 - proper redirect on fieldset delete 2017-09-27 16:02:29 -07:00
snipe
5410dc4255 Fixed link to contributing docs in readme 2017-09-27 15:30:20 -07:00
snipe
d1112bbc99 Fix created_at date display for groups index 2017-09-27 15:28:02 -07:00
snipe
ecf041fa10 Fixes #4043 - standardize groups API response 2017-09-27 15:18:29 -07:00
snipe
0ab9bc1db8 Added normalization midddleware, removed 2017-09-27 15:18:05 -07:00
snipe
73e788b94b Make min_amt fillable 2017-09-27 14:50:56 -07:00
snipe
e91a537552 Use more modern Request handler 2017-09-27 14:50:48 -07:00
snipe
ef8c1abf28 Fixes #3113 and #4040 2017-09-27 14:50:17 -07:00
snipe
bd0498aa69 Fixes #4016 - signature file missing from history tab 2017-09-27 12:58:08 -07:00
snipe
ea45033588 Merge branch 'develop' 2017-09-26 16:03:09 -07:00
snipe
5e1df7049c Make collation and charset for mysql an env variable 2017-09-26 16:02:55 -07:00
snipe
e27e1a78c3 Fix for case where a fieldset is assigned to a model, but no fields are assigned 2017-09-26 16:01:23 -07:00
snipe
d585a34a26 Prevent users from running this as root/admin user 2017-09-26 13:11:01 -07:00
snipe
4edaba648e Tweaks to upgrade script 2017-09-26 13:05:34 -07:00
snipe
9dca7396f3 Merge branch 'develop' 2017-09-26 11:12:55 -07:00
snipe
4324242475 Bumped version 2017-09-26 11:12:36 -07:00
snipe
eca5a05335 Fix forgotten password missing route (???) 2017-09-26 11:08:47 -07:00
snipe
aa4d3c3ffb Fix forgotten password missing route (???) 2017-09-26 11:07:47 -07:00
4902 changed files with 52813 additions and 489141 deletions

View File

@@ -755,6 +755,134 @@
"contributions": [
"code"
]
},
{
"login": "imjennyli",
"name": "Jenny Li",
"avatar_url": "https://avatars3.githubusercontent.com/u/404729?v=4",
"profile": "https://github.com/imjennyli",
"contributions": [
"doc"
]
},
{
"login": "GeoffYoung",
"name": "Geoff Young",
"avatar_url": "https://avatars0.githubusercontent.com/u/869227?v=4",
"profile": "https://github.com/GeoffYoung",
"contributions": [
"code"
]
},
{
"login": "BlueHatbRit",
"name": "Elliot Blackburn",
"avatar_url": "https://avatars3.githubusercontent.com/u/1068477?v=4",
"profile": "http://www.elliotblackburn.com",
"contributions": [
"doc"
]
},
{
"login": "TonisOrmisson",
"name": "Tõnis Ormisson",
"avatar_url": "https://avatars1.githubusercontent.com/u/6357451?v=4",
"profile": "http://andmemasin.eu",
"contributions": [
"code"
]
},
{
"login": "thakilla",
"name": "Nicolai Essig",
"avatar_url": "https://avatars0.githubusercontent.com/u/449411?v=4",
"profile": "http://www.nicolai-essig.de",
"contributions": [
"code"
]
},
{
"login": "techincolor",
"name": "Danielle",
"avatar_url": "https://avatars1.githubusercontent.com/u/14809698?v=4",
"profile": "https://github.com/techincolor",
"contributions": [
"doc"
]
},
{
"login": "TheVakman",
"name": "Lawrence",
"avatar_url": "https://avatars1.githubusercontent.com/u/18545156?v=4",
"profile": "https://github.com/TheVakman",
"contributions": [
"test",
"bug"
]
},
{
"login": "uknzaeinozpas",
"name": "uknzaeinozpas",
"avatar_url": "https://avatars1.githubusercontent.com/u/22473767?v=4",
"profile": "https://github.com/uknzaeinozpas",
"contributions": [
"test",
"code"
]
},
{
"login": "Gelob",
"name": "Ryan",
"avatar_url": "https://avatars3.githubusercontent.com/u/422752?v=4",
"profile": "https://github.com/Gelob",
"contributions": [
"doc"
]
},
{
"login": "vcordes79",
"name": "vcordes79",
"avatar_url": "https://avatars1.githubusercontent.com/u/10672546?v=4",
"profile": "https://github.com/vcordes79",
"contributions": [
"code"
]
},
{
"login": "fordster78",
"name": "fordster78",
"avatar_url": "https://avatars3.githubusercontent.com/u/27958330?v=4",
"profile": "https://github.com/fordster78",
"contributions": [
"code"
]
},
{
"login": "CronKz",
"name": "CronKz",
"avatar_url": "https://avatars0.githubusercontent.com/u/34064225?v=4",
"profile": "https://github.com/CronKz",
"contributions": [
"code"
]
},
{
"login": "tdb",
"name": "Tim Bishop",
"avatar_url": "https://avatars1.githubusercontent.com/u/585486?v=4",
"profile": "https://github.com/tdb",
"contributions": [
"code"
]
},
{
"login": "seanmcilvenna",
"name": "Sean McIlvenna",
"avatar_url": "https://avatars2.githubusercontent.com/u/5384694?v=4",
"profile": "https://www.seanmcilvenna.com",
"contributions": [
"code"
]
}
]
}

View File

@@ -8,17 +8,18 @@ APP_URL=null
APP_TIMEZONE='UTC'
APP_LOCALE=en
# --------------------------------------------
# REQUIRED: DATABASE SETTINGS
# --------------------------------------------
DB_CONNECTION=mysql
DB_HOST=localhost
DB_HOST=127.0.0.1
DB_DATABASE=null
DB_USERNAME=null
DB_PASSWORD=null
DB_PREFIX=null
DB_DUMP_PATH='/usr/bin'
DB_CHARSET=utf8mb4
DB_COLLATION=utf8mb4_unicode_ci
# --------------------------------------------
# OPTIONAL: SSL DATABASE SETTINGS
@@ -29,7 +30,6 @@ DB_SSL_CERT_PATH=null
DB_SSL_CA_PATH=null
DB_SSL_CIPHER=null
# --------------------------------------------
# REQUIRED: OUTGOING MAIL SERVER SETTINGS
# --------------------------------------------
@@ -44,14 +44,12 @@ MAIL_FROM_NAME='Snipe-IT'
MAIL_REPLYTO_ADDR=you@example.com
MAIL_REPLYTO_NAME='Snipe-IT'
# --------------------------------------------
# REQUIRED: IMAGE LIBRARY
# This should be gd or imagick
# --------------------------------------------
IMAGE_LIB=gd
# --------------------------------------------
# OPTIONAL: SESSION SETTINGS
# --------------------------------------------
@@ -62,6 +60,11 @@ COOKIE_NAME=snipeit_session
COOKIE_DOMAIN=null
SECURE_COOKIES=false
# --------------------------------------------
# OPTIONAL: SECURITY HEADER SETTINGS
# --------------------------------------------
REFERRER_POLICY=same-origin
ENABLE_CSP=false
# --------------------------------------------
# OPTIONAL: CACHE SETTINGS
@@ -70,6 +73,12 @@ CACHE_DRIVER=file
SESSION_DRIVER=file
QUEUE_DRIVER=sync
# --------------------------------------------
# OPTIONAL: REDIS SETTINGS
# --------------------------------------------
REDIS_HOST=null
REDIS_PASSWORD=null
REDIS_PORT-null
# --------------------------------------------
# OPTIONAL: AWS S3 SETTINGS
@@ -89,8 +98,10 @@ LOGIN_LOCKOUT_DURATION=60
# OPTIONAL: MISC
# --------------------------------------------
APP_LOG=single
APP_LOG_MAX_FILES=10
APP_LOCKED=false
FILESYSTEM_DISK=local
APP_TRUSTED_PROXIES=192.168.1.1,10.0.0.1
ALLOW_IFRAMING=false
APP_CIPHER=AES-256-CBC
GOOGLE_MAPS_API=

View File

@@ -12,20 +12,27 @@
#### Please confirm you have done the following before posting your bug report:
- [ ] I have enabled debug mode
- [ ] I have enabled debug mode
- [ ] I have read [checked the Common Issues page](https://snipe-it.readme.io/docs/common-issues)
-----
#### Please provide answers to these questions before posting your bug report:
#### Provide answers to these questions:
- Is this a fresh install or an upgrade?
- Version of Snipe-IT you're running
- Version of PHP you're running
- Version of MySQL/MariaDB you're running
- What OS and web server you're running Snipe-IT on
- What method you used to install Snipe-IT (install.sh, manual installation, docker, etc)
- WITH DEBUG TURNED ON, if you're getting an error in your browser, include that error
- What specific Snipe-IT page you're on, and what specific element you're interacting with to trigger the error
- If a stacktrace is provided in the error, include that too.
- Any errors that appear in your browser's error console.
- Confirm whether the error is [reproduceable on the demo](https://snipeitapp.com/demo).
- Include any additional information you can find in `app/storage/logs` and your webserver's logs.
- Confirm whether the error is reproducible on the demo: https://snipeitapp.com/demo.
- Include any additional information you can find in `storage/logs` and your webserver's logs.
- Include what you've done so far in the installation, and if you got any error messages along the way.
- Indicate whether or not you've manually edited any data directly in the database
Please do not post an issue without answering the related questions above. If you have opened a different issue and already answered these questions, answer them again, once for every ticket. It will be next to impossible for us to help you.
https://snipe-it.readme.io/docs/getting-help

19
.github/stale.yml vendored Normal file
View File

@@ -0,0 +1,19 @@
# Number of days of inactivity before an issue becomes stale
daysUntilStale: 60
# Number of days of inactivity before a stale issue is closed
daysUntilClose: 7
# Issues with these labels will never be considered stale
exemptLabels:
- pinned
- security
- ready for dev
- bounty
# Label to use when marking an issue as stale
staleLabel: stale
# Comment to post when marking an issue as stale. Set to `false` to disable
markComment: >
This issue has been automatically marked as stale because it has not had
recent activity. It will be closed if no further activity occurs. Thank you
for your contributions!
# Comment to post when closing a stale issue. Set to `false` to disable
closeComment: false

8
.gitignore vendored
View File

@@ -27,8 +27,16 @@ public/uploads/logo.png
public/uploads/logo.svg
public/uploads/models/*
public/uploads/suppliers/*
public/uploads/accessories/*
public/uploads/locations/*
public/uploads/manufacturers/*
public/uploads/components/*
public/uploads/consumables/*
public/uploads/companies/*
public/uploads/categories/*
public/uploads/users/*
storage/app/private_uploads/users/*
public/uploads/departments/*
storage/debugbar/
storage/dumps/*
storage/laravel-backups

View File

@@ -13,6 +13,8 @@ services:
php:
- 5.6
- 7.0
- 7.2
- 7.1.4
# execute any number of scripts before the test run, custom env's are available as variables
before_script:
@@ -43,7 +45,7 @@ before_script:
# use the $DB env variable to determine the phpunit.xml to use
# script: ./vendor/bin/codecept run --env testing-ci
script:
- ./vendor/bin/codecept run unit --env testing-ci
- ./vendor/bin/codecept run unit
# - ./vendor/bin/codecept run acceptance --env=testing-ci
- ./vendor/bin/codecept run functional --env=functional-travis
#script: ./vendor/bin/codecept run

View File

@@ -55,7 +55,7 @@ further defined and clarified by project maintainers.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported by contacting the project team at [INSERT EMAIL ADDRESS]. All
reported by contacting the project team at abuse@snipeitapp.com. All
complaints will be reviewed and investigated and will result in a response that
is deemed necessary and appropriate to the circumstances. The project team is
obligated to maintain confidentiality with regard to the reporter of an incident.

View File

@@ -1,6 +1,6 @@
### Contributing
Please see the documentation on [contributing and developing for Snipe-IT](https://snipe-it.readme.io/docs/contributing).
Please see the documentation on [contributing and developing for Snipe-IT](https://snipe-it.readme.io/docs/contributing-overview).
Please note that this project is released with a [Contributor Code of Conduct](CODE_OF_CONDUCT.md). By participating in this project you agree to abide by its terms.

View File

@@ -1,5 +1,6 @@
[![Build Status](https://travis-ci.org/snipe/snipe-it.svg?branch=develop)](https://travis-ci.org/snipe/snipe-it) [![Stories in Ready](https://badge.waffle.io/snipe/snipe-it.png?label=ready+for+dev&title=Ready+for+development)](http://waffle.io/snipe/snipe-it) [![Maintenance](https://img.shields.io/maintenance/yes/2017.svg)]() [![Crowdin](https://d322cqt584bo4o.cloudfront.net/snipe-it/localized.png)](https://crowdin.com/project/snipe-it) [![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/snipe/snipe-it?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) [![Docker Pulls](https://img.shields.io/docker/pulls/snipe/snipe-it.svg)](https://hub.docker.com/r/snipe/snipe-it/) [![Twitter Follow](https://img.shields.io/twitter/follow/snipeyhead.svg?style=social)](https://twitter.com/snipeyhead) [![Zenhub](https://raw.githubusercontent.com/ZenHubIO/support/master/zenhub-badge.png)](https://zenhub.io) [![Codacy Badge](https://api.codacy.com/project/badge/Grade/553ce52037fc43ea99149785afcfe641)](https://www.codacy.com/app/snipe/snipe-it?utm_source=github.com&utm_medium=referral&utm_content=snipe/snipe-it&utm_campaign=Badge_Grade)
[![All Contributors](https://img.shields.io/badge/all_contributors-81-orange.svg?style=flat-square)](#contributors)
[![Build Status](https://travis-ci.org/snipe/snipe-it.svg?branch=master)](https://travis-ci.org/snipe/snipe-it) [![Crowdin](https://d322cqt584bo4o.cloudfront.net/snipe-it/localized.svg)](https://crowdin.com/project/snipe-it) [![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/snipe/snipe-it?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) [![Docker Pulls](https://img.shields.io/docker/pulls/snipe/snipe-it.svg)](https://hub.docker.com/r/snipe/snipe-it/) [![Twitter Follow](https://img.shields.io/twitter/follow/snipeyhead.svg?style=social)](https://twitter.com/snipeyhead) [![Codacy Badge](https://api.codacy.com/project/badge/Grade/553ce52037fc43ea99149785afcfe641)](https://www.codacy.com/app/snipe/snipe-it?utm_source=github.com&utm_medium=referral&utm_content=snipe/snipe-it&utm_campaign=Badge_Grade)
[![All Contributors](https://img.shields.io/badge/all_contributors-94-orange.svg?style=flat-square)](#contributors)
[![Open Source Helpers](https://www.codetriage.com/snipe/snipe-it/badges/users.svg)](https://www.codetriage.com/snipe/snipe-it)
## Snipe-IT - Open Source Asset Management System
@@ -67,7 +68,9 @@ Thanks goes to all of these wonderful people ([emoji key](https://github.com/ken
| [<img src="https://avatars0.githubusercontent.com/u/8341172?v=3" width="110px;"/><br /><sub>Jay Richards</sub>](http://www.cordeos.com)<br />[💻](https://github.com/snipe/snipe-it/commits?author=technogenus "Code") | [<img src="https://avatars2.githubusercontent.com/u/7295127?v=3" width="110px;"/><br /><sub>Alexander Innes</sub>](https://necurity.co.uk)<br />[💻](https://github.com/snipe/snipe-it/commits?author=leostat "Code") | [<img src="https://avatars2.githubusercontent.com/u/334485?v=3" width="110px;"/><br /><sub>Danny Garcia</sub>](https://buzzedword.codes)<br />[💻](https://github.com/snipe/snipe-it/commits?author=buzzedword "Code") | [<img src="https://avatars2.githubusercontent.com/u/366855?v=3" width="110px;"/><br /><sub>archpoint</sub>](https://github.com/archpoint)<br />[💻](https://github.com/snipe/snipe-it/commits?author=archpoint "Code") | [<img src="https://avatars1.githubusercontent.com/u/67991?v=3" width="110px;"/><br /><sub>Jake McGraw</sub>](http://www.jakemcgraw.com)<br />[💻](https://github.com/snipe/snipe-it/commits?author=jakemcgraw "Code") | [<img src="https://avatars1.githubusercontent.com/u/1714374?v=3" width="110px;"/><br /><sub>FleischKarussel</sub>](https://github.com/FleischKarussel)<br />[📖](https://github.com/snipe/snipe-it/commits?author=FleischKarussel "Documentation") | [<img src="https://avatars3.githubusercontent.com/u/319644?v=3" width="110px;"/><br /><sub>Dylan Yi</sub>](https://github.com/feeva)<br />[💻](https://github.com/snipe/snipe-it/commits?author=feeva "Code") |
| [<img src="https://avatars2.githubusercontent.com/u/857740?v=3" width="110px;"/><br /><sub>Gil Rutkowski</sub>](http://FlashingCursor.com)<br />[💻](https://github.com/snipe/snipe-it/commits?author=flashingcursor "Code") | [<img src="https://avatars3.githubusercontent.com/u/129360?v=3" width="110px;"/><br /><sub>Desmond Morris</sub>](http://www.desmondmorris.com)<br />[💻](https://github.com/snipe/snipe-it/commits?author=desmondmorris "Code") | [<img src="https://avatars2.githubusercontent.com/u/52936?v=3" width="110px;"/><br /><sub>Nick Peelman</sub>](http://peelman.us)<br />[💻](https://github.com/snipe/snipe-it/commits?author=peelman "Code") | [<img src="https://avatars0.githubusercontent.com/u/53161?v=3" width="110px;"/><br /><sub>Abraham Vegh</sub>](https://abrahamvegh.com)<br />[💻](https://github.com/snipe/snipe-it/commits?author=abrahamvegh "Code") | [<img src="https://avatars0.githubusercontent.com/u/2818680?v=3" width="110px;"/><br /><sub>Mohamed Rashid</sub>](https://github.com/rashivkp)<br />[📖](https://github.com/snipe/snipe-it/commits?author=rashivkp "Documentation") | [<img src="https://avatars3.githubusercontent.com/u/1509456?v=3" width="110px;"/><br /><sub>Kasey</sub>](http://hinchk.github.io)<br />[💻](https://github.com/snipe/snipe-it/commits?author=HinchK "Code") | [<img src="https://avatars2.githubusercontent.com/u/10522541?v=3" width="110px;"/><br /><sub>Brett</sub>](https://github.com/BrettFagerlund)<br />[⚠️](https://github.com/snipe/snipe-it/commits?author=BrettFagerlund "Tests") |
| [<img src="https://avatars2.githubusercontent.com/u/16108587?v=3" width="110px;"/><br /><sub>Jason Spriggs</sub>](http://jasonspriggs.com)<br />[💻](https://github.com/snipe/snipe-it/commits?author=jasonspriggs "Code") | [<img src="https://avatars2.githubusercontent.com/u/1134568?v=3" width="110px;"/><br /><sub>Nate Felton</sub>](http://n8felton.wordpress.com)<br />[💻](https://github.com/snipe/snipe-it/commits?author=n8felton "Code") | [<img src="https://avatars2.githubusercontent.com/u/14036694?v=3" width="110px;"/><br /><sub>Manasses Ferreira</sub>](http://homepages.dcc.ufmg.br/~manassesferreira)<br />[💻](https://github.com/snipe/snipe-it/commits?author=manassesferreira "Code") | [<img src="https://avatars0.githubusercontent.com/u/15913949?v=3" width="110px;"/><br /><sub>Steve</sub>](https://github.com/steveelwood)<br />[⚠️](https://github.com/snipe/snipe-it/commits?author=steveelwood "Tests") | [<img src="https://avatars1.githubusercontent.com/u/3361683?v=3" width="110px;"/><br /><sub>matc</sub>](http://twitter.com/matc)<br />[⚠️](https://github.com/snipe/snipe-it/commits?author=matc "Tests") | [<img src="https://avatars3.githubusercontent.com/u/7405702?v=3" width="110px;"/><br /><sub>Cole R. Davis</sub>](http://www.davisracingteam.com)<br />[⚠️](https://github.com/snipe/snipe-it/commits?author=VanillaNinjaD "Tests") | [<img src="https://avatars2.githubusercontent.com/u/10167681?v=3" width="110px;"/><br /><sub>gibsonjoshua55</sub>](https://github.com/gibsonjoshua55)<br />[💻](https://github.com/snipe/snipe-it/commits?author=gibsonjoshua55 "Code") |
| [<img src="https://avatars2.githubusercontent.com/u/2809241?v=4" width="110px;"/><br /><sub>Robin Temme</sub>](https://github.com/zwerch)<br />[💻](https://github.com/snipe/snipe-it/commits?author=zwerch "Code") | [<img src="https://avatars0.githubusercontent.com/u/6961695?v=4" width="110px;"/><br /><sub>Iman</sub>](https://github.com/imanghafoori1)<br />[💻](https://github.com/snipe/snipe-it/commits?author=imanghafoori1 "Code") | [<img src="https://avatars1.githubusercontent.com/u/6551003?v=4" width="110px;"/><br /><sub>Richard Hofman</sub>](https://github.com/richardhofman6)<br />[💻](https://github.com/snipe/snipe-it/commits?author=richardhofman6 "Code") | [<img src="https://avatars0.githubusercontent.com/u/3697569?v=4" width="110px;"/><br /><sub>gizzmojr</sub>](https://github.com/gizzmojr)<br />[💻](https://github.com/snipe/snipe-it/commits?author=gizzmojr "Code") |
| [<img src="https://avatars2.githubusercontent.com/u/2809241?v=4" width="110px;"/><br /><sub>Robin Temme</sub>](https://github.com/zwerch)<br />[💻](https://github.com/snipe/snipe-it/commits?author=zwerch "Code") | [<img src="https://avatars0.githubusercontent.com/u/6961695?v=4" width="110px;"/><br /><sub>Iman</sub>](https://github.com/imanghafoori1)<br />[💻](https://github.com/snipe/snipe-it/commits?author=imanghafoori1 "Code") | [<img src="https://avatars1.githubusercontent.com/u/6551003?v=4" width="110px;"/><br /><sub>Richard Hofman</sub>](https://github.com/richardhofman6)<br />[💻](https://github.com/snipe/snipe-it/commits?author=richardhofman6 "Code") | [<img src="https://avatars0.githubusercontent.com/u/3697569?v=4" width="110px;"/><br /><sub>gizzmojr</sub>](https://github.com/gizzmojr)<br />[💻](https://github.com/snipe/snipe-it/commits?author=gizzmojr "Code") | [<img src="https://avatars3.githubusercontent.com/u/404729?v=4" width="110px;"/><br /><sub>Jenny Li</sub>](https://github.com/imjennyli)<br />[📖](https://github.com/snipe/snipe-it/commits?author=imjennyli "Documentation") | [<img src="https://avatars0.githubusercontent.com/u/869227?v=4" width="110px;"/><br /><sub>Geoff Young</sub>](https://github.com/GeoffYoung)<br />[💻](https://github.com/snipe/snipe-it/commits?author=GeoffYoung "Code") | [<img src="https://avatars3.githubusercontent.com/u/1068477?v=4" width="110px;"/><br /><sub>Elliot Blackburn</sub>](http://www.elliotblackburn.com)<br />[📖](https://github.com/snipe/snipe-it/commits?author=BlueHatbRit "Documentation") |
| [<img src="https://avatars1.githubusercontent.com/u/6357451?v=4" width="110px;"/><br /><sub>Tõnis Ormisson</sub>](http://andmemasin.eu)<br />[💻](https://github.com/snipe/snipe-it/commits?author=TonisOrmisson "Code") | [<img src="https://avatars0.githubusercontent.com/u/449411?v=4" width="110px;"/><br /><sub>Nicolai Essig</sub>](http://www.nicolai-essig.de)<br />[💻](https://github.com/snipe/snipe-it/commits?author=thakilla "Code") | [<img src="https://avatars1.githubusercontent.com/u/14809698?v=4" width="110px;"/><br /><sub>Danielle</sub>](https://github.com/techincolor)<br />[📖](https://github.com/snipe/snipe-it/commits?author=techincolor "Documentation") | [<img src="https://avatars1.githubusercontent.com/u/18545156?v=4" width="110px;"/><br /><sub>Lawrence</sub>](https://github.com/TheVakman)<br />[⚠️](https://github.com/snipe/snipe-it/commits?author=TheVakman "Tests") [🐛](https://github.com/snipe/snipe-it/issues?q=author%3ATheVakman "Bug reports") | [<img src="https://avatars1.githubusercontent.com/u/22473767?v=4" width="110px;"/><br /><sub>uknzaeinozpas</sub>](https://github.com/uknzaeinozpas)<br />[⚠️](https://github.com/snipe/snipe-it/commits?author=uknzaeinozpas "Tests") [💻](https://github.com/snipe/snipe-it/commits?author=uknzaeinozpas "Code") | [<img src="https://avatars3.githubusercontent.com/u/422752?v=4" width="110px;"/><br /><sub>Ryan</sub>](https://github.com/Gelob)<br />[📖](https://github.com/snipe/snipe-it/commits?author=Gelob "Documentation") | [<img src="https://avatars1.githubusercontent.com/u/10672546?v=4" width="110px;"/><br /><sub>vcordes79</sub>](https://github.com/vcordes79)<br />[💻](https://github.com/snipe/snipe-it/commits?author=vcordes79 "Code") |
| [<img src="https://avatars3.githubusercontent.com/u/27958330?v=4" width="110px;"/><br /><sub>fordster78</sub>](https://github.com/fordster78)<br />[💻](https://github.com/snipe/snipe-it/commits?author=fordster78 "Code") | [<img src="https://avatars0.githubusercontent.com/u/34064225?v=4" width="110px;"/><br /><sub>CronKz</sub>](https://github.com/CronKz)<br />[💻](https://github.com/snipe/snipe-it/commits?author=CronKz "Code") | [<img src="https://avatars1.githubusercontent.com/u/585486?v=4" width="110px;"/><br /><sub>Tim Bishop</sub>](https://github.com/tdb)<br />[💻](https://github.com/snipe/snipe-it/commits?author=tdb "Code") | [<img src="https://avatars2.githubusercontent.com/u/5384694?v=4" width="110px;"/><br /><sub>Sean McIlvenna</sub>](https://www.seanmcilvenna.com)<br />[💻](https://github.com/snipe/snipe-it/commits?author=seanmcilvenna "Code") |
<!-- ALL-CONTRIBUTORS-LIST:END -->
This project follows the [all-contributors](https://github.com/kentcdodds/all-contributors) specification. Contributions of any kind welcome!
@@ -76,7 +79,7 @@ This project follows the [all-contributors](https://github.com/kentcdodds/all-co
### Contributing
Please see the documentation on [contributing and developing for Snipe-IT](https://snipe-it.readme.io/docs/contributing).
Please see the documentation on [contributing and developing for Snipe-IT](https://snipe-it.readme.io/docs/contributing-overview).
Please note that this project is released with a [Contributor Code of Conduct](CODE_OF_CONDUCT.md). By participating in this project you agree to abide by its terms.

View File

@@ -16,7 +16,7 @@ class LdapSync extends Command
*
* @var string
*/
protected $signature = 'snipeit:ldap-sync {--location=} {--location_id=} {--summary}';
protected $signature = 'snipeit:ldap-sync {--location=} {--location_id=} {--base_dn=} {--summary} {--json_summary}';
/**
* The console command description.
@@ -55,31 +55,37 @@ class LdapSync extends Command
try {
$ldapconn = Ldap::connectToLdap();
} catch (\Exception $e) {
LOG::error($e);
}
try {
Ldap::bindAdminToLdap($ldapconn);
} catch (\Exception $e) {
if ($this->option('json_summary')) {
$json_summary = [ "error" => true, "error_message" => $e->getMessage(), "summary" => [] ];
$this->info(json_encode($json_summary));
}
LOG::error($e);
return [];
}
$summary = array();
$results = Ldap::findLdapUsers();
$ldap_ou_locations = Location::whereNotNull('ldap_ou')->get();
if (sizeof($ldap_ou_locations) > 0) {
LOG::debug('Some locations have special OUs set. Locations will be automatically set for users in those OUs.');
try {
if ($this->option('base_dn') != '') {
$search_base = $this->option('base_dn');
LOG::debug('Importing users from specified base DN: \"'.$search_base.'\".');
} else {
$search_base = null;
}
$results = Ldap::findLdapUsers($search_base);
} catch (\Exception $e) {
if ($this->option('json_summary')) {
$json_summary = [ "error" => true, "error_message" => $e->getMessage(), "summary" => [] ];
$this->info(json_encode($json_summary));
}
LOG::error($e);
return [];
}
$results = Ldap::findLdapUsers();
for ($i = 0; $i < $results["count"]; $i++) {
$results[$i]["ldap_location_override"] = false;
$results[$i]["location_id"] = 0;
}
/* Determine which location to assign users to by default. */
$location = NULL;
if ($this->option('location')!='') {
$location = Location::where('name', '=', $this->option('location'))->first();
@@ -89,40 +95,61 @@ class LdapSync extends Command
$location = Location::where('id', '=', $this->option('location_id'))->first();
LOG::debug('Location ID '.$this->option('location_id').' passed');
LOG::debug('Importing to '.$location->name.' ('.$location->id.')');
} else {
$location = NULL;
}
}
if (!isset($location)) {
LOG::debug('That location is invalid or a location was not provided, so no location will be assigned by default.');
}
// Grab subsets based on location-specific DNs, and overwrite location for these users.
foreach ($ldap_ou_locations as $ldap_loc) {
$location_users = Ldap::findLdapUsers($ldap_loc->ldap_ou);
$usernames = array();
for ($i = 0; $i < $location_users["count"]; $i++) {
$location_users[$i]["ldap_location_override"] = true;
$location_users[$i]["location_id"] = $ldap_loc->id;
$usernames[] = $location_users[$i][$ldap_result_username][0];
/* Process locations with explicitly defined OUs, if doing a full import. */
if ($this->option('base_dn')=='') {
// Retrieve locations with a mapped OU, and sort them from the shallowest to deepest OU (see #3993)
$ldap_ou_locations = Location::where('ldap_ou', '!=', '')->get()->toArray();
$ldap_ou_lengths = array();
foreach ($ldap_ou_locations as $location) {
$ldap_ou_lengths[] = strlen($location["ldap_ou"]);
}
// Delete located users from the general group.
foreach ($results as $key => $generic_entry) {
if (in_array($generic_entry[$ldap_result_username][0], $usernames)) {
unset($results[$key]);
array_multisort($ldap_ou_lengths, SORT_ASC, $ldap_ou_locations);
if (sizeof($ldap_ou_locations) > 0) {
LOG::debug('Some locations have special OUs set. Locations will be automatically set for users in those OUs.');
}
// Inject location information fields
for ($i = 0; $i < $results["count"]; $i++) {
$results[$i]["ldap_location_override"] = false;
$results[$i]["location_id"] = 0;
}
// Grab subsets based on location-specific DNs, and overwrite location for these users.
foreach ($ldap_ou_locations as $ldap_loc) {
$location_users = Ldap::findLdapUsers($ldap_loc["ldap_ou"]);
$usernames = array();
for ($i = 0; $i < $location_users["count"]; $i++) {
$location_users[$i]["ldap_location_override"] = true;
$location_users[$i]["location_id"] = $ldap_loc["id"];
$usernames[] = $location_users[$i][$ldap_result_username][0];
}
}
$global_count = $results['count'];
$results = array_merge($location_users, $results);
$results['count'] = $global_count;
// Delete located users from the general group.
foreach ($results as $key => $generic_entry) {
if (in_array($generic_entry[$ldap_result_username][0], $usernames)) {
unset($results[$key]);
}
}
$global_count = $results['count'];
$results = array_merge($location_users, $results);
$results['count'] = $global_count;
}
}
/* Create user account entries in Snipe-IT */
$tmp_pass = substr(str_shuffle("0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"), 0, 20);
$pass = bcrypt($tmp_pass);
for ($i = 0; $i < $results["count"]; $i++) {
if (empty($ldap_result_active_flag) || $results[$i][$ldap_result_active_flag][0] == "TRUE") {
@@ -135,6 +162,14 @@ class LdapSync extends Command
$item["ldap_location_override"] = isset($results[$i]["ldap_location_override"]) ? $results[$i]["ldap_location_override"]:"";
$item["location_id"] = isset($results[$i]["location_id"]) ? $results[$i]["location_id"]:"";
if ( array_key_exists('useraccountcontrol', $results[$i]) ) {
$enabled_accounts = [
'512', '544', '66048', '66080', '262656', '262688', '328192', '328224'
];
$item['activated'] = ( in_array($results[$i]['useraccountcontrol'][0], $enabled_accounts) ) ? 1 : 0;
} else {
$item['activated'] = 0;
}
// User exists
$item["createorupdate"] = 'updated';
@@ -145,18 +180,16 @@ class LdapSync extends Command
}
// Create the user if they don't exist.
$user->first_name = e($item["firstname"]);
$user->last_name = e($item["lastname"]);
$user->username = e($item["username"]);
$user->email = e($item["email"]);
$user->employee_num = e($item["employee_number"]);
$user->activated = 1;
$user->activated = $item['activated'];
if ($item['ldap_location_override'] == true) {
$user->location_id = $item['location_id'];
} else if ($location) {
} elseif ((isset($location)) && (!empty($location))) {
$user->location_id = e($location->id);
}
@@ -184,17 +217,16 @@ class LdapSync extends Command
if ($this->option('summary')) {
for ($x = 0; $x < count($summary); $x++) {
if ($summary[$x]['status']=='error') {
$this->error('ERROR: '.$summary[$x]['firstname'].' '.$summary[$x]['lastname'].' (username: '.$summary[$x]['username'].' was not imported: '.$summary[$x]['note']);
$this->error('ERROR: '.$summary[$x]['firstname'].' '.$summary[$x]['lastname'].' (username: '.$summary[$x]['username'].') was not imported: '.$summary[$x]['note']);
} else {
$this->info('User '.$summary[$x]['firstname'].' '.$summary[$x]['lastname'].' (username: '.$summary[$x]['username'].' was '.strtoupper($summary[$x]['createorupdate']).'.');
$this->info('User '.$summary[$x]['firstname'].' '.$summary[$x]['lastname'].' (username: '.$summary[$x]['username'].') was '.strtoupper($summary[$x]['createorupdate']).'.');
}
}
} else if ($this->option('json_summary')) {
$json_summary = [ "error" => false, "error_message" => "", "summary" => $summary ];
$this->info(json_encode($json_summary));
} else {
return $summary;
}
}
}

View File

@@ -78,12 +78,7 @@ class ObjectImportCommand extends Command
$logFile = $this->option('logfile');
\Log::useFiles($logFile);
if ($this->option('testrun')) {
$this->comment('====== TEST ONLY Item Import for '.$filename.' ====');
$this->comment('============== NO DATA WILL BE WRITTEN ==============');
} else {
$this->comment('======= Importing Items from '.$filename.' =========');
}
$this->comment('======= Importing Items from '.$filename.' =========');
$importer->import();
$this->bar = null;

View File

@@ -16,7 +16,8 @@ class RecryptFromMcrypt extends Command
*
* @var string
*/
protected $signature = 'snipeit:legacy-recrypt';
protected $signature = 'snipeit:legacy-recrypt
{--force : Force a re-crypt of encrypted data from MCRYPT.}';
/**
* The console command description.
@@ -48,6 +49,7 @@ class RecryptFromMcrypt extends Command
// If not, we can try to use the current APP_KEY if looks like it's old
$legacy_key = env('LEGACY_APP_KEY');
$key_parts = explode(':', $legacy_key);
$legacy_cipher = env('LEGACY_CIPHER', 'rijndael-256');
$errors = array();
if (!$legacy_key) {
@@ -60,6 +62,7 @@ class RecryptFromMcrypt extends Command
if (strlen($legacy_key) == 32) {
$legacy_length_check = true;
} elseif (array_key_exists('1', $key_parts) && (strlen($key_parts[1])==44)) {
$legacy_key = base64_decode($key_parts[1],true);
$legacy_length_check = true;
} else {
$legacy_length_check = false;
@@ -79,7 +82,9 @@ class RecryptFromMcrypt extends Command
$this->error('================================!!!! WARNING !!!!================================');
$this->comment("This tool will attempt to decrypt your old Snipe-IT (mcrypt, now deprecated) encrypted data and re-encrypt it using OpenSSL. \n\nYou should only continue if you have backed up any and all old APP_KEYs and have backed up your data.");
if ($this->confirm("Are you SURE you wish to continue?")) {
$force = ($this->option('force')) ? true : false;
if ($force || ($this->confirm("Are you SURE you wish to continue?"))) {
$backup_file = 'backups/env-backups/'.'app_key-'.date('Y-m-d-gis');
@@ -91,13 +96,21 @@ class RecryptFromMcrypt extends Command
}
$mcrypter = new McryptEncrypter($legacy_key);
if ($legacy_cipher){
$mcrypter = new McryptEncrypter($legacy_key,$legacy_cipher);
}else{
$mcrypter = new McryptEncrypter($legacy_key);
}
$settings = Setting::getSettings();
if ($settings->ldap_password=='') {
if ($settings->ldap_pword=='') {
$this->comment('INFO: No LDAP password found. Skipping... ');
} else {
$decrypted_ldap_pword = $mcrypter->decrypt($settings->ldap_pword);
$settings->ldap_pword = \Crypt::encrypt($decrypted_ldap_pword);
$settings->save();
}
/** @var CustomField[] $custom_fields */
$custom_fields = CustomField::where('field_encrypted','=', 1)->get();
$this->comment('INFO: Retrieving encrypted custom fields...');
@@ -110,32 +123,22 @@ class RecryptFromMcrypt extends Command
// Get all assets with a value in any of the fields that were encrypted
/** @var Asset[] $assets */
$assets = $query->get();
$bar = $this->output->createProgressBar(count($assets));
foreach ($custom_fields as $encrypted_field) {
// Try to decrypt the payload using the legacy app key
try {
$decrypted_field = $mcrypter->decrypt($encrypted_field);
$this->comment($decrypted_field);
} catch (\Exception $e) {
$errors[] = ' - ERROR: Could not decrypt field ['.$encrypted_field->name.']: '.$e->getMessage();
}
$bar->advance();
}
foreach ($assets as $asset) {
foreach ($custom_fields as $encrypted_field) {
$columnName = $encrypted_field->db_column;
// Make sure the value isn't null
if ($asset->{$encrypted_field}!='') {
if ($asset->{$columnName}!='') {
// Try to decrypt the payload using the legacy app key
try {
$decrypted_field = $mcrypter->decrypt($asset->{$encrypted_field});
$asset->{$encrypted_field} = \Crypt::encrypt($decrypted_field);
$decrypted_field = $mcrypter->decrypt($asset->{$columnName});
$asset->{$columnName} = \Crypt::encrypt($decrypted_field);
$this->comment($decrypted_field);
} catch (\Exception $e) {
$errors[] = ' - ERROR: Could not decrypt field ['.$encrypted_field->name.']: '.$e->getMessage();

View File

@@ -0,0 +1,105 @@
<?php
namespace App\Console\Commands;
use Illuminate\Console\Command;
use App\Models\Asset;
use App\Models\Setting;
use DB;
use Artisan;
class RegenerateAssetTags extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'snipeit:regenerate-tags {--start=} {--output= : info|warn|error|all} ';
/**
* The console command description.
*
* @var string
*/
protected $description = 'This utility will regenerate all asset tags. THIS IS DATA-DESTRUCTIVE AND SHOULD BE USED WITH CAUTION. ';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* @return mixed
*/
public function handle()
{
if ($this->confirm('This will regenerate all of the asset tags within your system. This action is data-destructive and should be used with caution. Do you wish to continue?'))
{
$output['info'] = [];
$output['warn'] = [];
$output['error'] = [];
$settings = Setting::getSettings();
$start_tag = ($this->option('start')) ? $this->option('start') : (($settings->next_auto_tag_base) ? Setting::getSettings()->next_auto_tag_base : 1) ;
$this->info('Starting at '.$start_tag);
$total_assets = Asset::orderBy('id','asc')->get();
$bar = $this->output->createProgressBar(count($total_assets));
try {
Artisan::call('backup:run');
} catch (\Exception $e) {
$output['error'][] = $e;
}
foreach ($total_assets as $asset) {
$start_tag++;
$output['info'][] = 'Asset tag:'.$asset->asset_tag;
$asset->asset_tag = $settings->auto_increment_prefix.$settings->auto_increment_prefix.$start_tag;
if ($settings->zerofill_count > 0) {
$asset->asset_tag = $settings->auto_increment_prefix.Asset::zerofill($start_tag, $settings->zerofill_count);
}
$output['info'][] = 'New Asset tag:'.$asset->asset_tag;
// Use forceSave here to override model level validation
$asset->forceSave();
}
$bar->finish();
$this->info("\n");
if (($this->option('output')=='all') || ($this->option('output')=='info')) {
foreach ($output['info'] as $key => $output_text) {
$this->info($output_text);
}
}
if (($this->option('output')=='all') || ($this->option('output')=='warn')) {
foreach ($output['warn'] as $key => $output_text) {
$this->warn($output_text);
}
}
if (($this->option('output')=='all') || ($this->option('output')=='error')) {
foreach ($output['error'] as $key => $output_text) {
$this->error($output_text);
}
}
}
}
}

View File

@@ -0,0 +1,75 @@
<?php
namespace App\Console\Commands;
use Illuminate\Console\Command;
use App\Models\Setting;
use App\Models\User;
class ResetDemoSettings extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'snipeit:demo-settings';
/**
* The console command description.
*
* @var string
*/
protected $description = 'This will reset the Snipe-IT demo settings back to default. ';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* @return mixed
*/
public function handle()
{
$this->info('Resetting the demo settings.');
$settings = Setting::first();
$settings->per_page = 20;
$settings->site_name = 'Snipe-IT Asset Management Demo';
$settings->auto_increment_assets = 1;
$settings->logo = 'snipe-logo.png';
$settings->alert_email = 'service@snipe-it.io';
$settings->header_color = null;
$settings->barcode_type = 'QRCODE';
$settings->default_currency = 'USD';
$settings->brand = 3;
$settings->ldap_enabled = 0;
$settings->full_multiple_companies_support = 1;
$settings->alt_barcode = 'C128';
$settings->email_domain = 'snipeitapp.com';
$settings->email_format = 'filastname';
$settings->username_format = 'filastname';
$settings->date_display_format = 'D M d, Y';
$settings->time_display_format = 'g:iA';
$settings->thumbnail_max_h = '30';
$settings->locale = 'en';
$settings->save();
if ($user = User::where('username', '=', 'admin')->first()) {
$user->locale = 'en';
$user->save();
}
}
}

View File

@@ -0,0 +1,148 @@
<?php
namespace App\Console\Commands;
use App\Models\CustomField;
use Illuminate\Console\Command;
use App\Models\Asset;
use Illuminate\Support\Facades\Storage;
class SyncAssetLocations extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'snipeit:sync-asset-locations {--output= : info|warn|error|all} ';
/**
* The console command description.
*
* @var string
*/
protected $description = 'This utility will sync the location_id of assets based on current state. It should not normally be needed, but is a safeguard in case we missed something in the Great Migration when flattening the assets to location relationship.';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* @return mixed
*/
public function handle()
{
$output['info'] = [];
$output['warn'] = [];
$output['error'] = [];
$total_assets = Asset::whereNull('deleted_at')->get();
$bar = $this->output->createProgressBar(count($total_assets));
// Unassigned
$rtd_assets = Asset::whereNull('assigned_to')->whereNull('deleted_at')->with('defaultLoc')->get();
$output['info'][] = 'There are '.$rtd_assets->count().' unassigned assets.';
foreach ($rtd_assets as $rtd_asset) {
$output['info'][] = 'Setting Unassigned Asset ' . $rtd_asset->id . ' ('.$rtd_asset->asset_tag.') to location: ' . $rtd_asset->rtd_location_id . " because their default location is: " . $rtd_asset->rtd_location_id;
$rtd_asset->location_id=$rtd_asset->rtd_location_id;
$rtd_asset->unsetEventDispatcher();
$rtd_asset->save();
$bar->advance();
}
$assigned_user_assets = Asset::where('assigned_type','App\Models\User')->whereNotNull('assigned_to')->whereNull('deleted_at')->get();
$output['info'][] = 'There are '.$assigned_user_assets->count().' assets checked out to users.';
foreach ($assigned_user_assets as $assigned_user_asset) {
if (($assigned_user_asset->assignedTo) && ($assigned_user_asset->assignedTo->userLoc)) {
$new_location=$assigned_user_asset->assignedTo->userloc->id;
$output['info'][] ='Setting User Asset ' . $assigned_user_asset->id . ' ('.$assigned_user_asset->asset_tag.') to ' . $assigned_user_asset->assignedTo->userLoc->name . ' which is id: ' . $new_location;
} else {
$output['warn'][] ='Asset ' . $assigned_user_asset->id . ' ('.$assigned_user_asset->asset_tag.') still has no location! ';
$new_location = $assigned_user_asset->rtd_location_id;
}
$assigned_user_asset->location_id=$new_location;
$assigned_user_asset->unsetEventDispatcher();
$assigned_user_asset->save();
$bar->advance();
}
$assigned_location_assets = Asset::where('assigned_type','App\Models\Location')
->whereNotNull('assigned_to')->whereNull('deleted_at')->get();
$output['info'][] = 'There are '.$assigned_location_assets->count().' assets checked out to locations.';
foreach ($assigned_location_assets as $assigned_location_asset) {
if ($assigned_location_asset->assignedTo) {
$assigned_location_asset->location_id = $assigned_location_asset->assignedTo->id;
$output['info'][] ='Setting Location Assigned asset ' . $assigned_location_asset->id . ' ('.$assigned_location_asset->asset_tag.') that is checked out to '.$assigned_location_asset->assignedTo->name.' (#'.$assigned_location_asset->assignedTo->id.') to location: ' . $assigned_location_asset->assetLoc()->id;
$assigned_location_asset->unsetEventDispatcher();
$assigned_location_asset->save();
} else {
$output['warn'][] ='Asset ' . $assigned_location_asset->id . ' ('.$assigned_location_asset->asset_tag.') did not return a valid associated location - perhaps it was deleted?';
}
$bar->advance();
}
// Assigned to assets
$assigned_asset_assets = Asset::where('assigned_type','App\Models\Asset')
->whereNotNull('assigned_to')->whereNull('deleted_at')->get();
$output['info'][] ='Asset-assigned assets: '.$assigned_asset_assets->count();
foreach ($assigned_asset_assets as $assigned_asset_asset) {
// Check to make sure there aren't any invalid relationships
if ($assigned_asset_asset->assetLoc()) {
$assigned_asset_asset->location_id = $assigned_asset_asset->assetLoc()->id;
$output['info'][] ='Setting Asset Assigned asset ' . $assigned_asset_asset->assetLoc()->id. ' ('.$assigned_asset_asset->asset_tag.') location to: ' . $assigned_asset_asset->assetLoc()->id;
$assigned_asset_asset->unsetEventDispatcher();
$assigned_asset_asset->save();
} else {
$output['warn'][] ='Asset Assigned asset ' . $assigned_asset_asset->id. ' ('.$assigned_asset_asset->asset_tag.') does not seem to have a valid location';
}
$bar->advance();
}
$unlocated_assets = Asset::whereNull("location_id")->whereNull('deleted_at')->get();
$output['info'][] ='Assets still without a location: '.$unlocated_assets->count();
foreach($unlocated_assets as $unlocated_asset) {
$output['warn'][] ='Asset: '.$unlocated_asset->id.' still has no location. ';
$bar->advance();
}
$bar->finish();
$this->info("\n");
if (($this->option('output')=='all') || ($this->option('output')=='info')) {
foreach ($output['info'] as $key => $output_text) {
$this->info($output_text);
}
}
if (($this->option('output')=='all') || ($this->option('output')=='warn')) {
foreach ($output['warn'] as $key => $output_text) {
$this->warn($output_text);
}
}
if (($this->option('output')=='all') || ($this->option('output')=='error')) {
foreach ($output['error'] as $key => $output_text) {
$this->error($output_text);
}
}
}
}

View File

@@ -0,0 +1,135 @@
<?php
namespace App\Console\Commands;
use Illuminate\Console\Command;
class Version extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'version:update {--branch=master} {--type=patch}';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Command description';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* @return mixed
*/
public function handle()
{
$use_branch = $this->option('branch');
$use_type = $this->option('type');
$git_branch = trim(shell_exec('git rev-parse --abbrev-ref HEAD'));
$build_version = trim(shell_exec('git rev-list --count '.$use_branch));
$versionFile = 'config/version.php';
$full_hash_version = str_replace("\n", '', shell_exec('git describe master --tags'));
$version = explode('-', $full_hash_version);
$app_version = $current_app_version = $version[0];
$hash_version = (array_key_exists('2', $version)) ? $version[2] : '';
$prerelease_version = '';
$this->line('Branch is: '.$use_branch);
$this->line('Type is: '.$use_type);
$this->line('Current version is: '.$full_hash_version);
if (count($version)==3) {
$this->line('This does not look like an alpha/beta release.');
} else {
if (array_key_exists('3',$version)) {
$this->line('The current version looks like a beta release.');
$prerelease_version = $version[1];
$hash_version = $version[3];
}
}
$app_version_raw = explode('.', $app_version);
$maj = str_replace('v', '', $app_version_raw[0]);
$min = $app_version_raw[1];
$patch = '';
// This is a major release that might not have a third .0
if (array_key_exists(2, $app_version_raw)) {
$patch = $app_version_raw[2];
}
if ($use_type=='major') {
$app_version = "v".($maj + 1).".$min.$patch";
} elseif ($use_type=='minor') {
$app_version = "v"."$maj.".($min + 1).".$patch";
} elseif ($use_type=='pre') {
$pre_raw = str_replace('beta','', $prerelease_version);
$pre_raw = str_replace('alpha','', $pre_raw);
$pre_raw = str_ireplace('rc','', $pre_raw);
$pre_raw = $pre_raw++;
$this->line('Setting the pre-release to '. $prerelease_version.'-'.$pre_raw);
$app_version = "v"."$maj.".($min + 1).".$patch";
} elseif ($use_type=='patch') {
$app_version = "v" . "$maj.$min." . ($patch + 1);
// If nothing is passed, leave the version as it is, just increment the build
} else {
$app_version = "v" . "$maj.$min." . $patch;
}
// Determine if this tag already exists, or if this prior to a release
$this->line('Running: git rev-parse master '.$current_app_version);
// $pre_release = trim(shell_exec('git rev-parse '.$use_branch.' '.$current_app_version.' 2>&1 1> /dev/null'));
if ($use_branch=='develop') {
$app_version = $app_version.'-pre';
}
$full_app_version = $app_version.' - build '.$build_version.'-'.$hash_version;
$array = var_export(
array(
'app_version' => $app_version,
'full_app_version' => $full_app_version,
'build_version' => $build_version,
'prerelease_version' => $prerelease_version,
'hash_version' => $hash_version,
'full_hash' => $full_hash_version,
'branch' => $git_branch),
true
);
// Construct our file content
$content = <<<CON
<?php
return $array;
CON;
// And finally write the file and output the current version
\File::put($versionFile, $content);
$this->info('Setting NEW version: '. $full_app_version.' ('.$git_branch.')');
}
}

View File

@@ -1,91 +0,0 @@
<?php
namespace App\Console\Commands;
use Symfony\Component\Console\Input\InputArgument;
use Illuminate\Console\Command;
class Versioning extends Command
{
/**
* The console command name.
*
* @var string
*/
protected $name = 'versioning:update';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Generate and update app\'s version via git.';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* @return void
*/
public function fire()
{
$versionFile = 'config/version.php';
$hash_version = str_replace("\n", '', shell_exec('git describe --tags'));
$version = explode('-', $hash_version);
$array = var_export(
array(
'app_version' => $version[0],
'build_version' => $version[1],
'hash_version' => $version[2],
'full_hash' => $hash_version),
true
);
// Construct our file content
$content = <<<CON
<?php
return $array;
CON;
// And finally write the file and output the current version
\File::put($versionFile, $content);
$this->line('Setting version: '. config('version.app_version').' build '.config('version.build_version').' ('.config('version.hash_version').')');
}
/**
* Get the console command arguments.
*
* @return array
*/
protected function getArguments()
{
return array(
);
}
/**
* Get the console command options.
*
* @return array
*/
protected function getOptions()
{
return array(
);
}
}

View File

@@ -19,13 +19,16 @@ class Kernel extends ConsoleKernel
Commands\SendInventoryAlerts::class,
Commands\SendExpectedCheckinAlerts::class,
Commands\ObjectImportCommand::class,
Commands\Versioning::class,
Commands\Version::class,
Commands\SystemBackup::class,
Commands\DisableLDAP::class,
Commands\Purge::class,
Commands\LdapSync::class,
Commands\FixDoubleEscape::class,
Commands\RecryptFromMcrypt::class
Commands\RecryptFromMcrypt::class,
Commands\ResetDemoSettings::class,
Commands\SyncAssetLocations::class,
Commands\RegenerateAssetTags::class,
];
/**
@@ -39,7 +42,7 @@ class Kernel extends ConsoleKernel
$schedule->command('snipeit:inventory-alerts')->daily();
$schedule->command('snipeit:expiring-alerts')->daily();
$schedule->command('snipeit:expected-checkins')->daily();
$schedule->command('snipeit:expected-checkin')->daily();
$schedule->command('snipeit:backup')->weekly();
$schedule->command('backup:clean')->daily();
}

View File

@@ -7,6 +7,6 @@ class CheckoutNotAllowed extends Exception
{
public function __toString()
{
"A checkout is not allowed under these circumstances";
return "A checkout is not allowed under these circumstances";
}
}

View File

@@ -7,6 +7,7 @@ use Illuminate\Auth\AuthenticationException;
use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
use App\Helpers\Helper;
use Illuminate\Validation\ValidationException;
use Log;
class Handler extends ExceptionHandler
{
@@ -34,7 +35,10 @@ class Handler extends ExceptionHandler
*/
public function report(Exception $exception)
{
parent::report($exception);
if ($this->shouldReport($exception)) {
Log::error($exception);
return parent::report($exception);
}
}
/**
@@ -63,7 +67,7 @@ class Handler extends ExceptionHandler
}
if ($e instanceof \Illuminate\Validation\ValidationException) {
return response()->json(Helper::formatStandardApiResponse('error', $e->response['messages'], $e->getMessage(), 400));
return response()->json(Helper::formatStandardApiResponse('error', null, $e->response['messages'], 400));
}
if ($this->isHttpException($e)) {

View File

@@ -127,7 +127,13 @@ class Helper
$floatString = str_replace(",", "", $floatString);
$floatString = str_replace($LocaleInfo["decimal_point"], ".", $floatString);
// Strip Currency symbol
$floatString = str_replace($LocaleInfo['currency_symbol'], '', $floatString);
// If no currency symbol is set, default to $ because Murica
$currencySymbol = $LocaleInfo['currency_symbol'];
if (empty($currencySymbol)) {
$currencySymbol = '$';
}
$floatString = str_replace($currencySymbol, '', $floatString);
return floatval($floatString);
}
@@ -454,19 +460,19 @@ class Helper
*/
public static function checkLowInventory()
{
$consumables = Consumable::with('users')->whereNotNull('min_amt')->get();
$accessories = Accessory::with('users')->whereNotNull('min_amt')->get();
$components = Component::with('assets')->whereNotNull('min_amt')->get();
$consumables = Consumable::withCount('consumableAssignments')->whereNotNull('min_amt')->get();
$accessories = Accessory::withCount('users')->whereNotNull('min_amt')->get();
$components = Component::withCount('assets')->whereNotNull('min_amt')->get();
$avail_consumables = 0;
$items_array = array();
$all_count = 0;
foreach ($consumables as $consumable) {
$avail = $consumable->numRemaining();
$avail = $consumable->qty - $consumable->consumable_assignment_count; //$consumable->numRemaining();
if ($avail < ($consumable->min_amt) + \App\Models\Setting::getSettings()->alert_threshold) {
if ($consumable->qty > 0) {
$percent = number_format((($consumable->numRemaining() / $consumable->qty) * 100), 0);
$percent = number_format((($avail / $consumable->qty) * 100), 0);
} else {
$percent = 100;
}
@@ -475,7 +481,7 @@ class Helper
$items_array[$all_count]['name'] = $consumable->name;
$items_array[$all_count]['type'] = 'consumables';
$items_array[$all_count]['percent'] = $percent;
$items_array[$all_count]['remaining']=$consumable->numRemaining();
$items_array[$all_count]['remaining'] = $avail;
$items_array[$all_count]['min_amt']=$consumable->min_amt;
$all_count++;
}
@@ -484,11 +490,11 @@ class Helper
}
foreach ($accessories as $accessory) {
$avail = $accessory->numRemaining();
$avail = $accessory->qty - $accessory->users_count;
if ($avail < ($accessory->min_amt) + \App\Models\Setting::getSettings()->alert_threshold) {
if ($accessory->qty > 0) {
$percent = number_format((($accessory->numRemaining() / $accessory->qty) * 100), 0);
$percent = number_format((($avail / $accessory->qty) * 100), 0);
} else {
$percent = 100;
}
@@ -497,7 +503,7 @@ class Helper
$items_array[$all_count]['name'] = $accessory->name;
$items_array[$all_count]['type'] = 'accessories';
$items_array[$all_count]['percent'] = $percent;
$items_array[$all_count]['remaining']=$accessory->numRemaining();
$items_array[$all_count]['remaining'] = $avail;
$items_array[$all_count]['min_amt']=$accessory->min_amt;
$all_count++;
}
@@ -505,10 +511,10 @@ class Helper
}
foreach ($components as $component) {
$avail = $component->numRemaining();
$avail = $component->qty - $component->assets_count;
if ($avail < ($component->min_amt) + \App\Models\Setting::getSettings()->alert_threshold) {
if ($component->qty > 0) {
$percent = number_format((($component->numRemaining() / $component->qty) * 100), 0);
$percent = number_format((($avail / $component->qty) * 100), 0);
} else {
$percent = 100;
}
@@ -517,7 +523,7 @@ class Helper
$items_array[$all_count]['name'] = $component->name;
$items_array[$all_count]['type'] = 'components';
$items_array[$all_count]['percent'] = $percent;
$items_array[$all_count]['remaining']=$component->numRemaining();
$items_array[$all_count]['remaining'] = $avail;
$items_array[$all_count]['min_amt']=$component->min_amt;
$all_count++;
}
@@ -725,5 +731,62 @@ class Helper
}
// Nicked from Drupal :)
// Returns a file size limit in bytes based on the PHP upload_max_filesize
// and post_max_size
public static function file_upload_max_size() {
static $max_size = -1;
if ($max_size < 0) {
// Start with post_max_size.
$post_max_size = Helper::parse_size(ini_get('post_max_size'));
if ($post_max_size > 0) {
$max_size = $post_max_size;
}
// If upload_max_size is less, then reduce. Except if upload_max_size is
// zero, which indicates no limit.
$upload_max = Helper::parse_size(ini_get('upload_max_filesize'));
if ($upload_max > 0 && $upload_max < $max_size) {
$max_size = $upload_max;
}
}
return $max_size;
}
public static function file_upload_max_size_readable() {
static $max_size = -1;
if ($max_size < 0) {
// Start with post_max_size.
$post_max_size = Helper::parse_size(ini_get('post_max_size'));
if ($post_max_size > 0) {
$max_size = ini_get('post_max_size');
}
// If upload_max_size is less, then reduce. Except if upload_max_size is
// zero, which indicates no limit.
$upload_max = Helper::parse_size(ini_get('upload_max_filesize'));
if ($upload_max > 0 && $upload_max < $max_size) {
$max_size = ini_get('upload_max_filesize');
}
}
return $max_size;
}
public static function parse_size($size) {
$unit = preg_replace('/[^bkmgtpezy]/i', '', $size); // Remove the non-unit characters from the size.
$size = preg_replace('/[^0-9\.]/', '', $size); // Remove the non-numeric characters from the size.
if ($unit) {
// Find the position of the unit in the ordered string which is the power of magnitude to multiply a kilobyte by.
return round($size * pow(1024, stripos('bkmgtpezy', $unit[0])));
}
else {
return round($size);
}
}
}

View File

@@ -18,6 +18,8 @@ use Illuminate\Http\Request;
use Slack;
use Str;
use View;
use Image;
use App\Http\Requests\ImageUploadRequest;
/** This controller handles all actions related to Accessories for
* the Snipe-IT Asset Management application.
@@ -52,13 +54,9 @@ class AccessoriesController extends Controller
public function create(Request $request)
{
$this->authorize('create', Accessory::class);
// Show the page
return view('accessories/edit')
->with('item', new Accessory)
->with('category_list', Helper::categoryList('accessory'))
->with('company_list', Helper::companyList())
->with('location_list', Helper::locationsList())
->with('manufacturer_list', Helper::manufacturerList());
$category_type = 'accessory';
return view('accessories/edit')->with('category_type', $category_type)
->with('item', new Accessory);
}
@@ -68,7 +66,7 @@ class AccessoriesController extends Controller
* @author [A. Gianotto] [<snipe@snipe.net>]
* @return Redirect
*/
public function store(Request $request)
public function store(ImageUploadRequest $request)
{
$this->authorize(Accessory::class);
// create a new model instance
@@ -87,6 +85,28 @@ class AccessoriesController extends Controller
$accessory->purchase_cost = Helper::ParseFloat(request('purchase_cost'));
$accessory->qty = request('qty');
$accessory->user_id = Auth::user()->id;
$accessory->supplier_id = request('supplier_id');
if ($request->hasFile('image')) {
if (!config('app.lock_passwords')) {
$image = $request->file('image');
$ext = $image->getClientOriginalExtension();
$file_name = "accessory-".str_random(18).'.'.$ext;
$path = public_path('/uploads/accessories');
if ($image->getClientOriginalExtension()!='svg') {
Image::make($image->getRealPath())->resize(null, 250, function ($constraint) {
$constraint->aspectRatio();
$constraint->upsize();
})->save($path.'/'.$file_name);
} else {
$image->move($path, $file_name);
}
$accessory->image = $file_name;
}
}
// Was the accessory created?
if ($accessory->save()) {
@@ -105,18 +125,15 @@ class AccessoriesController extends Controller
*/
public function edit(Request $request, $accessoryId = null)
{
// Check if the accessory exists
if (is_null($item = Accessory::find($accessoryId))) {
return redirect()->route('accessories.index')->with('error', trans('admin/accessories/message.does_not_exist'));
if ($item = Accessory::find($accessoryId)) {
$this->authorize($item);
$category_type = 'accessory';
return view('accessories/edit', compact('item'))->with('category_type', $category_type);
}
$this->authorize($item);
return redirect()->route('accessories.index')->with('error', trans('admin/accessories/message.does_not_exist'));
return view('accessories/edit', compact('item'))
->with('category_list', Helper::categoryList('accessory'))
->with('company_list', Helper::companyList())
->with('location_list', Helper::locationsList())
->with('manufacturer_list', Helper::manufacturerList());
}
@@ -127,7 +144,7 @@ class AccessoriesController extends Controller
* @param int $accessoryId
* @return Redirect
*/
public function update(Request $request, $accessoryId = null)
public function update(ImageUploadRequest $request, $accessoryId = null)
{
if (is_null($accessory = Accessory::find($accessoryId))) {
return redirect()->route('accessories.index')->with('error', trans('admin/accessories/message.does_not_exist'));
@@ -144,11 +161,38 @@ class AccessoriesController extends Controller
$accessory->manufacturer_id = request('manufacturer_id');
$accessory->order_number = request('order_number');
$accessory->model_number = request('model_number');
$accessory->purchase_date = request('purchase_date');
$accessory->purchase_cost = request('purchase_cost');
$accessory->purchase_date = request('purchase_date');
$accessory->purchase_cost = request('purchase_cost');
$accessory->qty = request('qty');
$accessory->supplier_id = request('supplier_id');
// Was the accessory updated?
if ($request->hasFile('image')) {
if (!config('app.lock_passwords')) {
$image = $request->file('image');
$ext = $image->getClientOriginalExtension();
$file_name = "accessory-".str_random(18).'.'.$ext;
$path = public_path('/uploads/accessories');
if ($image->getClientOriginalExtension()!='svg') {
Image::make($image->getRealPath())->resize(null, 250, function ($constraint) {
$constraint->aspectRatio();
$constraint->upsize();
})->save($path.'/'.$file_name);
} else {
$image->move($path, $file_name);
}
if (($accessory->image) && (file_exists($path.'/'.$accessory->image))) {
unlink($path.'/'.$accessory->image);
}
$accessory->image = $file_name;
}
}
// Was the accessory updated?
if ($accessory->save()) {
return redirect()->route('accessories.index')->with('success', trans('admin/accessories/message.update.success'));
}
@@ -197,11 +241,7 @@ class AccessoriesController extends Controller
if (isset($accessory->id)) {
return view('accessories/view', compact('accessory'));
}
// Prepare the error message
$error = trans('admin/accessories/message.does_not_exist', compact('id'));
// Redirect to the user management page
return redirect()->route('accessories')->with('error', $error);
return redirect()->route('accessories.index')->with('error', trans('admin/accessories/message.does_not_exist', compact('id')));
}
/**
@@ -222,7 +262,7 @@ class AccessoriesController extends Controller
$this->authorize('checkout', $accessory);
// Get the dropdown of users and then pass it to the checkout view
return view('accessories/checkout', compact('accessory'))->with('users_list', Helper::usersList());
return view('accessories/checkout', compact('accessory'));
}
@@ -247,7 +287,7 @@ class AccessoriesController extends Controller
$this->authorize('checkout', $accessory);
if (!$user = User::find(Input::get('assigned_to'))) {
return redirect()->route('accessories.index')->with('error', trans('admin/accessories/message.not_found'));
return redirect()->route('checkout/accessory', $accessory->id)->with('error', trans('admin/accessories/message.checkout.user_does_not_exist'));
}
// Update the accessory data
@@ -274,7 +314,8 @@ class AccessoriesController extends Controller
$data['note'] = $logaction->note;
$data['require_acceptance'] = $accessory->requireAcceptance();
// TODO: Port this to new mail notifications
if (($accessory->requireAcceptance()=='1') || ($accessory->getEula())) {
if ((($accessory->requireAcceptance()=='1') || ($accessory->getEula())) && ($user->email!='')) {
Mail::send('emails.accept-accessory', $data, function ($m) use ($user) {
$m->to($user->email, $user->first_name . ' ' . $user->last_name);
@@ -351,7 +392,7 @@ class AccessoriesController extends Controller
$data['item_tag'] = '';
$data['note'] = e($logaction->note);
if (($accessory->checkin_email()=='1')) {
if ((($accessory->checkin_email()=='1')) && ($user->email!='')) {
Mail::send('emails.checkin-asset', $data, function ($m) use ($user) {
$m->to($user->email, $user->first_name . ' ' . $user->last_name);
@@ -369,143 +410,5 @@ class AccessoriesController extends Controller
return redirect()->route('accessories.index')->with('error', trans('admin/accessories/message.checkin.error'));
}
/**
* Generates the JSON response for accessories listing view.
*
* Example:
* {
* "actions": "(links to available actions)",
* "category": "(link to category)",
* "company": "My Company",
* "location": "My Location",
* "min_amt": 2,
* "name": "(link to accessory),
* "numRemaining": 6,
* "order_number": null,
* "purchase_cost": "0.00",
* "purchase_date": null,
* "qty": 7
* },
*
* The names of the fields in the returns JSON correspond directly to the the
* names of the fields in the bootstrap-tables in the view.
*
* For debugging, see at /api/accessories/list
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @param Request $request
* @return string JSON containing accessories and their associated atrributes.
* @internal param int $accessoryId
*/
public function getDatatable(Request $request)
{
$this->authorize('index', Accessory::class);
$accessories = Company::scopeCompanyables(
Accessory::select('accessories.*')
->whereNull('accessories.deleted_at')
->with('category', 'company', 'manufacturer', 'users', 'location')
);
if (Input::has('search')) {
$accessories = $accessories->TextSearch(e(Input::get('search')));
}
$offset = request('offset', 0);
$limit = request('limit', 50);
$allowed_columns = ['name','min_amt','order_number','purchase_date','purchase_cost','company','category','model_number', 'manufacturer', 'location'];
$order = Input::get('order') === 'asc' ? 'asc' : 'desc';
$sort = in_array(Input::get('sort'), $allowed_columns) ? e(Input::get('sort')) : 'created_at';
switch ($sort) {
case 'category':
$accessories = $accessories->OrderCategory($order);
break;
case 'company':
$accessories = $accessories->OrderCompany($order);
break;
case 'location':
$accessories = $accessories->OrderLocation($order);
break;
case 'manufacturer':
$accessories = $accessories->OrderManufacturer($order);
break;
default:
$accessories = $accessories->orderBy($sort, $order);
break;
}
$accessCount = $accessories->count();
$accessories = $accessories->skip($offset)->take($limit)->get();
$rows = array();
foreach ($accessories as $accessory) {
$rows[] = $accessory->present()->forDataTable();
}
$data = array('total'=>$accessCount, 'rows'=>$rows);
return $data;
}
/**
* Generates the JSON response for accessory detail view.
*
* Example:
* <code>
* {
* "rows": [
* {
* "actions": "(link to available actions)",
* "name": "(link to user)"
* }
* ],
* "total": 1
* }
* </code>
*
* The names of the fields in the returns JSON correspond directly to the the
* names of the fields in the bootstrap-tables in the view.
*
* For debugging, see at /api/accessories/$accessoryID/view
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @param int $accessoryId
* @return string JSON containing accessories and their associated atrributes.
**/
public function getDataView(Request $request, $accessoryID)
{
$accessory = Accessory::find($accessoryID);
if (!Company::isCurrentUserHasAccess($accessory)) {
return ['total' => 0, 'rows' => []];
}
$accessory_users = $accessory->users;
$count = $accessory_users->count();
$rows = array();
foreach ($accessory_users as $user) {
$actions = '';
if (Gate::allows('checkin', $accessory)) {
$actions .= Helper::generateDatatableButton('checkin', route('checkin/accessory', $user->pivot->id));
}
if (Gate::allows('view', $user)) {
$name = (string) link_to_route('users.show', e($user->present()->fullName()), [$user->id]);
} else {
$name = e($user->present()->fullName());
}
$rows[] = array(
'name' => $name,
'actions' => $actions
);
}
$data = array('total'=>$count, 'rows'=>$rows);
return $data;
}
}

View File

@@ -7,6 +7,7 @@ use App\Http\Controllers\Controller;
use App\Helpers\Helper;
use App\Models\Accessory;
use App\Http\Transformers\AccessoriesTransformer;
use App\Models\Company;
class AccessoriesController extends Controller
@@ -33,10 +34,18 @@ class AccessoriesController extends Controller
$accessories->where('company_id','=',$request->input('company_id'));
}
if ($request->has('category_id')) {
$accessories->where('category_id','=',$request->input('category_id'));
}
if ($request->has('manufacturer_id')) {
$accessories->where('manufacturer_id','=',$request->input('manufacturer_id'));
}
if ($request->has('supplier_id')) {
$accessories->where('supplier_id','=',$request->input('supplier_id'));
}
$offset = $request->input('offset', 0);
$limit = $request->input('limit', 50);
$order = $request->input('order') === 'asc' ? 'asc' : 'desc';
@@ -95,8 +104,6 @@ class AccessoriesController extends Controller
{
$this->authorize('view', Accessory::class);
$accessory = Accessory::findOrFail($id);
$accessory_users = $accessory->users;
return (new AccessoriesTransformer)->transformAccessory($accessory);
}
@@ -128,10 +135,15 @@ class AccessoriesController extends Controller
public function checkedout($id)
{
$this->authorize('view', Accessory::class);
$accessory = Accessory::findOrFail($id)->with('users')->first();
$accessories_users = $accessory->users;
$total = $accessories_users->count();
return (new AccessoriesTransformer)->transformCheckedoutAccessories($accessories_users, $total);
$accessory = Accessory::findOrFail($id);
if (!Company::isCurrentUserHasAccess($accessory)) {
return ['total' => 0, 'rows' => []];
}
$accessory_users = $accessory->users;
$total = $accessory_users->count();
return (new AccessoriesTransformer)->transformCheckedoutAccessory($accessory_users, $total);
}

View File

@@ -40,10 +40,24 @@ class AssetMaintenancesController extends Controller
$maintenances = $maintenances->TextSearch(e($request->input('search')));
}
if ($request->has('asset_id')) {
$maintenances->where('asset_id', '=', $request->input('asset_id'));
}
$offset = request('offset', 0);
$limit = request('limit', 50);
$allowed_columns = ['id','title','asset_maintenance_time','asset_maintenance_type','cost','start_date','completion_date','notes','user_id'];
$allowed_columns = [
'id',
'title',
'asset_maintenance_time',
'asset_maintenance_type',
'cost',
'start_date',
'completion_date',
'notes',
'user_id'
];
$order = Input::get('order') === 'asc' ? 'asc' : 'desc';
$sort = in_array(Input::get('sort'), $allowed_columns) ? e($request->input('sort')) : 'created_at';
@@ -56,11 +70,9 @@ class AssetMaintenancesController extends Controller
break;
}
$total = $maintenances->count();
$maintenances = $maintenances->skip($offset)->take($limit)->get();
return (new AssetMaintenancesTransformer())->transformAssetMaintenances($maintenances, $maintenances->count());
return (new AssetMaintenancesTransformer())->transformAssetMaintenances($maintenances, $total);
}

View File

@@ -8,6 +8,7 @@ use App\Helpers\Helper;
use Illuminate\Http\Request;
use App\Http\Transformers\AssetModelsTransformer;
use App\Http\Transformers\AssetsTransformer;
use App\Http\Transformers\SelectlistTransformer;
/**
@@ -29,17 +30,22 @@ class AssetModelsController extends Controller
public function index(Request $request)
{
$this->authorize('view', AssetModel::class);
$allowed_columns = ['id','image','name','model_number','eol','notes','created_at','manufacturer'];
$allowed_columns = ['id','image','name','model_number','eol','notes','created_at','manufacturer','assets_count'];
$assetmodels = AssetModel::select(['models.id','models.image','models.name','model_number','eol','models.notes','models.created_at','category_id','manufacturer_id','depreciation_id','fieldset_id'])
$assetmodels = AssetModel::select(['models.id','models.image','models.name','model_number','eol','models.notes','models.created_at','category_id','manufacturer_id','depreciation_id','fieldset_id', 'models.deleted_at'])
->with('category','depreciation', 'manufacturer','fieldset')
->withCount('assets');
if ($request->has('status')) {
$assetmodels->onlyTrashed();
}
if ($request->has('search')) {
$assetmodels->TextSearch($request->input('search'));
}
$offset = $request->input('offset', 0);
$limit = $request->input('limit', 50);
$order = $request->input('order') === 'asc' ? 'asc' : 'desc';
@@ -55,6 +61,7 @@ class AssetModelsController extends Controller
}
$total = $assetmodels->count();
$assetmodels = $assetmodels->skip($offset)->take($limit)->get();
return (new AssetModelsTransformer)->transformAssetModels($assetmodels, $total);
@@ -154,8 +161,69 @@ class AssetModelsController extends Controller
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/models/message.assoc_users')));
}
if ($assetmodel->image) {
try {
unlink(public_path().'/uploads/models/'.$assetmodel->image);
} catch (\Exception $e) {
\Log::error($e);
}
}
$assetmodel->delete();
return response()->json(Helper::formatStandardApiResponse('success', null, trans('admin/assetmodels/message.delete.success')));
}
/**
* Gets a paginated collection for the select2 menus
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v4.0.16]
* @see \App\Http\Transformers\SelectlistTransformer
*
*/
public function selectlist(Request $request)
{
$assetmodels = AssetModel::select([
'models.id',
'models.name',
'models.image',
'models.model_number',
'models.manufacturer_id',
'models.category_id',
])->with('manufacturer','category');
$settings = \App\Models\Setting::getSettings();
if ($request->has('search')) {
$assetmodels = $assetmodels->SearchByManufacturerOrCat($request->input('search'));
}
$assetmodels = $assetmodels->OrderCategory('ASC')->OrderManufacturer('ASC')->orderby('models.name', 'asc')->orderby('models.model_number', 'asc')->paginate(50);
foreach ($assetmodels as $assetmodel) {
$assetmodel->use_text = '';
if ($settings->modellistCheckedValue('category')) {
$assetmodel->use_text .= (($assetmodel->category) ? e($assetmodel->category->name).' - ' : '');
}
if ($settings->modellistCheckedValue('manufacturer')) {
$assetmodel->use_text .= (($assetmodel->manufacturer) ? e($assetmodel->manufacturer->name).' ' : '');
}
$assetmodel->use_text .= e($assetmodel->name);
if (($settings->modellistCheckedValue('model_number')) && ($assetmodel->model_number!='')) {
$assetmodel->use_text .= ' (#'.e($assetmodel->model_number).')';
}
$assetmodel->use_image = ($settings->modellistCheckedValue('image') && ($assetmodel->image)) ? url('/').'/uploads/models/'.$assetmodel->image : null;
}
return (new SelectlistTransformer)->transformSelectlist($assetmodels);
}
}

View File

@@ -4,6 +4,7 @@ namespace App\Http\Controllers\Api;
use App\Helpers\Helper;
use App\Http\Controllers\Controller;
use App\Http\Requests\AssetRequest;
use App\Http\Requests\AssetCheckoutRequest;
use App\Http\Transformers\AssetsTransformer;
use App\Models\Asset;
use App\Models\AssetModel;
@@ -30,6 +31,7 @@ use Str;
use TCPDF;
use Validator;
use View;
use App\Http\Transformers\SelectlistTransformer;
/**
@@ -52,7 +54,9 @@ class AssetsController extends Controller
*/
public function index(Request $request)
{
$this->authorize('index', Asset::class);
$settings = Setting::getSettings();
$allowed_columns = [
'id',
@@ -69,36 +73,37 @@ class AssetsController extends Controller
'created_at',
'updated_at',
'purchase_date',
'purchase_cost'
'purchase_cost',
'last_audit_date',
'next_audit_date',
'warranty_months',
];
$filter = array();
if ($request->has('filter')) {
$filter = json_decode($request->input('filter'));
}
$all_custom_fields = CustomField::all(); //used as a 'cache' of custom fields throughout this page load
foreach ($all_custom_fields as $field) {
$allowed_columns[]=$field->db_column_name();
}
$assets = Company::scopeCompanyables(Asset::select('assets.*'))->with(
'assetloc', 'assetstatus', 'defaultLoc', 'assetlog', 'company',
$assets = Company::scopeCompanyables(Asset::select('assets.*'),"company_id","assets")
->with('location', 'assetstatus', 'assetlog', 'company', 'defaultLoc','assignedTo',
'model.category', 'model.manufacturer', 'model.fieldset','supplier');
// If we should search on everything
if (($request->has('search')) && (count($filter) == 0)) {
$assets->TextSearch($request->input('search'));
// otherwise loop through the filters and search strictly on them
} else {
if (count($filter) > 0) {
$assets->ByFilter($filter);
}
}
// These are used by the API to query against specific ID numbers
// These are used by the API to query against specific ID numbers.
// They are also used by the individual searches on detail pages like
// locations, etc.
if ($request->has('status_id')) {
$assets->where('status_id', '=', $request->input('status_id'));
$assets->where('assets.status_id', '=', $request->input('status_id'));
}
if ($request->has('model_id')) {
@@ -110,13 +115,19 @@ class AssetsController extends Controller
}
if ($request->has('location_id')) {
$assets->ByLocationId($request->input('location_id'));
$assets->where('assets.location_id', '=', $request->input('location_id'));
// dd($assets->toSql());
}
if ($request->has('supplier_id')) {
$assets->where('assets.supplier_id', '=', $request->input('supplier_id'));
}
if (($request->has('assigned_to')) && ($request->has('assigned_type'))) {
$assets->where('assets.assigned_to', '=', $request->input('assigned_to'))
->where('assets.assigned_type', '=', $request->input('assigned_type'));
}
if ($request->has('company_id')) {
$assets->where('assets.company_id', '=', $request->input('company_id'));
}
@@ -125,44 +136,103 @@ class AssetsController extends Controller
$assets->ByManufacturer($request->input('manufacturer_id'));
}
$request->has('order_number') ? $assets = $assets->where('order_number', '=', e($request->get('order_number'))) : '';
if ($request->has('depreciation_id')) {
$assets->ByDepreciationId($request->input('depreciation_id'));
}
$request->has('order_number') ? $assets = $assets->where('assets.order_number', '=', e($request->get('order_number'))) : '';
$offset = request('offset', 0);
$limit = $request->input('limit', 50);
$order = $request->input('order') === 'asc' ? 'asc' : 'desc';
// This is used by the sidenav, mostly
// We switched from using query scopes here because of a Laravel bug
// related to fulltext searches on complex queries.
// I am sad. :(
switch ($request->input('status')) {
case 'Deleted':
$assets->withTrashed()->Deleted();
break;
case 'Pending':
$assets->Pending();
$assets->join('status_labels AS status_alias',function ($join) {
$join->on('status_alias.id', "=", "assets.status_id")
->where('status_alias.deployable','=',0)
->where('status_alias.pending','=',1)
->where('status_alias.archived', '=', 0);
});
break;
case 'RTD':
$assets->RTD();
$assets->whereNull('assets.assigned_to')
->join('status_labels AS status_alias',function ($join) {
$join->on('status_alias.id', "=", "assets.status_id")
->where('status_alias.deployable','=',1)
->where('status_alias.pending','=',0)
->where('status_alias.archived', '=', 0);
});
break;
case 'Undeployable':
$assets->Undeployable();
break;
case 'Archived':
$assets->Archived();
$assets->join('status_labels AS status_alias',function ($join) {
$join->on('status_alias.id', "=", "assets.status_id")
->where('status_alias.deployable','=',0)
->where('status_alias.pending','=',0)
->where('status_alias.archived', '=', 1);
});
break;
case 'Requestable':
$assets->RequestableAssets();
$assets->where('assets.requestable', '=', 1)
->join('status_labels AS status_alias',function ($join) {
$join->on('status_alias.id', "=", "assets.status_id")
->where('status_alias.deployable','=',1)
->where('status_alias.pending','=',0)
->where('status_alias.archived', '=', 0);
});
break;
case 'Deployed':
$assets->Deployed();
// more sad, horrible workarounds for laravel bugs when doing full text searches
$assets->where('assets.assigned_to', '>', '0');
break;
default:
if ((!$request->has('status_id')) && ($settings->show_archived_in_list!='1')) {
// terrible workaround for complex-query Laravel bug in fulltext
$assets->join('status_labels AS status_alias',function ($join) {
$join->on('status_alias.id', "=", "assets.status_id")
->where('status_alias.archived', '=', 0);
});
// If there is a status ID, don't take show_archived_in_list into consideration
} else {
$assets->join('status_labels AS status_alias',function ($join) {
$join->on('status_alias.id', "=", "assets.status_id");
});
}
}
if (count($filter) > 0) {
$assets->ByFilter($filter);
} elseif ($request->has('search')) {
$assets->TextSearch($request->input('search'));
}
// This is kinda gross, but we need to do this because the Bootstrap Tables
// API passes custom field ordering as custom_fields.fieldname, and we have to strip
// that out to let the default sorter below order them correctly on the assets table.
$sort_override = str_replace('custom_fields.','', $request->input('sort')) ;
// This handles all of the pivot sorting (versus the assets.* fields in the allowed_columns array)
$column_sort = in_array($request->input('sort'), $allowed_columns) ? $request->input('sort') : 'assets.created_at';
switch ($request->input('sort')) {
// This handles all of the pivot sorting (versus the assets.* fields
// in the allowed_columns array)
$column_sort = in_array($sort_override, $allowed_columns) ? $sort_override : 'assets.created_at';
switch ($sort_override) {
case 'model':
$assets->OrderModels($order);
break;
@@ -180,6 +250,8 @@ class AssetsController extends Controller
break;
case 'location':
$assets->OrderLocation($order);
case 'rtd_location':
$assets->OrderRtdLocation($order);
break;
case 'status_label':
$assets->OrderStatus($order);
@@ -194,7 +266,8 @@ class AssetsController extends Controller
$assets->orderBy($column_sort, $order);
break;
}
$total = $assets->count();
$assets = $assets->skip($offset)->take($limit)->get();
return (new AssetsTransformer)->transformAssets($assets, $total);
@@ -211,12 +284,65 @@ class AssetsController extends Controller
*/
public function show($id)
{
if ($asset = Asset::withTrashed()->find($id)) {
if ($asset = Asset::with('assetstatus')->with('assignedTo')->withTrashed()->findOrFail($id)) {
$this->authorize('view', $asset);
return (new AssetsTransformer)->transformAsset($asset);
}
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/hardware/message.does_not_exist')), 200);
}
/**
* Gets a paginated collection for the select2 menus
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v4.0.16]
* @see \App\Http\Transformers\SelectlistTransformer
*
*/
public function selectlist(Request $request)
{
$assets = Company::scopeCompanyables(Asset::select([
'assets.id',
'assets.name',
'assets.asset_tag',
'assets.model_id',
'assets.assigned_to',
'assets.assigned_type',
'assets.status_id'
])->with('model', 'assetstatus', 'assignedTo')->NotArchived());
if ($request->has('search')) {
$assets = $assets->AssignedSearch($request->input('search'));
}
$assets = $assets->paginate(50);
// Loop through and set some custom properties for the transformer to use.
// This lets us have more flexibility in special cases like assets, where
// they may not have a ->name value but we want to display something anyway
foreach ($assets as $asset) {
$asset->use_text = $asset->present()->fullName;
if (($asset->checkedOutToUser()) && ($asset->assigned)) {
$asset->use_text .= ' → '.$asset->assigned->getFullNameAttribute();
}
if ($asset->assetstatus->getStatuslabelType()=='pending') {
$asset->use_text .= '('.$asset->assetstatus->getStatuslabelType().')';
}
$asset->use_image = ($asset->getImageUrl()) ? $asset->getImageUrl() : null;
}
return (new SelectlistTransformer)->transformSelectlist($assets);
}
@@ -242,7 +368,7 @@ class AssetsController extends Controller
$asset->model_id = $request->get('model_id');
$asset->order_number = $request->get('order_number');
$asset->notes = $request->get('notes');
$asset->asset_tag = $request->get('asset_tag');
$asset->asset_tag = $request->get('asset_tag', Asset::autoincrement_asset());
$asset->user_id = Auth::id();
$asset->archived = '0';
$asset->physical = '1';
@@ -261,12 +387,12 @@ class AssetsController extends Controller
$model = AssetModel::find($request->get('model_id'));
if ($model->fieldset) {
foreach ($model->fieldset->fields as $field) {
$asset->{$field->convertUnicodeDbSlug()} = e($request->input($field->convertUnicodeDbSlug()));
$asset->{$field->convertUnicodeDbSlug()} = e($request->input($field->convertUnicodeDbSlug(), null));
}
}
if ($asset->save()) {
$asset->logCreate();
if ($request->get('assigned_user')) {
$target = User::find(request('assigned_user'));
} elseif ($request->get('assigned_asset')) {
@@ -329,31 +455,34 @@ class AssetsController extends Controller
$asset->requestable = $request->get('requestable') : '';
($request->has('rtd_location_id')) ?
$asset->rtd_location_id = $request->get('rtd_location_id') : '';
($request->has('rtd_location_id')) ?
$asset->location_id = $request->get('rtd_location_id') : '';
($request->has('company_id')) ?
$asset->company_id = Company::getIdForCurrentUser($request->get('company_id')) : '';
if ($request->has('model_id')) {
if (($model = AssetModel::find($request->get('model_id'))) && (isset($model->fieldset))) {
foreach ($model->fieldset->fields as $field) {
if ($request->has($field->convertUnicodeDbSlug())) {
$asset->{$field->convertUnicodeDbSlug()} = e($request->input($field->convertUnicodeDbSlug()));
}
// Update custom fields
if (($model = AssetModel::find($asset->model_id)) && (isset($model->fieldset))) {
foreach ($model->fieldset->fields as $field) {
if ($request->has($field->convertUnicodeDbSlug())) {
$asset->{$field->convertUnicodeDbSlug()} = e($request->input($field->convertUnicodeDbSlug()));
}
}
}
if ($asset->save()) {
if ($request->get('assigned_user')) {
$target = User::find(request('assigned_user'));
} elseif ($request->get('assigned_asset')) {
$target = Asset::find(request('assigned_asset'));
} elseif ($request->get('assigned_location')) {
$target = Location::find(request('assigned_location'));
if (($request->has('assigned_user')) && ($target = User::find($request->get('assigned_user')))) {
$location = $target->location_id;
} elseif (($request->has('assigned_asset')) && ($target = Asset::find($request->get('assigned_asset')))) {
$location = $target->location_id;
} elseif (($request->has('assigned_location')) && ($target = Location::find($request->get('assigned_location')))) {
$location = $target->id;
}
if (isset($target)) {
$asset->checkOut($target, Auth::user(), date('Y-m-d H:i:s'), '', 'Checked out on asset update', e($request->get('name')));
$asset->checkOut($target, Auth::user(), date('Y-m-d H:i:s'), '', 'Checked out on asset update', e($request->get('name')), $location);
}
return response()->json(Helper::formatStandardApiResponse('success', $asset, trans('admin/hardware/message.update.success')));
@@ -402,7 +531,7 @@ class AssetsController extends Controller
* @since [v4.0]
* @return JsonResponse
*/
public function checkout(Request $request, $asset_id)
public function checkout(AssetCheckoutRequest $request, $asset_id)
{
$this->authorize('checkout', Asset::class);
$asset = Asset::findOrFail($asset_id);
@@ -413,25 +542,61 @@ class AssetsController extends Controller
$this->authorize('checkout', $asset);
if ($request->has('user_id')) {
$target = User::find($request->input('user_id'));
} elseif ($request->has('asset_id')) {
$target = Asset::find($request->input('asset_id'));
} elseif ($request->has('location_id')) {
$target = Location::find($request->input('location_id'));
$error_payload = [];
$error_payload['asset'] = [
'id' => $asset->id,
'asset_tag' => $asset->asset_tag,
];
// This item is checked out to a location
if (request('checkout_to_type')=='location') {
$target = Location::find(request('assigned_location'));
$asset->location_id = ($target) ? $target->id : '';
$error_payload['target_id'] = $request->input('assigned_location');
$error_payload['target_type'] = 'location';
} elseif (request('checkout_to_type')=='asset') {
$target = Asset::where('id','!=',$asset_id)->find(request('assigned_asset'));
$asset->location_id = $target->rtd_location_id;
// Override with the asset's location_id if it has one
if ($target->location_id!='') {
$asset->location_id = ($target) ? $target->location_id : '';
}
$error_payload['target_id'] = $request->input('assigned_asset');
$error_payload['target_type'] = 'asset';
} elseif (request('checkout_to_type')=='user') {
// Fetch the target and set the asset's new location_id
$target = User::find(request('assigned_user'));
$asset->location_id = ($target) ? $target->location_id : '';
$error_payload['target_id'] = $request->input('assigned_user');
$error_payload['target_type'] = 'user';
}
if (!isset($target)) {
return response()->json(Helper::formatStandardApiResponse('error', ['asset'=> e($asset->asset_tag)], 'No valid checkout target specified for asset '.e($asset->asset_tag).'.'));
return response()->json(Helper::formatStandardApiResponse('error', $error_payload, 'Checkout target for asset '.e($asset->asset_tag).' is invalid - '.$error_payload['target_type'].' does not exist.'));
}
$checkout_at = request('checkout_at', date("Y-m-d H:i:s"));
$expected_checkin = request('expected_checkin', null);
$note = request('note', null);
$asset_name = request('name', null);
// Set the location ID to the RTD location id if there is one
if ($asset->rtd_location_id!='') {
$asset->location_id = $target->rtd_location_id;
}
if ($asset->checkOut($target, Auth::user(), $checkout_at, $expected_checkin, $note, $asset_name)) {
if ($asset->checkOut($target, Auth::user(), $checkout_at, $expected_checkin, $note, $asset_name, $asset->location_id)) {
return response()->json(Helper::formatStandardApiResponse('success', ['asset'=> e($asset->asset_tag)], trans('admin/hardware/message.checkout.success')));
}
@@ -447,7 +612,7 @@ class AssetsController extends Controller
* @since [v4.0]
* @return JsonResponse
*/
public function checkin($asset_id)
public function checkin(Request $request, $asset_id)
{
$this->authorize('checkin', Asset::class);
$asset = Asset::findOrFail($asset_id);
@@ -465,6 +630,13 @@ class AssetsController extends Controller
$asset->assignedTo()->disassociate($asset);
$asset->accepted = null;
$asset->name = e(Input::get('name'));
$asset->location_id = $asset->rtd_location_id;
if ($request->has('location_id')) {
$asset->location_id = $request->input('location_id');
}
$asset->location_id = $asset->rtd_location_id;
if (Input::has('status_id')) {
$asset->status_id = e(Input::get('status_id'));
@@ -481,6 +653,9 @@ class AssetsController extends Controller
$data['item_tag'] = $asset->asset_tag;
$data['item_serial'] = $asset->serial;
$data['note'] = $logaction->note;
$data['manufacturer_name'] = $asset->model->manufacturer->name;
$data['model_name'] = $asset->model->name;
$data['model_number'] = $asset->model->model_number;
if ((($asset->checkin_email()=='1')) && (isset($user)) && (!config('app.lock_passwords'))) {
Mail::send('emails.checkin-asset', $data, function ($m) use ($user) {
@@ -524,7 +699,11 @@ class AssetsController extends Controller
if ($asset) {
// We don't want to log this as a normal update, so let's bypass that
$asset->unsetEventDispatcher();
$asset->next_audit_date = $request->input('next_audit_date');
$asset->last_audit_date = date('Y-m-d h:i:s');
if ($asset->save()) {
$log = $asset->logAudit(request('note'),request('location_id'));
return response()->json(Helper::formatStandardApiResponse('success', [

View File

@@ -7,6 +7,7 @@ use App\Http\Controllers\Controller;
use App\Helpers\Helper;
use App\Models\Category;
use App\Http\Transformers\CategoriesTransformer;
use App\Http\Transformers\SelectlistTransformer;
class CategoriesController extends Controller
{
@@ -20,9 +21,9 @@ class CategoriesController extends Controller
public function index(Request $request)
{
$this->authorize('view', Category::class);
$allowed_columns = ['id', 'name','category_type','use_default_eula','require_acceptance','checkin_email'];
$allowed_columns = ['id', 'name','category_type', 'category_type','use_default_eula','eula_text', 'require_acceptance','checkin_email', 'assets_count', 'accessories_count', 'consumables_count', 'components_count', 'image'];
$categories = Category::select(['id', 'created_at', 'updated_at', 'name','category_type','use_default_eula','require_acceptance','checkin_email'])
$categories = Category::select(['id', 'created_at', 'updated_at', 'name','category_type','use_default_eula','eula_text', 'require_acceptance','checkin_email','image'])
->withCount('assets', 'accessories', 'consumables', 'components');
if ($request->has('search')) {
@@ -32,7 +33,7 @@ class CategoriesController extends Controller
$offset = $request->input('offset', 0);
$limit = $request->input('limit', 50);
$order = $request->input('order') === 'asc' ? 'asc' : 'desc';
$sort = in_array($request->input('sort'), $allowed_columns) ? $request->input('sort') : 'created_at';
$sort = in_array($request->input('sort'), $allowed_columns) ? $request->input('sort') : 'assets_count';
$categories->orderBy($sort, $order);
$total = $categories->count();
@@ -128,4 +129,40 @@ class CategoriesController extends Controller
return response()->json(Helper::formatStandardApiResponse('success', null, trans('admin/categories/message.delete.success')));
}
/**
* Gets a paginated collection for the select2 menus
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v4.0.16]
* @see \App\Http\Transformers\SelectlistTransformer
*
*/
public function selectlist(Request $request, $category_type = 'asset')
{
$categories = Category::select([
'id',
'name',
'image',
]);
if ($request->has('search')) {
$categories = $categories->where('name', 'LIKE', '%'.$request->get('search').'%');
}
$categories = $categories->where('category_type', $category_type)->orderBy('name', 'ASC')->paginate(50);
// Loop through and set some custom properties for the transformer to use.
// This lets us have more flexibility in special cases like assets, where
// they may not have a ->name value but we want to display something anyway
foreach ($categories as $category) {
$category->use_image = ($category->image) ? url('/').'/uploads/categories/'.$category->image : null;
}
return (new SelectlistTransformer)->transformSelectlist($categories);
}
}

View File

@@ -7,6 +7,7 @@ use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use App\Helpers\Helper;
use App\Models\Company;
use App\Http\Transformers\SelectlistTransformer;
class CompaniesController extends Controller
{
@@ -21,12 +22,20 @@ class CompaniesController extends Controller
{
$this->authorize('view', Company::class);
$allowed_columns = ['id','name'];
$allowed_columns = [
'id',
'name',
'created_at',
'updated_at',
'users_count',
'assets_count',
'licenses_count',
'accessories_count',
'consumables_count',
'components_count',
];
$companies = Company::withCount('assets','licenses','accessories','consumables','components','users')
->withCount('users')->withCount('users')->withCount('assets')
->withCount('licenses')->withCount('accessories')
->withCount('consumables')->withCount('components');
$companies = Company::withCount('assets','licenses','accessories','consumables','components','users');
if ($request->has('search')) {
$companies->TextSearch($request->input('search'));
@@ -141,4 +150,37 @@ class CompaniesController extends Controller
}
}
/**
* Gets a paginated collection for the select2 menus
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v4.0.16]
* @see \App\Http\Transformers\SelectlistTransformer
*
*/
public function selectlist(Request $request)
{
$companies = Company::select([
'companies.id',
'companies.name',
'companies.image',
]);
if ($request->has('search')) {
$companies = $companies->where('companies.name', 'LIKE', '%'.$request->get('search').'%');
}
$companies = $companies->orderBy('name', 'ASC')->paginate(50);
// Loop through and set some custom properties for the transformer to use.
// This lets us have more flexibility in special cases like assets, where
// they may not have a ->name value but we want to display something anyway
foreach ($companies as $company) {
$company->use_image = ($company->image) ? url('/').'/uploads/companies/'.$company->image : null;
}
return (new SelectlistTransformer)->transformSelectlist($companies);
}
}

View File

@@ -31,10 +31,14 @@ class ComponentsController extends Controller
$components = $components->TextSearch($request->input('search'));
}
if ($request->has('company_id')) {
$components->where('company_id','=',$request->input('company_id'));
}
$offset = request('offset', 0);
$limit = request('limit', 50);
$allowed_columns = ['id','name','min_amt','order_number','serial','purchase_date','purchase_cost','company','category','qty','location'];
$allowed_columns = ['id','name','min_amt','order_number','serial','purchase_date','purchase_cost','company','category','qty','location','image'];
$order = $request->input('order') === 'asc' ? 'asc' : 'desc';
$sort = in_array($request->input('sort'), $allowed_columns) ? $request->input('sort') : 'created_at';
@@ -149,7 +153,7 @@ class ComponentsController extends Controller
*/
public function getAssets(Request $request, $id)
{
$this->authorize('index', Asset::class);
$this->authorize('view', \App\Models\Asset::class);
$component = Component::findOrFail($id);
$assets = $component->assets();
@@ -158,6 +162,6 @@ class ComponentsController extends Controller
$limit = $request->input('limit', 50);
$total = $assets->count();
$assets = $assets->skip($offset)->take($limit)->get();
return (new ComponentsAssetsTransformer)->transformAssets($assets, $total);
return (new ComponentsTransformer)->transformCheckedoutComponents($assets, $total);
}
}

View File

@@ -43,7 +43,7 @@ class ConsumablesController extends Controller
$offset = request('offset', 0);
$limit = request('limit', 50);
$allowed_columns = ['id','name','order_number','min_amt','purchase_date','purchase_cost','company','category','model_number', 'item_no', 'manufacturer','location','qty'];
$allowed_columns = ['id','name','order_number','min_amt','purchase_date','purchase_cost','company','category','model_number', 'item_no', 'manufacturer','location','qty','image'];
$order = $request->input('order') === 'asc' ? 'asc' : 'desc';
$sort = in_array($request->input('sort'), $allowed_columns) ? $request->input('sort') : 'created_at';
@@ -160,7 +160,6 @@ class ConsumablesController extends Controller
*/
public function getDataView($consumableId)
{
//$consumable = Consumable::find($consumableID);
$consumable = Consumable::with(array('consumableAssignments'=>
function ($query) {
$query->orderBy('created_at', 'DESC');
@@ -171,17 +170,15 @@ class ConsumablesController extends Controller
},
))->find($consumableId);
// $consumable->load('consumableAssignments.admin','consumableAssignments.user');
if (!Company::isCurrentUserHasAccess($consumable)) {
return ['total' => 0, 'rows' => []];
}
$this->authorize('view', Component::class);
$this->authorize('view', Consumable::class);
$rows = array();
foreach ($consumable->consumableAssignments as $consumable_assignment) {
$rows[] = [
'name' => $consumable_assignment->user->present()->nameUrl(),
'name' => ($consumable_assignment->user) ? $consumable_assignment->user->present()->nameUrl() : 'Deleted User',
'created_at' => ($consumable_assignment->created_at->format('Y-m-d H:i:s')=='-0001-11-30 00:00:00') ? '' : $consumable_assignment->created_at->format('Y-m-d H:i:s'),
'admin' => ($consumable_assignment->admin) ? $consumable_assignment->admin->present()->nameUrl() : '',
];

View File

@@ -2,11 +2,14 @@
namespace App\Http\Controllers\Api;
use App\Helpers\Helper;
use App\Http\Controllers\Controller;
use App\Http\Transformers\CustomFieldsTransformer;
use App\Models\CustomField;
use App\Models\CustomFieldset;
use Illuminate\Http\Request;
use Validator;
use Illuminate\Validation\Rule;
class CustomFieldsController extends Controller
{
@@ -27,6 +30,81 @@ class CustomFieldsController extends Controller
$total = count($fields);
return (new CustomFieldsTransformer)->transformCustomFields($fields, $total);
}
/**
* Shows the given field
* @author [V. Cordes] [<volker@fdatek.de>]
* @param int $id
* @since [v4.1.10]
* @return View
*/
public function show($id)
{
$this->authorize('show', CustomField::class);
if ($field = CustomField::find($id)) {
return (new CustomFieldsTransformer)->transformCustomField($field);
}
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/custom_fields/message.field.invalid')), 200);
}
/**
* Update the specified field
*
* @author [V. Cordes] [<volker@fdatek.de>]
* @since [v4.1.10]
* @param \Illuminate\Http\Request $request
* @param int $id
* @return \Illuminate\Http\Response
*/
public function update(Request $request, $id)
{
$this->authorize('edit', CustomField::class);
$field = CustomField::findOrFail($id);
$data = $request->all();
$validator = Validator::make($data, $field->validationRules());
if ($validator->fails()) {
return response()->json(Helper::formatStandardApiResponse('error', null, $validator->errors()));
}
$field->fill($data);
if ($field->save()) {
return response()->json(Helper::formatStandardApiResponse('success', $field, trans('admin/custom_fields/message.field.update.success')));
}
return response()->json(Helper::formatStandardApiResponse('error', null, $field->getErrors()));
}
/**
* Store a newly created field.
*
* @author [V. Cordes] [<volker@fdatek.de>]
* @since [v4.1.10]
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response
*/
public function store(Request $request)
{
$this->authorize('create', CustomField::class);
$field = new CustomField;
$data = $request->all();
$validator = Validator::make($data, $field->validationRules());
if ($validator->fails()) {
return response()->json(Helper::formatStandardApiResponse('error', null, $validator->errors()));
}
$field->fill($data);
if ($field->save()) {
return response()->json(Helper::formatStandardApiResponse('success', $field, trans('admin/custom_fields/message.field.create.success')));
}
return response()->json(Helper::formatStandardApiResponse('error', null, $field->getErrors()));
}
public function postReorder(Request $request, $id)
{
$fieldset = CustomFieldset::find($id);
@@ -47,6 +125,38 @@ class CustomFieldsController extends Controller
}
public function associate(Request $request, $field_id)
{
$this->authorize('edit', CustomFieldset::class);
$field = CustomField::findOrFail($field_id);
$fieldset_id = $request->input('fieldset_id');
foreach ($field->fieldset as $fieldset) {
if ($fieldset->id == $fieldset_id) {
return response()->json(Helper::formatStandardApiResponse('success', $fieldset, trans('admin/custom_fields/message.fieldset.update.success')));
}
}
$fieldset = CustomFieldset::findOrFail($fieldset_id);
$fieldset->fields()->attach($field->id, ["required" => ($request->input('required') == "on"), "order" => $request->input('order', $fieldset->fields->count())]);
return response()->json(Helper::formatStandardApiResponse('success', $fieldset, trans('admin/custom_fields/message.fieldset.update.success')));
}
public function disassociate(Request $request, $field_id)
{
$this->authorize('edit', CustomFieldset::class);
$field = CustomField::findOrFail($field_id);
$fieldset_id = $request->input('fieldset_id');
foreach ($field->fieldset as $fieldset) {
if ($fieldset->id == $fieldset_id) {
$fieldset->fields()->detach($field->id);
return response()->json(Helper::formatStandardApiResponse('success', $fieldset, trans('admin/custom_fields/message.fieldset.update.success')));
}
}
$fieldset = CustomFieldset::findOrFail($fieldset_id);
return response()->json(Helper::formatStandardApiResponse('success', $fieldset, trans('admin/custom_fields/message.fieldset.update.success')));
}
/**
* Delete a custom field.
@@ -57,15 +167,15 @@ class CustomFieldsController extends Controller
*/
public function destroy($field_id)
{
$field = CustomField::find($field_id);
$field = CustomField::findOrFail($field_id);
if ($field->fieldset->count() >0) {
return response()->json(Helper::formatStandardApiResponse('error', null, 'Field is in use.'));
} else {
$field->delete();
return response()->json(Helper::formatStandardApiResponse('success', null, trans('admin/custom_fields/message.field.delete.success')));
}
$field->delete();
return response()->json(Helper::formatStandardApiResponse('success', null, trans('admin/custom_fields/message.field.delete.success')));
}
}

View File

@@ -126,7 +126,7 @@ class CustomFieldsetsController extends Controller
{
$this->authorize('delete', CustomFieldset::class);
$fieldset = CustomFieldset::findOrFail($id);
$modelsCount = $fieldset->models->count();
$fieldsCount = $fieldset->fields->count();
@@ -141,7 +141,23 @@ class CustomFieldsetsController extends Controller
return response()->json(Helper::formatStandardApiResponse('error', null, 'Unspecified error'));
}
/**
* Return JSON containing a list of fields belonging to a fieldset.
*
* @author [V. Cordes] [<volker@fdatek.de>]
* @since [v4.1.10]
* @param $fieldsetId
* @return string JSON
*/
public function fields($id)
{
$this->authorize('view', CustomFieldset::class);
$set = CustomFieldset::findOrFail($id);
$fields = $set->fields->get();
return (new CustomFieldsTransformer)->transformCustomFields($fields, $fields->count());
}
}

View File

@@ -8,6 +8,7 @@ use App\Models\Department;
use App\Http\Transformers\DepartmentsTransformer;
use App\Helpers\Helper;
use Auth;
use App\Http\Transformers\SelectlistTransformer;
class DepartmentsController extends Controller
{
@@ -21,7 +22,7 @@ class DepartmentsController extends Controller
public function index(Request $request)
{
$this->authorize('view', Department::class);
$allowed_columns = ['id','name'];
$allowed_columns = ['id','name','image'];
$departments = Department::select([
'id',
@@ -30,7 +31,8 @@ class DepartmentsController extends Controller
'company_id',
'manager_id',
'created_at',
'updated_at'
'updated_at',
'image'
])->with('users')->with('location')->with('manager')->with('company')->withCount('users');
if ($request->has('search')) {
@@ -110,4 +112,38 @@ class DepartmentsController extends Controller
}
/**
* Gets a paginated collection for the select2 menus
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v4.0.16]
* @see \App\Http\Transformers\SelectlistTransformer
*
*/
public function selectlist(Request $request)
{
$departments = Department::select([
'id',
'name',
'image',
]);
if ($request->has('search')) {
$departments = $departments->where('name', 'LIKE', '%'.$request->get('search').'%');
}
$departments = $departments->orderBy('name', 'ASC')->paginate(50);
// Loop through and set some custom properties for the transformer to use.
// This lets us have more flexibility in special cases like assets, where
// they may not have a ->name value but we want to display something anyway
foreach ($departments as $department) {
$department->use_image = ($department->image) ? url('/').'/uploads/departments/'.$department->image : null;
}
return (new SelectlistTransformer)->transformSelectlist($departments);
}
}

View File

@@ -20,7 +20,7 @@ class GroupsController extends Controller
public function index(Request $request)
{
$this->authorize('view', Group::class);
$allowed_columns = ['id','name','created_at'];
$allowed_columns = ['id','name','created_at', 'users_count'];
$groups = Group::select('id','name','permissions','created_at','updated_at')->withCount('users');
@@ -73,7 +73,7 @@ class GroupsController extends Controller
{
$this->authorize('view', Group::class);
$group = Group::findOrFail($id);
return $group;
return (new GroupsTransformer)->transformGroup($group);
}

View File

@@ -5,7 +5,9 @@ namespace App\Http\Controllers\Api;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use App\Http\Transformers\LicensesTransformer;
use App\Http\Transformers\LicenseSeatsTransformer;
use App\Models\License;
use App\Models\LicenseSeat;
use App\Models\Company;
class LicensesController extends Controller
@@ -21,11 +23,8 @@ class LicensesController extends Controller
public function index(Request $request)
{
$this->authorize('view', License::class);
$licenses = Company::scopeCompanyables(License::with('company', 'licenseSeatsRelation', 'manufacturer', 'supplier'));
$licenses = Company::scopeCompanyables(License::with('company', 'manufacturer', 'freeSeats', 'supplier')->withCount('freeSeats'));
if ($request->has('search')) {
$licenses = $licenses->TextSearch($request->input('search'));
}
if ($request->has('company_id')) {
$licenses->where('company_id','=',$request->input('company_id'));
@@ -71,30 +70,38 @@ class LicensesController extends Controller
$licenses->where('supplier_id','=',$request->input('supplier_id'));
}
if ($request->has('search')) {
$licenses = $licenses->TextSearch($request->input('search'));
}
$offset = request('offset', 0);
$limit = request('limit', 50);
$order = $request->input('order') === 'asc' ? 'asc' : 'desc';
switch ($request->input('sort')) {
case 'manufacturer':
$licenses = $licenses->OrderManufacturer($order);
case 'manufacturer':
$licenses = $licenses->leftJoin('manufacturers', 'licenses.manufacturer_id', '=', 'manufacturers.id')->orderBy('manufacturers.name', $order);
break;
case 'supplier':
$licenses = $licenses->OrderSupplier($order);
$licenses = $licenses->leftJoin('suppliers', 'licenses.supplier_id', '=', 'suppliers.id')->orderBy('suppliers.name', $order);
break;
case 'company':
$licenses = $licenses->OrderCompany($order);
$licenses = $licenses->leftJoin('companies', 'licenses.company_id', '=', 'companies.id')->orderBy('companies.name', $order);
break;
default:
$allowed_columns = ['id','name','purchase_cost','expiration_date','purchase_order','order_number','notes','purchase_date','serial','company','license_name','license_email'];
$allowed_columns = ['id','name','purchase_cost','expiration_date','purchase_order','order_number','notes','purchase_date','serial','company','license_name','license_email','free_seats_count','seats'];
$sort = in_array($request->input('sort'), $allowed_columns) ? e($request->input('sort')) : 'created_at';
$licenses = $licenses->orderBy($sort, $order);
break;
}
$total = $licenses->count();
$licenses = $licenses->skip($offset)->take($limit)->get();
return (new LicensesTransformer)->transformLicenses($licenses, $total);
@@ -161,4 +168,38 @@ class LicensesController extends Controller
{
//
}
/**
* Get license seat listing
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v1.0]
* @param int $licenseId
* @return \Illuminate\Contracts\View\View
*/
public function seats(Request $request, $licenseId)
{
if ($license = License::find($licenseId)) {
$seats = LicenseSeat::where('license_id', $licenseId)->with('license', 'user', 'asset');
$offset = request('offset', 0);
$limit = request('limit', 50);
$order = $request->input('order') === 'asc' ? 'asc' : 'desc';
$total = $seats->count();
$seats = $seats->skip($offset)->take($limit)->get();
if ($seats) {
return (new LicenseSeatsTransformer)->transformLicenseSeats($seats, $total);
}
}
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/licenses/message.does_not_exist')), 200);
}
}

View File

@@ -7,6 +7,7 @@ use App\Http\Controllers\Controller;
use App\Helpers\Helper;
use App\Models\Location;
use App\Http\Transformers\LocationsTransformer;
use App\Http\Transformers\SelectlistTransformer;
class LocationsController extends Controller
{
@@ -20,10 +21,12 @@ class LocationsController extends Controller
public function index(Request $request)
{
$this->authorize('view', Location::class);
$allowed_columns = ['id','name','address','address2','city','state','country','zip','created_at',
'updated_at','parent_id', 'manager_id'];
$allowed_columns = [
'id','name','address','address2','city','state','country','zip','created_at',
'updated_at','manager_id','image',
'assigned_assets_count','users_count','assets_count','currency'];
$locations = Location::select([
$locations = Location::with('parent', 'manager', 'childLocations')->select([
'locations.id',
'locations.name',
'locations.address',
@@ -36,23 +39,36 @@ class LocationsController extends Controller
'locations.manager_id',
'locations.created_at',
'locations.updated_at',
'locations.image',
'locations.currency'
])->withCount('assets')->withCount('users');
])->withCount('assignedAssets')
->withCount('assets')
->withCount('users');
if ($request->has('search')) {
$locations = $locations->TextSearch($request->input('search'));
}
$offset = $request->input('offset', 0);
$limit = $request->input('limit', 50);
$order = $request->input('order') === 'asc' ? 'asc' : 'desc';
$sort = in_array($request->input('sort'), $allowed_columns) ? $request->input('sort') : 'created_at';
$locations->orderBy($sort, $order);
switch ($request->input('sort')) {
case 'parent':
$locations->OrderParent($order);
break;
default:
$locations->orderBy($sort, $order);
break;
}
$total = $locations->count();
$locations = $locations->skip($offset)->take($limit)->get();
return (new LocationsTransformer)->transformLocations($locations, $total);
}
@@ -74,7 +90,6 @@ class LocationsController extends Controller
return response()->json(Helper::formatStandardApiResponse('success', (new LocationsTransformer)->transformLocation($location), trans('admin/locations/message.create.success')));
}
return response()->json(Helper::formatStandardApiResponse('error', null, $location->getErrors()));
}
/**
@@ -109,7 +124,13 @@ class LocationsController extends Controller
$location->fill($request->all());
if ($location->save()) {
return response()->json(Helper::formatStandardApiResponse('success', (new LocationsTransformer)->transformLocation($location), trans('admin/locations/message.update.success')));
return response()->json(
Helper::formatStandardApiResponse(
'success',
(new LocationsTransformer)->transformLocation($location),
trans('admin/locations/message.update.success')
)
);
}
return response()->json(Helper::formatStandardApiResponse('error', null, $location->getErrors()));
@@ -129,7 +150,42 @@ class LocationsController extends Controller
$location = Location::findOrFail($id);
$this->authorize('delete', $location);
$location->delete();
return response()->json(Helper::formatStandardApiResponse('success', null, trans('admin/locations/message.delete.success')));
return response()->json(Helper::formatStandardApiResponse('success', null, trans('admin/locations/message.delete.success')));
}
/**
* Gets a paginated collection for the select2 menus
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v4.0.16]
* @see \App\Http\Transformers\SelectlistTransformer
*
*/
public function selectlist(Request $request)
{
$locations = Location::select([
'locations.id',
'locations.name',
'locations.image',
]);
if ($request->has('search')) {
$locations = $locations->where('locations.name', 'LIKE', '%'.$request->get('search').'%');
}
$locations = $locations->orderBy('name', 'ASC')->paginate(50);
// Loop through and set some custom properties for the transformer to use.
// This lets us have more flexibility in special cases like assets, where
// they may not have a ->name value but we want to display something anyway
foreach ($locations as $location) {
$location->use_text = $location->name;
$location->use_image = ($location->image) ? url('/').'/uploads/locations/'.$location->image : null;
}
return (new SelectlistTransformer)->transformSelectlist($locations);
}
}

View File

@@ -8,6 +8,7 @@ use App\Helpers\Helper;
use App\Models\Manufacturer;
use App\Http\Transformers\DatatablesTransformer;
use App\Http\Transformers\ManufacturersTransformer;
use App\Http\Transformers\SelectlistTransformer;
class ManufacturersController extends Controller
{
@@ -21,10 +22,10 @@ class ManufacturersController extends Controller
public function index(Request $request)
{
$this->authorize('view', Manufacturer::class);
$allowed_columns = ['id','name','url','support_url','support_email','support_phone','created_at','updated_at'];
$allowed_columns = ['id','name','url','support_url','support_email','support_phone','created_at','updated_at','image', 'assets_count', 'consumables_count', 'components_count', 'licenses_count'];
$manufacturers = Manufacturer::select(
array('id','name','url','support_url','support_email','support_phone','created_at','updated_at')
array('id','name','url','support_url','support_email','support_phone','created_at','updated_at','image')
)->withCount('assets')->withCount('licenses')->withCount('consumables')->withCount('accessories');
@@ -120,4 +121,39 @@ class ManufacturersController extends Controller
return response()->json(Helper::formatStandardApiResponse('success', null, trans('admin/manufacturers/message.delete.success')));
}
/**
* Gets a paginated collection for the select2 menus
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v4.0.16]
* @see \App\Http\Transformers\SelectlistTransformer
*
*/
public function selectlist(Request $request)
{
$manufacturers = Manufacturer::select([
'id',
'name',
'image',
]);
if ($request->has('search')) {
$manufacturers = $manufacturers->where('name', 'LIKE', '%'.$request->get('search').'%');
}
$manufacturers = $manufacturers->orderBy('name', 'ASC')->paginate(50);
// Loop through and set some custom properties for the transformer to use.
// This lets us have more flexibility in special cases like assets, where
// they may not have a ->name value but we want to display something anyway
foreach ($manufacturers as $manufacturer) {
$manufacturer->use_text = $manufacturer->name;
$manufacturer->use_image = ($manufacturer->image) ? url('/').'/uploads/manufacturers/'.$manufacturer->image : null;
}
return (new SelectlistTransformer)->transformSelectlist($manufacturers);
}
}

View File

@@ -42,19 +42,21 @@ class ReportsController extends Controller
$allowed_columns = [
'id',
'created_at'
'created_at',
'target_id',
'user_id',
'action_type',
'note'
];
$sort = in_array($request->input('sort'), $allowed_columns) ? e($request->input('sort')) : 'created_at';
$order = $request->input('order') === 'asc' ? 'asc' : 'desc';
$order = ($request->input('order') == 'asc') ? 'asc' : 'desc';
$offset = request('offset', 0);
$limit = request('limit', 50);
$total = $actionlogs->count();
$actionlogs = $actionlogs->orderBy($sort, $order);
$actionlogs = $actionlogs->skip($offset)->take($limit)->get();
return (new ActionlogsTransformer)->transformActionlogs($actionlogs, $total);
$actionlogs = $actionlogs->orderBy($sort, $order)->skip($offset)->take($limit)->get();
return response()->json((new ActionlogsTransformer)->transformActionlogs($actionlogs, $total), 200, ['Content-Type' => 'application/json;charset=utf8'], JSON_UNESCAPED_UNICODE);
}
}

View File

@@ -5,78 +5,22 @@ namespace App\Http\Controllers\Api;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use App\Models\Ldap;
use Validator;
use App\Models\Setting;
use Mail;
class SettingsController extends Controller
{
/**
* Display a listing of the resource.
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v4.0]
*
* @return \Illuminate\Http\Response
*/
public function index()
public function ldaptest()
{
//
}
if (Setting::getSettings()->ldap_enabled!='1') {
\Log::debug('LDAP is not enabled cannot test.');
return response()->json(['message' => 'LDAP is not enabled, cannot test.'], 400);
}
/**
* Store a newly created resource in storage.
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v4.0]
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response
*/
public function store(Request $request)
{
//
}
/**
* Display the specified resource.
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @param int $id
* @return \Illuminate\Http\Response
*/
public function show($id)
{
//
}
/**
* Update the specified resource in storage.
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v4.0]
* @param \Illuminate\Http\Request $request
* @param int $id
* @return \Illuminate\Http\Response
*/
public function update(Request $request, $id)
{
//
}
/**
* Remove the specified resource from storage.
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v4.0]
* @param int $id
* @return \Illuminate\Http\Response
*/
public function destroy($id)
{
//
}
public function getLdapTest()
{
\Log::debug('Preparing to test LDAP connection');
try {
@@ -98,4 +42,85 @@ class SettingsController extends Controller
}
public function ldaptestlogin(Request $request)
{
if (Setting::getSettings()->ldap_enabled!='1') {
\Log::debug('LDAP is not enabled. Cannot test.');
return response()->json(['message' => 'LDAP is not enabled, cannot test.'], 400);
}
$rules = array(
'ldaptest_user' => 'required',
'ldaptest_password' => 'required'
);
$validator = Validator::make($request->all(), $rules);
if ($validator->fails()) {
\Log::debug('LDAP Validation test failed.');
$validation_errors = implode(' ',$validator->errors()->all());
return response()->json(['message' => $validator->errors()->all()], 400);
}
\Log::debug('Preparing to test LDAP login');
try {
$connection = Ldap::connectToLdap();
try {
Ldap::bindAdminToLdap($connection);
\Log::debug('Attempting to bind to LDAP for LDAP test');
try {
$ldap_user = Ldap::findAndBindUserLdap($request->input('ldaptest_user'), $request->input('ldaptest_password'));
if ($ldap_user) {
\Log::debug('It worked! '. $request->input('ldaptest_user').' successfully binded to LDAP.');
return response()->json(['message' => 'It worked! '. $request->input('ldaptest_user').' successfully binded to LDAP.'], 200);
}
return response()->json(['message' => 'Login Failed. '. $request->input('ldaptest_user').' did not successfully bind to LDAP.'], 400);
} catch (\Exception $e) {
\Log::debug('LDAP login failed');
return response()->json(['message' => $e->getMessage()], 400);
}
} catch (\Exception $e) {
\Log::debug('Bind failed');
return response()->json(['message' => $e->getMessage()], 400);
//return response()->json(['message' => $e->getMessage()], 500);
}
} catch (\Exception $e) {
\Log::debug('Connection failed');
return response()->json(['message' => $e->getMessage()], 500);
}
}
/**
* Test the email configuration
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v3.0]
* @return Redirect
*/
public function ajaxTestEmail()
{
if (!config('app.lock_passwords')) {
try {
Mail::send('emails.test', [], function ($m) {
$m->to(config('mail.reply_to.address'), config('mail.reply_to.name'));
$m->replyTo(config('mail.reply_to.address'), config('mail.reply_to.name'));
$m->subject(trans('mail.test_email'));
});
return response()->json(['message' => 'Mail sent to '.config('mail.reply_to.address')], 200);
} catch (Exception $e) {
return response()->json(['message' => $e->getMessage()], 500);
}
}
return response()->json(['message' => 'Mail would have been sent, but this application is in demo mode! '], 200);
}
}

View File

@@ -22,7 +22,7 @@ class StatuslabelsController extends Controller
public function index(Request $request)
{
$this->authorize('view', Statuslabel::class);
$allowed_columns = ['id','name','created_at'];
$allowed_columns = ['id','name','created_at', 'assets_count'];
$statuslabels = Statuslabel::withCount('assets');
@@ -137,8 +137,14 @@ class StatuslabelsController extends Controller
$this->authorize('delete', Statuslabel::class);
$statuslabel = Statuslabel::findOrFail($id);
$this->authorize('delete', $statuslabel);
$statuslabel->delete();
return response()->json(Helper::formatStandardApiResponse('success', null, trans('admin/statuslabels/message.delete.success')));
// Check that there are no assets associated
if ($statuslabel->assets()->count() == 0) {
$statuslabel->delete();
return response()->json(Helper::formatStandardApiResponse('success', null, trans('admin/statuslabels/message.delete.success')));
}
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/statuslabels/message.assoc_assets')));
}
@@ -155,22 +161,23 @@ class StatuslabelsController extends Controller
public function getAssetCountByStatuslabel()
{
$statusLabels = Statuslabel::with('assets')->get();
$statuslabels = Statuslabel::with('assets')->groupBy('id')->withCount('assets')->get();
$labels=[];
$points=[];
$colors=[];
foreach ($statusLabels as $statusLabel) {
if ($statusLabel->assets()->count() > 0) {
$labels[]=$statusLabel->name;
$points[]=$statusLabel->assets()->whereNull('assigned_to')->count();
if ($statusLabel->color!='') {
$colors[]=$statusLabel->color;
foreach ($statuslabels as $statuslabel) {
if ($statuslabel->assets_count > 0) {
$labels[]=$statuslabel->name. ' ('.number_format($statuslabel->assets_count).')';
$points[]=$statuslabel->assets_count;
if ($statuslabel->color!='') {
$colors[]=$statuslabel->color;
}
}
}
$labels[]='Deployed';
$points[]=Asset::whereNotNull('assigned_to')->count();
$colors_array = array_merge($colors, Helper::chartColors());
$result= [

View File

@@ -7,6 +7,8 @@ use App\Http\Controllers\Controller;
use App\Helpers\Helper;
use App\Models\Supplier;
use App\Http\Transformers\SuppliersTransformer;
use App\Http\Transformers\SelectlistTransformer;
class SuppliersController extends Controller
{
@@ -20,11 +22,11 @@ class SuppliersController extends Controller
public function index(Request $request)
{
$this->authorize('view', Supplier::class);
$allowed_columns = ['id','name','address','phone','contact','fax','email'];
$allowed_columns = ['id','name','address','phone','contact','fax','email','image','assets_count','licenses_count', 'accessories_count'];
$suppliers = Supplier::select(
array('id','name','address','address2','city','state','country','fax', 'phone','email','contact','created_at','updated_at','deleted_at')
)->withCount('assets')->withCount('licenses')->whereNull('deleted_at');
array('id','name','address','address2','city','state','country','fax', 'phone','email','contact','created_at','updated_at','deleted_at','image')
)->withCount('assets')->withCount('licenses')->withCount('accessories')->whereNull('deleted_at');
if ($request->has('search')) {
@@ -113,10 +115,60 @@ class SuppliersController extends Controller
public function destroy($id)
{
$this->authorize('delete', Supplier::class);
$supplier = Supplier::findOrFail($id);
$supplier = Supplier::with('asset_maintenances', 'assets', 'licenses')->withCount('asset_maintenances','assets', 'licenses')->findOrFail($id);
$this->authorize('delete', $supplier);
if ($supplier->assets_count > 0) {
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/suppliers/message.delete.assoc_assets', ['asset_count' => (int) $supplier->assets_count])));
}
if ($supplier->asset_maintenances_count > 0) {
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/suppliers/message.delete.assoc_maintenances', ['asset_maintenances_count' => $supplier->asset_maintenances_count])));
}
if ($supplier->licenses_count > 0) {
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/suppliers/message.delete.assoc_licenses', ['licenses_count' => (int) $supplier->licenses_count])));
}
$supplier->delete();
return response()->json(Helper::formatStandardApiResponse('success', null, trans('admin/suppliers/message.delete.success')));
}
/**
* Gets a paginated collection for the select2 menus
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v4.0.16]
* @see \App\Http\Transformers\SelectlistTransformer
*
*/
public function selectlist(Request $request)
{
$suppliers = Supplier::select([
'id',
'name',
'image',
]);
if ($request->has('search')) {
$suppliers = $suppliers->where('suppliers.name', 'LIKE', '%'.$request->get('search').'%');
}
$suppliers = $suppliers->orderBy('name', 'ASC')->paginate(50);
// Loop through and set some custom properties for the transformer to use.
// This lets us have more flexibility in special cases like assets, where
// they may not have a ->name value but we want to display something anyway
foreach ($suppliers as $supplier) {
$supplier->use_text = $supplier->name;
$supplier->use_image = ($supplier->image) ? url('/').'/uploads/suppliers/'.$supplier->image : null;
}
return (new SelectlistTransformer)->transformSelectlist($suppliers);
}
}

View File

@@ -10,6 +10,8 @@ use App\Models\User;
use App\Helpers\Helper;
use App\Http\Requests\SaveUserRequest;
use App\Models\Asset;
use App\Http\Transformers\AssetsTransformer;
use App\Http\Transformers\SelectlistTransformer;
class UsersController extends Controller
{
@@ -31,6 +33,12 @@ class UsersController extends Controller
'users.two_factor_enrolled',
'users.jobtitle',
'users.email',
'users.phone',
'users.address',
'users.city',
'users.state',
'users.country',
'users.zip',
'users.username',
'users.location_id',
'users.manager_id',
@@ -42,37 +50,41 @@ class UsersController extends Controller
'users.last_login',
'users.deleted_at',
'users.department_id',
'users.activated'
])->with('manager', 'groups', 'userloc', 'company', 'department','throttle','assets','licenses','accessories','consumables')
'users.activated',
'users.avatar',
])->with('manager', 'groups', 'userloc', 'company', 'department','assets','licenses','accessories','consumables')
->withCount('assets','licenses','accessories','consumables');
$users = Company::scopeCompanyables($users);
if ($request->has('search')) {
$users = $users->TextSearch($request->input('search'));
}
if (($request->has('deleted')) && ($request->input('deleted')=='true')) {
$users = $users->GetDeleted();
}
if ($request->has('company_id')) {
$users = $users->where('company_id', '=', $request->input('company_id'));
$users = $users->where('users.company_id', '=', $request->input('company_id'));
}
if ($request->has('location_id')) {
$users = $users->where('location_id', '=', $request->input('location_id'));
$users = $users->where('users.location_id', '=', $request->input('location_id'));
}
if ($request->has('group_id')) {
$users = $users->ByGroup($request->get('group_id'));
}
if ($request->has('department_id')) {
$users = $users->where('department_id','=',$request->input('department_id'));
$users = $users->where('users.department_id','=',$request->input('department_id'));
}
if ($request->has('search')) {
$users = $users->TextSearch($request->input('search'));
}
$order = $request->input('order') === 'asc' ? 'asc' : 'desc';
$offset = request('offset', 0);
$limit = request('limit', 50);
$limit = request('limit', 20);
switch ($request->input('sort')) {
case 'manager':
@@ -89,19 +101,84 @@ class UsersController extends Controller
[
'last_name','first_name','email','jobtitle','username','employee_num',
'assets','accessories', 'consumables','licenses','groups','activated','created_at',
'two_factor_enrolled','two_factor_optin','last_login'
'two_factor_enrolled','two_factor_optin','last_login', 'assets_count', 'licenses_count',
'consumables_count', 'accessories_count', 'phone', 'address', 'city', 'state',
'country', 'zip'
];
$sort = in_array($request->get('sort'), $allowed_columns) ? $request->get('sort') : 'first_name';
$users = $users->orderBy($sort, $order);
break;
}
$total = $users->count();
$users = $users->skip($offset)->take($limit)->get();
return (new UsersTransformer)->transformUsers($users, $total);
}
/**
* Gets a paginated collection for the select2 menus
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v4.0.16]
* @see \App\Http\Transformers\SelectlistTransformer
*
*/
public function selectlist(Request $request)
{
$users = User::select(
[
'users.id',
'users.username',
'users.employee_num',
'users.first_name',
'users.last_name',
'users.gravatar',
'users.avatar',
'users.email',
]
);
$users = Company::scopeCompanyables($users);
if ($request->has('search')) {
$users = $users->where('first_name', 'LIKE', '%'.$request->get('search').'%')
->orWhere('last_name', 'LIKE', '%'.$request->get('search').'%')
->orWhere('username', 'LIKE', '%'.$request->get('search').'%')
->orWhere('employee_num', 'LIKE', '%'.$request->get('search').'%');
}
$users = $users->orderBy('last_name', 'asc')->orderBy('first_name', 'asc');
$users = $users->paginate(50);
foreach ($users as $user) {
$name_str = '';
if ($user->last_name!='') {
$name_str .= e($user->last_name).', ';
}
$name_str .= e($user->first_name);
if ($user->username!='') {
$name_str .= ' ('.e($user->username).')';
}
if ($user->employee_num!='') {
$name_str .= ' - #'.e($user->employee_num);
}
$user->use_text = $name_str;
$user->use_image = ($user->present()->gravatar) ? $user->present()->gravatar : null;
}
return (new SelectlistTransformer)->transformSelectlist($users);
}
/**
* Store a newly created resource in storage.
*
@@ -118,7 +195,7 @@ class UsersController extends Controller
$user->password = bcrypt($request->input('password'));
if ($user->save()) {
return response()->json(Helper::formatStandardApiResponse('success', (new UsersTransformer)->transformUser($user), trans('admin/users/message.create.success')));
return response()->json(Helper::formatStandardApiResponse('success', (new UsersTransformer)->transformUser($user), trans('admin/users/message.success.create')));
}
return response()->json(Helper::formatStandardApiResponse('error', null, $user->getErrors()));
}
@@ -153,10 +230,17 @@ class UsersController extends Controller
$user = User::findOrFail($id);
$user->fill($request->all());
if ($user->id == $request->input('manager_id')) {
return response()->json(Helper::formatStandardApiResponse('error', null, 'You cannot be your own manager'));
}
if ($request->has('password')) {
$user->password = bcrypt($request->input('password'));
}
// Update the location of any assets checked out to this user
Asset::where('assigned_type', User::class)
->where('assigned_to', $user->id)->update(['location_id' => $request->input('location_id', null)]);
if ($user->save()) {
return response()->json(Helper::formatStandardApiResponse('success', (new UsersTransformer)->transformUser($user), trans('admin/users/message.success.update')));
@@ -202,6 +286,6 @@ class UsersController extends Controller
{
$this->authorize('view', User::class);
$assets = Asset::where('assigned_to', '=', $id)->with('model')->get();
return response()->json($assets);
return (new AssetsTransformer)->transformAssets($assets, $assets->count());
}
}

View File

@@ -63,85 +63,6 @@ class AssetMaintenancesController extends Controller
}
/**
* Generates the JSON response for asset maintenances listing view.
*
* @see AssetMaintenancesController::getIndex() method that generates view
* @author Vincent Sposato <vincent.sposato@gmail.com>
* @version v1.0
* @since [v1.8]
* @return String JSON
*/
public function getDatatable(Request $request)
{
$maintenances = AssetMaintenance::with('asset', 'supplier', 'asset.company', 'admin');
if (Input::has('search')) {
$maintenances = $maintenances->TextSearch(e($request->input('search')));
}
$offset = request('offset', 0);
$limit = request('limit', 50);
$allowed_columns = ['id','title','asset_maintenance_time','asset_maintenance_type','cost','start_date','completion_date','notes','user_id'];
$order = Input::get('order') === 'asc' ? 'asc' : 'desc';
$sort = in_array(Input::get('sort'), $allowed_columns) ? e($request->input('sort')) : 'created_at';
switch ($sort) {
case 'user_id':
$maintenances = $maintenances->OrderAdmin($order);
break;
default:
$maintenances = $maintenances->orderBy($sort, $order);
break;
}
$maintenancesCount = $maintenances->count();
$maintenances = $maintenances->skip($offset)->take($limit)->get();
$rows = array();
$settings = Setting::getSettings();
foreach ($maintenances as $maintenance) {
$actions = '';
if (Gate::allows('update', Asset::class)) {
$actions .= Helper::generateDatatableButton('edit', route('maintenances.edit', $maintenance->id));
$actions .= Helper::generateDatatableButton(
'delete',
route('maintenances.destroy', $maintenance->id),
$enabled = true,
trans('admin/asset_maintenances/message.delete.confirm'),
$maintenance->title
);
}
if (($maintenance->cost) && (isset($maintenance->asset)) && ($maintenance->asset->assetloc) && ($maintenance->asset->assetloc->currency!='')) {
$maintenance_cost = $maintenance->asset->assetloc->currency.$maintenance->cost;
} else {
$maintenance_cost = $settings->default_currency.$maintenance->cost;
}
$rows[] = array(
'id' => $maintenance->id,
'asset_name' => ($maintenance->asset) ? (string)link_to_route('maintenances.show', $maintenance->asset->present()->Name(), ['maintenance' => $maintenance->asset->id]) : 'Deleted Asset' ,
'title' => $maintenance->title,
'notes' => $maintenance->notes,
'supplier' => ($maintenance->supplier) ? (string)link_to_route('suppliers.show', $maintenance->supplier->name, ['maintenance'=>$maintenance->supplier->id]) : 'Deleted Supplier',
'cost' => $maintenance_cost,
'asset_maintenance_type' => e($maintenance->asset_maintenance_type),
'start_date' => $maintenance->start_date,
'asset_maintenance_time' => $maintenance->asset_maintenance_time,
'completion_date' => $maintenance->completion_date,
'user_id' => ($maintenance->admin) ? (string)link_to_route('users.show', $maintenance->admin->present()->fullName(), ['user'=>$maintenance->admin->id]) : '',
'actions' => $actions,
'company' => ($maintenance->asset->company) ? $maintenance->asset->company->name : ''
);
}
$data = array('total' => $maintenancesCount, 'rows' => $rows);
return $data;
}
/**
* Returns a form view to create a new asset maintenance.
@@ -154,16 +75,21 @@ class AssetMaintenancesController extends Controller
*/
public function create()
{
$asset = null;
if ($asset = Asset::find(request('asset_id'))) {
// We have to set this so that the correct property is set in the select2 ajax dropdown
$asset->asset_id = $asset->id;
}
// Prepare Asset Maintenance Type List
$assetMaintenanceType = [
'' => 'Select an asset maintenance type',
] + AssetMaintenance::getImprovementOptions();
// Mark the selected asset, if it came in
// Render the view
return view('asset_maintenances/edit')
->with('asset_list', Helper::detailedAssetList())
->with('selectedAsset', request('asset_id'))
->with('supplier_list', Helper::suppliersList())
->with('asset', $asset)
->with('assetMaintenanceType', $assetMaintenanceType)
->with('item', new AssetMaintenance);
}
@@ -260,9 +186,7 @@ class AssetMaintenancesController extends Controller
// Get Supplier List
// Render the view
return view('asset_maintenances/edit')
->with('asset_list', Helper::detailedAssetList())
->with('selectedAsset', null)
->with('supplier_list', Helper::suppliersList())
->with('assetMaintenanceType', $assetMaintenanceType)
->with('item', $assetMaintenance);

View File

@@ -17,6 +17,7 @@ use App\Models\Company;
use Config;
use App\Helpers\Helper;
use Illuminate\Http\Request;
use App\Http\Requests\ImageUploadRequest;
use Symfony\Component\HttpFoundation\JsonResponse;
@@ -34,12 +35,12 @@ class AssetModelsController extends Controller
* the content for the accessories listing, which is generated in getDatatable.
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @see AssetModelsController::getDatatable() method that generates the JSON response
* @since [v1.0]
* @return View
*/
public function index()
{
$this->authorize('index', AssetModel::class);
return view('models/index');
}
@@ -52,11 +53,10 @@ class AssetModelsController extends Controller
*/
public function create()
{
// Show the page
return view('models/edit')
->with('category_list', Helper::categoryList('asset'))
$this->authorize('create', AssetModel::class);
$category_type = 'asset';
return view('models/edit')->with('category_type',$category_type)
->with('depreciation_list', Helper::depreciationList())
->with('manufacturer_list', Helper::manufacturerList())
->with('item', new AssetModel);
}
@@ -68,9 +68,10 @@ class AssetModelsController extends Controller
* @since [v1.0]
* @return Redirect
*/
public function store(Request $request)
public function store(ImageUploadRequest $request)
{
$this->authorize('create', AssetModel::class);
// Create a new asset model
$model = new AssetModel;
@@ -90,14 +91,21 @@ class AssetModelsController extends Controller
}
if (Input::file('image')) {
$image = Input::file('image');
$file_name = str_random(25).".".$image->getClientOriginalExtension();
$path = public_path('uploads/models/'.$file_name);
Image::make($image->getRealPath())->resize(500, null, function ($constraint) {
$constraint->aspectRatio();
$constraint->upsize();
})->save($path);
$file_name = str_slug($image->getClientOriginalName()) . "." . $image->getClientOriginalExtension();
$path = app('models_upload_path');
if ($image->getClientOriginalExtension()!='svg') {
Image::make($image->getRealPath())->resize(500, null, function ($constraint) {
$constraint->aspectRatio();
$constraint->upsize();
})->save($path.'/'.$file_name);
} else {
$image->move($path, $file_name);
}
$model->image = $file_name;
}
// Was it created?
@@ -119,7 +127,8 @@ class AssetModelsController extends Controller
*/
public function apiStore(Request $request)
{
//COPYPASTA!!!! FIXME
//COPYPASTA!!!! FIXME
$this->authorize('create', AssetModel::class);
$model = new AssetModel;
$settings=Input::all();
@@ -157,17 +166,16 @@ class AssetModelsController extends Controller
*/
public function edit($modelId = null)
{
// Check if the model exists
if (is_null($item = AssetModel::find($modelId))) {
// Redirect to the model management page
return redirect()->route('models.index')->with('error', trans('admin/models/message.does_not_exist'));
$this->authorize('edit', AssetModel::class);
if ($item = AssetModel::find($modelId)) {
$category_type = 'asset';
$view = View::make('models/edit', compact('item','category_type'));
$view->with('depreciation_list', Helper::depreciationList());
return $view;
}
$view = View::make('models/edit', compact('item'));
$view->with('category_list', Helper::categoryList('asset'));
$view->with('depreciation_list', Helper::depreciationList());
$view->with('manufacturer_list', Helper::manufacturerList());
return $view;
return redirect()->route('models.index')->with('error', trans('admin/models/message.does_not_exist'));
}
@@ -180,23 +188,23 @@ class AssetModelsController extends Controller
* @param int $modelId
* @return Redirect
*/
public function update(Request $request, $modelId = null)
public function update(ImageUploadRequest $request, $modelId = null)
{
$this->authorize('edit', AssetModel::class);
// Check if the model exists
if (is_null($model = AssetModel::find($modelId))) {
// Redirect to the models management page
return redirect()->route('models.index')->with('error', trans('admin/models/message.does_not_exist'));
}
$model->depreciation_id = $request->input('depreciation_id');
$model->eol = $request->input('eol');
$model->depreciation_id = $request->input('depreciation_id');
$model->eol = $request->input('eol');
$model->name = $request->input('name');
$model->model_number = $request->input('model_number');
$model->manufacturer_id = $request->input('manufacturer_id');
$model->category_id = $request->input('category_id');
$model->notes = $request->input('notes');
$model->requestable = Input::has('requestable');
$model->requestable = $request->input('requestable', '0');
if ($request->input('custom_fieldset')=='') {
$model->fieldset_id = null;
@@ -204,21 +212,38 @@ class AssetModelsController extends Controller
$model->fieldset_id = $request->input('custom_fieldset');
}
if (Input::file('image')) {
$image = Input::file('image');
$file_name = str_random(25).".".$image->getClientOriginalExtension();
$path = public_path('uploads/models/'.$file_name);
Image::make($image->getRealPath())->resize(300, null, function ($constraint) {
$constraint->aspectRatio();
$constraint->upsize();
})->save($path);
$model->image = $file_name;
}
$old_image = $model->image;
if ($request->input('image_delete') == 1 && Input::file('image') == "") {
// Set the model's image property to null if the image is being deleted
if ($request->input('image_delete') == 1) {
$model->image = null;
}
if ($request->file('image')) {
$image = $request->file('image');
$file_name = $model->id.'-'.str_slug($image->getClientOriginalName()) . "." . $image->getClientOriginalExtension();
if ($image->getClientOriginalExtension()!='svg') {
Image::make($image->getRealPath())->resize(500, null, function ($constraint) {
$constraint->aspectRatio();
$constraint->upsize();
})->save(app('models_upload_path').$file_name);
} else {
$image->move(app('models_upload_path'), $file_name);
}
$model->image = $file_name;
}
if ((($request->file('image')) && (isset($old_image)) && ($old_image!='')) || ($request->input('image_delete') == 1)) {
try {
unlink(app('models_upload_path').$old_image);
} catch (\Exception $e) {
\Log::error($e);
}
}
if ($model->save()) {
return redirect()->route("models.index")->with('success', trans('admin/models/message.update.success'));
}
@@ -236,6 +261,7 @@ class AssetModelsController extends Controller
*/
public function destroy($modelId)
{
$this->authorize('delete', AssetModel::class);
// Check if the model exists
if (is_null($model = AssetModel::find($modelId))) {
return redirect()->route('models.index')->with('error', trans('admin/models/message.not_found'));
@@ -245,6 +271,15 @@ class AssetModelsController extends Controller
// Throw an error that this model is associated with assets
return redirect()->route('models.index')->with('error', trans('admin/models/message.assoc_users'));
}
if ($model->image) {
try {
unlink(public_path().'/uploads/models/'.$model->image);
} catch (\Exception $e) {
\Log::error($e);
}
}
// Delete the model
$model->delete();
@@ -263,7 +298,7 @@ class AssetModelsController extends Controller
*/
public function getRestore($modelId = null)
{
$this->authorize('create', AssetModel::class);
// Get user information
$model = AssetModel::withTrashed()->find($modelId);
@@ -294,6 +329,7 @@ class AssetModelsController extends Controller
*/
public function show($modelId = null)
{
$this->authorize('view', AssetModel::class);
$model = AssetModel::withTrashed()->find($modelId);
if (isset($model->id)) {
@@ -352,49 +388,6 @@ class AssetModelsController extends Controller
/**
* Get the asset information to present to the model view detail page
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v2.0]
* @param Request $request
* @param $modelID
* @return String JSON
* @internal param int $modelId
*/
public function getDataView(Request $request, $modelID)
{
$assets = Asset::where('model_id', '=', $modelID)->with('company', 'assetstatus');
if (Input::has('search')) {
$assets = $assets->TextSearch(e($request->input('search')));
}
$offset = request('offset', 0);
$limit = request('limit', 50);
$allowed_columns = ['name', 'serial','asset_tag'];
$order = $request->input('order') === 'asc' ? 'asc' : 'desc';
$sort = in_array($request->input('sort'), $allowed_columns) ? e($request->input('sort')) : 'created_at';
$assets = $assets->orderBy($sort, $order);
$assetsCount = $assets->count();
$assets = $assets->skip($offset)->take($limit)->get();
$rows = array();
$all_custom_fields = CustomField::all();
foreach ($assets as $asset) {
$rows[] = $asset->present()->forDataTable($all_custom_fields);
}
$data = array('total' => $assetsCount, 'rows' => $rows);
return $data;
}
/**
* Returns a view that allows the user to bulk edit model attrbutes
@@ -405,20 +398,46 @@ class AssetModelsController extends Controller
*/
public function postBulkEdit(Request $request)
{
$models_raw_array = Input::get('ids');
$models = AssetModel::whereIn('id', $models_raw_array)->get();
$nochange = ['NC' => 'No Change'];
$fieldset_list = $nochange + Helper::customFieldsetList();
$depreciation_list = $nochange + Helper::depreciationList();
$category_list = $nochange + Helper::categoryList('asset');
$manufacturer_list = $nochange + Helper::manufacturerList();
return view('models/bulk-edit', compact('models'))
->with('manufacturer_list', $manufacturer_list)
->with('category_list', $category_list)
->with('fieldset_list', $fieldset_list)
->with('depreciation_list', $depreciation_list);
$models_raw_array = Input::get('ids');
// Make sure some IDs have been selected
if ((is_array($models_raw_array)) && (count($models_raw_array) > 0)) {
$models = AssetModel::whereIn('id', $models_raw_array)->withCount('assets')->orderBy('assets_count', 'ASC')->get();
// If deleting....
if ($request->input('bulk_actions')=='delete') {
$valid_count = 0;
foreach ($models as $model) {
if ($model->assets_count == 0) {
$valid_count++;
}
}
return view('models/bulk-delete', compact('models'))->with('valid_count', $valid_count);
// Otherwise display the bulk edit screen
} else {
$nochange = ['NC' => 'No Change'];
$fieldset_list = $nochange + Helper::customFieldsetList();
$depreciation_list = $nochange + Helper::depreciationList();
$category_list = $nochange + Helper::categoryList('asset');
$manufacturer_list = $nochange + Helper::manufacturerList();
return view('models/bulk-edit', compact('models'))
->with('manufacturer_list', $manufacturer_list)
->with('category_list', $category_list)
->with('fieldset_list', $fieldset_list)
->with('depreciation_list', $depreciation_list);
}
}
return redirect()->route('models.index')
->with('error', 'You must select at least one model to edit.');
}
@@ -437,6 +456,7 @@ class AssetModelsController extends Controller
$models_raw_array = Input::get('ids');
$update_array = array();
if (($request->has('manufacturer_id') && ($request->input('manufacturer_id')!='NC'))) {
$update_array['manufacturer_id'] = $request->input('manufacturer_id');
}
@@ -463,4 +483,52 @@ class AssetModelsController extends Controller
}
/**
* Validate and delete the given Asset Models. An Asset Model
* cannot be deleted if there are associated assets.
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v1.0]
* @param int $modelId
* @return Redirect
*/
public function postBulkDelete(Request $request)
{
$models_raw_array = Input::get('ids');
if ((is_array($models_raw_array)) && (count($models_raw_array) > 0)) {
$models = AssetModel::whereIn('id', $models_raw_array)->withCount('assets')->get();
$del_error_count = 0;
$del_count = 0;
foreach ($models as $model) {
\Log::debug($model->id);
if ($model->assets_count > 0) {
$del_error_count++;
} else {
$model->delete();
$del_count++;
}
}
\Log::debug($del_count);
\Log::debug($del_error_count);
if ($del_error_count == 0) {
return redirect()->route('models.index')
->with('success', trans('admin/models/message.bulkdelete.success',['success_count'=> $del_count] ));
}
return redirect()->route('models.index')
->with('warning', trans('admin/models/message.bulkdelete.success_partial', ['fail_count'=>$del_error_count, 'success_count'=> $del_count]));
}
return redirect()->route('models.index')
->with('error', trans('admin/models/message.bulkdelete.error'));
}
}

View File

@@ -38,6 +38,7 @@ use Symfony\Component\HttpFoundation\File\Exception\FileException;
use TCPDF;
use Validator;
use View;
use App\Models\CheckoutRequest;
/**
* This class controls all actions related to assets for
@@ -75,7 +76,7 @@ class AssetsController extends Controller
} else {
$company = null;
}
return view('hardware/index')->with('company',$company);
return view('hardware/index')->with('company', $company);
}
/**
@@ -94,7 +95,6 @@ class AssetsController extends Controller
}
$this->authorize('view', $asset);
return redirect()->route('hardware.show', $asset->id)->with('topsearch', $topsearch);
}
/**
@@ -111,24 +111,17 @@ class AssetsController extends Controller
$this->authorize('create', Asset::class);
$view = View::make('hardware/edit')
->with('supplier_list', Helper::suppliersList())
->with('company_list', Helper::companyList())
->with('model_list', Helper::modelList())
->with('statuslabel_list', Helper::statusLabelList())
->with('location_list', Helper::locationsList())
->with('item', new Asset)
->with('manufacturer', Helper::manufacturerList()) //handled in modal now?
->with('category', Helper::categoryList('asset')) //handled in modal now?
->with('statuslabel_types', Helper::statusTypeList()) //handled in modal now?
->with('users_list', Helper::usersList())
->with('assets_list', Helper::assetsList())
->with('locations_list', Helper::locationsList());
->with('statuslabel_types', Helper::statusTypeList());
if ($request->has('model_id')) {
$selected_model = AssetModel::find($request->input('model_id'));
$view->with('selected_model', $selected_model);
} else {
}
return $view;
}
@@ -142,17 +135,18 @@ class AssetsController extends Controller
public function store(AssetRequest $request)
{
$this->authorize(Asset::class);
// create a new model instance
$asset = new Asset();
$asset->model()->associate(AssetModel::find(e(Input::get('model_id'))));
$asset->name = Input::get('name');
$asset->serial = Input::get('serial');
$asset->company_id = Company::getIdForCurrentUser(Input::get('company_id'));
$asset->model_id = Input::get('model_id');
$asset->order_number = Input::get('order_number');
$asset->notes = Input::get('notes');
$asset->asset_tag = Input::get('asset_tag');
$asset = new Asset();
$asset->model()->associate(AssetModel::find($request->input('model_id')));
$asset->name = $request->input('name');
$asset->serial = $request->input('serial');
$asset->company_id = Company::getIdForCurrentUser($request->input('company_id'));
$asset->model_id = $request->input('model_id');
$asset->order_number = $request->input('order_number');
$asset->notes = $request->input('notes');
$asset->asset_tag = $request->input('asset_tag');
$asset->user_id = Auth::id();
$asset->archived = '0';
$asset->physical = '1';
@@ -166,10 +160,13 @@ class AssetsController extends Controller
$asset->requestable = request('requestable', 0);
$asset->rtd_location_id = request('rtd_location_id', null);
// Create the image (if one was chosen.)
if (Input::has('image')) {
if ($asset->assigned_to=='') {
$asset->location_id = $request->input('rtd_location_id', null);
}
$image = Input::get('image');
// Create the image (if one was chosen.)
if ($request->has('image')) {
$image = $request->input('image');
// After modification, the image is prefixed by mime info like the following:
// data:image/jpeg;base64,; This causes the image library to be unhappy, so we need to remove it.
@@ -201,45 +198,42 @@ class AssetsController extends Controller
->put('default', $messageBag));
return response()->json(['image' => $e->getMessage()], 422);
}
}
// Update custom fields in the database.
// Validation for these fields is handled through the AssetRequest form request
// FIXME: No idea why this is returning a Builder error on db_column_name.
// Need to investigate and fix. Using static method for now.
$model = AssetModel::find($request->get('model_id'));
if ($model->fieldset) {
foreach ($model->fieldset->fields as $field) {
if ($field->field_encrypted=='1') {
if (Gate::allows('admin')) {
$asset->{$field->convertUnicodeDbSlug()} = \Crypt::encrypt($request->input($field->convertUnicodeDbSlug()));
}
} else {
$asset->{$field->convertUnicodeDbSlug()} = $request->input($field->convertUnicodeDbSlug());
}
}
}
// Was the asset created?
if ($asset->save()) {
$asset->logCreate();
if(request('assigned_user')) {
if (request('assigned_user')) {
$target = User::find(request('assigned_user'));
} elseif(request('assigned_asset')) {
$location = $target->location_id;
} elseif (request('assigned_asset')) {
$target = Asset::find(request('assigned_asset'));
} elseif(request('assigned_location')) {
$location = $target->location_id;
} elseif (request('assigned_location')) {
$target = Location::find(request('assigned_location'));
$location = $target->id;
}
if (isset($target)) {
$asset->checkOut($target, Auth::user(), date('Y-m-d H:i:s'), '', 'Checked out on asset creation', e(Input::get('name')));
$asset->checkOut($target, Auth::user(), date('Y-m-d H:i:s'), '', 'Checked out on asset creation', e(Input::get('name')), $location);
}
// Redirect to the asset listing page
\Session::flash('success', trans('admin/hardware/message.create.success'));
@@ -268,15 +262,9 @@ class AssetsController extends Controller
$this->authorize($item);
return view('hardware/edit', compact('item'))
->with('model_list', Helper::modelList())
->with('supplier_list', Helper::suppliersList())
->with('company_list', Helper::companyList())
->with('locations_list', Helper::locationsList())
->with('statuslabel_list', Helper::statusLabelList())
->with('assigned_to', Helper::usersList())
->with('manufacturer', Helper::manufacturerList())
->with('statuslabel_types', Helper::statusTypeList())
->with('category', Helper::categoryList('asset'));
->with('model_list', Helper::modelList())
->with('statuslabel_list', Helper::statusLabelList())
->with('statuslabel_types', Helper::statusTypeList());
}
@@ -291,7 +279,6 @@ class AssetsController extends Controller
public function update(AssetRequest $request, $assetId = null)
{
// Check if the asset exists
if (!$asset = Asset::find($assetId)) {
// Redirect to the asset management page with error
@@ -309,6 +296,11 @@ class AssetsController extends Controller
$asset->requestable = $request->has('requestable');
$asset->rtd_location_id = $request->input('rtd_location_id', null);
if ($asset->assigned_to=='') {
$asset->location_id = $request->input('rtd_location_id', null);
}
if ($request->has('image_delete')) {
unlink(public_path().'/uploads/assets/'.$asset->image);
$asset->image = '';
@@ -369,7 +361,6 @@ class AssetsController extends Controller
if (Gate::allows('admin')) {
$asset->{$field->convertUnicodeDbSlug()} = \Crypt::encrypt(e($request->input($field->convertUnicodeDbSlug())));
}
} else {
$asset->{$field->convertUnicodeDbSlug()} = $request->input($field->convertUnicodeDbSlug());
}
@@ -380,12 +371,11 @@ class AssetsController extends Controller
if ($asset->save()) {
// Redirect to the new asset page
\Session::flash('success', trans('admin/hardware/message.update.success'));
return response()->json(['redirect_url' => route("view/hardware", $assetId)]);
return response()->json(['redirect_url' => route("hardware.show", $assetId)]);
}
\Input::flash();
\Session::flash('errors', $asset->getErrors());
return response()->json(['errors' => $asset->getErrors()], 500);
}
/**
@@ -407,19 +397,11 @@ class AssetsController extends Controller
$this->authorize('delete', $asset);
DB::table('assets')
->where('id', $asset->id)
->update(array('assigned_to' => null));
->where('id', $asset->id)
->update(array('assigned_to' => null));
$asset->delete();
$logaction = new Actionlog();
$logaction->item_type = Asset::class;
$logaction->item_id = $asset->id;
$logaction->created_at = date("Y-m-d H:i:s");
$logaction->user_id = Auth::user()->id;
$log = $logaction->logaction('deleted');
// Redirect to the asset management page
return redirect()->route('hardware.index')->with('success', trans('admin/hardware/message.delete.success'));
}
@@ -442,11 +424,12 @@ class AssetsController extends Controller
$this->authorize('checkout', $asset);
if ($asset->availableForCheckout()) {
return view('hardware/checkout', compact('asset'));
}
return redirect()->route('hardware.index')->with('error', trans('admin/hardware/message.checkout.not_available'));
// Get the dropdown of users and then pass it to the checkout view
return view('hardware/checkout', compact('asset'))
->with('users_list', Helper::usersList())
->with('assets_list', Helper::assetsList())
->with('locations_list', Helper::locationsList());
}
@@ -468,17 +451,34 @@ class AssetsController extends Controller
return redirect()->route('hardware.index')->with('error', trans('admin/hardware/message.checkout.not_available'));
}
$this->authorize('checkout', $asset);
if(request('assigned_user')) {
$target = User::find(request('assigned_user'));
} elseif(request('assigned_asset')) {
$target = Asset::find(request('assigned_asset'));
} elseif(request('assigned_location')) {
$target = Location::find(request('assigned_location'));
}
// $user = User::find(Input::get('assigned_to'));
$admin = Auth::user();
// This item is checked out to a location
if (request('checkout_to_type')=='location') {
$target = Location::find(request('assigned_location'));
$asset->location_id = ($target) ? $target->id : '';
} elseif (request('checkout_to_type')=='asset') {
$target = Asset::where('id','!=',$assetId)->find(request('assigned_asset'));
$asset->location_id = $target->rtd_location_id;
// Override with the asset's location_id if it has one
if ($target->location_id!='') {
$asset->location_id = ($target) ? $target->location_id : '';
}
} elseif (request('checkout_to_type')=='user') {
// Fetch the target and set the asset's new location_id
$target = User::find(request('assigned_user'));
$asset->location_id = ($target) ? $target->location_id : '';
}
// No valid target was found - error out
if (!$target) {
return redirect()->back()->with('error', trans('admin/hardware/message.checkout.error'))->withErrors($asset->getErrors());
}
if ((Input::has('checkout_at')) && (Input::get('checkout_at')!= date("Y-m-d"))) {
$checkout_at = Input::get('checkout_at');
} else {
@@ -490,12 +490,13 @@ class AssetsController extends Controller
} else {
$expected_checkin = '';
}
if ($asset->checkOut($target, $admin, $checkout_at, $expected_checkin, e(Input::get('note')), Input::get('name'))) {
// Redirect to the new asset page
return redirect()->route("hardware.index")->with('success', trans('admin/hardware/message.checkout.success'));
}
// Redirect to the asset management page with error
// Redirect to the asset management page with error
return redirect()->to("hardware/$assetId/checkout")->with('error', trans('admin/hardware/message.checkout.error'))->withErrors($asset->getErrors());
}
@@ -519,7 +520,6 @@ class AssetsController extends Controller
$this->authorize('checkin', $asset);
return view('hardware/checkin', compact('asset'))->with('statusLabel_list', Helper::statusLabelList())->with('backto', $backto);
}
@@ -544,7 +544,7 @@ class AssetsController extends Controller
$this->authorize('checkin', $asset);
$admin = Auth::user();
if($asset->assignedType() == Asset::USER) {
if ($asset->assignedType() == Asset::USER) {
$user = $asset->assignedTo;
}
if (is_null($target = $asset->assignedTo)) {
@@ -562,17 +562,28 @@ class AssetsController extends Controller
if (Input::has('status_id')) {
$asset->status_id = e(Input::get('status_id'));
}
$asset->location_id = $asset->rtd_location_id;
if (Input::has('location_id')) {
$asset->location_id = e(Input::get('location_id'));
}
// Was the asset updated?
if ($asset->save()) {
$logaction = $asset->logCheckin($target, e(request('note')));
$data['log_id'] = $logaction->id;
$data['first_name'] = get_class($target) == User::class ? $target->first_name : '';
$data['last_name'] = get_class($target) == User::class ? $target->last_name : '';
$data['item_name'] = $asset->present()->name();
$data['checkin_date'] = $logaction->created_at;
$data['item_tag'] = $asset->asset_tag;
$data['item_serial'] = $asset->serial;
$data['note'] = $logaction->note;
$data['manufacturer_name'] = $asset->model->manufacturer->name;
$data['model_name'] = $asset->model->name;
$data['model_number'] = $asset->model->model_number;
if ((($asset->checkin_email()=='1')) && (isset($user)) && (!empty($user->email)) && (!config('app.lock_passwords'))) {
Mail::send('emails.checkin-asset', $data, function ($m) use ($user) {
@@ -583,7 +594,7 @@ class AssetsController extends Controller
}
if ($backto=='user') {
return redirect()->to("admin/users/".$user->id.'/view')->with('success', trans('admin/hardware/message.checkin.success'));
return redirect()->route("users.show", $user->id)->with('success', trans('admin/hardware/message.checkin.success'));
}
return redirect()->route("hardware.index")->with('success', trans('admin/hardware/message.checkin.success'));
}
@@ -607,15 +618,18 @@ class AssetsController extends Controller
$asset = Asset::withTrashed()->find($assetId);
$this->authorize('view', $asset);
$settings = Setting::getSettings();
$audit_log = Actionlog::where('action_type','=','audit')->where('item_id','=',$assetId)->where('item_type','=',Asset::class)->orderBy('created_at','DESC')->first();
if (isset($asset)) {
$audit_log = Actionlog::where('action_type', '=', 'audit')
->where('item_id', '=', $assetId)
->where('item_type', '=', Asset::class)
->orderBy('created_at', 'DESC')->first();
if (!is_null($asset->assetloc)) {
$use_currency = $asset->assetloc->currency;
if ($asset->location) {
$use_currency = $asset->location->currency;
} else {
if ($settings->default_currency!='') {
$use_currency = $settings->default_currency;
} else {
@@ -629,10 +643,10 @@ class AssetsController extends Controller
);
return view('hardware/view', compact('asset', 'qr_code', 'settings'))
->with('use_currency', $use_currency)->with('audit_log',$audit_log);
->with('use_currency', $use_currency)->with('audit_log', $audit_log);
}
return redirect()->route('hardware.index')->with('error', trans('admin/hardware/message.does_not_exist', compact('id')));
return redirect()->route('hardware.index')->with('error', trans('admin/hardware/message.does_not_exist'));
}
/**
@@ -648,24 +662,25 @@ class AssetsController extends Controller
$settings = Setting::getSettings();
if ($settings->qr_code == '1') {
$asset = Asset::find($assetId);
$size = Helper::barcodeDimensions($settings->barcode_type);
$qr_file = public_path().'/uploads/barcodes/qr-'.str_slug($asset->asset_tag).'-'.str_slug($asset->id).'.png';
$asset = Asset::withTrashed()->find($assetId);
if ($asset) {
$size = Helper::barcodeDimensions($settings->barcode_type);
$qr_file = public_path().'/uploads/barcodes/qr-'.str_slug($asset->asset_tag).'-'.str_slug($asset->id).'.png';
if (isset($asset->id,$asset->asset_tag)) {
if (file_exists($qr_file)) {
$header = ['Content-type' => 'image/png'];
return response()->file($qr_file, $header);
} else {
$barcode = new \Com\Tecnick\Barcode\Barcode();
$barcode_obj = $barcode->getBarcodeObj($settings->barcode_type, route('hardware.show', $asset->id), $size['height'], $size['width'], 'black', array(-2, -2, -2, -2));
file_put_contents($qr_file, $barcode_obj->getPngData());
return response($barcode_obj->getPngData())->header('Content-type', 'image/png');
if (isset($asset->id, $asset->asset_tag)) {
if (file_exists($qr_file)) {
$header = ['Content-type' => 'image/png'];
return response()->file($qr_file, $header);
} else {
$barcode = new \Com\Tecnick\Barcode\Barcode();
$barcode_obj = $barcode->getBarcodeObj($settings->barcode_type, route('hardware.show', $asset->id), $size['height'], $size['width'], 'black', array(-2, -2, -2, -2));
file_put_contents($qr_file, $barcode_obj->getPngData());
return response($barcode_obj->getPngData())->header('Content-type', 'image/png');
}
}
}
return 'That asset is invalid';
}
}
@@ -683,19 +698,21 @@ class AssetsController extends Controller
$asset = Asset::find($assetId);
$barcode_file = public_path().'/uploads/barcodes/'.str_slug($settings->alt_barcode).'-'.str_slug($asset->asset_tag).'.png';
if (isset($asset->id,$asset->asset_tag)) {
if (isset($asset->id, $asset->asset_tag)) {
if (file_exists($barcode_file)) {
$header = ['Content-type' => 'image/png'];
return response()->file($barcode_file, $header);
} else {
// Calculate barcode width in pixel based on label width (inch)
$barcode_width = ($settings->labels_width - $settings->labels_display_sgutter) * 96.000000000001;
$barcode = new \Com\Tecnick\Barcode\Barcode();
$barcode_obj = $barcode->getBarcodeObj($settings->alt_barcode, $asset->asset_tag, 250, 20);
$barcode_obj = $barcode->getBarcodeObj($settings->alt_barcode,$asset->asset_tag,($barcode_width < 300 ? $barcode_width : 300),50);
file_put_contents($barcode_file, $barcode_obj->getPngData());
return response($barcode_obj->getPngData())->header('Content-type', 'image/png');
}
}
}
/**
@@ -723,18 +740,9 @@ class AssetsController extends Controller
$asset->assigned_to = '';
return view('hardware/edit')
->with('supplier_list', Helper::suppliersList())
->with('model_list', Helper::modelList())
->with('statuslabel_list', Helper::statusLabelList())
->with('statuslabel_types', Helper::statusTypeList())
->with('assigned_to', Helper::usersList())
->with('item', $asset)
->with('locations_list', Helper::locationsList())
->with('manufacturer', Helper::manufacturerList())
->with('category', Helper::categoryList('asset'))
->with('users_list', Helper::usersList())
->with('assets_list', Helper::assetsList())
->with('company_list', Helper::companyList());
->with('item', $asset);
}
/**
@@ -762,7 +770,6 @@ class AssetsController extends Controller
*/
public function postImportHistory(Request $request)
{
if (!ini_get("auto_detect_line_endings")) {
ini_set("auto_detect_line_endings", '1');
}
@@ -780,9 +787,7 @@ class AssetsController extends Controller
foreach ($results as $row) {
if (is_array($row)) {
$row = array_change_key_case($row, CASE_LOWER);
$asset_tag = Helper::array_smart_fetch($row, "asset tag");
if (!array_key_exists($asset_tag, $item)) {
@@ -797,7 +802,6 @@ class AssetsController extends Controller
$item[$asset_tag][$batch_counter]['email'] = Helper::array_smart_fetch($row, "email");
if ($asset = Asset::where('asset_tag', '=', $asset_tag)->first()) {
$item[$asset_tag][$batch_counter]['asset_id'] = $asset->id;
$base_username = User::generateFormattedNameFromFullName(Setting::getSettings()->username_format, $item[$asset_tag][$batch_counter]['name']);
@@ -854,12 +858,10 @@ class AssetsController extends Controller
} else {
$status['error'][]['asset'][$asset_tag]['msg'] = 'Asset and user was matched but could not be saved.';
}
} else {
$item[$asset_tag][$batch_counter]['checkedout_to'] = null;
$status['error'][]['user'][Helper::array_smart_fetch($row, "name")]['msg'] = 'User does not exist so no checkin log was created.';
}
} else {
$item[$asset_tag][$batch_counter]['asset_id'] = null;
$status['error'][]['asset'][$asset_tag]['msg'] = 'Asset does not exist so no match was attempted.';
@@ -875,7 +877,6 @@ class AssetsController extends Controller
// Only do this if a matching user was found
if ((array_key_exists('checkedout_to', $asset_batch[$x])) && ($asset_batch[$x]['checkedout_to']!='')) {
if (($total_in_batch > 1) && ($x < $total_in_batch) && (array_key_exists($next, $asset_batch))) {
$checkin_date = Carbon::parse($asset_batch[$next]['checkout_date'])->subDay(1)->format('Y-m-d H:i:s');
$asset_batch[$x]['real_checkin'] = $checkin_date;
@@ -912,6 +913,14 @@ class AssetsController extends Controller
if (isset($asset->id)) {
// Restore the asset
Asset::withTrashed()->where('id', $assetId)->restore();
$logaction = new Actionlog();
$logaction->item_type = Asset::class;
$logaction->item_id = $asset->id;
$logaction->created_at = date("Y-m-d H:i:s");
$logaction->user_id = Auth::user()->id;
$logaction->logaction('restored');
return redirect()->route('hardware.index')->with('success', trans('admin/hardware/message.restore.success'));
}
return redirect()->route('hardware.index')->with('error', trans('admin/hardware/message.does_not_exist'));
@@ -933,27 +942,23 @@ class AssetsController extends Controller
if (!$asset = Asset::find($assetId)) {
return redirect()->route('hardware.index')->with('error', trans('admin/hardware/message.does_not_exist'));
}
$this->authorize('update', $asset);
$destinationPath = config('app.private_uploads').'/assets';
if (Input::hasFile('assetfile')) {
foreach (Input::file('assetfile') as $file) {
if ($request->hasFile('assetfile')) {
foreach ($request->file('assetfile') as $file) {
$extension = $file->getClientOriginalExtension();
$filename = 'hardware-'.$asset->id.'-'.str_random(8);
$filename .= '-'.str_slug($file->getClientOriginalName()).'.'.$extension;
$upload_success = $file->move($destinationPath, $filename);
//Log the deletion of seats to the log
$file->move($destinationPath, $filename);
$asset->logUpload($filename, e(Input::get('notes')));
}
} else {
return redirect()->back()->with('error', trans('admin/hardware/message.upload.nofiles'));
}
if ($upload_success) {
return redirect()->back()->with('success', trans('admin/hardware/message.upload.success'));
}
return redirect()->back()->with('error', trans('admin/hardware/message.upload.error'));
return redirect()->back()->with('error', trans('admin/hardware/message.upload.nofiles'));
}
/**
@@ -982,13 +987,10 @@ class AssetsController extends Controller
}
$log->delete();
return redirect()->back()->with('success', trans('admin/hardware/message.deletefile.success'));
}
// Prepare the error message
$error = trans('admin/hardware/message.does_not_exist', compact('id'));
// Redirect to the hardware management page
return redirect()->route('hardware.index')->with('error', $error);
return redirect()->route('hardware.index')->with('error', trans('admin/hardware/message.does_not_exist'));
}
/**
@@ -1036,8 +1038,6 @@ class AssetsController extends Controller
{
$this->authorize('update', Asset::class);
if (!$request->has('ids')) {
return redirect()->back()->with('error', 'No assets selected');
}
@@ -1049,33 +1049,23 @@ class AssetsController extends Controller
if ($request->has('bulk_actions')) {
if ($request->input('bulk_actions')=='labels') {
$count = 0;
return view('hardware/labels')
->with('assets', Asset::find($asset_ids))
->with('settings', Setting::getSettings())
->with('count', $count)
->with('settings',
Setting::getSettings()
);
->with('count', $count);
} elseif ($request->input('bulk_actions')=='delete') {
$assets = Asset::with('assignedTo', 'assetloc')->find($asset_ids);
$assets->each(function($asset) {
$this->authorize('delete',$asset);
$assets = Asset::with('assignedTo', 'location')->find($asset_ids);
$assets->each(function ($asset) {
$this->authorize('delete', $asset);
});
return view('hardware/bulk-delete')->with('assets', $assets);
// Bulk edit
} elseif ($request->input('bulk_actions')=='edit') {
return view('hardware/bulk')
->with('assets', request('ids'))
->with('supplier_list', Helper::suppliersList())
->with('statuslabel_list', Helper::statusLabelList())
->with('location_list', Helper::locationsList())
->with('models_list', Helper::modelList())
->with(
'companies_list',
array('' => '') + array('clear' => trans('general.remove_company')) + Helper::companyList()
@@ -1093,71 +1083,81 @@ class AssetsController extends Controller
* @internal param array $assets
* @since [v2.0]
*/
public function postBulkSave()
public function postBulkSave(Request $request)
{
$this->authorize('update', Asset::class);
if (Input::has('ids')) {
$assets = Input::get('ids');
if ((Input::has('purchase_date'))
|| (Input::has('purchase_cost'))
|| (Input::has('supplier_id'))
|| (Input::has('order_number'))
|| (Input::has('warranty_months'))
|| (Input::has('rtd_location_id'))
|| (Input::has('requestable'))
|| (Input::has('company_id'))
|| (Input::has('status_id'))
|| (Input::has('model_id'))
\Log::debug($request->input('ids'));
if (($request->has('ids')) && (count($request->input('ids')) > 0)) {
$assets = $request->input('ids');
if (($request->has('purchase_date'))
|| ($request->has('purchase_cost'))
|| ($request->has('supplier_id'))
|| ($request->has('order_number'))
|| ($request->has('warranty_months'))
|| ($request->has('rtd_location_id'))
|| ($request->has('requestable'))
|| ($request->has('company_id'))
|| ($request->has('status_id'))
|| ($request->has('model_id'))
) {
foreach ($assets as $key => $value) {
$update_array = array();
if (Input::has('purchase_date')) {
$update_array['purchase_date'] = e(Input::get('purchase_date'));
if ($request->has('purchase_date')) {
$update_array['purchase_date'] = $request->input('purchase_date');
}
if (Input::has('purchase_cost')) {
$update_array['purchase_cost'] = Helper::ParseFloat(e(Input::get('purchase_cost')));
if ($request->has('purchase_cost')) {
$update_array['purchase_cost'] = Helper::ParseFloat($request->input('purchase_cost'));
}
if (Input::has('supplier_id')) {
$update_array['supplier_id'] = e(Input::get('supplier_id'));
if ($request->has('supplier_id')) {
$update_array['supplier_id'] = $request->input('supplier_id');
}
if (Input::has('model_id')) {
$update_array['model_id'] = e(Input::get('model_id'));
if ($request->has('model_id')) {
$update_array['model_id'] = $request->input('model_id');
}
if (Input::has('company_id')) {
if (Input::get('company_id')=="clear") {
if ($request->has('company_id')) {
if ($request->input('company_id')=="clear") {
$update_array['company_id'] = null;
} else {
$update_array['company_id'] = e(Input::get('company_id'));
$update_array['company_id'] = $request->input('company_id');
}
}
if (Input::has('order_number')) {
$update_array['order_number'] = e(Input::get('order_number'));
if ($request->has('order_number')) {
$update_array['order_number'] = $request->input('order_number');
}
if (Input::has('warranty_months')) {
$update_array['warranty_months'] = e(Input::get('warranty_months'));
if ($request->has('warranty_months')) {
$update_array['warranty_months'] = $request->input('warranty_months');
}
if (Input::has('rtd_location_id')) {
$update_array['rtd_location_id'] = e(Input::get('rtd_location_id'));
if ($request->has('rtd_location_id')) {
$update_array['rtd_location_id'] = $request->input('rtd_location_id');
if (($request->has('update_real_loc'))
&& (($request->input('update_real_loc')) == '1'))
{
$update_array['location_id'] = $request->input('rtd_location_id');
}
}
if (Input::has('status_id')) {
$update_array['status_id'] = e(Input::get('status_id'));
if ($request->has('status_id')) {
$update_array['status_id'] = $request->input('status_id');
}
if (Input::has('requestable')) {
$update_array['requestable'] = e(Input::get('requestable'));
if ($request->has('requestable')) {
$update_array['requestable'] = $request->input('requestable');
}
DB::table('assets')
->where('id', $key)
->update($update_array);
->where('id', $key)
->update($update_array);
} // endforeach
return redirect()->to("hardware")->with('success', trans('admin/hardware/message.update.success'));
return redirect()->route("hardware.index")->with('success', trans('admin/hardware/message.update.success'));
// no values given, nothing to update
}
return redirect()->to("hardware")->with('info', trans('admin/hardware/message.update.nothing_updated'));
return redirect()->route("hardware.index")->with('warning', trans('admin/hardware/message.update.nothing_updated'));
} // endif
return redirect()->to("hardware");
return redirect()->route("hardware.index")->with('warning', trans('No assets selected, so nothing was updated.'));
}
/**
@@ -1171,8 +1171,7 @@ class AssetsController extends Controller
public function postBulkDelete()
{
$this->authorize('delete', Asset::class);
if (Input::has('ids')) {
$assets = Asset::find(Input::get('ids'));
foreach ($assets as $asset) {
@@ -1180,9 +1179,8 @@ class AssetsController extends Controller
$update_array['assigned_to'] = null;
DB::table('assets')
->where('id', $asset->id)
->update($update_array);
->where('id', $asset->id)
->update($update_array);
} // endforeach
return redirect()->to("hardware")->with('success', trans('admin/hardware/message.delete.success'));
// no values given, nothing to update
@@ -1195,10 +1193,9 @@ class AssetsController extends Controller
{
$this->authorize('checkout', Asset::class);
// Filter out assets that are not deployable.
$assets_list = Company::scopeCompanyables(Asset::RTD()->get(), 'assets.company_id')->pluck('detailed_name', 'id')->toArray();
return view('hardware/bulk-checkout')
->with('users_list', Helper::usersList())
->with('assets_list', $assets_list);
->with('users_list', Helper::usersList());
}
public function postBulkCheckout(Request $request)
@@ -1210,6 +1207,14 @@ class AssetsController extends Controller
$user = User::find(e(Input::get('assigned_to')));
$admin = Auth::user();
if (!$user) {
return redirect()->route('hardware/bulkcheckout')->withInput()->with('error', trans('admin/hardware/message.checkout.user_does_not_exist'));
}
if (!is_array(Input::get('selected_assets'))) {
return redirect()->route('hardware/bulkcheckout')->withInput()->with('error', trans('admin/hardware/message.checkout.no_assets_selected'));
}
$asset_ids = array_filter(Input::get('selected_assets'));
if ((Input::has('checkout_at')) && (Input::get('checkout_at')!= date("Y-m-d"))) {
@@ -1224,13 +1229,22 @@ class AssetsController extends Controller
$expected_checkin = '';
}
$errors = [];
DB::transaction(function () use ($user, $admin, $checkout_at, $expected_checkin, $errors, $asset_ids) {
foreach ($asset_ids as $asset_id) {
$asset = Asset::find($asset_id);
$this->authorize('checkout', $asset);
$error = $asset->checkOutToUser($user, $admin, $checkout_at, $expected_checkin, e(Input::get('note')), null);
$error = $asset->checkOut($user, $admin, $checkout_at, $expected_checkin, e(Input::get('note')), null);
if ($user->location_id!='') {
$asset->location_id = $user->location_id;
$asset->unsetEventDispatcher();
$asset->save();
}
if ($error) {
array_merge_recursive($errors, $asset->getErrors()->toArray());
@@ -1247,23 +1261,25 @@ class AssetsController extends Controller
}
public function quickScan(Request $request)
public function quickScan()
{
$this->authorize('audit', Asset::class);
$dt = Carbon::now()->addMonths(12)->toDateString();
return view('hardware/quickscan')->with('next_audit_date', $dt)->with('locations_list', Helper::locationsList());
return view('hardware/quickscan')->with('next_audit_date', $dt);
}
public function audit(Request $request, $id)
public function audit($id)
{
$settings = Setting::getSettings();
$this->authorize('audit', Asset::class);
$dt = Carbon::now()->addMonths(12)->toDateString();
$dt = Carbon::now()->addMonths($settings->audit_interval)->toDateString();
$asset = Asset::findOrFail($id);
return view('hardware/audit')->with('asset', $asset)->with('next_audit_date', $dt)->with('locations_list', Helper::locationsList());
return view('hardware/audit')->with('asset', $asset)->with('next_audit_date', $dt)->with('locations_list');
}
public function auditStore(Request $request, $id)
{
$this->authorize('audit', Asset::class);
@@ -1279,13 +1295,25 @@ class AssetsController extends Controller
}
$asset = Asset::findOrFail($id);
// We don't want to log this as a normal update, so let's bypass that
$asset->unsetEventDispatcher();
$asset->next_audit_date = $request->input('next_audit_date');
$asset->last_audit_date = date('Y-m-d h:i:s');
if ($asset->save()) {
$asset->logAudit(request('note'),request('location_id'));
$asset->logAudit(request('note'), request('location_id'));
return redirect()->to("hardware")->with('success', trans('admin/hardware/message.audit.success'));
}
}
public function getRequestedIndex($id = null)
{
if ($id) {
$requestedItems = CheckoutRequest::where('user_id', $id)->with('user', 'requestedItem')->get();
}
$requestedItems = CheckoutRequest::with('user', 'requestedItem')->get();
return view('hardware/requested', compact('requestedItems'));
}
}

View File

@@ -47,6 +47,7 @@ class LoginController extends Controller
public function __construct()
{
$this->middleware('guest', ['except' => ['logout','postTwoFactorAuth','getTwoFactorAuth','getTwoFactorEnroll']]);
\Session::put('backUrl', \URL::previous());
}
@@ -320,4 +321,9 @@ class LoginController extends Controller
return redirect()->route('login');
}
public function redirectTo()
{
return Session::get('backUrl') ? Session::get('backUrl') : $this->redirectTo;
}
}

View File

@@ -0,0 +1,23 @@
<?php
namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use Illuminate\Foundation\Auth\ResetsPasswords;
class RegisterController extends Controller
{
public function __construct()
{
$this->middleware('guest');
}
public function showRegistrationForm() {
abort(404,'Page not found');
}
public function register() {
abort(404,'Page not found');
}
}

View File

@@ -25,7 +25,7 @@ class ResetPasswordController extends Controller
*
* @var string
*/
protected $redirectTo = '/home';
protected $redirectTo = '/';
/**
* Create a new controller instance.

View File

@@ -15,6 +15,8 @@ use Lang;
use Redirect;
use Str;
use View;
use Image;
use App\Http\Requests\ImageUploadRequest;
/**
* This class controls all actions related to Categories for
@@ -38,6 +40,7 @@ class CategoriesController extends Controller
public function index()
{
// Show the page
$this->authorize('view', Category::class);
return view('categories/index');
}
@@ -53,6 +56,7 @@ class CategoriesController extends Controller
public function create()
{
// Show the page
$this->authorize('create', Category::class);
$category_types= Helper::categoryTypeList();
return view('categories/edit')->with('item', new Category)
->with('category_types', $category_types);
@@ -67,11 +71,10 @@ class CategoriesController extends Controller
* @since [v1.0]
* @return \Illuminate\Http\RedirectResponse
*/
public function store(Request $request)
public function store(ImageUploadRequest $request)
{
// create a new model instance
$this->authorize('create', Category::class);
$category = new Category();
// Update the category data
$category->name = $request->input('name');
$category->category_type = $request->input('category_type');
$category->eula_text = $request->input('eula_text');
@@ -80,6 +83,18 @@ class CategoriesController extends Controller
$category->checkin_email = $request->input('checkin_email', '0');
$category->user_id = Auth::id();
if ($request->file('image')) {
$image = $request->file('image');
$file_name = str_random(25).".".$image->getClientOriginalExtension();
$path = public_path('uploads/categories/'.$file_name);
Image::make($image->getRealPath())->resize(200, null, function ($constraint) {
$constraint->aspectRatio();
$constraint->upsize();
})->save($path);
$category->image = $file_name;
}
if ($category->save()) {
return redirect()->route('categories.index')->with('success', trans('admin/categories/message.create.success'));
}
@@ -98,10 +113,9 @@ class CategoriesController extends Controller
*/
public function edit($categoryId = null)
{
// Check if the category exists
$this->authorize('edit', Category::class);
if (is_null($item = Category::find($categoryId))) {
// Redirect to the blogs management page
return redirect()->to('admin/settings/categories')->with('error', trans('admin/categories/message.does_not_exist'));
return redirect()->route('categories.index')->with('error', trans('admin/categories/message.does_not_exist'));
}
$category_types= Helper::categoryTypeList();
@@ -120,9 +134,9 @@ class CategoriesController extends Controller
* @return \Illuminate\Http\RedirectResponse
* @since [v1.0]
*/
public function update(Request $request, $categoryId = null)
public function update(ImageUploadRequest $request, $categoryId = null)
{
// Check if the blog post exists
$this->authorize('edit', Category::class);
if (is_null($category = Category::find($categoryId))) {
// Redirect to the categories management page
return redirect()->to('admin/categories')->with('error', trans('admin/categories/message.does_not_exist'));
@@ -138,6 +152,38 @@ class CategoriesController extends Controller
$category->require_acceptance = $request->input('require_acceptance', '0');
$category->checkin_email = $request->input('checkin_email', '0');
$old_image = $category->image;
// Set the model's image property to null if the image is being deleted
if ($request->input('image_delete') == 1) {
$category->image = null;
}
if ($request->file('image')) {
$image = $request->file('image');
$file_name = $category->id.'-'.str_slug($image->getClientOriginalName()) . "." . $image->getClientOriginalExtension();
if ($image->getClientOriginalExtension()!='svg') {
Image::make($image->getRealPath())->resize(500, null, function ($constraint) {
$constraint->aspectRatio();
$constraint->upsize();
})->save(app('categories_upload_path').$file_name);
} else {
$image->move(app('categories_upload_path'), $file_name);
}
$category->image = $file_name;
}
if ((($request->file('image')) && (isset($old_image)) && ($old_image!='')) || ($request->input('image_delete') == 1)) {
try {
unlink(app('categories_upload_path').$old_image);
} catch (\Exception $e) {
\Log::error($e);
}
}
if ($category->save()) {
// Redirect to the new category page
return redirect()->route('categories.index')->with('success', trans('admin/categories/message.update.success'));
@@ -156,24 +202,25 @@ class CategoriesController extends Controller
*/
public function destroy($categoryId)
{
$this->authorize('delete', Category::class);
// Check if the category exists
if (is_null($category = Category::find($categoryId))) {
return redirect()->to('admin/settings/categories')->with('error', trans('admin/categories/message.not_found'));
return redirect()->route('categories.index')->with('error', trans('admin/categories/message.not_found'));
}
if ($category->has_models() > 0) {
return redirect()->to('admin/settings/categories')->with('error', trans('admin/categories/message.assoc_items', ['asset_type'=>'model']));
return redirect()->route('categories.index')->with('error', trans('admin/categories/message.assoc_items', ['asset_type'=>'model']));
} elseif ($category->accessories()->count() > 0) {
return redirect()->to('admin/settings/categories')->with('error', trans('admin/categories/message.assoc_items', ['asset_type'=>'accessory']));
return redirect()->route('categories.index')->with('error', trans('admin/categories/message.assoc_items', ['asset_type'=>'accessory']));
} elseif ($category->consumables()->count() > 0) {
return redirect()->to('admin/settings/categories')->with('error', trans('admin/categories/message.assoc_items', ['asset_type'=>'consumable']));
return redirect()->route('categories.index')->with('error', trans('admin/categories/message.assoc_items', ['asset_type'=>'consumable']));
} elseif ($category->components()->count() > 0) {
return redirect()->to('admin/settings/categories')->with('error', trans('admin/categories/message.assoc_items', ['asset_type'=>'component']));
return redirect()->route('categories.index')->with('error', trans('admin/categories/message.assoc_items', ['asset_type'=>'component']));
}
$category->delete();
// Redirect to the locations management page
return redirect()->to(route('categories.index'))->with('success', trans('admin/categories/message.delete.success'));
return redirect()->route('categories.index')->with('success', trans('admin/categories/message.delete.success'));
}
@@ -189,6 +236,7 @@ class CategoriesController extends Controller
*/
public function show($id)
{
$this->authorize('view', Category::class);
if ($category = Category::find($id)) {
if ($category->category_type=='asset') {

View File

@@ -7,6 +7,8 @@ use Lang;
use Redirect;
use View;
use Illuminate\Http\Request;
use Image;
use App\Http\Requests\ImageUploadRequest;
/**
* This controller handles all actions related to Companies for
@@ -50,11 +52,22 @@ final class CompaniesController extends Controller
* @param Request $request
* @return \Illuminate\Http\RedirectResponse
*/
public function store(Request $request)
public function store(ImageUploadRequest $request)
{
$company = new Company;
$company->name = $request->input('name');
if ($request->file('image')) {
$image = $request->file('image');
$file_name = str_random(25).".".$image->getClientOriginalExtension();
$path = public_path('uploads/companies/'.$file_name);
Image::make($image->getRealPath())->resize(200, null, function ($constraint) {
$constraint->aspectRatio();
$constraint->upsize();
})->save($path);
$company->image = $file_name;
}
if ($company->save()) {
return redirect()->route('companies.index')
->with('success', trans('admin/companies/message.create.success'));
@@ -89,7 +102,7 @@ final class CompaniesController extends Controller
* @param int $companyId
* @return \Illuminate\Http\RedirectResponse
*/
public function update(Request $request, $companyId)
public function update(ImageUploadRequest $request, $companyId)
{
if (is_null($company = Company::find($companyId))) {
return redirect()->route('companies.index')->with('error', trans('admin/companies/message.does_not_exist'));
@@ -97,6 +110,38 @@ final class CompaniesController extends Controller
$company->name = $request->input('name');
$old_image = $company->image;
// Set the model's image property to null if the image is being deleted
if ($request->input('image_delete') == 1) {
$company->image = null;
}
if ($request->file('image')) {
$image = $request->file('image');
$file_name = $company->id.'-'.str_slug($image->getClientOriginalName()) . "." . $image->getClientOriginalExtension();
if ($image->getClientOriginalExtension()!='svg') {
Image::make($image->getRealPath())->resize(500, null, function ($constraint) {
$constraint->aspectRatio();
$constraint->upsize();
})->save(app('companies_upload_path').$file_name);
} else {
$image->move(app('companies_upload_path'), $file_name);
}
$company->image = $file_name;
}
if ((($request->file('image')) && (isset($old_image)) && ($old_image!='')) || ($request->input('image_delete') == 1)) {
try {
unlink(app('companies_upload_path').$old_image);
} catch (\Exception $e) {
\Log::error($e);
}
}
if ($company->save()) {
return redirect()->route('companies.index')
->with('success', trans('admin/companies/message.update.success'));

View File

@@ -2,6 +2,8 @@
namespace App\Http\Controllers;
use App\Helpers\Helper;
use App\Http\Requests\ImageUploadRequest;
use App\Models\Actionlog;
use App\Models\Company;
use App\Models\Component;
use App\Models\CustomField;
@@ -21,6 +23,7 @@ use View;
use Validator;
use Illuminate\Http\Request;
use Gate;
use Image;
/**
* This class controls all actions related to Components for
@@ -57,12 +60,9 @@ class ComponentsController extends Controller
public function create()
{
$this->authorize('create', Component::class);
// Show the page
return view('components/edit')
->with('item', new Component)
->with('category_list', Helper::categoryList('component'))
->with('company_list', Helper::companyList())
->with('location_list', Helper::locationsList());
$category_type = 'component';
return view('components/edit')->with('category_type',$category_type)
->with('item', new Component);
}
@@ -74,22 +74,34 @@ class ComponentsController extends Controller
* @since [v3.0]
* @return \Illuminate\Http\RedirectResponse
*/
public function store()
public function store(ImageUploadRequest $request)
{
$this->authorize('create', Component::class);
$component = new Component();
$component->name = Input::get('name');
$component->category_id = Input::get('category_id');
$component->location_id = Input::get('location_id');
$component->company_id = Company::getIdForCurrentUser(Input::get('company_id'));
$component->order_number = Input::get('order_number');
$component->min_amt = Input::get('min_amt');
$component->serial = Input::get('serial');
$component->purchase_date = Input::get('purchase_date');
$component->purchase_cost = request('purchase_cost');
$component->qty = Input::get('qty');
$component->name = $request->input('name');
$component->category_id = $request->input('category_id');
$component->location_id = $request->input('location_id');
$component->company_id = Company::getIdForCurrentUser($request->input('company_id'));
$component->order_number = $request->input('order_number', null);
$component->min_amt = $request->input('min_amt', null);
$component->serial = $request->input('serial', null);
$component->purchase_date = $request->input('purchase_date', null);
$component->purchase_cost = $request->input('purchase_cost', null);
$component->qty = $request->input('qty');
$component->user_id = Auth::id();
if ($request->file('image')) {
$image = $request->file('image');
$file_name = str_random(25).".".$image->getClientOriginalExtension();
$path = public_path('uploads/components/'.$file_name);
Image::make($image->getRealPath())->resize(200, null, function ($constraint) {
$constraint->aspectRatio();
$constraint->upsize();
})->save($path);
$component->image = $file_name;
}
if ($component->save()) {
return redirect()->route('components.index')->with('success', trans('admin/components/message.create.success'));
}
@@ -107,16 +119,18 @@ class ComponentsController extends Controller
*/
public function edit($componentId = null)
{
if (is_null($item = Component::find($componentId))) {
return redirect()->route('components.index')->with('error', trans('admin/components/message.does_not_exist'));
if ($item = Component::find($componentId)) {
$this->authorize('update', $item);
$category_type = 'component';
return view('components/edit', compact('item'))->with('category_type', $category_type);
}
return redirect()->route('components.index')->with('error', trans('admin/components/message.does_not_exist'));
$this->authorize('update', $item);
return view('components/edit', compact('item'))
->with('category_list', Helper::categoryList('component'))
->with('company_list', Helper::companyList())
->with('location_list', Helper::locationsList());
}
@@ -129,7 +143,7 @@ class ComponentsController extends Controller
* @since [v3.0]
* @return \Illuminate\Http\RedirectResponse
*/
public function update($componentId = null)
public function update(ImageUploadRequest $request, $componentId = null)
{
if (is_null($component = Component::find($componentId))) {
return redirect()->route('components.index')->with('error', trans('admin/components/message.does_not_exist'));
@@ -150,6 +164,19 @@ class ComponentsController extends Controller
$component->purchase_cost = request('purchase_cost');
$component->qty = Input::get('qty');
if ($request->file('image')) {
$image = $request->file('image');
$file_name = str_random(25).".".$image->getClientOriginalExtension();
$path = public_path('uploads/components/'.$file_name);
Image::make($image->getRealPath())->resize(200, null, function ($constraint) {
$constraint->aspectRatio();
$constraint->upsize();
})->save($path);
$component->image = $file_name;
} elseif ($request->input('image_delete')=='1') {
$component->image = null;
}
if ($component->save()) {
return redirect()->route('components.index')->with('success', trans('admin/components/message.update.success'));
}
@@ -228,7 +255,7 @@ class ComponentsController extends Controller
return redirect()->route('components.index')->with('error', trans('admin/components/message.not_found'));
}
$this->authorize('checkout', $component);
return view('components/checkout', compact('component'))->with('assets_list', Helper::detailedAssetList());
return view('components/checkout', compact('component'));
}
/**
@@ -287,36 +314,97 @@ class ComponentsController extends Controller
return redirect()->route('components.index')->with('success', trans('admin/components/message.checkout.success'));
}
/**
* Returns a view that allows the checkin of a component from an asset.
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @see ComponentsController::postCheckout() method that stores the data.
* @since [v4.1.4]
* @param int $componentId
* @return \Illuminate\Contracts\View\View
*/
public function getCheckin($component_asset_id)
{
// This could probably be done more cleanly but I am very tired. - @snipe
if ($component_assets = DB::table('components_assets')->find($component_asset_id)) {
if (is_null($component = Component::find($component_assets->component_id))) {
return redirect()->route('components.index')->with('error', trans('admin/components/messages.not_found'));
}
if (is_null($asset = Asset::find($component_assets->asset_id))) {
return redirect()->route('components.index')->with('error',
trans('admin/components/message.not_found'));
}
$this->authorize('checkin', $component);
return view('components/checkin', compact('component_assets','component','asset'));
}
return redirect()->route('components.index')->with('error', trans('admin/components/messages.not_found'));
}
/**
* Return JSON data to populate the components view,
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @see ComponentsController::getView() method that returns the view.
* @since [v3.0]
* @param int $componentId
* @return string JSON
*/
public function getDataView($componentId)
* Validate and store checkin data.
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @see ComponentsController::getCheckout() method that returns the form.
* @since [v4.1.4]
* @param Request $request
* @param int $componentId
* @return \Illuminate\Http\RedirectResponse
*/
public function postCheckin(Request $request, $component_asset_id)
{
if (is_null($component = Component::with('assets')->find($componentId))) {
// Redirect to the component management page with error
return redirect()->route('components.index')->with('error', trans('admin/components/message.not_found'));
}
if ($component_assets = DB::table('components_assets')->find($component_asset_id)) {
if (is_null($component = Component::find($component_assets->component_id))) {
return redirect()->route('components.index')->with('error',
trans('admin/components/message.not_found'));
}
if (!Company::isCurrentUserHasAccess($component)) {
return ['total' => 0, 'rows' => []];
}
$this->authorize('view', $component);
$rows = array();
$all_custom_fields = CustomField::all(); // Cached for table;
foreach ($component->assets as $component_assignment) {
$rows[] = $component_assignment->present()->forDataTable($all_custom_fields);
}
$this->authorize('checkin', $component);
$componentCount = $component->assets->count();
$data = array('total' => $componentCount, 'rows' => $rows);
return $data;
$max_to_checkin = $component_assets->assigned_qty;
$validator = Validator::make($request->all(), [
"checkin_qty" => "required|numeric|between:1,$max_to_checkin"
]);
if ($validator->fails()) {
return redirect()->back()
->withErrors($validator)
->withInput();
}
// Validation passed, so let's figure out what we have to do here.
$qty_remaining_in_checkout = ($component_assets->assigned_qty - (int)$request->input('checkin_qty'));
// We have to modify the record to reflect the new qty that's
// actually checked out.
$component_assets->assigned_qty = $qty_remaining_in_checkout;
DB::table('components_assets')->where('id',
$component_asset_id)->update(['assigned_qty' => $qty_remaining_in_checkout]);
$log = new Actionlog();
$log->user_id = Auth::user()->id;
$log->action_type = 'checkin from';
$log->target_type = Asset::class;
$log->target_id = $component_assets->asset_id;
$log->item_id = $component_assets->component_id;
$log->item_type = Component::class;
$log->note = $request->input('note');
$log->save();
// If the checked-in qty is exactly the same as the assigned_qty,
// we can simply delete the associated components_assets record
if ($qty_remaining_in_checkout == 0) {
DB::table('components_assets')->where('id', '=', $component_asset_id)->delete();
}
return redirect()->route('components.index')->with('success',
trans('admin/components/message.checkout.success'));
}
return redirect()->route('components.index')->with('error', trans('admin/components/message.not_found'));
}
}

View File

@@ -19,6 +19,8 @@ use Slack;
use Str;
use View;
use Gate;
use Image;
use App\Http\Requests\ImageUploadRequest;
/**
* This controller handles all actions related to Consumables for
@@ -54,13 +56,9 @@ class ConsumablesController extends Controller
public function create()
{
$this->authorize('create', Consumable::class);
// Show the page
return view('consumables/edit')
->with('item', new Consumable)
->with('category_list', Helper::categoryList('consumable'))
->with('company_list', Helper::companyList())
->with('location_list', Helper::locationsList())
->with('manufacturer_list', Helper::manufacturerList());
$category_type = 'consumable';
return view('consumables/edit')->with('category_type', $category_type)
->with('item', new Consumable);
}
@@ -72,24 +70,36 @@ class ConsumablesController extends Controller
* @since [v1.0]
* @return \Illuminate\Http\RedirectResponse
*/
public function store()
public function store(ImageUploadRequest $request)
{
$this->authorize('create', Consumable::class);
$consumable = new Consumable();
$consumable->name = Input::get('name');
$consumable->category_id = Input::get('category_id');
$consumable->location_id = Input::get('location_id');
$consumable->company_id = Company::getIdForCurrentUser(Input::get('company_id'));
$consumable->order_number = Input::get('order_number');
$consumable->min_amt = Input::get('min_amt');
$consumable->manufacturer_id = Input::get('manufacturer_id');
$consumable->model_number = Input::get('model_number');
$consumable->item_no = Input::get('item_no');
$consumable->purchase_date = Input::get('purchase_date');
$consumable->purchase_cost = Helper::ParseFloat(Input::get('purchase_cost'));
$consumable->qty = Input::get('qty');
$consumable->name = $request->input('name');
$consumable->category_id = $request->input('category_id');
$consumable->location_id = $request->input('location_id');
$consumable->company_id = Company::getIdForCurrentUser($request->input('company_id'));
$consumable->order_number = $request->input('order_number');
$consumable->min_amt = $request->input('min_amt');
$consumable->manufacturer_id = $request->input('manufacturer_id');
$consumable->model_number = $request->input('model_number');
$consumable->item_no = $request->input('item_no');
$consumable->purchase_date = $request->input('purchase_date');
$consumable->purchase_cost = Helper::ParseFloat($request->input('purchase_cost'));
$consumable->qty = $request->input('qty');
$consumable->user_id = Auth::id();
if ($request->file('image')) {
$image = $request->file('image');
$file_name = str_random(25).".".$image->getClientOriginalExtension();
$path = public_path('uploads/consumables/'.$file_name);
Image::make($image->getRealPath())->resize(200, null, function ($constraint) {
$constraint->aspectRatio();
$constraint->upsize();
})->save($path);
$consumable->image = $file_name;
}
if ($consumable->save()) {
return redirect()->route('consumables.index')->with('success', trans('admin/consumables/message.create.success'));
}
@@ -109,17 +119,14 @@ class ConsumablesController extends Controller
*/
public function edit($consumableId = null)
{
if (is_null($item = Consumable::find($consumableId))) {
return redirect()->route('consumables.index')->with('error', trans('admin/consumables/message.does_not_exist'));
if ($item = Consumable::find($consumableId)) {
$this->authorize($item);
$category_type = 'consumable';
return view('consumables/edit', compact('item'))->with('category_type', $category_type);
}
$this->authorize($item);
return redirect()->route('consumables.index')->with('error', trans('admin/consumables/message.does_not_exist'));
return view('consumables/edit', compact('item'))
->with('category_list', Helper::categoryList('consumable'))
->with('company_list', Helper::companyList())
->with('location_list', Helper::locationsList())
->with('manufacturer_list', Helper::manufacturerList());
}
@@ -132,7 +139,7 @@ class ConsumablesController extends Controller
* @since [v1.0]
* @return \Illuminate\Http\RedirectResponse
*/
public function update($consumableId = null)
public function update(ImageUploadRequest $request, $consumableId = null)
{
if (is_null($consumable = Consumable::find($consumableId))) {
return redirect()->route('consumables.index')->with('error', trans('admin/consumables/message.does_not_exist'));
@@ -140,19 +147,32 @@ class ConsumablesController extends Controller
$this->authorize($consumable);
$consumable->name = Input::get('name');
$consumable->category_id = Input::get('category_id');
$consumable->location_id = Input::get('location_id');
$consumable->company_id = Company::getIdForCurrentUser(Input::get('company_id'));
$consumable->order_number = Input::get('order_number');
$consumable->min_amt = Input::get('min_amt');
$consumable->manufacturer_id = Input::get('manufacturer_id');
$consumable->model_number = Input::get('model_number');
$consumable->item_no = Input::get('item_no');
$consumable->purchase_date = Input::get('purchase_date');
$consumable->purchase_cost = Helper::ParseFloat(Input::get('purchase_cost'));
$consumable->name = $request->input('name');
$consumable->category_id = $request->input('category_id');
$consumable->location_id = $request->input('location_id');
$consumable->company_id = Company::getIdForCurrentUser($request->input('company_id'));
$consumable->order_number = $request->input('order_number');
$consumable->min_amt = $request->input('min_amt');
$consumable->manufacturer_id = $request->input('manufacturer_id');
$consumable->model_number = $request->input('model_number');
$consumable->item_no = $request->input('item_no');
$consumable->purchase_date = $request->input('purchase_date');
$consumable->purchase_cost = Helper::ParseFloat(Input::get('purchase_cost'));
$consumable->qty = Helper::ParseFloat(Input::get('qty'));
if ($request->file('image')) {
$image = $request->file('image');
$file_name = str_random(25).".".$image->getClientOriginalExtension();
$path = public_path('uploads/consumables/'.$file_name);
Image::make($image->getRealPath())->resize(200, null, function ($constraint) {
$constraint->aspectRatio();
$constraint->upsize();
})->save($path);
$consumable->image = $file_name;
} elseif ($request->input('image_delete')=='1') {
$consumable->image = null;
}
if ($consumable->save()) {
return redirect()->route('consumables.index')->with('success', trans('admin/consumables/message.update.success'));
}
@@ -194,7 +214,7 @@ class ConsumablesController extends Controller
if (isset($consumable->id)) {
return view('consumables/view', compact('consumable'));
}
return redirect()->route('consumables')->with('error', trans('admin/consumables/message.does_not_exist', compact('id')));
return redirect()->route('consumables.index')->with('error', trans('admin/consumables/message.does_not_exist', compact('id')));
}
/**
@@ -209,10 +229,10 @@ class ConsumablesController extends Controller
public function getCheckout($consumableId)
{
if (is_null($consumable = Consumable::find($consumableId))) {
return redirect()->route('consumables.index')->with('error', trans('admin/consumables/message.not_found'));
return redirect()->route('consumables.index')->with('error', trans('admin/consumables/message.does_not_exist'));
}
$this->authorize('checkout', $consumable);
return view('consumables/checkout', compact('consumable'))->with('users_list', Helper::usersList());
return view('consumables/checkout', compact('consumable'));
}
/**
@@ -238,7 +258,7 @@ class ConsumablesController extends Controller
// Check if the user exists
if (is_null($user = User::find($assigned_to))) {
// Redirect to the consumable management page with error
return redirect()->route('consumables.index')->with('error', trans('admin/consumables/message.user_does_not_exist'));
return redirect()->route('checkout/consumable', $consumable)->with('error', trans('admin/consumables/message.checkout.user_does_not_exist'));
}
// Update the consumable data
@@ -259,7 +279,7 @@ class ConsumablesController extends Controller
$data['note'] = $logaction->note;
$data['require_acceptance'] = $consumable->requireAcceptance();
if (($consumable->requireAcceptance()=='1') || ($consumable->getEula())) {
if ((($consumable->requireAcceptance()=='1') || ($consumable->getEula())) && $user->email!='') {
Mail::send('emails.accept-asset', $data, function ($m) use ($user) {
$m->to($user->email, $user->first_name . ' ' . $user->last_name);

View File

@@ -1,6 +1,7 @@
<?php
namespace App\Http\Controllers;
use App\Http\Requests\CustomFieldRequest;
use View;
use App\Models\CustomFieldset;
use App\Models\CustomField;
@@ -69,7 +70,7 @@ class CustomFieldsController extends Controller
* @since [v1.8]
* @return Redirect
*/
public function store(Request $request)
public function store(CustomFieldRequest $request)
{
$field = new CustomField([
"name" => $request->get("name"),
@@ -81,27 +82,19 @@ class CustomFieldsController extends Controller
]);
if (!in_array(Input::get('format'), array_keys(CustomField::$PredefinedFormats))) {
$field->format = e($request->get("custom_format"));
} else {
$field->format = e($request->get("format"));
}
$validator = Validator::make(Input::all(), $field->rules);
if ($validator->passes()) {
$results = $field->save();
if ($results) {
return redirect()->route("fields.index")->with("success", trans('admin/custom_fields/message.field.create.success'));
} else {
dd($field);
return redirect()->back()->withInput()->with('error', trans('admin/custom_fields/message.field.create.error'));
}
if ($field->save()) {
return redirect()->route("fields.index")->with("success", trans('admin/custom_fields/message.field.create.success'));
} else {
return redirect()->back()->withInput()->withErrors($validator);
// dd($field);
return redirect()->back()->withInput()->with('error', trans('admin/custom_fields/message.field.create.error'));
}
}
@@ -169,7 +162,7 @@ class CustomFieldsController extends Controller
* @since [v4.0]
* @return Redirect
*/
public function update(Request $request, $id)
public function update(CustomFieldRequest $request, $id)
{
$field = CustomField::find($id);
@@ -186,13 +179,12 @@ class CustomFieldsController extends Controller
$field->format = e($request->get("format"));
}
$validator = Validator::make(Input::all(), $field->rules);
if ($field->save()) {
return redirect()->route("fields.index")->with("success", trans('admin/custom_fields/message.field.update.success'));
}
return redirect()->back()->withInput()->withErrors($validator);
return redirect()->back()->withInput()->with('error', trans('admin/custom_fields/message.field.update.error'));
}

View File

@@ -37,19 +37,25 @@ class CustomFieldsetsController extends Controller
public function show($id)
{
$cfset = CustomFieldset::with('fields')->where('id', '=', $id)->orderBy('id', 'ASC')->first();
$custom_fields_list = ["" => "Add New Field to Fieldset"] + CustomField::pluck("name", "id")->toArray();
$maxid = 0;
foreach ($cfset->fields() as $field) {
if ($field->pivot->order > $maxid) {
$maxid=$field->pivot->order;
}
if (isset($custom_fields_list[$field->id])) {
unset($custom_fields_list[$field->id]);
if ($cfset) {
$custom_fields_list = ["" => "Add New Field to Fieldset"] + CustomField::pluck("name", "id")->toArray();
$maxid = 0;
foreach ($cfset->fields() as $field) {
if ($field->pivot->order > $maxid) {
$maxid=$field->pivot->order;
}
if (isset($custom_fields_list[$field->id])) {
unset($custom_fields_list[$field->id]);
}
}
return view("custom_fields.fieldsets.view")->with("custom_fieldset", $cfset)->with("maxid", $maxid+1)->with("custom_fields_list", $custom_fields_list);
}
return view("custom_fields.fieldsets.view")->with("custom_fieldset", $cfset)->with("maxid", $maxid+1)->with("custom_fields_list", $custom_fields_list);
return redirect()->route("fields.index")->with("error", trans('admin/custom_fields/message.fieldset.does_not_exist'));
}
@@ -133,16 +139,21 @@ class CustomFieldsetsController extends Controller
*/
public function destroy($id)
{
//
$fieldset = CustomFieldset::find($id);
$models = AssetModel::where("fieldset_id", "=", $id);
if ($models->count() == 0) {
$fieldset->delete();
return redirect()->route("fields.show")->with("success", trans('admin/custom_fields/message.fieldset.delete.success'));
} else {
return redirect()->route("fields.show")->with("error", trans('admin/custom_fields/message.fieldset.delete.in_use'));
if ($fieldset) {
$models = AssetModel::where("fieldset_id", "=", $id);
if ($models->count() == 0) {
$fieldset->delete();
return redirect()->route("fields.index")->with("success", trans('admin/custom_fields/message.fieldset.delete.success'));
} else {
return redirect()->route("fields.index")->with("error", trans('admin/custom_fields/message.fieldset.delete.in_use'));
}
}
return redirect()->route("fields.index")->with("error", trans('admin/custom_fields/message.fieldset.does_not_exist'));
}

View File

@@ -39,8 +39,8 @@ class DashboardController extends Controller
$counts['grand_total'] = $counts['asset'] + $counts['accessory'] + $counts['license'] + $counts['consumable'];
if ((!file_exists(storage_path().'/oauth-private.key')) || (!file_exists(storage_path().'/oauth-public.key'))) {
\Artisan::call('passport:install');
\Artisan::call('migrate', ['--force' => true]);
\Artisan::call('passport:install');
}
return view('dashboard')->with('asset_stats', $asset_stats)->with('counts', $counts);

View File

@@ -6,6 +6,8 @@ use Illuminate\Http\Request;
use App\Models\Department;
use App\Helpers\Helper;
use Auth;
use Image;
use App\Http\Requests\ImageUploadRequest;
class DepartmentsController extends Controller
{
@@ -27,13 +29,11 @@ class DepartmentsController extends Controller
public function index(Request $request)
{
$this->authorize('index', Department::class);
$company = null;
if ($request->has('company_id')) {
$company = Company::find($request->input('company_id'));
} else {
$company = null;
}
return view('departments/index')->with('company',$company);
return view('departments/index')->with('company', $company);
}
@@ -45,7 +45,7 @@ class DepartmentsController extends Controller
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response
*/
public function store(Request $request)
public function store(ImageUploadRequest $request)
{
$this->authorize('create', Department::class);
$department = new Department;
@@ -53,12 +53,21 @@ class DepartmentsController extends Controller
$department->user_id = Auth::user()->id;
$department->manager_id = ($request->has('manager_id' ) ? $request->input('manager_id') : null);
if ($request->file('image')) {
$image = $request->file('image');
$file_name = str_random(25).".".$image->getClientOriginalExtension();
$path = public_path('uploads/departments/'.$file_name);
Image::make($image->getRealPath())->resize(200, null, function ($constraint) {
$constraint->aspectRatio();
$constraint->upsize();
})->save($path);
$department->image = $file_name;
}
if ($department->save()) {
return redirect()->route("departments.index")->with('success', trans('admin/departments/message.create.success'));
}
return redirect()->back()->withInput()->withErrors($department->getErrors());
}
/**
@@ -91,10 +100,7 @@ class DepartmentsController extends Controller
*/
public function create()
{
return view('departments/edit')->with('item', new Department)
->with('manager_list', Helper::managerList())
->with('location_list', Helper::locationsList())
->with('company_list', Helper::companyList());
return view('departments/edit')->with('item', new Department);
}
@@ -135,30 +141,53 @@ class DepartmentsController extends Controller
if (is_null($item = Department::find($id))) {
return redirect()->back()->with('error', trans('admin/locations/message.does_not_exist'));
}
return view('departments/edit', compact('item'))
->with('manager_list', Helper::managerList())
->with('location_list', Helper::locationsList())
->with('company_list', Helper::companyList());
return view('departments/edit', compact('item'));
}
public function update(Request $request, $id) {
public function update(ImageUploadRequest $request, $id) {
$this->authorize('create', Department::class);
if (is_null($department = Department::find($id))) {
return redirect()->to('admin/settings/departments')->with('error', trans('admin/departments/message.does_not_exist'));
return redirect()->route('departments.index')->with('error', trans('admin/departments/message.does_not_exist'));
}
$department->fill($request->all());
$department->manager_id = ($request->has('manager_id' ) ? $request->input('manager_id') : null);
$old_image = $department->image;
// Set the model's image property to null if the image is being deleted
if ($request->input('image_delete') == 1) {
$department->image = null;
}
if ($request->file('image')) {
$image = $request->file('image');
$file_name = $department->id.'-'.str_slug($image->getClientOriginalName()) . "." . $image->getClientOriginalExtension();
if ($image->getClientOriginalExtension()!='svg') {
Image::make($image->getRealPath())->resize(500, null, function ($constraint) {
$constraint->aspectRatio();
$constraint->upsize();
})->save(app('departments_upload_path').$file_name);
} else {
$image->move(app('departments_upload_path'), $file_name);
}
$department->image = $file_name;
}
if ((($request->file('image')) && (isset($old_image)) && ($old_image!='')) || ($request->input('image_delete') == 1)) {
try {
unlink(app('departments_upload_path').$old_image);
} catch (\Exception $e) {
\Log::error($e);
}
}
if ($department->save()) {
return redirect()->route("departments.index")->with('success', trans('admin/departments/message.update.success'));
}
return redirect()->back()->withInput()->withErrors($department->getErrors());
}
}

View File

@@ -155,5 +155,24 @@ class DepreciationsController extends Controller
return redirect()->route('depreciations.index')->with('success', trans('admin/depreciations/message.delete.success'));
}
/**
* Returns a view that displays a form to display depreciation listing
*
* @author [A. Gianotto] [<snipe@snipe.net]
* @see DepreciationsController::postEdit()
* @param int $depreciationId
* @since [v1.0]
* @return \Illuminate\Contracts\View\View
*/
public function show($id)
{
if (is_null($depreciation = Depreciation::find($id))) {
// Redirect to the blogs management page
return redirect()->route('depreciations.index')->with('error', trans('admin/depreciations/message.does_not_exist'));
}
return view('depreciations/view', compact('depreciation'));
}
}

View File

@@ -47,7 +47,7 @@ class GroupsController extends Controller
$group = new Group;
// Get all the available permissions
$permissions = config('permissions');
$groupPermissions = array();
$groupPermissions = Helper::selectedPermissionsArray($permissions, $permissions);
$selectedPermissions = Input::old('permissions', $groupPermissions);
// Show the page
@@ -84,13 +84,18 @@ class GroupsController extends Controller
* @since [v1.0]
* @return \Illuminate\Contracts\View\View
*/
public function edit($id = null)
public function edit($id)
{
$group = Group::find($id);
$permissions = config('permissions');
$groupPermissions = $group->decodePermissions();
$selected_array = Helper::selectedPermissionsArray($permissions, $groupPermissions);
return view('groups.edit', compact('group', 'permissions', 'selected_array', 'groupPermissions'));
if ($group) {
$permissions = config('permissions');
$groupPermissions = $group->decodePermissions();
$selected_array = Helper::selectedPermissionsArray($permissions, $groupPermissions);
return view('groups.edit', compact('group', 'permissions', 'selected_array', 'groupPermissions'));
}
return redirect()->route('groups.index')->with('error', trans('admin/groups/message.group_not_found'));
}
/**
@@ -142,4 +147,24 @@ class GroupsController extends Controller
return redirect()->route('groups.index')->with('error', trans('general.feature_disabled'));
}
/**
* Returns a view that invokes the ajax tables which actually contains
* the content for the group detail page.
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @param int $locationId
* @since [v4.0.11]
* @return \Illuminate\Contracts\View\View
*/
public function show($id)
{
$group = Group::find($id);
if ($group) {
return view('groups/view', compact('group'));
}
return redirect()->route('groups.index')->with('error', trans('admin/groups/message.group_not_found', compact('id')));
}
}

View File

@@ -67,10 +67,7 @@ class LicensesController extends Controller
return view('licenses/edit')
//->with('license_options',$license_options)
->with('depreciation_list', Helper::depreciationList())
->with('supplier_list', Helper::suppliersList())
->with('maintained_list', $maintained_list)
->with('company_list', Helper::companyList())
->with('manufacturer_list', Helper::manufacturerList())
->with('item', new License);
}
@@ -144,10 +141,7 @@ class LicensesController extends Controller
return view('licenses/edit', compact('item'))
->with('depreciation_list', Helper::depreciationList())
->with('supplier_list', Helper::suppliersList())
->with('company_list', Helper::companyList())
->with('maintained_list', $maintained_list)
->with('manufacturer_list', Helper::manufacturerList());
->with('maintained_list', $maintained_list);
}
@@ -187,6 +181,7 @@ class LicensesController extends Controller
$license->termination_date = $request->input('termination_date');
$license->seats = e($request->input('seats'));
$license->manufacturer_id = $request->input('manufacturer_id');
$license->supplier_id = $request->input('supplier_id');
if ($license->save()) {
return redirect()->route('licenses.show', ['license' => $licenseId])->with('success', trans('admin/licenses/message.update.success'));
@@ -244,18 +239,19 @@ class LicensesController extends Controller
* @param int $seatId
* @return \Illuminate\Contracts\View\View
*/
public function getCheckout($seatId)
public function getCheckout($licenceId)
{
// Check if the license seat exists
if (is_null($licenseSeat = LicenseSeat::find($seatId))) {
// Redirect to the asset management page with error
return redirect()->route('licenses.index')->with('error', trans('admin/licenses/message.not_found'));
// Check that the license is valid
if ($license = License::where('id',$licenceId)->first()) {
// If the license is valid, check that there is an available seat
if ($license->getAvailSeatsCountAttribute() < 1) {
return redirect()->route('licenses.index')->with('error', 'There are no available seats for this license');
}
}
$this->authorize('checkout', $licenseSeat);
return view('licenses/checkout', compact('licenseSeat'))
->with('users_list', Helper::usersList())
->with('asset_list', Helper::detailedAssetList());
$this->authorize('checkout', $license);
return view('licenses/checkout', compact('license'));
}
@@ -269,80 +265,84 @@ class LicensesController extends Controller
* @param int $seatId
* @return \Illuminate\Http\RedirectResponse
*/
public function postCheckout(Request $request, $seatId)
public function postCheckout(Request $request, $licenseId)
{
$licenseSeat = LicenseSeat::find($seatId);
$assigned_to = e($request->input('assigned_to'));
$asset_id = e($request->input('asset_id'));
$this->authorize('checkout', $licenseSeat);
// Check that the license is valid
if ($license = License::where('id',$licenseId)->first()) {
// Declare the rules for the form validation
$rules = [
'note' => 'string',
'asset_id' => 'required_without:assigned_to',
];
// Create a new validator instance from our validation rules
$validator = Validator::make(Input::all(), $rules);
// If validation fails, we'll exit the operation now.
if ($validator->fails()) {
// Ooops.. something went wrong
return redirect()->back()->withInput()->withErrors($validator);
}
$target = null;
if ($assigned_to!='') {
// Check if the user exists
if (is_null($target = User::find($assigned_to))) {
// Redirect to the asset management page with error
return redirect()->route('licenses.index')->with('error', trans('admin/licenses/message.user_does_not_exist'));
}
}
if ($asset_id!='') {
if (is_null($target = Asset::find($asset_id))) {
// Redirect to the asset management page with error
return redirect()->route('licenses.index')->with('error', trans('admin/licenses/message.asset_does_not_exist'));
// If the license is valid, check that there is an available seat
if ($license->getAvailSeatsCountAttribute() < 1) {
return redirect()->route('licenses.index')->with('error', 'There are no available seats for this license');
}
if (($request->has('assigned_to')) && ($request->has('asset_id'))) {
return redirect()->back()->withInput()->with('error', trans('admin/licenses/message.select_asset_or_person'));
// Get the next available seat for this license
$next = $license->freeSeat();
if (!$next) {
return redirect()->route('licenses.index')->with('error', 'There are no available seats for this license');
}
if (!$licenseSeat = LicenseSeat::where('id', '=', $next->id)->first()) {
return redirect()->route('licenses.index')->with('error', 'There are no available seats for this license');
}
$this->authorize('checkout', $license);
// Declare the rules for the form validation
$rules = [
'note' => 'string|nullable',
'asset_id' => 'required_without:assigned_to',
];
// Create a new validator instance from our validation rules
$validator = Validator::make(Input::all(), $rules);
// If validation fails, we'll exit the operation now.
if ($validator->fails()) {
// Ooops.. something went wrong
return redirect()->back()->withInput()->withErrors($validator);
}
$target = null;
// This item is checked out to a an asset
if (request('checkout_to_type')=='asset') {
if (is_null($target = Asset::find(request('asset_id')))) {
return redirect()->route('licenses.index')->with('error', trans('admin/licenses/message.asset_does_not_exist'));
}
$licenseSeat->asset_id = $request->input('asset_id');
// Override asset's assigned user if available
if ($target->checkedOutToUser()) {
$licenseSeat->assigned_to = $target->assigned_to;
}
} else {
// Fetch the target and set the license user
if (is_null($target = User::find(request('assigned_to')))) {
return redirect()->route('licenses.index')->with('error', trans('admin/licenses/message.user_does_not_exist'));
}
$licenseSeat->assigned_to = request('assigned_to');
}
$licenseSeat->user_id = Auth::user()->id;
if ($licenseSeat->save()) {
$licenseSeat->logCheckout($request->input('note'), $target);
return redirect()->route("licenses.index")->with('success', trans('admin/licenses/message.checkout.success'));
}
}
return redirect()->route('licenses.index')->with('error', trans('admin/licenses/message.not_found'));
// Check if the asset exists
if (is_null($licenseSeat)) {
// Redirect to the asset management page with error
return redirect()->route('licenses.index')->with('error', trans('admin/licenses/message.not_found'));
}
if ($request->input('asset_id') == '') {
$licenseSeat->asset_id = null;
} else {
$licenseSeat->asset_id = $request->input('asset_id');
}
// Update the asset data
if ($request->input('assigned_to') == '') {
$licenseSeat->assigned_to = null;
} else {
$licenseSeat->assigned_to = $request->input('assigned_to');
}
// Was the asset updated?
if ($licenseSeat->save()) {
$licenseSeat->logCheckout($request->input('note'), $target);
$data['license_id'] =$licenseSeat->license_id;
$data['note'] = $request->input('note');
// Redirect to the new asset page
return redirect()->route("licenses.index")->with('success', trans('admin/licenses/message.checkout.success'));
}
// Redirect to the asset management page with error
return redirect()->to("admin/licenses/{$asset_id}/checkout")->with('error', trans('admin/licenses/message.create.error'))->with('license', new License);
return redirect()->route("licenses.index")->with('error', trans('admin/licenses/message.checkout.error'));
}
@@ -358,12 +358,19 @@ class LicensesController extends Controller
public function getCheckin($seatId = null, $backTo = null)
{
// Check if the asset exists
if (is_null($licenseseat = LicenseSeat::find($seatId))) {
if (is_null($licenseSeat = LicenseSeat::find($seatId))) {
// Redirect to the asset management page with error
return redirect()->route('licenses.index')->with('error', trans('admin/licenses/message.not_found'));
}
$this->authorize('checkin', $licenseseat);
return view('licenses/checkin', compact('licenseseat'))->with('backto', $backTo);
if (is_null($license = License::find($licenseSeat->license_id))) {
// Redirect to the asset management page with error
return redirect()->route('licenses.index')->with('error', trans('admin/licenses/message.not_found'));
}
$this->authorize('checkout', $license);
return view('licenses/checkin', compact('licenseSeat'))->with('backto', $backTo);
}
@@ -386,8 +393,7 @@ class LicensesController extends Controller
}
$license = License::find($licenseSeat->license_id);
$this->authorize('checkin', $licenseSeat);
$this->authorize('checkout', $license);
if (!$license->reassignable) {
// Not allowed to checkin
@@ -441,17 +447,15 @@ class LicensesController extends Controller
public function show($licenseId = null)
{
$license = License::find($licenseId);
$license = $license->load('assignedusers', 'licenseSeats.user', 'licenseSeats.asset');
$license = License::with('assignedusers', 'licenseSeats.user', 'licenseSeats.asset')->find($licenseId);
if (isset($license->id)) {
$license = $license->load('assignedusers', 'licenseSeats.user', 'licenseSeats.asset');
if ($license) {
$this->authorize('view', $license);
return view('licenses/view', compact('license'));
}
$error = trans('admin/licenses/message.does_not_exist', compact('id'));
return redirect()->route('licenses.index')->with('error', $error);
return redirect()->route('licenses.index')->with('error', trans('admin/licenses/message.does_not_exist', compact('id')));
}
public function getClone($licenseId = null)
{
@@ -474,11 +478,8 @@ class LicensesController extends Controller
// Show the page
return view('licenses/edit')
->with('depreciation_list', Helper::depreciationList())
->with('supplier_list', Helper::suppliersList())
->with('item', $license)
->with('maintained_list', $maintained_list)
->with('company_list', Helper::companyList())
->with('manufacturer_list', Helper::manufacturerList());
->with('maintained_list', $maintained_list);
}
@@ -491,7 +492,7 @@ class LicensesController extends Controller
* @param int $licenseId
* @return \Illuminate\Http\RedirectResponse
*/
public function postUpload($licenseId = null)
public function postUpload(Request $request, $licenseId = null)
{
$license = License::find($licenseId);
// the license is valid
@@ -520,13 +521,16 @@ class LicensesController extends Controller
//Log the upload to the log
$license->logUpload($filename, e($request->input('notes')));
}
// This being called from a modal seems to confuse redirect()->back()
// It thinks we should go to the dashboard. As this is only used
// from the modal at present, hardcode the redirect. Longterm
// maybe we evaluate something else.
if ($upload_success) {
return redirect()->back()->with('success', trans('admin/licenses/message.upload.success'));
return redirect()->route('licenses.show', $license->id)->with('success', trans('admin/licenses/message.upload.success'));
}
return redirect()->back()->with('error', trans('admin/licenses/message.upload.error'));
return redirect()->route('licenses.show', $license->id)->with('error', trans('admin/licenses/message.upload.error'));
}
return redirect()->back()->with('error', trans('admin/licenses/message.upload.nofiles'));
return redirect()->route('licenses.show', $license->id)->with('error', trans('admin/licenses/message.upload.nofiles'));
}
// Prepare the error message
$error = trans('admin/licenses/message.does_not_exist', compact('id'));
@@ -589,61 +593,10 @@ class LicensesController extends Controller
$file = $log->get_src('licenses');
return Response::download($file);
}
// Prepare the error message
$error = trans('admin/licenses/message.does_not_exist', compact('id'));
// Redirect to the licence management page
return redirect()->route('licenses.index')->with('error', $error);
return redirect()->route('licenses.index')->with('error', trans('admin/licenses/message.does_not_exist', compact('id')));
}
/**
* Generates a JSON response to populate the licence index datatables.
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @see LicensesController::getIndex() method that provides the view
* @since [v1.0]
* @return String JSON
*/
public function getDatatable(Request $request)
{
$this->authorize('view', License::class);
$licenses = Company::scopeCompanyables(License::with('company', 'licenseSeatsRelation', 'manufacturer'));
if (Input::has('search')) {
$licenses = $licenses->TextSearch($request->input('search'));
}
$offset = request('offset', 0);
$limit = request('limit', 50);
$allowed_columns = ['id','name','purchase_cost','expiration_date','purchase_order','order_number','notes','purchase_date','serial','manufacturer','company'];
$order = $request->input('order') === 'asc' ? 'asc' : 'desc';
$sort = in_array($request->input('sort'), $allowed_columns) ? e($request->input('sort')) : 'created_at';
switch ($sort) {
case 'manufacturer':
$licenses = $licenses->OrderManufacturer($order);
break;
case 'company':
$licenses = $licenses->OrderCompany($order);
break;
default:
$licenses = $licenses->orderBy($sort, $order);
break;
}
$licenseCount = $licenses->count();
$licenses = $licenses->skip($offset)->take($limit)->get();
$rows = array();
foreach ($licenses as $license) {
$rows[] = $license->present()->forDataTable();
}
$data = array('total' => $licenseCount, 'rows' => $rows);
return $data;
}
/**
* Generates the next free seat ID for checkout.

View File

@@ -16,6 +16,8 @@ use Validator;
use View;
use Auth;
use Symfony\Component\HttpFoundation\JsonResponse;
use Image;
use App\Http\Requests\ImageUploadRequest;
/**
* This controller handles all actions related to Locations for
@@ -38,6 +40,7 @@ class LocationsController extends Controller
public function index()
{
// Grab all the locations
$this->authorize('view', Location::class);
$locations = Location::orderBy('created_at', 'DESC')->with('parent', 'assets', 'assignedassets')->get();
// Show the page
@@ -55,6 +58,7 @@ class LocationsController extends Controller
*/
public function create()
{
$this->authorize('create', Location::class);
$locations = Location::orderBy('name', 'ASC')->get();
$location_options_array = Location::getLocationHierarchy($locations);
@@ -63,8 +67,7 @@ class LocationsController extends Controller
return view('locations/edit')
->with('location_options', $location_options)
->with('item', new Location)
->with('manager_list', Helper::managerList());
->with('item', new Location);
}
@@ -77,21 +80,34 @@ class LocationsController extends Controller
* @since [v1.0]
* @return \Illuminate\Http\RedirectResponse
*/
public function store()
public function store(ImageUploadRequest $request)
{
$this->authorize('create', Location::class);
$location = new Location();
$location->name = Input::get('name');
$location->parent_id = Input::get('parent_id', null);
$location->currency = Input::get('currency', '$');
$location->address = Input::get('address');
$location->address2 = Input::get('address2');
$location->city = Input::get('city');
$location->state = Input::get('state');
$location->country = Input::get('country');
$location->zip = Input::get('zip');
$location->manager_id = Input::get('manager_id');
$location->name = $request->input('name');
$location->parent_id = $request->input('parent_id', null);
$location->currency = $request->input('currency', '$');
$location->address = $request->input('address');
$location->address2 = $request->input('address2');
$location->city = $request->input('city');
$location->state = $request->input('state');
$location->country = $request->input('country');
$location->zip = $request->input('zip');
$location->ldap_ou = $request->input('ldap_ou');
$location->manager_id = $request->input('manager_id');
$location->user_id = Auth::id();
if ($request->file('image')) {
$image = $request->file('image');
$file_name = str_random(25).".".$image->getClientOriginalExtension();
$path = public_path('uploads/locations/'.$file_name);
Image::make($image->getRealPath())->resize(600, null, function ($constraint) {
$constraint->aspectRatio();
$constraint->upsize();
})->save($path);
$location->image = $file_name;
}
if ($location->save()) {
return redirect()->route("locations.index")->with('success', trans('admin/locations/message.create.success'));
}
@@ -107,21 +123,22 @@ class LocationsController extends Controller
* @since [v1.0]
* @return String JSON
*/
public function apiStore()
public function apiStore(Request $request)
{
$this->authorize('create', Location::class);
$new['currency']=Setting::first()->default_currency;
// create a new location instance
$location = new Location();
// Save the location data
$location->name = Input::get('name');
$location->name = $request->input('name');
$location->currency = Setting::first()->default_currency; //e(Input::get('currency'));
$location->address = ''; //e(Input::get('address'));
// $location->address2 = e(Input::get('address2'));
$location->city = Input::get('city');
$location->city = $request->input('city');
$location->state = '';//e(Input::get('state'));
$location->country = Input::get('country');
$location->country = $request->input('country');
// $location->zip = e(Input::get('zip'));
$location->user_id = Auth::id();
@@ -145,9 +162,10 @@ class LocationsController extends Controller
*/
public function edit($locationId = null)
{
$this->authorize('edit', Location::class);
// Check if the location exists
if (is_null($item = Location::find($locationId))) {
return redirect()->to('admin/settings/locations')->with('error', trans('admin/locations/message.does_not_exist'));
return redirect()->route('locations.index')->with('error', trans('admin/locations/message.does_not_exist'));
}
// Show the page
@@ -156,7 +174,6 @@ class LocationsController extends Controller
$location_options = Location::flattenLocationsArray($location_options_array);
$location_options = array('' => 'Top Level') + $location_options;
return view('locations/edit', compact('item'))
->with('location_options', $location_options)
->with('manager_list', Helper::managerList());
@@ -172,32 +189,62 @@ class LocationsController extends Controller
* @since [v1.0]
* @return \Illuminate\Http\RedirectResponse
*/
public function update($locationId = null)
public function update(ImageUploadRequest $request, $locationId = null)
{
$this->authorize('edit', Location::class);
// Check if the location exists
if (is_null($location = Location::find($locationId))) {
return redirect()->to('admin/settings/locations')->with('error', trans('admin/locations/message.does_not_exist'));
return redirect()->route('locations.index')->with('error', trans('admin/locations/message.does_not_exist'));
}
// Update the location data
$location->name = Input::get('name');
$location->parent_id = Input::get('parent_id', null);
$location->currency = Input::get('currency', '$');
$location->address = Input::get('address');
$location->address2 = Input::get('address2');
$location->city = Input::get('city');
$location->state = Input::get('state');
$location->country = Input::get('country');
$location->zip = Input::get('zip');
$location->ldap_ou = Input::get('ldap_ou');
$location->manager_id = Input::get('manager_id');
$location->name = $request->input('name');
$location->parent_id = $request->input('parent_id', null);
$location->currency = $request->input('currency', '$');
$location->address = $request->input('address');
$location->address2 = $request->input('address2');
$location->city = $request->input('city');
$location->state = $request->input('state');
$location->country = $request->input('country');
$location->zip = $request->input('zip');
$location->ldap_ou = $request->input('ldap_ou');
$location->manager_id = $request->input('manager_id');
$old_image = $location->image;
// Set the model's image property to null if the image is being deleted
if ($request->input('image_delete') == 1) {
$location->image = null;
}
if ($request->file('image')) {
$image = $request->file('image');
$file_name = $location->id.'-'.str_slug($image->getClientOriginalName()) . "." . $image->getClientOriginalExtension();
if ($image->getClientOriginalExtension()!='svg') {
Image::make($image->getRealPath())->resize(600, null, function ($constraint) {
$constraint->aspectRatio();
$constraint->upsize();
})->save(app('locations_upload_path').$file_name);
} else {
$image->move(app('locations_upload_path'), $file_name);
}
$location->image = $file_name;
}
if ((($request->file('image')) && (isset($old_image)) && ($old_image!='')) || ($request->input('image_delete') == 1)) {
try {
unlink(app('locations_upload_path').$old_image);
} catch (\Exception $e) {
\Log::error($e);
}
}
// Was the location updated?
if ($location->save()) {
// Redirect to the saved location page
return redirect()->route("locations.index")->with('success', trans('admin/locations/message.update.success'));
}
// Redirect to the location management page
return redirect()->back()->withInput()->withInput()->withErrors($location->getErrors());
}
@@ -211,21 +258,23 @@ class LocationsController extends Controller
*/
public function destroy($locationId)
{
// Check if the location exists
$this->authorize('delete', Location::class);
if (is_null($location = Location::find($locationId))) {
// Redirect to the blogs management page
return redirect()->to(route('locations.index'))->with('error', trans('admin/locations/message.not_found'));
}
if ($location->users->count() > 0) {
return redirect()->to(route('locations.index'))->with('error', trans('admin/locations/message.assoc_users'));
} elseif ($location->childLocations->count() > 0) {
return redirect()->to(route('locations.index'))->with('error', trans('admin/locations/message.assoc_child_loc'));
} elseif ($location->assets->count() > 0) {
return redirect()->to(route('locations.index'))->with('error', trans('admin/locations/message.assoc_assets'));
} elseif ($location->assignedassets->count() > 0) {
return redirect()->to(route('locations.index'))->with('error', trans('admin/locations/message.assoc_assets'));
} else {
$location->delete();
return redirect()->to(route('locations.index'))->with('success', trans('admin/locations/message.delete.success'));
@@ -249,11 +298,8 @@ class LocationsController extends Controller
if (isset($location->id)) {
return view('locations/view', compact('location'));
}
// Prepare the error message
$error = trans('admin/locations/message.does_not_exist', compact('id'));
// Redirect to the user management page
return redirect()->route('locations.index')->with('error', $error);
return redirect()->route('locations.index')->with('error', trans('admin/locations/message.does_not_exist', compact('id')));
}
}

View File

@@ -2,6 +2,7 @@
namespace App\Http\Controllers;
use App\Helpers\Helper;
use App\Http\Requests\ImageUploadRequest;
use App\Models\CustomField;
use App\Models\Manufacturer;
use Auth;
@@ -13,6 +14,7 @@ use Redirect;
use Str;
use View;
use Illuminate\Http\Request;
use Image;
/**
* This controller handles all actions related to Manufacturers for
@@ -33,6 +35,7 @@ class ManufacturersController extends Controller
*/
public function index()
{
$this->authorize('index', Manufacturer::class);
return view('manufacturers/index', compact('manufacturers'));
}
@@ -47,6 +50,7 @@ class ManufacturersController extends Controller
*/
public function create()
{
$this->authorize('create', Manufacturer::class);
return view('manufacturers/edit')->with('item', new Manufacturer);
}
@@ -60,9 +64,10 @@ class ManufacturersController extends Controller
* @param Request $request
* @return \Illuminate\Http\RedirectResponse
*/
public function store(Request $request)
public function store(ImageUploadRequest $request)
{
$this->authorize('create', Manufacturer::class);
$manufacturer = new Manufacturer;
$manufacturer->name = $request->input('name');
$manufacturer->user_id = Auth::user()->id;
@@ -72,6 +77,18 @@ class ManufacturersController extends Controller
$manufacturer->support_email = $request->input('support_email');
if ($request->file('image')) {
$image = $request->file('image');
$file_name = str_slug($image->getClientOriginalName()).".".$image->getClientOriginalExtension();
$path = public_path('uploads/manufacturers/'.$file_name);
Image::make($image->getRealPath())->resize(200, null, function ($constraint) {
$constraint->aspectRatio();
$constraint->upsize();
})->save($path);
$manufacturer->image = $file_name;
}
if ($manufacturer->save()) {
return redirect()->route('manufacturers.index')->with('success', trans('admin/manufacturers/message.create.success'));
@@ -90,6 +107,7 @@ class ManufacturersController extends Controller
*/
public function edit($id = null)
{
$this->authorize('edit', Manufacturer::class);
// Check if the manufacturer exists
if (is_null($item = Manufacturer::find($id))) {
return redirect()->route('manufacturers.index')->with('error', trans('admin/manufacturers/message.does_not_exist'));
@@ -109,8 +127,9 @@ class ManufacturersController extends Controller
* @return \Illuminate\Http\RedirectResponse
* @since [v1.0]
*/
public function update(Request $request, $manufacturerId = null)
public function update(ImageUploadRequest $request, $manufacturerId = null)
{
$this->authorize('edit', Manufacturer::class);
// Check if the manufacturer exists
if (is_null($manufacturer = Manufacturer::find($manufacturerId))) {
// Redirect to the manufacturer page
@@ -124,6 +143,38 @@ class ManufacturersController extends Controller
$manufacturer->support_phone = $request->input('support_phone');
$manufacturer->support_email = $request->input('support_email');
$old_image = $manufacturer->image;
// Set the model's image property to null if the image is being deleted
if ($request->input('image_delete') == 1) {
$manufacturer->image = null;
}
if ($request->file('image')) {
$image = $request->file('image');
$file_name = $manufacturer->id.'-'.str_slug($image->getClientOriginalName()) . "." . $image->getClientOriginalExtension();
if ($image->getClientOriginalExtension()!='svg') {
Image::make($image->getRealPath())->resize(500, null, function ($constraint) {
$constraint->aspectRatio();
$constraint->upsize();
})->save(app('manufacturers_upload_path').$file_name);
} else {
$image->move(app('manufacturers_upload_path'), $file_name);
}
$manufacturer->image = $file_name;
}
if ((($request->file('image')) && (isset($old_image)) && ($old_image!='')) || ($request->input('image_delete') == 1)) {
try {
unlink(app('manufacturers_upload_path').$old_image);
} catch (\Exception $e) {
\Log::error($e);
}
}
if ($manufacturer->save()) {
return redirect()->route('manufacturers.index')->with('success', trans('admin/manufacturers/message.update.success'));
}
@@ -140,6 +191,7 @@ class ManufacturersController extends Controller
*/
public function destroy($manufacturerId)
{
$this->authorize('delete', Manufacturer::class);
// Check if the manufacturer exists
if (is_null($manufacturer = Manufacturer::find($manufacturerId))) {
// Redirect to the manufacturers page
@@ -150,6 +202,16 @@ class ManufacturersController extends Controller
// Redirect to the asset management page
return redirect()->route('manufacturers.index')->with('error', trans('admin/manufacturers/message.assoc_users'));
}
if ($manufacturer->image) {
try {
unlink(public_path().'/uploads/manufacturers/'.$manufacturer->image);
} catch (\Exception $e) {
\Log::error($e);
}
}
// Delete the manufacturer
$manufacturer->delete();
// Redirect to the manufacturers management page
@@ -158,170 +220,29 @@ class ManufacturersController extends Controller
/**
* Returns a view that invokes the ajax tables which actually contains
* the content for the manufacturers detail listing, which is generated in getDatatable.
* the content for the manufacturers detail listing, which is generated via API.
* This data contains a listing of all assets that belong to that manufacturer.
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @see ManufacturersController::getDataView()
* @param int $manufacturerId
* @since [v1.0]
* @return \Illuminate\Contracts\View\View
*/
public function show($manufacturerId = null)
{
$this->authorize('view', Manufacturer::class);
$manufacturer = Manufacturer::find($manufacturerId);
if (isset($manufacturer->id)) {
return view('manufacturers/view', compact('manufacturer'));
}
// Prepare the error message
$error = trans('admin/manufacturers/message.does_not_exist', compact('id'));
$error = trans('admin/manufacturers/message.does_not_exist');
// Redirect to the user management page
return redirect()->route('manufacturers')->with('error', $error);
return redirect()->route('manufacturers.index')->with('error', $error);
}
/**
* Generates the JSON used to display the manufacturer detail.
* This JSON returns data on all of the assets with the specified
* manufacturer ID number.
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @see ManufacturersController::getView()
* @param int $manufacturerId
* @param string $itemType
* @param Request $request
* @return String JSON* @since [v1.0]
*/
public function getDataView($manufacturerId, $itemType = null, Request $request)
{
$manufacturer = Manufacturer::find($manufacturerId);
switch ($itemType) {
case "assets":
return $this->getDataAssetsView($manufacturer, $request);
case "licenses":
return $this->getDataLicensesView($manufacturer, $request);
case "accessories":
return $this->getDataAccessoriesView($manufacturer, $request);
case "consumables":
return $this->getDataConsumablesView($manufacturer, $request);
}
return "We shouldn't be here";
}
protected function getDataAssetsView(Manufacturer $manufacturer, Request $request)
{
$manufacturer = $manufacturer->load('assets.model', 'assets.assignedTo', 'assets.assetstatus', 'assets.company');
$manufacturer_assets = $manufacturer->assets();
if ($request->has('search')) {
$manufacturer_assets = $manufacturer_assets->TextSearch(e($request->input('search')));
}
$offset = request('offset', 0);
$limit = request('limit', 50);
$order = $request->input('order') === 'asc' ? 'asc' : 'desc';
$allowed_columns = ['id','name','serial','asset_tag'];
$sort = in_array($request->input('sort'), $allowed_columns) ? $request->input('sort') : 'created_at';
$count = $manufacturer_assets->count();
$manufacturer_assets = $manufacturer_assets->skip($offset)->take($limit)->get();
$rows = array();
$all_custom_fields = CustomField::all(); // cached;
foreach ($manufacturer_assets as $asset) {
$rows[] = $asset->present()->forDataTable($all_custom_fields);
}
$data = array('total' => $count, 'rows' => $rows);
return $data;
}
protected function getDataLicensesView(Manufacturer $manufacturer, Request $request)
{
$manufacturer = $manufacturer->load('licenses.company', 'licenses.manufacturer', 'licenses.licenseSeatsRelation');
$licenses = $manufacturer->licenses;
if ($request->has('search')) {
$licenses = $licenses->TextSearch($request->input('search'));
}
$licenseCount = $licenses->count();
$rows = array();
foreach ($licenses as $license) {
$rows[] = $license->present()->forDataTable();
}
$data = array('total' => $licenseCount, 'rows' => $rows);
return $data;
}
public function getDataAccessoriesView(Manufacturer $manufacturer, Request $request)
{
$manufacturer = $manufacturer->load(
'accessories.location',
'accessories.company',
'accessories.category',
'accessories.manufacturer',
'accessories.users'
);
$accessories = $manufacturer->accessories();
if ($request->has('search')) {
$accessories = $accessories->TextSearch(e($request->input('search')));
}
$offset = request('offset', 0);
$limit = request('limit', 50);
$accessCount = $accessories->count();
$accessories = $accessories->skip($offset)->take($limit)->get();
$rows = array();
foreach ($accessories as $accessory) {
$rows[] = $accessory->present()->forDataTable();
}
$data = array('total'=>$accessCount, 'rows'=>$rows);
return $data;
}
public function getDataConsumablesView($manufacturer, Request $request)
{
$manufacturer = $manufacturer->load(
'consumables.location',
'consumables.company',
'consumables.category',
'consumables.manufacturer',
'consumables.users'
);
$consumables = $manufacturer->consumables();
if ($request->has('search')) {
$consumables = $consumables->TextSearch(e($request->input('search')));
}
$offset = request('offset', 0);
$limit = request('limit', 50);
$consumCount = $consumables->count();
$consumables = $consumables->skip($offset)->take($limit)->get();
$rows = array();
foreach ($consumables as $consumable) {
$rows[] = $consumable->present()->forDataTable();
}
$data = array('total' => $consumCount, 'rows' => $rows);
return $data;
}
}

View File

@@ -29,4 +29,13 @@ class ModalController extends Controller
function user() {
return view('modals.user');
}
function category() {
return view('modals.category');
}
function manufacturer() {
return view('modals.manufacturer');
}
}

View File

@@ -11,6 +11,7 @@ use App\Models\Setting;
use Gate;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Hash;
use App\Http\Requests\ImageUploadRequest;
/**
* This controller handles all actions related to User Profiles for
@@ -30,8 +31,7 @@ class ProfileController extends Controller
public function getIndex()
{
$user = Auth::user();
$location_list = Helper::locationsList();
return view('account/profile', compact('user'))->with('location_list', $location_list);
return view('account/profile', compact('user'));
}
/**
@@ -41,7 +41,7 @@ class ProfileController extends Controller
* @since [v1.0]
* @return \Illuminate\Http\RedirectResponse
*/
public function postIndex()
public function postIndex(ImageUploadRequest $request)
{
$user = Auth::user();
@@ -109,12 +109,12 @@ class ProfileController extends Controller
{
if (config('app.lock_passwords')) {
return redirect()->route('account.password.index')->with('error', Lang::get('admin/users/table.lock_passwords'));
return redirect()->route('account.password.index')->with('error', trans('admin/users/table.lock_passwords'));
}
$user = Auth::user();
if ($user->ldap_import=='1') {
return redirect()->route('account.password.index')->with('error', Lang::get('admin/users/message.error.password_ldap'));
return redirect()->route('account.password.index')->with('error', trans('admin/users/message.error.password_ldap'));
}
$rules = array(
@@ -143,5 +143,25 @@ class ProfileController extends Controller
}
/**
* Save the menu state of open/closed when the user clicks on the hamburger
* menu.
*
* This URL is triggered via jquery in
* resources/views/layouts/default.blade.php
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v4.0]
* @return View
*/
public function getMenuState(Request $request) {
if ($request->input('state')=='open') {
$request->session()->put('menu_state', 'open');
} else {
$request->session()->put('menu_state', 'closed');
}
}
}

View File

@@ -7,6 +7,7 @@ use App\Models\Actionlog;
use App\Models\Asset;
use App\Models\AssetMaintenance;
use App\Models\CustomField;
use App\Models\Depreciation;
use App\Models\License;
use App\Models\Setting;
use Carbon\Carbon;
@@ -15,6 +16,7 @@ use Illuminate\Support\Facades\View;
use Input;
use League\Csv\Reader;
use Symfony\Component\HttpFoundation\StreamedResponse;
use Illuminate\Http\Request;
/**
* This controller handles all actions related to Reports for
@@ -102,59 +104,93 @@ class ReportsController extends Controller
* @since [v1.0]
* @return \Illuminate\Http\Response
*/
public function exportAssetReport()
public function exportAssetReport(Request $request)
{
\Debugbar::disable();
$customfields = CustomField::get();
$response = new StreamedResponse(function () use ($customfields) {
$response = new StreamedResponse(function () use ($customfields, $request) {
// Open output stream
$handle = fopen('php://output', 'w');
Asset::with('assignedTo', 'assetLoc','defaultLoc','assignedTo','model','supplier','assetstatus','model.manufacturer')->orderBy('created_at', 'DESC')->chunk(500, function($assets) use($handle, $customfields) {
$headers=[
trans('general.company'),
trans('admin/hardware/table.asset_tag'),
trans('admin/hardware/form.manufacturer'),
trans('admin/hardware/form.model'),
trans('general.model_no'),
trans('general.name'),
trans('admin/hardware/table.serial'),
trans('general.status'),
trans('admin/hardware/table.purchase_date'),
trans('admin/hardware/table.purchase_cost'),
trans('admin/hardware/form.order'),
trans('admin/hardware/form.supplier'),
trans('admin/hardware/table.checkoutto'),
trans('admin/hardware/table.checkout_date'),
trans('admin/hardware/table.location'),
trans('general.notes'),
];
foreach ($customfields as $field) {
$headers[]=$field->name;
}
fputcsv($handle, $headers);
$assets = Asset::with('assignedTo', 'location','defaultLoc','assignedTo','model','supplier','assetstatus','model.manufacturer');
// This is used by the sidenav, mostly
switch ($request->input('status')) {
case 'Deleted':
$assets->withTrashed()->Deleted();
break;
case 'Pending':
$assets->Pending();
break;
case 'RTD':
$assets->RTD();
break;
case 'Undeployable':
$assets->Undeployable();
break;
case 'Archived':
$assets->Archived();
break;
case 'Requestable':
$assets->RequestableAssets();
break;
case 'Deployed':
$assets->Deployed();
break;
}
$headers=[
trans('general.company'),
trans('admin/hardware/table.asset_tag'),
trans('admin/hardware/form.manufacturer'),
trans('general.category'),
trans('admin/hardware/form.model'),
trans('general.model_no'),
trans('general.name'),
trans('admin/hardware/table.serial'),
trans('general.status'),
trans('admin/hardware/table.purchase_date'),
trans('admin/hardware/table.purchase_cost'),
trans('admin/hardware/form.order'),
trans('general.supplier'),
trans('admin/hardware/table.checkoutto'),
trans('general.type'),
trans('admin/hardware/table.checkout_date'),
trans('admin/hardware/table.location'),
trans('general.notes'),
];
foreach ($customfields as $field) {
$headers[]=$field->name;
}
fputcsv($handle, $headers);
$assets->orderBy('created_at', 'DESC')->chunk(500, function($assets) use($handle, $customfields) {
foreach ($assets as $asset) {
// Add a new row with data
$values=[
($asset->company) ? $asset->company->name : '',
$asset->asset_tag,
($asset->model->manufacturer) ? $asset->model->manufacturer->name : '',
($asset->model->category) ? $asset->model->category->name : '',
($asset->model) ? $asset->model->name : '',
($asset->model->model_number) ? $asset->model->model_number : '',
($asset->name) ? $asset->name : '',
($asset->serial) ? $asset->serial : '',
($asset->assetstatus) ? e($asset->assetstatus->name) : '',
($asset->assetstatus) ? e($asset->present()->statusText) : '',
($asset->purchase_date) ? e($asset->purchase_date) : '',
($asset->purchase_cost > 0) ? Helper::formatCurrencyOutput($asset->purchase_cost) : '',
($asset->order_number) ? e($asset->order_number) : '',
($asset->supplier) ? e($asset->supplier->name) : '',
($asset->assignedTo) ? e($asset->assignedTo->present()->name()) : '',
($asset->checkedOutToUser() && $asset->assigned) ? e($asset->assigned->getFullNameAttribute()) : ($asset->assigned ? e($asset->assigned->display_name) : ''),
($asset->checkedOutToUser() && $asset->assigned) ? 'user' : e($asset->assignedType()),
($asset->last_checkout!='') ? e($asset->last_checkout) : '',
e($asset->assetLoc->present()->name()),
($asset->location) ? e($asset->location->name) : '',
($asset->notes) ? e($asset->notes) : '',
];
foreach ($customfields as $field) {
@@ -168,7 +204,8 @@ class ReportsController extends Controller
fclose($handle);
}, 200, [
'Content-Type' => 'text/csv',
'Content-Disposition' => 'attachment; filename="assets-'.date('Y-m-d-his').'.csv"',
'Content-Disposition'
=> 'attachment; filename="'.(($request->has('status')) ? trim($request->input('status')) : 'all').'-assets-'.date('Y-m-d-his').'.csv"',
]);
return $response;
@@ -185,11 +222,12 @@ class ReportsController extends Controller
public function getDeprecationReport()
{
$depreciations = Depreciation::get();
// Grab all the assets
$assets = Asset::with( 'assignedTo', 'assetstatus', 'defaultLoc', 'assetloc', 'assetlog', 'company', 'model.category', 'model.depreciation')
$assets = Asset::with( 'assignedTo', 'assetstatus', 'defaultLoc', 'location', 'assetlog', 'company', 'model.category', 'model.depreciation')
->orderBy('created_at', 'DESC')->get();
return view('reports/depreciation', compact('assets'));
return view('reports/depreciation', compact('assets'))->with('depreciations',$depreciations);
}
/**
@@ -241,7 +279,7 @@ class ReportsController extends Controller
$row[] = ''; // Empty string if unassigned
}
if (( $asset->assigned_to > 0 ) && ( $location = $asset->assetLoc )) {
if (( $asset->assigned_to > 0 ) && ( $location = $asset->location )) {
if ($location->city) {
$row[] = e($location->city) . ', ' . e($location->state);
} elseif ($location->name) {
@@ -253,8 +291,8 @@ class ReportsController extends Controller
$row[] = ''; // Empty string if location is not set
}
if ($asset->assetloc) {
$currency = e($asset->assetloc->currency);
if ($asset->location) {
$currency = e($asset->location->currency);
} else {
$currency = e(Setting::first()->default_currency);
}
@@ -388,251 +426,332 @@ class ReportsController extends Controller
* @since [v1.0]
* @return \Illuminate\Http\Response
*/
public function postCustom()
public function postCustom(Request $request)
{
$assets = Asset::orderBy('created_at', 'DESC')->with('company', 'assignedTo', 'assetloc', 'defaultLoc', 'model', 'supplier', 'assetstatus', 'model.manufacturer')->get();
\Debugbar::disable();
$customfields = CustomField::get();
$response = new StreamedResponse(function () use ($customfields, $request) {
$rows = [ ];
$header = [ ];
if (e(Input::get('company')) == '1') {
$header[] = 'Company Name';
}
if (e(Input::get('asset_name')) == '1') {
$header[] = 'Asset Name';
}
if (e(Input::get('asset_tag')) == '1') {
$header[] = 'Asset Tag';
}
if (e(Input::get('manufacturer')) == '1') {
$header[] = 'Manufacturer';
}
if (e(Input::get('model')) == '1') {
$header[] = 'Model';
$header[] = 'Model Number';
}
if (e(Input::get('category')) == '1') {
$header[] = 'Category';
}
if (e(Input::get('serial')) == '1') {
$header[] = 'Serial';
}
if (e(Input::get('purchase_date')) == '1') {
$header[] = 'Purchase Date';
}
if (( e(Input::get('purchase_cost')) == '1' ) && ( e(Input::get('depreciation')) != '1' )) {
$header[] = 'Purchase Cost';
}
if (e(Input::get('eol')) == '1') {
$header[] = 'EOL';
}
if (e(Input::get('order')) == '1') {
$header[] = 'Order Number';
}
if (e(Input::get('supplier')) == '1') {
$header[] = 'Supplier';
}
if (e(Input::get('location')) == '1') {
$header[] = 'Location';
}
if (e(Input::get('assigned_to')) == '1') {
$header[] = 'Assigned To';
}
if (e(Input::get('username')) == '1') {
$header[] = 'Username';
}
if (e(Input::get('employee_num')) == '1') {
$header[] = 'Employee No.';
}
if (e(Input::get('status')) == '1') {
$header[] = 'Status';
}
if (e(Input::get('warranty')) == '1') {
$header[] = 'Warranty';
$header[] = 'Warranty Expires';
}
if (e(Input::get('depreciation')) == '1') {
$header[] = 'Purchase Cost';
$header[] = 'Value';
$header[] = 'Diff';
}
if (e(Input::get('expected_checkin')) == '1') {
$header[] = trans('admin/hardware/form.expected_checkin');
}
if (e(Input::get('notes')) == '1') {
$header[] = trans('general.notes');
}
foreach ($customfields as $customfield) {
if (e(Input::get($customfield->db_column_name())) == '1') {
$header[] = $customfield->name;
}
}
$header = array_map('trim', $header);
$rows[] = implode($header, ',');
foreach ($assets as $asset) {
$row = [ ];
if (e(Input::get('company')) == '1') {
$row[] = is_null($asset->company) ? '' : '"'.$asset->company->name.'"';
// Open output stream
$handle = fopen('php://output', 'w');
if ($request->has('use_bom')) {
fprintf($handle, chr(0xEF) . chr(0xBB) . chr(0xBF));
}
if (e(Input::get('asset_name')) == '1') {
$row[] = '"' .e($asset->name) . '"';
}
if (e(Input::get('asset_tag')) == '1') {
$row[] = e($asset->asset_tag);
}
if (e(Input::get('manufacturer')) == '1') {
if ($asset->model->manufacturer) {
$row[] = '"' .e($asset->model->manufacturer->name) . '"';
} else {
$row[] = '';
}
}
if (e(Input::get('model')) == '1') {
$row[] = '"' . e($asset->model->name) . '"';
$row[] = '"' . e($asset->model->model_number) . '"';
}
if (e(Input::get('category')) == '1') {
$row[] = '"' .e($asset->model->category->name) . '"';
}
if (e(Input::get('serial')) == '1') {
$row[] = e($asset->serial);
}
if (e(Input::get('purchase_date')) == '1') {
$row[] = e($asset->purchase_date);
}
if (e(Input::get('purchase_cost')) == '1' && ( e(Input::get('depreciation')) != '1' )) {
$row[] = '"' . Helper::formatCurrencyOutput($asset->purchase_cost) . '"';
}
if (e(Input::get('eol')) == '1') {
$row[] = '"' .($asset->present()->eol_date()) ? $asset->present()->eol_date() : ''. '"';
}
if (e(Input::get('order')) == '1') {
if ($asset->order_number) {
$row[] = e($asset->order_number);
} else {
$row[] = '';
}
}
if (e(Input::get('supplier')) == '1') {
if ($asset->supplier) {
$row[] = '"' .e($asset->supplier->name) . '"';
} else {
$row[] = '';
}
}
if (e(Input::get('location')) == '1') {
if($asset->assetLoc) {
$show_loc = $asset->assetLoc->present()->name();
} else {
$show_loc = 'Default location '.$asset->rtd_location_id.' is invalid';
}
$row[] = $show_loc;
}
$header = [];
if (e(Input::get('assigned_to')) == '1') {
if ($asset->assignedTo) {
$row[] = '"' .e($asset->assignedTo->present()->name()). '"';
} else {
$row[] = ''; // Empty string if unassigned
}
if ($request->has('company')) {
$header[] = trans('general.company');
}
if (e(Input::get('username')) == '1') {
// Only works if we're checked out to a user, not anything else.
if ($asset->checkedOutToUser()) {
$row[] = '"' .e($asset->assignedTo->username). '"';
} else {
$row[] = ''; // Empty string if unassigned
}
if ($request->has('asset_name')) {
$header[] = trans('admin/hardware/form.name');
}
if (e(Input::get('employee_num')) == '1') {
// Only works if we're checked out to a user, not anything else.
if ($asset->checkedOutToUser()) {
$row[] = '"' .e($asset->assignedTo->employee_num). '"';
} else {
$row[] = ''; // Empty string if unassigned
}
if ($request->has('asset_tag')) {
$header[] = trans('admin/hardware/table.asset_tag');
}
if (e(Input::get('status')) == '1') {
if (( $asset->status_id == '0' ) && ( $asset->assigned_to == '0' )) {
$row[] = trans('general.ready_to_deploy');
} elseif (( $asset->status_id == '' ) && ( $asset->assigned_to == '0' )) {
$row[] = trans('general.pending');
} elseif ($asset->assetstatus) {
$row[] = '"' .e($asset->assetstatus->name). '"';
} else {
$row[] = '';
}
}
if (e(Input::get('warranty')) == '1') {
if ($asset->warranty_months) {
$row[] = $asset->warranty_months;
$row[] = $asset->present()->warrantee_expires();
} else {
$row[] = '';
$row[] = '';
}
}
if (e(Input::get('depreciation')) == '1') {
$depreciation = $asset->getDepreciatedValue();
$row[] = '"' . Helper::formatCurrencyOutput($asset->purchase_cost) . '"';
$row[] = '"' . Helper::formatCurrencyOutput($depreciation) . '"';
$row[] = '"' . Helper::formatCurrencyOutput($asset->purchase_cost) . '"';
}
if (e(Input::get('expected_checkin')) == '1') {
if ($asset->expected_checkin) {
$row[] = '"' .e($asset->expected_checkin). '"';
} else {
$row[] = ''; // Empty string if blankd
}
if ($request->has('model')) {
$header[] = trans('admin/hardware/form.model');
$header[] = trans('general.model_no');
}
if (e(Input::get('notes')) == '1') {
if ($asset->notes) {
$row[] = '"' .$asset->notes . '"';
} else {
$row[] = '';
}
if ($request->has('category')) {
$header[] = trans('general.category');
}
if ($request->has('manufacturer')) {
$header[] = trans('admin/hardware/form.manufacturer');
}
if ($request->has('serial')) {
$header[] = trans('admin/hardware/table.serial');
}
if ($request->has('purchase_date')) {
$header[] = trans('admin/hardware/table.purchase_date');
}
if (($request->has('purchase_cost')) || ($request->has('depreciation'))) {
$header[] = trans('admin/hardware/table.purchase_cost');
}
if ($request->has('eol')) {
$header[] = trans('admin/hardware/table.eol');
}
if ($request->has('order')) {
$header[] = trans('admin/hardware/form.order');
}
if ($request->has('supplier')) {
$header[] = trans('general.supplier');
}
if ($request->has('location')) {
$header[] = trans('admin/hardware/table.location');
}
if ($request->has('assigned_to')) {
$header[] = trans('admin/hardware/table.checkoutto');
$header[] = trans('general.type');
}
if ($request->has('username')) {
$header[] = 'Username';
}
if ($request->has('employee_num')) {
$header[] = 'Employee No.';
}
if ($request->has('status')) {
$header[] = trans('general.status');
}
if ($request->has('warranty')) {
$header[] = 'Warranty';
$header[] = 'Warranty Expires';
}
if ($request->has('depreciation')) {
$header[] = 'Value';
$header[] = 'Diff';
}
if ($request->has('checkout_date')) {
$header[] = trans('admin/hardware/table.checkout_date');
}
if ($request->has('expected_checkin')) {
$header[] = trans('admin/hardware/form.expected_checkin');
}
if ($request->has('created_at')) {
$header[] = trans('general.created_at');
}
if ($request->has('updated_at')) {
$header[] = trans('general.updated_at');
}
if ($request->has('last_audit_date')) {
$header[] = trans('general.last_audit');
}
if ($request->has('next_audit_date')) {
$header[] = trans('general.next_audit_date');
}
if ($request->has('notes')) {
$header[] = trans('general.notes');
}
foreach ($customfields as $customfield) {
$column_name = $customfield->db_column_name();
if (e(Input::get($customfield->db_column_name())) == '1') {
$row[] = str_replace(",", "\,", $asset->$column_name);
$header[] = $customfield->name;
}
}
$rows[] = implode($row, ',');
}
fputcsv($handle, $header);
$assets = \App\Models\Company::scopeCompanyables(Asset::select('assets.*'))->with(
'location', 'assetstatus', 'assetlog', 'company', 'defaultLoc','assignedTo',
'model.category', 'model.manufacturer','supplier');
if ($request->has('by_location_id')) {
$assets->where('assets.location_id', $request->input('by_location_id'));
}
if ($request->has('by_supplier_id')) {
$assets->where('assets.supplier_id', $request->input('by_supplier_id'));
}
if ($request->has('by_company_id')) {
$assets->where('assets.company_id', $request->input('by_company_id'));
}
if ($request->has('by_model_id')) {
$assets->where('assets.model_id', $request->input('by_model_id'));
}
if ($request->has('by_category_id')) {
$assets->InCategory($request->input('by_category_id'));
}
if ($request->has('by_manufacturer_id')) {
$assets->ByManufacturer($request->input('by_manufacturer_id'));
}
if ($request->has('by_order_number')) {
$assets->where('assets.order_number', $request->input('by_order_number'));
}
if ($request->has('by_status_id')) {
$assets->where('assets.status_id', $request->input('by_status_id'));
}
if (($request->has('purchase_start')) && ($request->has('purchase_end'))) {
$assets->whereBetween('assets.purchase_date', [$request->input('purchase_start'), $request->input('purchase_end')]);
}
if (($request->has('created_start')) && ($request->has('created_end'))) {
$assets->whereBetween('assets.created_at', [$request->input('created_start'), $request->input('created_end')]);
}
$assets->orderBy('assets.created_at', 'ASC')->chunk(500, function($assets) use($handle, $customfields, $request) {
foreach ($assets as $asset) {
$row = [];
if ($request->has('company')) {
$row[] = ($asset->company) ? $asset->company->name : '';
}
if ($request->has('asset_name')) {
$row[] = ($asset->name) ? $asset->name : '';
}
if ($request->has('asset_tag')) {
$row[] = ($asset->asset_tag) ? $asset->asset_tag : '';
}
if ($request->has('model')) {
$row[] = ($asset->model) ? $asset->model->name : '';
$row[] = ($asset->model) ? $asset->model->model_number : '';
}
if ($request->has('category')) {
$row[] = (($asset->model) && ($asset->model->category)) ? $asset->model->category->name : '';
}
if ($request->has('manufacturer')) {
$row[] = ($asset->model && $asset->model->manufacturer) ? $asset->model->manufacturer->name : '';
}
if ($request->has('serial')) {
$row[] = ($asset->serial) ? $asset->serial : '';
}
if ($request->has('purchase_date')) {
$row[] = ($asset->purchase_date) ? $asset->purchase_date : '';
}
if ($request->has('purchase_cost')) {
$row[] = ($asset->purchase_cost) ? Helper::formatCurrencyOutput($asset->purchase_cost) : '';
}
if ($request->has('eol')) {
$row[] = ($asset->purchase_date!='') ? $asset->present()->eol_date() : '';
}
if ($request->has('order')) {
$row[] = ($asset->order_number) ? $asset->order_number : '';
}
if ($request->has('supplier')) {
$row[] = ($asset->supplier) ? $asset->supplier->name : '';
}
if ($request->has('location')) {
$row[] = ($asset->location) ? $asset->location->present()->name() : '';
}
if ($request->has('assigned_to')) {
$row[] = ($asset->checkedOutToUser() && $asset->assigned) ? e($asset->assigned->getFullNameAttribute()) : ($asset->assigned ? e($asset->assigned->display_name) : '');
$row[] = ($asset->checkedOutToUser() && $asset->assigned) ? 'user' : e($asset->assignedType());
}
if ($request->has('username')) {
// Only works if we're checked out to a user, not anything else.
if ($asset->checkedOutToUser()) {
$row[] = ($asset->assignedto) ? $asset->assignedto->username : '';
} else {
$row[] = ''; // Empty string if unassigned
}
}
if ($request->has('employee_num')) {
// Only works if we're checked out to a user, not anything else.
if ($asset->checkedOutToUser()) {
$row[] = ($asset->assignedto) ? $asset->assignedto->employee_num : '';
} else {
$row[] = ''; // Empty string if unassigned
}
}
if ($request->has('status')) {
$row[] = ($asset->assetstatus) ? $asset->assetstatus->name.' ('.$asset->present()->statusMeta.')' : '';
}
if ($request->has('warranty')) {
$row[] = ($asset->warranty_months) ? $asset->warranty_months : '';
$row[] = $asset->present()->warrantee_expires();
}
if ($request->has('depreciation')) {
$depreciation = $asset->getDepreciatedValue();
$diff = ($asset->purchase_cost - $depreciation);
$row[] = Helper::formatCurrencyOutput($depreciation);
$row[] = Helper::formatCurrencyOutput($diff);
}
if ($request->has('checkout_date')) {
$row[] = ($asset->last_checkout) ? $asset->last_checkout : '';
}
if ($request->has('expected_checkin')) {
$row[] = ($asset->expected_checkin) ? $asset->expected_checkin : '';
}
if ($request->has('created_at')) {
$row[] = ($asset->created_at) ? $asset->created_at : '';
}
if ($request->has('updated_at')) {
$row[] = ($asset->updated_at) ? $asset->updated_at : '';
}
if ($request->has('last_audit_date')) {
$row[] = ($asset->last_audit_date) ? $asset->last_audit_date : '';
}
if ($request->has('next_audit_date')) {
$row[] = ($asset->next_audit_date) ? $asset->next_audit_date : '';
}
if ($request->has('notes')) {
$row[] = ($asset->notes) ? $asset->notes : '';
}
foreach ($customfields as $customfield) {
$column_name = $customfield->db_column_name();
if ($request->has($customfield->db_column_name())) {
$row[] = $asset->$column_name;
}
}
fputcsv($handle, $row);
}
});
// Close the output stream
fclose($handle);
}, 200, [
'Content-Type' => 'text/csv',
'Content-Disposition'
=> 'attachment; filename="custom-assets-report-'.date('Y-m-d-his').'.csv"',
]);
return $response;
// spit out a csv
if (array_filter($rows)) {
$csv = implode($rows, "\n");
$response = Response::make($csv, 200);
$response->header('Content-Type', 'text/csv');
$response->header('Content-disposition', 'attachment;filename='.date('Y-m-d-His').'-custom-asset-report.csv');
return $response;
} else {
return redirect()->to("reports/custom")
->with('error', trans('admin/reports/message.error'));
}
}

View File

@@ -21,6 +21,7 @@ use App\Models\User;
use App\Http\Requests\SetupUserRequest;
use App\Http\Requests\ImageUploadRequest;
use App\Http\Requests\SettingsLdapRequest;
use App\Helpers\Helper;
/**
* This controller handles all actions related to Settings for
@@ -66,7 +67,7 @@ class SettingsController extends Controller
$start_settings['url_config'] = url('/');
$start_settings['real_url'] = $pageURL;
// Curl the .env file to make sure it's not accessible via a browser
$ch = curl_init($protocol . $host.'/.env');
curl_setopt($ch, CURLOPT_HEADER, true); // we want headers
@@ -136,28 +137,6 @@ class SettingsController extends Controller
->with('section', 'Pre-Flight Check');
}
/**
* Test the email configuration
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v3.0]
* @return Redirect
*/
public function ajaxTestEmail()
{
try {
Mail::send('emails.test', [], function ($m) {
$m->to(config('mail.from.address'), config('mail.from.name'));
$m->replyTo(config('mail.reply_to.address'), config('mail.reply_to.name'));
$m->subject(trans('mail.test_email'));
});
return 'success';
} catch (Exception $e) {
return 'error';
}
}
/**
* Save the first admin user from Setup.
@@ -171,28 +150,31 @@ class SettingsController extends Controller
$user = new User;
$user->first_name = $data['first_name']= e(Input::get('first_name'));
$user->last_name = e(Input::get('last_name'));
$user->email = $data['email'] = e(Input::get('email'));
$user->first_name = $data['first_name']= $request->input('first_name');
$user->last_name = $request->input('last_name');
$user->email = $data['email'] = $request->input('email');
$user->activated = 1;
$permissions = array('superuser' => 1);
$user->permissions = json_encode($permissions);
$user->username = $data['username'] = e(Input::get('username'));
$user->password = bcrypt(Input::get('password'));
$data['password'] = Input::get('password');
$user->username = $data['username'] = $request->input('username');
$user->password = bcrypt($request->input('password'));
$data['password'] = $request->input('password');
$settings = new Setting;
$settings->site_name = e(Input::get('site_name'));
$settings->alert_email = e(Input::get('email'));
$settings->full_multiple_companies_support = $request->input('full_multiple_companies_support', 0);
$settings->site_name = $request->input('site_name');
$settings->alert_email = $request->input('email');
$settings->alerts_enabled = 1;
$settings->pwd_secure_min = 10;
$settings->brand = 1;
$settings->locale = 'en';
$settings->default_currency = 'USD';
$settings->locale = $request->input('locale', 'en');
$settings->default_currency = $request->input('default_currency', "USD");
$settings->user_id = 1;
$settings->email_domain = e(Input::get('email_domain'));
$settings->email_format = e(Input::get('email_format'));
$settings->email_domain = $request->input('email_domain');
$settings->email_format = $request->input('email_format');
$settings->next_auto_tag_base = 1;
$settings->auto_increment_assets = $request->input('auto_increment_assets', 0);
$settings->auto_increment_prefix = $request->input('auto_increment_prefix');
if ((!$user->isValid()) || (!$settings->isValid())) {
@@ -263,8 +245,8 @@ class SettingsController extends Controller
$output = Artisan::output();
if ((!file_exists(storage_path().'/oauth-private.key')) || (!file_exists(storage_path().'/oauth-public.key'))) {
Artisan::call('passport:install');
Artisan::call('migrate', ['--force' => true]);
Artisan::call('passport:install');
}
@@ -332,13 +314,23 @@ class SettingsController extends Controller
return redirect()->to('admin')->with('error', trans('admin/settings/message.update.error'));
}
$setting->modellist_displays = '';
if (($request->has('show_in_model_list')) && (count($request->input('show_in_model_list')) > 0))
{
$setting->modellist_displays = implode(',', $request->input('show_in_model_list'));
}
$setting->full_multiple_companies_support = $request->input('full_multiple_companies_support', '0');
$setting->load_remote = $request->input('load_remote', '0');
$setting->show_archived_in_list = $request->input('show_archived_in_list', '0');
$setting->dashboard_message = $request->input('dashboard_message');
$setting->email_domain = $request->input('email_domain');
$setting->email_format = $request->input('email_format');
$setting->username_format = $request->input('username_format');
$setting->require_accept_signature = $request->input('require_accept_signature');
if (config('app.lock_passwords')) {
if (!config('app.lock_passwords')) {
$setting->login_note = $request->input('login_note');
}
@@ -391,6 +383,9 @@ class SettingsController extends Controller
$setting->brand = $request->input('brand', '1');
$setting->header_color = $request->input('header_color');
$setting->support_footer = $request->input('support_footer');
$setting->footer_text = $request->input('footer_text');
$setting->show_url_in_emails = $request->input('show_url_in_emails', '0');
// Only allow the site name and CSS to be changed if lock_passwords is false
@@ -414,7 +409,7 @@ class SettingsController extends Controller
$file_name = "logo.".$image->getClientOriginalExtension();
$path = public_path('uploads');
if ($image->getClientOriginalExtension()!='svg') {
Image::make($image->getRealPath())->resize(null, 40, function ($constraint) {
Image::make($image->getRealPath())->resize(null, 150, function ($constraint) {
$constraint->aspectRatio();
$constraint->upsize();
})->save($path.'/'.$file_name);
@@ -572,6 +567,7 @@ class SettingsController extends Controller
$setting->alert_threshold = $request->input('alert_threshold');
$setting->audit_interval = $request->input('audit_interval');
$setting->audit_warning_days = $request->input('audit_warning_days');
$setting->show_alerts_in_menu = $request->input('show_alerts_in_menu', '0');
if ($setting->save()) {
return redirect()->route('settings.index')
@@ -767,6 +763,7 @@ class SettingsController extends Controller
$setting->labels_fontsize = $request->input('labels_fontsize');
$setting->labels_pagewidth = $request->input('labels_pagewidth');
$setting->labels_pageheight = $request->input('labels_pageheight');
$setting->labels_display_company_name = $request->input('labels_display_company_name', '0');
@@ -846,6 +843,7 @@ class SettingsController extends Controller
$setting->is_ad = $request->input('is_ad', '0');
$setting->ldap_tls = $request->input('ldap_tls', '0');
$setting->ldap_pw_sync = $request->input('ldap_pw_sync', '0');
$setting->custom_forgot_pass_url = $request->input('custom_forgot_pass_url');
if ($setting->save()) {
return redirect()->route('settings.index')
@@ -907,12 +905,30 @@ class SettingsController extends Controller
public function postBackups()
{
if (!config('app.lock_passwords')) {
Artisan::call('backup:run');
return redirect()->route('settings.backups.index')->with('success', trans('admin/settings/message.backup.generated'));
} else {
return redirect()->to("settings.backups.index")->with('error', trans('general.feature_disabled'));
}
$output = Artisan::output();
// Backup completed
if (!preg_match('/failed/', $output)) {
return redirect()->route('settings.backups.index')
->with('success', trans('admin/settings/message.backup.generated'));
}
$formatted_output = str_replace('Backup completed!', '', $output);
$output_split = explode('...', $formatted_output);
if (array_key_exists(2, $output_split)) {
return redirect()->route("settings.backups.index")->with('error', $output_split[2]);
}
return redirect()->route("settings.backups.index")->with('error', $formatted_output);
}
return redirect()->route("settings.backups.index")->with('error', trans('general.feature_disabled'));
}
@@ -1023,4 +1039,28 @@ class SettingsController extends Controller
public function api() {
return view('settings.api');
}
/**
* Test the email configuration
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v3.0]
* @return Redirect
*/
public function ajaxTestEmail()
{
try {
Mail::send('emails.test', [], function ($m) {
$m->to(config('mail.from.address'), config('mail.from.name'));
$m->replyTo(config('mail.reply_to.address'), config('mail.reply_to.name'));
$m->subject(trans('mail.test_email'));
});
return response()->json(Helper::formatStandardApiResponse('success', null, 'Maiol sent!'));
} catch (Exception $e) {
return response()->json(Helper::formatStandardApiResponse('success', null, $e->getMessage()));
}
}
}

View File

@@ -32,18 +32,18 @@ class StatuslabelsController extends Controller
public function index()
{
return view('statuslabels/index', compact('statuslabels'));
$this->authorize('view', Statuslabel::class);
return view('statuslabels.index', compact('statuslabels'));
}
public function show($id)
{
$statuslabel = Statuslabel::find($id);
if (isset($statuslabel->id)) {
return view('statuslabels/view', compact('statuslabel'));
$this->authorize('view', Statuslabel::class);
if ($statuslabel = Statuslabel::find($id)) {
return view('statuslabels.view')->with('statuslabel', $statuslabel);
}
return redirect()->route('statuslabels.index')->with('error', trans('admin/locations/message.does_not_exist', compact('id')));
return redirect()->route('statuslabels.index')->with('error', trans('admin/statuslabels/message.does_not_exist', compact('id')));
}
@@ -56,6 +56,7 @@ class StatuslabelsController extends Controller
public function create()
{
// Show the page
$this->authorize('create', Statuslabel::class);
$item = new Statuslabel;
$use_statuslabel_type = $item->getStatuslabelType();
$statuslabel_types = Helper::statusTypeList();
@@ -73,6 +74,7 @@ class StatuslabelsController extends Controller
public function store(Request $request)
{
$this->authorize('create', Statuslabel::class);
// create a new model instance
$statusLabel = new Statuslabel();
@@ -107,6 +109,7 @@ class StatuslabelsController extends Controller
*/
public function apiStore(Request $request)
{
$this->authorize('create', Statuslabel::class);
$statuslabel = new Statuslabel();
if (!$request->has('statuslabel_types')) {
return JsonResponse::create(["error" => trans('validation.statuslabel_type')], 500);
@@ -138,6 +141,7 @@ class StatuslabelsController extends Controller
*/
public function edit($statuslabelId = null)
{
$this->authorize('update', Statuslabel::class);
// Check if the Statuslabel exists
if (is_null($item = Statuslabel::find($statuslabelId))) {
// Redirect to the blogs management page
@@ -160,6 +164,7 @@ class StatuslabelsController extends Controller
*/
public function update(Request $request, $statuslabelId = null)
{
$this->authorize('update', Statuslabel::class);
// Check if the Statuslabel exists
if (is_null($statuslabel = Statuslabel::find($statuslabelId))) {
// Redirect to the blogs management page
@@ -198,19 +203,18 @@ class StatuslabelsController extends Controller
*/
public function destroy($statuslabelId)
{
$this->authorize('delete', Statuslabel::class);
// Check if the Statuslabel exists
if (is_null($statuslabel = Statuslabel::find($statuslabelId))) {
// Redirect to the blogs management page
return redirect()->route('statuslabels.index')->with('error', trans('admin/statuslabels/message.not_found'));
}
if ($statuslabel->has_assets() == 0) {
// Check that there are no assets associated
if ($statuslabel->assets()->count() == 0) {
$statuslabel->delete();
// Redirect to the statuslabels management page
return redirect()->route('statuslabels.index')->with('success', trans('admin/statuslabels/message.delete.success'));
}
// Redirect to the asset management page
return redirect()->route('statuslabels.index')->with('error', trans('admin/statuslabels/message.assoc_assets'));
}

View File

@@ -13,6 +13,7 @@ use Str;
use View;
use Auth;
use Illuminate\Http\Request;
use App\Http\Requests\ImageUploadRequest;
use Symfony\Component\HttpFoundation\JsonResponse;
@@ -32,6 +33,7 @@ class SuppliersController extends Controller
public function index()
{
// Grab all the suppliers
$this->authorize('view', Supplier::class);
$suppliers = Supplier::orderBy('created_at', 'DESC')->get();
// Show the page
@@ -46,6 +48,7 @@ class SuppliersController extends Controller
*/
public function create()
{
$this->authorize('create', Supplier::class);
return view('suppliers/edit')->with('item', new Supplier);
}
@@ -56,8 +59,9 @@ class SuppliersController extends Controller
* @param Request $request
* @return \Illuminate\Http\RedirectResponse
*/
public function store(Request $request)
public function store(ImageUploadRequest $request)
{
$this->authorize('create', Supplier::class);
// Create a new supplier
$supplier = new Supplier;
// Save the location data
@@ -76,20 +80,18 @@ class SuppliersController extends Controller
$supplier->url = $supplier->addhttp(request('url'));
$supplier->user_id = Auth::id();
if (Input::file('image')) {
if ($request->file('image')) {
$image = $request->file('image');
$file_name = str_random(25).".".$image->getClientOriginalExtension();
$path = public_path('uploads/suppliers/'.$file_name);
Image::make($image->getRealPath())->resize(300, null, function ($constraint) {
Image::make($image->getRealPath())->resize(200, null, function ($constraint) {
$constraint->aspectRatio();
$constraint->upsize();
})->save($path);
$supplier->image = $file_name;
$supplier->image = $file_name;
}
// Was it created?
if ($supplier->save()) {
// Redirect to the new supplier page
return redirect()->route('suppliers.index')->with('success', trans('admin/suppliers/message.create.success'));
}
return redirect()->back()->withInput()->withErrors($supplier->getErrors());
@@ -101,6 +103,7 @@ class SuppliersController extends Controller
*/
public function apiStore(Request $request)
{
$this->authorize('create', Supplier::class);
$supplier = new Supplier;
$supplier->name = $request->input('name');
$supplier->user_id = Auth::id();
@@ -119,6 +122,7 @@ class SuppliersController extends Controller
*/
public function edit($supplierId = null)
{
$this->authorize('edit', Supplier::class);
// Check if the supplier exists
if (is_null($item = Supplier::find($supplierId))) {
// Redirect to the supplier page
@@ -136,8 +140,9 @@ class SuppliersController extends Controller
* @param int $supplierId
* @return \Illuminate\Http\RedirectResponse
*/
public function update($supplierId = null, Request $request)
public function update($supplierId = null, ImageUploadRequest $request)
{
$this->authorize('edit', Supplier::class);
// Check if the supplier exists
if (is_null($supplier = Supplier::find($supplierId))) {
// Redirect to the supplier page
@@ -159,21 +164,39 @@ class SuppliersController extends Controller
$supplier->url = $supplier->addhttp(request('url'));
$supplier->notes = request('notes');
if (Input::file('image')) {
$image = $request->file('image');
$file_name = str_random(25).".".$image->getClientOriginalExtension();
$path = public_path('uploads/suppliers/'.$file_name);
Image::make($image->getRealPath())->resize(300, null, function ($constraint) {
$constraint->aspectRatio();
$constraint->upsize();
})->save($path);
$supplier->image = $file_name;
}
if (request('image_delete') == 1 && $request->file('image') == "") {
$old_image = $supplier->image;
// Set the model's image property to null if the image is being deleted
if ($request->input('image_delete') == 1) {
$supplier->image = null;
}
if ($request->file('image')) {
$image = $request->file('image');
$file_name = $supplier->id.'-'.str_slug($image->getClientOriginalName()) . "." . $image->getClientOriginalExtension();
if ($image->getClientOriginalExtension()!='svg') {
Image::make($image->getRealPath())->resize(500, null, function ($constraint) {
$constraint->aspectRatio();
$constraint->upsize();
})->save(app('suppliers_upload_path').$file_name);
} else {
$image->move(app('suppliers_upload_path'), $file_name);
}
$supplier->image = $file_name;
}
if ((($request->file('image')) && (isset($old_image)) && ($old_image!='')) || ($request->input('image_delete') == 1)) {
try {
unlink(app('suppliers_upload_path').$old_image);
} catch (\Exception $e) {
\Log::error($e);
}
}
if ($supplier->save()) {
return redirect()->route('suppliers.index')->with('success', trans('admin/suppliers/message.update.success'));
}
@@ -190,23 +213,30 @@ class SuppliersController extends Controller
*/
public function destroy($supplierId)
{
// Check if the supplier exists
if (is_null($supplier = Supplier::find($supplierId))) {
// Redirect to the suppliers page
$this->authorize('delete', Supplier::class);
if (is_null($supplier = Supplier::with('asset_maintenances', 'assets', 'licenses')->withCount('asset_maintenances','assets','licenses')->find($supplierId))) {
return redirect()->route('suppliers.index')->with('error', trans('admin/suppliers/message.not_found'));
}
if ($supplier->num_assets() == 0) {
// Delete the supplier
$supplier->delete();
// Redirect to the suppliers management page
return redirect()->route('suppliers.index')->with(
'success',
trans('admin/suppliers/message.delete.success')
);
if ($supplier->assets_count > 0) {
return redirect()->route('suppliers.index')->with('error', trans('admin/suppliers/message.delete.assoc_assets', ['asset_count' => (int) $supplier->assets_count]));
}
// Redirect to the asset management page
return redirect()->route('suppliers.index')->with('error', trans('admin/suppliers/message.assoc_users'));
if ($supplier->asset_maintenances_count > 0) {
return redirect()->route('suppliers.index')->with('error', trans('admin/suppliers/message.delete.assoc_maintenances', ['asset_maintenances_count' => $supplier->asset_maintenances_count]));
}
if ($supplier->licenses_count > 0) {
return redirect()->route('suppliers.index')->with('error', trans('admin/suppliers/message.delete.assoc_licenses', ['licenses_count' => (int) $supplier->licenses_count]));
}
$supplier->delete();
return redirect()->route('suppliers.index')->with('success',
trans('admin/suppliers/message.delete.success')
);
}
@@ -228,7 +258,7 @@ class SuppliersController extends Controller
$error = trans('admin/suppliers/message.does_not_exist', compact('id'));
// Redirect to the user management page
return redirect()->route('suppliers')->with('error', $error);
return redirect()->route('suppliers.index')->with('error', $error);
}
}

View File

@@ -33,6 +33,7 @@ use URL;
use View;
use Illuminate\Http\Request;
use Gate;
use Artisan;
/**
* This controller handles all actions related to Users for
@@ -84,10 +85,6 @@ class UsersController extends Controller
$permissions = $this->filterDisplayable($permissions);
return view('users/edit', compact('groups', 'userGroups', 'permissions', 'userPermissions'))
->with('location_list', Helper::locationsList())
->with('manager_list', Helper::managerList())
->with('company_list', Helper::companyList())
->with('department_list', Helper::departmentList())
->with('user', new User);
}
@@ -109,7 +106,6 @@ class UsersController extends Controller
$user->password = bcrypt($request->input('password'));
$data['password'] = $request->input('password');
}
// Update the user
$user->first_name = $request->input('first_name');
$user->last_name = $request->input('last_name');
$user->locale = $request->input('locale');
@@ -122,6 +118,11 @@ class UsersController extends Controller
$user->company_id = Company::getIdForUser($request->input('company_id', null));
$user->manager_id = $request->input('manager_id', null);
$user->notes = $request->input('notes');
$user->address = $request->input('address', null);
$user->city = $request->input('city', null);
$user->state = $request->input('state', null);
$user->country = $request->input('country', null);
$user->zip = $request->input('zip', null);
// Strip out the superuser permission if the user isn't a superadmin
$permissions_array = $request->input('permission');
@@ -231,9 +232,9 @@ class UsersController extends Controller
public function edit($id)
{
try {
$user = User::find($id);
if ($user = User::find($id)) {
$this->authorize('update', $user);
$permissions = config('permissions');
@@ -243,19 +244,14 @@ class UsersController extends Controller
$user->permissions = $user->decodePermissions();
$userPermissions = Helper::selectedPermissionsArray($permissions, $user->permissions);
$permissions = $this->filterDisplayable($permissions);
} catch (UserNotFoundException $e) {
$error = trans('admin/users/message.user_not_found', compact('id'));
return redirect()->route('users.index')->with('error', $error);
return view('users/edit', compact('user', 'groups', 'userGroups', 'permissions', 'userPermissions'))->with('item', $user);
}
// Show the page
return view('users/edit', compact('user', 'groups', 'userGroups', 'permissions', 'userPermissions'))
->with('location_list', Helper::locationsList())
->with('department_list', Helper::departmentList())
->with('company_list', Helper::companyList())
->with('manager_list', Helper::managerList());
$error = trans('admin/users/message.user_not_found', compact('id'));
return redirect()->route('users.index')->with('error', $error);
}
/**
@@ -281,6 +277,10 @@ class UsersController extends Controller
try {
$user = User::find($id);
if ($user->id == $request->input('manager_id')) {
return redirect()->back()->withInput()->with('error', 'You cannot be your own manager.');
}
$this->authorize('update', $user);
// Figure out of this user was an admin before this edit
$orig_permissions_array = $user->decodePermissions();
@@ -320,15 +320,24 @@ class UsersController extends Controller
$user->locale = $request->input('locale');
$user->employee_num = $request->input('employee_num');
$user->activated = $request->input('activated', $user->activated);
$user->jobtitle = $request->input('jobtitle');
$user->jobtitle = $request->input('jobtitle', null);
$user->phone = $request->input('phone');
$user->location_id = $request->input('location_id', null);
$user->company_id = Company::getIdForUser($request->input('company_id', null));
$user->manager_id = $request->input('manager_id', null);
$user->notes = $request->input('notes');
$user->department_id = $request->input('department_id', null);
$user->address = $request->input('address', null);
$user->city = $request->input('city', null);
$user->state = $request->input('state', null);
$user->country = $request->input('country', null);
$user->zip = $request->input('zip', null);
// Update the location of any assets checked out to this user
Asset::where('assigned_type', User::class)
->where('assigned_to', $user->id)->update(['location_id' => $request->input('location_id', null)]);
// Do we want to update the user password?
if ($request->has('password')) {
$user->password = bcrypt($request->input('password'));
@@ -376,6 +385,11 @@ class UsersController extends Controller
return redirect()->route('users.index')->with('error', 'This user still has ' . $user->assets()->count() . ' assets associated with them.');
}
if (count($user->assets) > 0) {
// Redirect to the user management page
return redirect()->route('users.index')->with('error', 'This user still has ' . count($user->assets) . ' assets associated with them.');
}
if ($user->licenses()->count() > 0) {
// Redirect to the user management page
return redirect()->route('users.index')->with('error', 'This user still has ' . $user->assets()->count() . ' assets associated with them.');
@@ -417,7 +431,7 @@ class UsersController extends Controller
public function postBulkEdit(Request $request)
{
$this->authorize('update', User::class);
if ((!Input::has('ids')) || (count(Input::has('ids')) == 0)) {
if ((!Input::has('ids')) || (count(Input::input('ids')) == 0)) {
return redirect()->back()->with('error', 'No users selected');
} else {
@@ -429,11 +443,6 @@ class UsersController extends Controller
if ($request->input('bulk_actions')=='edit') {
return view('users/bulk-edit', compact('users'))
->with('location_list', Helper::locationsList())
->with('company_list', Helper::companyList())
->with('manager_list', Helper::managerList())
->with('manager_list', Helper::managerList())
->with('department_list', Helper::departmentList())
->with('groups', Group::pluck('name', 'id'));
}
@@ -452,7 +461,7 @@ class UsersController extends Controller
public function postBulkEditSave(Request $request)
{
$this->authorize('update', User::class);
if ((!Input::has('ids')) || (count(Input::has('ids')) == 0)) {
if ((!Input::has('ids')) || (count(Input::input('ids')) == 0)) {
return redirect()->back()->with('error', 'No users selected');
} else {
@@ -471,6 +480,11 @@ class UsersController extends Controller
if ($request->has('company_id')) {
$update_array['company_id'] = $request->input('company_id');
}
if ($request->has('locale')) {
$update_array['locale'] = $request->input('locale');
}
if ($request->has('manager_id')) {
@@ -719,7 +733,7 @@ class UsersController extends Controller
$user->first_name = '';
$user->last_name = '';
$user->email = substr($user->email, ($pos = strpos($user->email, '@')) !== false ? $pos : 0);
;
$user->id = null;
// Get this user groups
@@ -732,10 +746,6 @@ class UsersController extends Controller
// Show the page
return view('users/edit', compact('permissions', 'userPermissions'))
->with('location_list', Helper::locationsList())
->with('company_list', Helper::companyList())
->with('manager_list', Helper::managerList())
->with('department_list', Helper::departmentList())
->with('user', $user)
->with('groups', Group::pluck('name', 'id'))
->with('userGroups', $userGroups)
@@ -1024,128 +1034,20 @@ class UsersController extends Controller
*/
public function postLDAP(Request $request)
{
$this->authorize('update', User::class);
ini_set('max_execution_time', 600); //600 seconds = 10 minutes
ini_set('memory_limit', '500M');
// Call Artisan LDAP import command.
$location_id = $request->input('location_id');
Artisan::call('snipeit:ldap-sync', ['--location_id' => $location_id, '--json_summary' => true]);
$ldap_result_username = Setting::getSettings()->ldap_username_field;
$ldap_result_last_name = Setting::getSettings()->ldap_lname_field;
$ldap_result_first_name = Setting::getSettings()->ldap_fname_field;
// Collect and parse JSON summary.
$ldap_results_json = Artisan::output();
$ldap_results = json_decode($ldap_results_json, true);
$ldap_result_active_flag = Setting::getSettings()->ldap_active_flag_field;
$ldap_result_emp_num = Setting::getSettings()->ldap_emp_num;
$ldap_result_email = Setting::getSettings()->ldap_email;
try {
$ldapconn = Ldap::connectToLdap();
} catch (\Exception $e) {
return redirect()->back()->withInput()->with('error', $e->getMessage());
// Direct user to appropriate status page.
if ($ldap_results['error']) {
return redirect()->back()->withInput()->with('error', $ldap_results['error_message']);
} else {
return redirect()->route('ldap/user')->with('success', "LDAP Import successful.")->with('summary', $ldap_results['summary']);
}
try {
Ldap::bindAdminToLdap($ldapconn);
} catch (\Exception $e) {
return redirect()->back()->withInput()->with('error', $e->getMessage());
}
$summary = array();
$ldap_ou_locations = Location::whereNotNull('ldap_ou')->get();
$results = Ldap::findLdapUsers();
// Inject location information fields
for ($i = 0; $i < $results["count"]; $i++) {
$results[$i]["ldap_location_override"] = false;
$results[$i]["location_id"] = 0;
}
// Grab subsets based on location-specific DNs, and overwrite location for these users.
foreach ($ldap_ou_locations as $ldap_loc) {
$location_users = Ldap::findLdapUsers($ldap_loc->ldap_ou);
$usernames = array();
for ($i = 0; $i < $location_users["count"]; $i++) {
$location_users[$i]["ldap_location_override"] = true;
$location_users[$i]["location_id"] = $ldap_loc->id;
$usernames[] = $location_users[$i][$ldap_result_username][0];
}
// Delete located users from the general group.
foreach ($results as $key => $generic_entry) {
if (in_array($generic_entry[$ldap_result_username][0], $location_users)) {
unset($results[$key]);
}
}
$global_count = $results['count'];
$results = array_merge($location_users, $results);
$results['count'] = $global_count;
}
$tmp_pass = substr(str_shuffle("0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"), 0, 20);
$pass = bcrypt($tmp_pass);
for ($i = 0; $i < $results["count"]; $i++) {
if (empty($ldap_result_active_flag) || $results[$i][$ldap_result_active_flag][0] == "TRUE") {
$item = array();
$item["username"] = isset($results[$i][$ldap_result_username][0]) ? $results[$i][$ldap_result_username][0] : "";
$item["employee_number"] = isset($results[$i][$ldap_result_emp_num][0]) ? $results[$i][$ldap_result_emp_num][0] : "";
$item["lastname"] = isset($results[$i][$ldap_result_last_name][0]) ? $results[$i][$ldap_result_last_name][0] : "";
$item["firstname"] = isset($results[$i][$ldap_result_first_name][0]) ? $results[$i][$ldap_result_first_name][0] : "";
$item["email"] = isset($results[$i][$ldap_result_email][0]) ? $results[$i][$ldap_result_email][0] : "" ;
$item["ldap_location_override"] = isset($results[$i]["ldap_location_override"]) ? $results[$i]["ldap_location_override"]:"";
$item["location_id"] = isset($results[$i]["location_id"]) ? $results[$i]["location_id"]:"";
if( array_key_exists('useraccountcontrol', $results[$i]) ) {
$enabled_accounts = [
'512', '544', '66048', '66080', '262656', '262688', '328192', '328224'
];
$item['activated'] = ( in_array($results[$i]['useraccountcontrol'][0], $enabled_accounts) ) ? 1 : 0;
} else {
$item['activated'] = 0;
}
// User exists
$item["createorupdate"] = 'updated';
if (!$user = User::where('username', $item["username"])->first()) {
$user = new User;
$user->password = $pass;
$item["createorupdate"] = 'created';
}
// Create the user if they don't exist.
$user->first_name = $item["firstname"];
$user->last_name = $item["lastname"];
$user->username = $item["username"];
$user->email = $item["email"];
$user->employee_num = e($item["employee_number"]);
$user->activated = $item['activated'];
if ($item['ldap_location_override'] == true) {
$user->location_id = $item['location_id'];
} else if ($request->input('location_id')!='') {
$user->location_id = e($request->input('location_id'));
}
$user->notes = 'Imported from LDAP';
$user->ldap_import = 1;
$errors = '';
if ($user->save()) {
$item["note"] = $item["createorupdate"];
$item["status"]='success';
} else {
foreach ($user->getErrors()->getMessages() as $key => $err) {
$errors .='<li>'.$err[0];
}
$item["note"] = $errors;
$item["status"]='error';
}
array_push($summary, $item);
}
}
return redirect()->route('ldap/user')->with('success', "LDAP Import successful.")->with('summary', $summary);
}
@@ -1166,7 +1068,7 @@ class UsersController extends Controller
// Open output stream
$handle = fopen('php://output', 'w');
User::with('assets', 'accessories', 'consumables', 'licenses', 'manager', 'groups', 'userloc', 'company','throttle')->orderBy('created_at', 'DESC')->chunk(500, function($users) use($handle) {
User::with('assets', 'accessories', 'consumables', 'department', 'licenses', 'manager', 'groups', 'userloc', 'company','throttle')->orderBy('created_at', 'DESC')->chunk(500, function($users) use($handle) {
$headers=[
// strtolower to prevent Excel from trying to open it as a SYLK file
strtolower(trans('general.id')),
@@ -1178,6 +1080,7 @@ class UsersController extends Controller
trans('admin/users/table.email'),
trans('admin/users/table.manager'),
trans('admin/users/table.location'),
trans('general.department'),
trans('general.assets'),
trans('general.licenses'),
trans('general.accessories'),
@@ -1208,6 +1111,7 @@ class UsersController extends Controller
$user->email,
($user->manager) ? $user->manager->present()->fullName() : '',
($user->userloc) ? $user->userloc->name : '',
($user->department) ? $user->department->name : '',
$user->assets->count(),
$user->licenses->count(),
$user->accessories->count(),
@@ -1250,4 +1154,24 @@ class UsersController extends Controller
return response()->json(['message' => trans('admin/settings/general.two_factor_reset_error')], 500);
}
}
/**
* LDAP form processing.
*
* @author Aladin Alaily
* @since [v1.8]
* @return \Illuminate\Http\RedirectResponse
*/
public function printInventory($id)
{
$show_user = User::where('id',$id)->withTrashed()->first();
$assets = Asset::where('assigned_to', $id)->where('assigned_type', User::class)->with('model', 'model.category')->get();
$licenses = $show_user->licenses()->get();
$accessories = $show_user->accessories()->get();
$consumables = $show_user->consumables()->get();
return view('users/print')->with('assets', $assets)->with('licenses',$licenses)->with('accessories', $accessories)->with('consumables', $consumables)->with('show_user', $show_user);
}
}

View File

@@ -68,17 +68,12 @@ class ViewAssetsController extends Controller
public function getRequestableIndex()
{
$assets = Asset::with('model', 'defaultLoc', 'assetloc', 'assignedTo', 'requests')->Hardware()->RequestableAssets()->get();
$assets = Asset::with('model', 'defaultLoc', 'location', 'assignedTo', 'requests')->Hardware()->RequestableAssets()->get();
$models = AssetModel::with('category', 'requests', 'assets')->RequestableModels()->get();
return view('account/requestable-assets', compact('user', 'assets', 'models'));
}
public function getRequestedIndex()
{
$requestedItems = CheckoutRequest::with('user', 'requestedItem')->get();
return view('admin/requested-assets', compact('requestedItems'));
}
public function getRequestItem($itemType, $itemId = null)
@@ -289,9 +284,10 @@ class ViewAssetsController extends Controller
public function getAcceptAsset($logID = null)
{
if (!$findlog = Actionlog::where('id', $logID)->first()) {
echo 'no record';
//return redirect()->to('account')->with('error', trans('admin/hardware/message.does_not_exist'));
$findlog = Actionlog::where('id', $logID)->first();
if (!$findlog) {
return redirect()->to('account/view-assets')->with('error', 'No matching record.');
}
if ($findlog->accepted_id!='') {

View File

@@ -19,10 +19,13 @@ class Kernel extends HttpKernel
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
\App\Http\Middleware\FrameGuard::class,
\App\Http\Middleware\XssProtectHeader::class,
\App\Http\Middleware\ReferrerPolicyHeader::class,
\App\Http\Middleware\ContentSecurityPolicyHeader::class,
\App\Http\Middleware\NosniffGuard::class,
\App\Http\Middleware\CheckForSetup::class,
\Fideloper\Proxy\TrustProxies::class,
\App\Http\Middleware\CheckForDebug::class,
// \Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class,
];
/**

View File

@@ -0,0 +1,35 @@
<?php
namespace App\Http\Middleware;
use Closure;
class ContentSecurityPolicyHeader
{
/**
* Handle the given request and get the response.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return \Illuminate\Http\Response
*/
public function handle($request, Closure $next)
{
if ((config('app.debug')=='true') || (config('app.enable_csp')!='true')) {
$response = $next($request);
return $response;
}
$policy[] = "default-src 'self'";
$policy[] = "style-src 'self' 'unsafe-inline' oss.maxcdn.com";
$policy[] = "script-src 'self' 'unsafe-inline' oss.mafxcdn.com cdnjs.cloudflare.com'";
$policy[] = "connect-src 'self'";
$policy[] = "object-src 'none'";
$policy[] = "font-src 'self' data:";
$policy[] = "img-src 'self' data: gravatar.com";
$policy = join(';', $policy);
$response = $next($request);
$response->headers->set('Content-Security-Policy', $policy);
return $response;
}
}

View File

@@ -0,0 +1,21 @@
<?php
namespace App\Http\Middleware;
use Closure;
class ReferrerPolicyHeader
{
/**
* Handle the given request and get the response.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return \Illuminate\Http\Response
*/
public function handle($request, Closure $next)
{
$response = $next($request);
$response->headers->set('Referrer-Policy', config('app.referrer_policy'));
return $response;
}
}

View File

@@ -14,8 +14,9 @@ class XssProtectHeader
*/
public function handle($request, Closure $next)
{
$mode = '1;mode=block';
$response = $next($request);
$response->headers->set('X-XSS-Protection', '1');
$response->headers->set('X-XSS-Protection', $mode);
return $response;
}
}

View File

@@ -23,10 +23,14 @@ class AssetCheckoutRequest extends Request
*/
public function rules()
{
return [
"assigned_user" => 'required_without_all:assigned_asset,assigned_location',
"assigned_asset" => 'required_without_all:assigned_user,assigned_location',
"assigned_location" => 'required_without_all:assigned_user,assigned_asset',
$rules = [
"assigned_user" => 'required_without_all:assigned_asset,assigned_location',
"assigned_asset" => 'required_without_all:assigned_user,assigned_location|different:'.$this->id,
"assigned_location" => 'required_without_all:assigned_user,assigned_asset',
"checkout_to_type" => 'required|in:asset,location,user'
];
return $rules;
}
}

View File

@@ -36,13 +36,16 @@ class AssetRequest extends Request
'checkin_date' => 'date',
'supplier_id' => 'integer|nullable',
'status' => 'integer|nullable',
'asset_tag' => 'required',
'purchase_cost' => 'numeric|nullable',
"assigned_user" => 'sometimes:required_without_all:assigned_asset,assigned_location',
"assigned_asset" => 'sometimes:required_without_all:assigned_user,assigned_location',
"assigned_location" => 'sometimes:required_without_all:assigned_user,assigned_asset',
];
$settings = \App\Models\Setting::getSettings();
$rules['asset_tag'] = ($settings->auto_increment_assets == '1') ? 'max:255' : 'required';
$model = AssetModel::find($this->request->get('model_id'));
if (($model) && ($model->fieldset)) {

View File

@@ -0,0 +1,59 @@
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Http\Request;
class CustomFieldRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* @return bool
*/
public function authorize()
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules(Request $request)
{
$rules = [];
switch($this->method())
{
// Brand new
case 'POST':
{
$rules['name'] = "required|unique:custom_fields";
break;
}
// Save all fields
case 'PUT':
$rules['name'] = "required";
break;
// Save only what's passed
case 'PATCH':
{
$rules['name'] = "required";
break;
}
default:break;
}
$rules['custom_format'] = 'valid_regex';
return $rules;
}
}

View File

@@ -24,7 +24,8 @@ class ImageUploadRequest extends Request
public function rules()
{
return [
'image' => 'mimes:png,gif,jpg,jpeg,svg|max:2000'
'image' => 'mimes:png,gif,jpg,jpeg,svg|max:2000',
'avatar' => 'mimes:png,gif,jpg,jpeg,svg|max:2000',
];
}

View File

@@ -26,7 +26,7 @@ class ItemImportRequest extends FormRequest
public function rules()
{
return [
//
'import-type' => 'required',
];
}

View File

@@ -30,12 +30,13 @@ class SaveUserRequest extends Request
switch($this->method())
{
// Brand new asset
// Brand new user
case 'POST':
{
$rules['first_name'] = 'required|string|min:1';
$rules['username'] = 'required_unless:ldap_import,1|string|min:1';
$rules['password'] = Setting::passwordComplexityRulesSaving('store');
break;
}
// Save all fields
@@ -43,11 +44,13 @@ class SaveUserRequest extends Request
$rules['first_name'] = 'required|string|min:1';
$rules['username'] = 'required_unless:ldap_import,1|string|min:1';
$rules['password'] = Setting::passwordComplexityRulesSaving('update');
break;
// Save only what's passed
case 'PATCH':
{
$rules['password'] = Setting::passwordComplexityRulesSaving('update');
break;
}
default:break;

View File

@@ -25,6 +25,7 @@ class AccessoriesTransformer
'name' => e($accessory->name),
'company' => ($accessory->company) ? ['id' => $accessory->company->id,'name'=> e($accessory->company->name)] : null,
'manufacturer' => ($accessory->manufacturer) ? ['id' => $accessory->manufacturer->id,'name'=> e($accessory->manufacturer->name)] : null,
'supplier' => ($accessory->supplier) ? ['id' => $accessory->supplier->id,'name'=> e($accessory->supplier->name)] : null,
'model_number' => ($accessory->model_number) ? e($accessory->model_number) : null,
'category' => ($accessory->category) ? ['id' => $accessory->category->id,'name'=> e($accessory->category->name)] : null,
'location' => ($accessory->location) ? ['id' => $accessory->location->id,'name'=> e($accessory->location->name)] : null,
@@ -35,6 +36,7 @@ class AccessoriesTransformer
'order_number' => ($accessory->order_number) ? e($accessory->order_number) : null,
'min_qty' => ($accessory->min_amt) ? (int) $accessory->min_amt : null,
'remaining_qty' => $accessory->numRemaining(),
'image' => ($accessory->image) ? url('/').'/uploads/accessories/'.e($accessory->image) : null,
'created_at' => Helper::getFormattedDateObject($accessory->created_at, 'datetime'),
'updated_at' => Helper::getFormattedDateObject($accessory->updated_at, 'datetime'),
@@ -59,13 +61,26 @@ class AccessoriesTransformer
}
public function transformCheckedoutAccessories (Collection $accessories_users, $total)
public function transformCheckedoutAccessory ($accessory_users, $total)
{
$array = array();
foreach ($accessories_users as $user) {
$array[] = (new UsersTransformer)->transformUser($user);
foreach ($accessory_users as $user) {
$array[] = [
'assigned_pivot_id' => $user->pivot->id,
'id' => (int) $user->id,
'username' => e($user->username),
'name' => e($user->getFullNameAttribute()),
'first_name'=> e($user->first_name),
'last_name'=> e($user->last_name),
'employee_number' => e($user->employee_num),
'type' => 'user',
'available_actions' => ['checkin' => true]
];
}
return (new DatatablesTransformer)->transformDatatables($array, $total);
}

View File

@@ -37,7 +37,7 @@ class ActionlogsTransformer
] : null,
'created_at' => Helper::getFormattedDateObject($actionlog->created_at, 'datetime'),
'updated_at' => Helper::getFormattedDateObject($actionlog->updated_at, 'datetime'),
'next_audit_date' => ($actionlog->itemType()=='asset') ? Helper::getFormattedDateObject($actionlog->calcNextAuditDate(), 'date'): null,
'next_audit_date' => ($actionlog->itemType()=='asset') ? Helper::getFormattedDateObject($actionlog->calcNextAuditDate(null, $actionlog->item), 'date'): null,
'days_to_next_audit' => $actionlog->daysUntilNextAudit($settings->audit_interval, $actionlog->item),
'action_type' => $actionlog->present()->actionType(),
'admin' => ($actionlog->user) ? [
@@ -52,7 +52,9 @@ class ActionlogsTransformer
'type' => e($actionlog->targetType()),
] : null,
'note' => e($actionlog->note),
'note' => ($actionlog->note) ? e($actionlog->note): null,
'signature_file' => ($actionlog->accept_signature) ? route('log.signature.view', ['filename' => $actionlog->accept_signature ]) : null,
'log_meta' => ($actionlog->log_meta) ? json_decode($actionlog->log_meta): null,
];

View File

@@ -28,7 +28,7 @@ class AssetModelsTransformer
'id' => (int) $assetmodel->manufacturer->id,
'name'=> e($assetmodel->manufacturer->name)
] : null,
'image' => ($assetmodel->image!='') ? url('/').'/uploads/models/'.e($assetmodel->image) : null,
'image' => ($assetmodel->image!='') ? app('models_upload_url').e($assetmodel->image) : null,
'model_number' => e($assetmodel->model_number),
'depreciation' => ($assetmodel->depreciation) ? [
'id' => (int) $assetmodel->depreciation->id,
@@ -47,13 +47,15 @@ class AssetModelsTransformer
'notes' => e($assetmodel->notes),
'created_at' => Helper::getFormattedDateObject($assetmodel->created_at, 'datetime'),
'updated_at' => Helper::getFormattedDateObject($assetmodel->updated_at, 'datetime'),
'deleted_at' => Helper::getFormattedDateObject($assetmodel->deleted_at, 'datetime'),
];
$permissions_array['available_actions'] = [
'update' => Gate::allows('update', AssetModel::class) ? true : false,
'delete' => Gate::allows('delete', AssetModel::class) ? true : false,
'clone' => Gate::allows('create', AssetModel::class) ? true : false,
'update' => (Gate::allows('update', AssetModel::class) && ($assetmodel->deleted_at=='')) ? true : false,
'delete' => (Gate::allows('delete', AssetModel::class) && ($assetmodel->assets_count==0) && ($assetmodel->deleted_at=='')) ? true : false,
'clone' => (Gate::allows('create', AssetModel::class) && ($assetmodel->deleted_at=='')) ,
'restore' => (Gate::allows('create', AssetModel::class) && ($assetmodel->deleted_at!='')) ? true : false,
];
$array += $permissions_array;

View File

@@ -30,16 +30,19 @@ class AssetsTransformer
'id' => (int) $asset->model->id,
'name'=> e($asset->model->name)
] : null,
'model_number' => ($asset->model) ? e($asset->model->model_number) : null,
'model_number' => (($asset->model) && ($asset->model->model_number)) ? e($asset->model->model_number) : null,
'eol' => ($asset->purchase_date!='') ? Helper::getFormattedDateObject($asset->present()->eol_date(), 'date') : null ,
'status_label' => ($asset->assetstatus) ? [
'id' => (int) $asset->assetstatus->id,
'name'=> e($asset->assetstatus->name)
'name'=> e($asset->assetstatus->name),
'status_type'=> e($asset->assetstatus->getStatuslabelType()),
'status_meta' => e($asset->present()->statusMeta),
] : null,
'category' => ($asset->model->category) ? [
'category' => (($asset->model) && ($asset->model->category)) ? [
'id' => (int) $asset->model->category->id,
'name'=> e($asset->model->category->name)
] : null,
'manufacturer' => ($asset->model->manufacturer) ? [
'manufacturer' => (($asset->model) && ($asset->model->manufacturer)) ? [
'id' => (int) $asset->model->manufacturer->id,
'name'=> e($asset->model->manufacturer->name)
] : null,
@@ -47,15 +50,15 @@ class AssetsTransformer
'id' => (int) $asset->supplier->id,
'name'=> e($asset->supplier->name)
] : null,
'notes' => e($asset->notes),
'order_number' => e($asset->order_number),
'notes' => ($asset->notes) ? e($asset->notes) : null,
'order_number' => ($asset->order_number) ? e($asset->order_number) : null,
'company' => ($asset->company) ? [
'id' => (int) $asset->company->id,
'name'=> e($asset->company->name)
] : null,
'location' => ($asset->assetLoc) ? [
'id' => (int) $asset->assetLoc->id,
'name'=> e($asset->assetLoc->name)
'location' => ($asset->location) ? [
'id' => (int) $asset->location->id,
'name'=> e($asset->location->name)
] : null,
'rtd_location' => ($asset->defaultLoc) ? [
'id' => (int) $asset->defaultLoc->id,
@@ -63,10 +66,13 @@ class AssetsTransformer
] : null,
'image' => ($asset->getImageUrl()) ? $asset->getImageUrl() : null,
'assigned_to' => $this->transformAssignedTo($asset),
'warranty' => ($asset->warranty_months > 0) ? e($asset->warranty_months . ' ' . trans('admin/hardware/form.months')) : null,
'warranty_months' => ($asset->warranty_months > 0) ? e($asset->warranty_months . ' ' . trans('admin/hardware/form.months')) : null,
'warranty_expires' => ($asset->warranty_months > 0) ? Helper::getFormattedDateObject($asset->warranty_expires, 'date') : null,
'created_at' => Helper::getFormattedDateObject($asset->created_at, 'datetime'),
'updated_at' => Helper::getFormattedDateObject($asset->updated_at, 'datetime'),
'last_audit_date' => Helper::getFormattedDateObject($asset->last_audit_date, 'datetime'),
'next_audit_date' => Helper::getFormattedDateObject($asset->next_audit_date, 'date'),
'deleted_at' => Helper::getFormattedDateObject($asset->deleted_at, 'datetime'),
'purchase_date' => Helper::getFormattedDateObject($asset->purchase_date, 'date'),
'last_checkout' => Helper::getFormattedDateObject($asset->last_checkout, 'datetime'),
'expected_checkin' => Helper::getFormattedDateObject($asset->expected_checkin, 'date'),
@@ -75,32 +81,30 @@ class AssetsTransformer
];
if ($asset->model->fieldset) {
if (($asset->model) && ($asset->model->fieldset) && (count($asset->model->fieldset->fields)> 0)) {
$fields_array = array();
foreach ($asset->model->fieldset->fields as $field) {
if ($field->isFieldDecryptable($asset->{$field->convertUnicodeDbSlug()})) {
$decrypted = \App\Helpers\Helper::gracefulDecrypt($field,$asset->{$field->convertUnicodeDbSlug()});
$value = (Gate::allows('superadmin')) ? $decrypted : strtoupper(trans('admin/custom_fields/general.encrypted'));
// $fields_array = [$field->convertUnicodeDbSlug() => $value];
$fields_array[$field->name] = [
'field' => $field->convertUnicodeDbSlug(),
'value' => $value
'value' => $value,
'field_format' => $field->format,
];
} else {
$fields_array[$field->name] = [
'field' => $field->convertUnicodeDbSlug(),
'value' => $asset->{$field->convertUnicodeDbSlug()}
'value' => $asset->{$field->convertUnicodeDbSlug()},
'field_format' => $field->format,
];
//$fields_array = [$field->convertUnicodeDbSlug() => $asset->{$field->convertUnicodeDbSlug()}];
}
//array += $fields_array;
$array['custom_fields'] = $fields_array;
}
} else {
@@ -111,10 +115,23 @@ class AssetsTransformer
'checkout' => (bool) Gate::allows('checkout', Asset::class),
'checkin' => (bool) Gate::allows('checkin', Asset::class),
'clone' => Gate::allows('create', Asset::class) ? true : false,
'restore' => false,
'update' => (bool) Gate::allows('update', Asset::class),
'delete' => (bool) Gate::allows('delete', Asset::class),
];
if ($asset->deleted_at!='') {
$permissions_array['available_actions'] = [
'checkout' => true,
'checkin' => false,
'clone' => Gate::allows('create', Asset::class) ? true : false,
'restore' => Gate::allows('create', Asset::class) ? true : false,
'update' => false,
'delete' => false,
];
}
$array += $permissions_array;
return $array;
}
@@ -127,19 +144,19 @@ class AssetsTransformer
public function transformAssignedTo($asset)
{
if ($asset->checkedOutToUser()) {
return $asset->assignedTo ? [
'id' => (int) $asset->assignedTo->id,
'username' => e($asset->assignedTo->username),
'name' => e($asset->assignedTo->getFullNameAttribute()),
'first_name'=> e($asset->assignedTo->first_name),
'last_name'=> e($asset->assignedTo->last_name),
'employee_number' => e($asset->assignedTo->employee_num),
return $asset->assigned ? [
'id' => (int) $asset->assigned->id,
'username' => e($asset->assigned->username),
'name' => e($asset->assigned->getFullNameAttribute()),
'first_name'=> e($asset->assigned->first_name),
'last_name'=> ($asset->assigned->last_name) ? e($asset->assigned->last_name) : null,
'employee_number' => ($asset->assigned->employee_num) ? e($asset->assigned->employee_num) : null,
'type' => 'user'
] : null;
}
return $asset->assignedTo ? [
'id' => $asset->assignedTo->id,
'name' => $asset->assignedTo->display_name,
return $asset->assigned ? [
'id' => $asset->assigned->id,
'name' => $asset->assigned->display_name,
'type' => $asset->assignedType()
] : null;
}

View File

@@ -25,8 +25,9 @@ class CategoriesTransformer
$array = [
'id' => (int) $category->id,
'name' => e($category->name),
'type' => e($category->category_type),
'use_default_eula' => ($category->use_default_eula =='1') ? true : false,
'image' => ($category->image) ? app('categories_upload_url').e($category->image) : null,
'category_type' => e($category->category_type),
'eula' => ($category->getEula()) ? true : false,
'checkin_email' => ($category->checkin_email =='1') ? true : false,
'require_acceptance' => ($category->require_acceptance =='1') ? true : false,
'assets_count' => $category->assets_count,
@@ -39,7 +40,7 @@ class CategoriesTransformer
$permissions_array['available_actions'] = [
'update' => Gate::allows('update', Category::class) ? true : false,
'delete' => Gate::allows('delete', Category::class) ? true : false,
'delete' => (Gate::allows('delete', Category::class) && ($category->assets_count == 0) && ($category->accessories_count == 0) && ($category->consumables_count == 0) && ($category->components_count == 0)) ? true : false,
];
$array += $permissions_array;

View File

@@ -25,6 +25,7 @@ class CompaniesTransformer
$array = [
'id' => (int) $company->id,
'name' => e($company->name),
'image' => ($company->image) ? app('companies_upload_url').e($company->image) : null,
"created_at" => Helper::getFormattedDateObject($company->created_at, 'datetime'),
"updated_at" => Helper::getFormattedDateObject($company->updated_at, 'datetime'),
"assets_count" => (int) $company->assets_count,
@@ -37,7 +38,7 @@ class CompaniesTransformer
$permissions_array['available_actions'] = [
'update' => Gate::allows('update', Company::class) ? true : false,
'delete' => Gate::allows('delete', Company::class) ? true : false,
'delete' => (Gate::allows('delete', Company::class) && ($company->assets_count == 0) && ($company->accessories_count == 0) && ($company->consumables_count == 0) && ($company->components_count == 0) && ($company->users_count == 0)) ? true : false,
];
$array += $permissions_array;

View File

@@ -22,7 +22,8 @@ class ComponentsTransformer
$array = [
'id' => (int) $component->id,
'name' => e($component->name),
'serial_number' => e($component->serial),
'image' => ($component->image) ? e(url('/').'/uploads/components/'.e($component->image)) : null,
'serial' => ($component->serial) ? e($component->serial) : null,
'location' => ($component->location) ? [
'id' => (int) $component->location->id,
'name' => e($component->location->name)
@@ -33,6 +34,10 @@ class ComponentsTransformer
'id' => (int) $component->category->id,
'name' => e($component->category->name)
] : null,
'location' => ($component->location) ? [
'id' => (int) $component->location->id,
'name' => e($component->location->name)
] : null,
'order_number' => e($component->order_number),
'purchase_date' => Helper::getFormattedDateObject($component->purchase_date, 'date'),
'purchase_cost' => Helper::formatCurrencyOutput($component->purchase_cost),
@@ -58,12 +63,22 @@ class ComponentsTransformer
}
public function transformCheckedoutComponents(Collection $components_users, $total)
public function transformCheckedoutComponents(Collection $components_assets, $total)
{
$array = array();
foreach ($components_users as $user) {
$array[] = (new UsersTransformer)->transformUser($user);
foreach ($components_assets as $asset) {
$array[] = [
'assigned_pivot_id' => $asset->pivot->id,
'id' => (int) $asset->id,
'name' => e($asset->model->present()->name) .' '.e($asset->present()->name),
'qty' => $asset->pivot->assigned_qty,
'type' => 'asset',
'created_at' => Helper::getFormattedDateObject($asset->pivot->created_at, 'datetime'),
'available_actions' => ['checkin' => true]
];
}
return (new DatatablesTransformer)->transformDatatables($array, $total);
}
}

View File

@@ -22,14 +22,15 @@ class ConsumablesTransformer
{
$array = [
'id' => (int) $consumable->id,
'name' => e($consumable->name),
'image' => ($consumable->image) ? e(url('/').'/uploads/consumables/'.e($consumable->image)) : null,
'category' => ($consumable->category) ? ['id' => $consumable->category->id, 'name' => e($consumable->category->name)] : null,
'company' => ($consumable->company) ? ['id' => (int) $consumable->company->id, 'name' => e($consumable->company->name)] : null,
'item_no' => e($consumable->item_no),
'location' => ($consumable->location) ? ['id' => (int) $consumable->location->id, 'name' => e($consumable->location->name)] : null,
'manufacturer' => ($consumable->manufacturer) ? ['id' => (int) $consumable->manufacturer->id, 'name' => e($consumable->manufacturer->name)] : null,
'min_amt' => (int) $consumable->min_amt,
'model_number' => e($consumable->model_number),
'name' => e($consumable->name),
'model_number' => ($consumable->model_number!='') ? e($consumable->model_number) : null,
'remaining' => $consumable->numRemaining(),
'order_number' => e($consumable->order_number),
'purchase_cost' => Helper::formatCurrencyOutput($consumable->purchase_cost),

View File

@@ -22,6 +22,7 @@ class CustomFieldsTransformer
{
$array = [
'id' => $field->id,
'name' => e($field->name),
'db_column_name' => e($field->db_column_name()),
'format' => e($field->format),

View File

@@ -25,6 +25,7 @@ class DepartmentsTransformer
$array = [
'id' => (int) $department->id,
'name' => e($department->name),
'image' => ($department->image) ? app('departments_upload_url').e($department->image) : null,
'company' => ($department->company) ? [
'id' => (int) $department->company->id,
'name'=> e($department->company->name)
@@ -46,7 +47,7 @@ class DepartmentsTransformer
$permissions_array['available_actions'] = [
'update' => Gate::allows('update', Department::class) ? true : false,
'delete' => Gate::allows('delete', Department::class) ? true : false,
'delete' => (Gate::allows('delete', Department::class) && ($department->users_count==0) && ($department->deleted_at=='')) ? true : false,
];
$array += $permissions_array;

View File

@@ -23,7 +23,7 @@ class GroupsTransformer
$array = [
'id' => (int) $group->id,
'name' => e($group->name),
'permissions' => $group->permissions,
'permissions' => json_decode($group->permissions),
'users_count' => (int) $group->users_count,
'created_at' => Helper::getFormattedDateObject($group->created_at, 'datetime'),
'updated_at' => Helper::getFormattedDateObject($group->updated_at, 'datetime'),

View File

@@ -29,7 +29,6 @@ class ImportsTransformer
'header_row' => $import->header_row,
'first_row' => $import->first_row,
'field_map' => $import->field_map,
];
return $array;

View File

@@ -0,0 +1,62 @@
<?php
namespace App\Http\Transformers;
use App\Models\LicenseSeat;
use Gate;
use Illuminate\Database\Eloquent\Collection;
use App\Helpers\Helper;
class LicenseSeatsTransformer
{
public function transformLicenseSeats (Collection $seats, $total)
{
$array = array();
$seat_count = 0;
foreach ($seats as $seat) {
$seat_count++;
$array[] = self::transformLicenseSeat($seat, $seat_count);
}
return (new DatatablesTransformer)->transformDatatables($array, $total);
}
public function transformLicenseSeat (LicenseSeat $seat, $seat_count)
{
$array = [
'id' => (int) $seat->id,
'license_id' => (int) $seat->license->id,
'name' => 'Seat '.$seat_count,
'assigned_user' => ($seat->user) ? [
'id' => (int) $seat->user->id,
'name'=> e($seat->user->present()->fullName)
] : null,
'assigned_asset' => ($seat->asset) ? [
'id' => (int) $seat->asset->id,
'name'=> e($seat->asset->present()->fullName)
] : null,
'location' => ($seat->location()) ? [
'id' => (int) $seat->location()->id,
'name'=> e($seat->location()->name)
] : null,
'reassignable' => (bool) $seat->license->reassignable,
'user_can_checkout' => (($seat->assigned_to=='') && ($seat->asset_id=='')) ? true : false,
];
$permissions_array['available_actions'] = [
'checkout' => Gate::allows('checkout', License::class) ? true : false,
'checkin' => Gate::allows('checkin', License::class) ? true : false,
'clone' => Gate::allows('create', License::class) ? true : false,
'update' => Gate::allows('update', License::class) ? true : false,
'delete' => Gate::allows('delete', License::class) ? true : false,
];
$array += $permissions_array;
return $array;
}
}

View File

@@ -25,25 +25,22 @@ class LicensesTransformer
'name' => e($license->name),
'company' => ($license->company) ? ['id' => (int) $license->company->id,'name'=> e($license->company->name)] : null,
'manufacturer' => ($license->manufacturer) ? ['id' => (int) $license->manufacturer->id,'name'=> e($license->manufacturer->name)] : null,
'product_key' => e($license->serial),
'product_key' => (Gate::allows('viewKeys', License::class)) ? e($license->serial) : '------------',
'order_number' => e($license->order_number),
'purchase_order' => e($license->purchase_order),
'purchase_date' => Helper::getFormattedDateObject($license->purchase_date, 'date'),
'purchase_cost' => e($license->purchase_cost),
'depreciation' => ($license->depreciation) ? ['id' => (int) $license->depreciation->id,'name'=> e($license->depreciation->name)] : null,
'notes' => e($license->notes),
'expiration_date' => Helper::getFormattedDateObject($license->expiration_date, 'date'),
'total_seats' => (int) $license->seats,
'next_seat' => ($license->freeSeat()) ? (int) $license->freeSeat()->id : null,
'remaining_qty' => (int) $license->remaincount(),
'min_qty' => $license->remaincount(),
'seats' => (int) $license->seats,
'free_seats_count' => (int) $license->free_seats_count,
'license_name' => e($license->license_name),
'license_email' => e($license->license_email),
'maintained' => ($license->maintained == 1) ? true : false,
'supplier' => ($license->supplier) ? ['id' => (int) $license->supplier->id,'name'=> e($license->supplier->name)] : null,
'created_at' => Helper::getFormattedDateObject($license->created_at, 'datetime'),
'updated_at' => Helper::getFormattedDateObject($license->updated_at, 'datetime'),
'user_can_checkout' => (bool) ($license->remaincount() > 0),
'user_can_checkout' => (bool) ($license->free_seats_count > 0),
];
$permissions_array['available_actions'] = [

View File

@@ -33,14 +33,17 @@ class LocationsTransformer
$array = [
'id' => (int) $location->id,
'name' => e($location->name),
'address' => e($location->address),
'city' => e($location->city),
'state' => e($location->state),
'country' => e($location->country),
'zip' => e($location->zip),
'assets_checkedout' => $location->assets()->count(),
'assets_default' => $location->assignedassets()->count(),
'image' => ($location->image) ? app('locations_upload_url').e($location->image) : null,
'address' => ($location->address) ? e($location->address) : null,
'address2' => ($location->address2) ? e($location->address2) : null,
'city' => ($location->city) ? e($location->city) : null,
'state' => ($location->state) ? e($location->state) : null,
'country' => ($location->country) ? e($location->country) : null,
'zip' => ($location->zip) ? e($location->zip) : null,
'assigned_assets_count' => (int) $location->assigned_assets_count,
'assets_count' => (int) $location->assets_count,
'users_count' => (int) $location->users_count,
'currency' => ($location->currency) ? e($location->currency) : null,
'created_at' => Helper::getFormattedDateObject($location->created_at, 'datetime'),
'updated_at' => Helper::getFormattedDateObject($location->updated_at, 'datetime'),
'parent' => ($location->parent) ? [
@@ -55,7 +58,7 @@ class LocationsTransformer
$permissions_array['available_actions'] = [
'update' => Gate::allows('update', Location::class) ? true : false,
'delete' => Gate::allows('delete', Location::class) ? true : false,
'delete' => (Gate::allows('delete', Location::class) && ($location->assigned_assets_count==0) && ($location->assets_count==0) && ($location->users_count==0) && ($location->deleted_at=='')) ? true : false,
];
$array += $permissions_array;

View File

@@ -26,6 +26,7 @@ class ManufacturersTransformer
'id' => (int) $manufacturer->id,
'name' => e($manufacturer->name),
'url' => e($manufacturer->url),
'image' => ($manufacturer->image) ? app('manufacturers_upload_url').e($manufacturer->image) : null,
'support_url' => e($manufacturer->support_url),
'support_phone' => e($manufacturer->support_phone),
'support_email' => e($manufacturer->support_email),
@@ -39,7 +40,7 @@ class ManufacturersTransformer
$permissions_array['available_actions'] = [
'update' => Gate::allows('update', Manufacturer::class) ? true : false,
'delete' => Gate::allows('delete', Manufacturer::class) ? true : false,
'delete' => (Gate::allows('delete', Manufacturer::class) && ($manufacturer->assets_count == 0) && ($manufacturer->licenses_count==0) && ($manufacturer->consumables_count==0) && ($manufacturer->accessories_count==0) && ($manufacturer->deleted_at=='')) ? true : false,
];
$array += $permissions_array;

View File

@@ -0,0 +1,57 @@
<?php
namespace App\Http\Transformers;
use Illuminate\Pagination\LengthAwarePaginator;
/**
* Class SelectlistTransformer
*
* This handles the standardized formatting of the API response we need to provide for
* the rich (text and images) Select2 javascript.
*
* @package App\Http\Transformers
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v4.0.16]
* @return \Illuminate\Http\Response
*/
class SelectlistTransformer
{
public function transformSelectlist (LengthAwarePaginator $select_items)
{
$items_array=[];
// Loop through the paginated collection to set the array values
foreach ($select_items as $select_item) {
$items_array[]= [
'id' => (int) $select_item->id,
'text' => ($select_item->use_text) ? e($select_item->use_text) : e($select_item->name),
'image' => ($select_item->use_image) ? e($select_item->use_image) : null,
];
}
// This is weird and awful, but the only way I can find to allow the user to
// clear the selection - @snipe
if (count($items_array) > 0) {
array_unshift($items_array, ['id' =>'', 'text'=> trans('general.clear_selection')]);
}
$results = [
'items' => $items_array,
'pagination' =>
[
'more' => ($select_items->currentPage() >= $select_items->lastPage()) ? false : true,
'per_page' => $select_items->perPage()
],
'total_count' => $select_items->total(),
'page' => $select_items->currentPage(),
'page_count' => $select_items->lastPage()
];
return $results;
}
}

View File

@@ -26,6 +26,7 @@ class StatuslabelsTransformer
'type' => $statuslabel->getStatuslabelType(),
'color' => ($statuslabel->color) ? e($statuslabel->color) : null,
'show_in_nav' => ($statuslabel->show_in_nav=='1') ? true : false,
'assets_count' => (int) $statuslabel->assets_count,
'notes' => e($statuslabel->notes),
'created_at' => Helper::getFormattedDateObject($statuslabel->created_at, 'datetime'),
'updated_at' => Helper::getFormattedDateObject($statuslabel->updated_at, 'datetime'),
@@ -33,7 +34,7 @@ class StatuslabelsTransformer
$permissions_array['available_actions'] = [
'update' => Gate::allows('update', Statuslabel::class) ? true : false,
'delete' => Gate::allows('delete', Statuslabel::class) ? true : false,
'delete' => (Gate::allows('delete', Statuslabel::class) && ($statuslabel->assets_count == 0)) ? true : false,
];
$array += $permissions_array;

View File

@@ -25,6 +25,7 @@ class SuppliersTransformer
$array = [
'id' => (int) $supplier->id,
'name' => e($supplier->name),
'image' => ($supplier->image) ? app('suppliers_upload_url').e($supplier->image) : null,
'address' => ($supplier->address) ? e($supplier->address) : null,
'address2' => ($supplier->address2) ? e($supplier->address2) : null,
'city' => ($supplier->city) ? e($supplier->city) : null,
@@ -36,8 +37,8 @@ class SuppliersTransformer
'email' => ($supplier->email) ? e($supplier->email) : null,
'contact' => ($supplier->contact) ? e($supplier->contact) : null,
'assets_count' => (int) $supplier->assets_count,
'accessories_count' => (int) $supplier->accessories_count,
'licenses_count' => (int) $supplier->licenses_count,
'image' => ($supplier->image) ? e($supplier->image) : null,
'notes' => ($supplier->notes) ? e($supplier->notes) : null,
'created_at' => Helper::getFormattedDateObject($supplier->created_at, 'datetime'),
'updated_at' => Helper::getFormattedDateObject($supplier->updated_at, 'datetime'),
@@ -46,7 +47,7 @@ class SuppliersTransformer
$permissions_array['available_actions'] = [
'update' => Gate::allows('update', Supplier::class) ? true : false,
'delete' => Gate::allows('delete', Supplier::class) ? true : false,
'delete' => (Gate::allows('delete', Supplier::class) && ($supplier->assets_count == 0) && ($supplier->licenses_count == 0) && ($supplier->accessories_count == 0)) ? true : false,
];
$array += $permissions_array;

View File

@@ -23,9 +23,10 @@ class UsersTransformer
{
$array = [
'id' => (int) $user->id,
'avatar' => e($user->present()->gravatar),
'name' => e($user->first_name).' '.($user->last_name),
'firstname' => e($user->first_name),
'lastname' => e($user->last_name),
'first_name' => e($user->first_name),
'last_name' => e($user->last_name),
'username' => e($user->username),
'employee_num' => e($user->employee_num),
'manager' => ($user->manager) ? [
@@ -33,6 +34,12 @@ class UsersTransformer
'name'=> e($user->manager->username)
] : null,
'jobtitle' => ($user->jobtitle) ? e($user->jobtitle) : null,
'phone' => ($user->phone) ? e($user->phone) : null,
'address' => ($user->address) ? e($user->address) : null,
'city' => ($user->city) ? e($user->city) : null,
'state' => ($user->state) ? e($user->state) : null,
'country' => ($user->country) ? e($user->country) : null,
'zip' => ($user->zip) ? e($user->zip) : null,
'email' => e($user->email),
'department' => ($user->department) ? [
'id' => (int) $user->department->id,
@@ -42,6 +49,7 @@ class UsersTransformer
'id' => (int) $user->userloc->id,
'name'=> e($user->userloc->name)
] : null,
'notes'=> e($user->notes),
'permissions' => $user->decodePermissions(),
'activated' => ($user->activated =='1') ? true : false,
'two_factor_activated' => ($user->two_factor_active()) ? true : false,
@@ -57,7 +65,7 @@ class UsersTransformer
$permissions_array['available_actions'] = [
'update' => (Gate::allows('update', User::class) && ($user->deleted_at=='')) ? true : false,
'delete' => (Gate::allows('delete', User::class) && ($user->deleted_at=='')) ? true : false,
'delete' => (Gate::allows('delete', User::class) && ($user->deleted_at=='') && ($user->assets_count == 0) && ($user->licenses_count == 0) && ($user->accessories_count == 0) && ($user->consumables_count == 0)) ? true : false,
'clone' => (Gate::allows('create', User::class) && ($user->deleted_at=='')) ,
'restore' => (Gate::allows('create', User::class) && ($user->deleted_at!='')) ? true : false,
];

View File

@@ -41,6 +41,9 @@ class AccessoryImporter extends ItemImporter
$this->log("No Matching Accessory, Creating a new one");
$accessory = new Accessory();
$accessory->fill($this->sanitizeItemForStoring($accessory));
//FIXME: this disables model validation. Need to find a way to avoid double-logs without breaking everything.
// $accessory->unsetEventDispatcher();
if ($accessory->save()) {
$accessory->logCreate('Imported using CSV Importer');
$this->log('Accessory ' . $this->item["name"] . ' was created');

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