Compare commits
110 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 25884a893e | |||
| d1e9fbfa24 | |||
| da015ec4a8 | |||
| 1451b4f45d | |||
| b6da68a69c | |||
| dee92cfc6c | |||
| dec77890bd | |||
| 0e1289f12f | |||
| 7b33f95e83 | |||
| ab6744dfba | |||
| 0fd940ffa4 | |||
| 5893e25b43 | |||
| 7c3bbe3097 | |||
| 858d382e26 | |||
| de16fee00a | |||
| 7deab0f53b | |||
| e59ec8b27f | |||
| 6d98bd6846 | |||
| 58768e5aee | |||
| 28a450ea25 | |||
| 1393f44070 | |||
| 8016939f31 | |||
| c1ad2f9376 | |||
| 9575cd2651 | |||
| cf086b711e | |||
| 53db96edad | |||
| 3b62c4a83a | |||
| 5f3147cf36 | |||
| 738896bdc2 | |||
| e2834fab90 | |||
| d687e1d762 | |||
| 6256abddf2 | |||
| b26fbf986f | |||
| 5c9b1ed43a | |||
| 14eb6b387b | |||
| 35ebe33e4e | |||
| 9035707bd6 | |||
| aa1e06f021 | |||
| 30b1cfabf5 | |||
| e75d22ab73 | |||
| b1e17743b8 | |||
| e2c0f01a10 | |||
| f88fee0f21 | |||
| c0669150fb | |||
| f3c12f38b6 | |||
| 5e19178a30 | |||
| 90cddb7aee | |||
| 6d828964be | |||
| 971fcf5800 | |||
| 2ad270cf33 | |||
| 8ce78c6b31 | |||
| af3c8195af | |||
| 117b4c59cc | |||
| 194d0733d4 | |||
| a371e8d53f | |||
| 8f09cca043 | |||
| 39bca49e8f | |||
| b8269020ae | |||
| 601c129bbf | |||
| b293d00699 | |||
| 75a0cf97e2 | |||
| c055e3af21 | |||
| a1f93e733c | |||
| 49073742b5 | |||
| 187206cb88 | |||
| 8420cb7ec1 | |||
| 75252bce05 | |||
| 794824713e | |||
| 8f6ea84fca | |||
| ea1b792a93 | |||
| 4ffb8f14b8 | |||
| d023f61bc4 | |||
| dd5ca73602 | |||
| 2632f730d1 | |||
| 24c158bfe6 | |||
| 3d4a5a8066 | |||
| db7e0b56f2 | |||
| f2478d813c | |||
| 192aa9eb71 | |||
| 0eef0fc1dd | |||
| 81f8fe34cd | |||
| f744696043 | |||
| 29b0780c6c | |||
| 6b3b673daa | |||
| a4876e9f3e | |||
| 925258bfb4 | |||
| 1a10aa0dda | |||
| d6f8d1b464 | |||
| 09a102fea8 | |||
| 304fce73fc | |||
| 295a68bb7a | |||
| 3aeb521782 | |||
| f587d2248b | |||
| 8579c5a68a | |||
| 835b461d7d | |||
| b8a37a0c73 | |||
| 41b5b1dfd0 | |||
| c7596e7741 | |||
| d4fa81301d | |||
| ec7245965f | |||
| de76e8db5f | |||
| a52575c7bf | |||
| bf6703c2e8 | |||
| 4db1dd8afc | |||
| c39e3acb59 | |||
| 7a44da85a0 | |||
| 890b613f71 | |||
| 1014bd74e0 | |||
| db385e024b | |||
| c8bff3ef38 |
@@ -1650,6 +1650,15 @@
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "timothyfarmer",
|
||||
"name": "Tim Farmer",
|
||||
"avatar_url": "https://avatars1.githubusercontent.com/u/7632599?v=4",
|
||||
"profile": "https://github.com/timothyfarmer",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
+8
-1
@@ -72,13 +72,20 @@ ENABLE_CSP=false
|
||||
CACHE_DRIVER=file
|
||||
SESSION_DRIVER=file
|
||||
QUEUE_DRIVER=sync
|
||||
CACHE_PREFIX=snipeit
|
||||
|
||||
# --------------------------------------------
|
||||
# OPTIONAL: REDIS SETTINGS
|
||||
# --------------------------------------------
|
||||
REDIS_HOST=null
|
||||
REDIS_PASSWORD=null
|
||||
REDIS_PORT-null
|
||||
REDIS_PORT=null
|
||||
|
||||
# --------------------------------------------
|
||||
# OPTIONAL: MEMCACHED SETTINGS
|
||||
# --------------------------------------------
|
||||
MEMCACHED_HOST=null
|
||||
MEMCACHED_PORT=null
|
||||
|
||||
# --------------------------------------------
|
||||
# OPTIONAL: AWS S3 SETTINGS
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
# You can add one username per supported platform and one custom link
|
||||
# patreon: # Replace with your Patreon username
|
||||
# open_collective: # Replace with your Open Collective username
|
||||
# ko_fi: # Replace with your Ko-fi username
|
||||
custom: https://snipeitapp.com/donate
|
||||
@@ -50,3 +50,4 @@ tests/_support/_generated/*
|
||||
/storage/oauth-public.key
|
||||
|
||||
*.cache
|
||||
/public/storage
|
||||
|
||||
+7
-2
@@ -16,8 +16,13 @@ services:
|
||||
php:
|
||||
- 5.6
|
||||
- 7.0
|
||||
- 7.2
|
||||
- 7.1.4
|
||||
- 7.1
|
||||
- 7.2
|
||||
- 7.3
|
||||
|
||||
matrix:
|
||||
allow_failures:
|
||||
- php: 7.3
|
||||
|
||||
# execute any number of scripts before the test run, custom env's are available as variables
|
||||
before_script:
|
||||
|
||||
+8
-12
@@ -18,9 +18,8 @@ patch \
|
||||
curl \
|
||||
vim \
|
||||
git \
|
||||
cron \
|
||||
mysql-client \
|
||||
cron \
|
||||
supervisor \
|
||||
&& apt-get clean \
|
||||
&& rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
|
||||
|
||||
@@ -69,7 +68,9 @@ RUN \
|
||||
&& rm -r "/var/www/html/storage/app/backups" && ln -fs "/var/lib/snipeit/dumps" "/var/www/html/storage/app/backups" \
|
||||
&& mkdir "/var/lib/snipeit/keys" && ln -fs "/var/lib/snipeit/keys/oauth-private.key" "/var/www/html/storage/oauth-private.key" \
|
||||
&& ln -fs "/var/lib/snipeit/keys/oauth-public.key" "/var/www/html/storage/oauth-public.key" \
|
||||
&& chown docker "/var/lib/snipeit/keys/"
|
||||
&& chown docker "/var/lib/snipeit/keys/" \
|
||||
&& chmod +x /var/www/html/artisan \
|
||||
&& echo "Finished setting up application in /var/www/html"
|
||||
|
||||
############## DEPENDENCIES via COMPOSER ###################
|
||||
|
||||
@@ -96,16 +97,11 @@ VOLUME ["/var/lib/snipeit"]
|
||||
|
||||
##### START SERVER
|
||||
|
||||
COPY docker/entrypoint.sh /entrypoint.sh
|
||||
RUN chmod +x /entrypoint.sh
|
||||
COPY docker/startup.sh docker/supervisord.conf /
|
||||
COPY docker/supervisor-exit-event-listener /usr/bin/supervisor-exit-event-listener
|
||||
RUN chmod +x /startup.sh /usr/bin/supervisor-exit-event-listener
|
||||
|
||||
# Add Tini
|
||||
ENV TINI_VERSION v0.14.0
|
||||
ADD https://github.com/krallin/tini/releases/download/${TINI_VERSION}/tini /tini
|
||||
RUN chmod +x /tini
|
||||
ENTRYPOINT ["/tini", "--"]
|
||||
|
||||
CMD ["/entrypoint.sh"]
|
||||
CMD ["/startup.sh"]
|
||||
|
||||
EXPOSE 80
|
||||
EXPOSE 443
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
[](https://travis-ci.org/snipe/snipe-it) [](https://crowdin.com/project/snipe-it) [](https://gitter.im/snipe/snipe-it?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) [](https://hub.docker.com/r/snipe/snipe-it/) [](https://twitter.com/snipeitapp) [](https://www.codacy.com/app/snipe/snipe-it?utm_source=github.com&utm_medium=referral&utm_content=snipe/snipe-it&utm_campaign=Badge_Grade)
|
||||
[](#contributors) [](https://www.codetriage.com/snipe/snipe-it)
|
||||
[](#contributors) [](https://www.codetriage.com/snipe/snipe-it)
|
||||
|
||||
|
||||
## Snipe-IT - Open Source Asset Management System
|
||||
@@ -10,7 +10,7 @@ It is built on [Laravel 5.4](http://laravel.com).
|
||||
|
||||
Snipe-IT is actively developed and we're [releasing quite frequently](https://github.com/snipe/snipe-it/releases). ([Check out the live demo here](https://snipeitapp.com/demo/).)
|
||||
|
||||
__This is web-based software__. This means there there is no executable file (aka no .exe files), and it must be run on a web server and accessed through a web browser. It runs on any Mac OSX, flavor of Linux, as well as Windows, and we have a [Docker image](https://snipe-it.readme.io/docs/docker) available if that's what you're into.
|
||||
__This is web-based software__. This means there is no executable file (aka no .exe files), and it must be run on a web server and accessed through a web browser. It runs on any Mac OSX, flavor of Linux, as well as Windows, and we have a [Docker image](https://snipe-it.readme.io/docs/docker) available if that's what you're into.
|
||||
|
||||
-----
|
||||
|
||||
@@ -59,6 +59,7 @@ Since the release of the JSON REST API, several third-party developers have been
|
||||
- [InQRy](https://github.com/Microsoft/InQRy) by [@Microsoft](https://github.com/Microsoft)
|
||||
- [SnipeitPS](https://github.com/snazy2000/SnipeitPS) by [@snazy2000](https://github.com/snazy2000) - Powershell API Wrapper for Snipe-it
|
||||
- [jamf2snipe](https://github.com/ParadoxGuitarist/jamf2snipe) by [@ParadoxGuitarist](https://github.com/ParadoxGuitarist) - Python script to sync assets between a JAMFPro instance and a Snipe-II instance
|
||||
- [Marksman](https://github.com/Scope-IT/marksman) - A Windows agent for Snipe-IT
|
||||
|
||||
As these were created by third-parties, Snipe-IT cannot provide support for these project, and you should contact the developers directly if you need assistance. Additionally, Snipe-IT makes no guarantees as to the reliability, accuracy or maintainability of these libraries. Use at your own risk. :)
|
||||
|
||||
@@ -95,7 +96,7 @@ Thanks goes to all of these wonderful people ([emoji key](https://github.com/ken
|
||||
| [<img src="https://avatars2.githubusercontent.com/u/982885?v=4" width="110px;"/><br /><sub>Martin Stub</sub>](http://martinstub.dk)<br />[🌍](#translation-stubben "Translation") | [<img src="https://avatars2.githubusercontent.com/u/28959963?v=4" width="110px;"/><br /><sub>Meyer Flavio</sub>](https://github.com/meyerf99)<br />[🌍](#translation-meyerf99 "Translation") | [<img src="https://avatars3.githubusercontent.com/u/796443?v=4" width="110px;"/><br /><sub>Micael Rodrigues</sub>](https://github.com/MicaelRodrigues)<br />[🌍](#translation-MicaelRodrigues "Translation") | [<img src="https://avatars0.githubusercontent.com/u/10481331?v=4" width="110px;"/><br /><sub>Mikael Rasmussen</sub>](http://rubixy.com/)<br />[🌍](#translation-mikaelssen "Translation") | [<img src="https://avatars1.githubusercontent.com/u/1544552?v=4" width="110px;"/><br /><sub>IxFail</sub>](https://github.com/IxFail)<br />[🌍](#translation-IxFail "Translation") | [<img src="https://avatars3.githubusercontent.com/u/18483118?v=4" width="110px;"/><br /><sub>Mohammed Fota</sub>](http://www.mohammedfota.com)<br />[🌍](#translation-MohammedFota "Translation") | [<img src="https://avatars0.githubusercontent.com/u/227080?v=4" width="110px;"/><br /><sub>Moayad Alserihi</sub>](https://github.com/omego)<br />[🌍](#translation-omego "Translation") |
|
||||
| [<img src="https://avatars0.githubusercontent.com/u/1680266?v=4" width="110px;"/><br /><sub>saymd</sub>](https://github.com/saymd)<br />[🌍](#translation-saymd "Translation") | [<img src="https://avatars0.githubusercontent.com/u/1826808?v=4" width="110px;"/><br /><sub>Patrik Larsson</sub>](https://nordsken.se)<br />[🌍](#translation-pooot "Translation") | [<img src="https://avatars1.githubusercontent.com/u/20584746?v=4" width="110px;"/><br /><sub>drcryo</sub>](https://github.com/drcryo)<br />[🌍](#translation-drcryo "Translation") | [<img src="https://avatars1.githubusercontent.com/u/19408004?v=4" width="110px;"/><br /><sub>pawel1615</sub>](https://github.com/pawel1615)<br />[🌍](#translation-pawel1615 "Translation") | [<img src="https://avatars2.githubusercontent.com/u/23340468?v=4" width="110px;"/><br /><sub>bodrovics</sub>](https://github.com/bodrovics)<br />[🌍](#translation-bodrovics "Translation") | [<img src="https://avatars0.githubusercontent.com/u/3257654?v=4" width="110px;"/><br /><sub>priatna</sub>](https://github.com/priatna)<br />[🌍](#translation-priatna "Translation") | [<img src="https://avatars1.githubusercontent.com/u/5358374?v=4" width="110px;"/><br /><sub>Fan Jiang</sub>](https://amayume.net)<br />[🌍](#translation-ProfFan "Translation") |
|
||||
| [<img src="https://avatars1.githubusercontent.com/u/22555451?v=4" width="110px;"/><br /><sub>ragnarcx</sub>](https://github.com/ragnarcx)<br />[🌍](#translation-ragnarcx "Translation") | [<img src="https://avatars2.githubusercontent.com/u/18654582?v=4" width="110px;"/><br /><sub>Rein van Haaren</sub>](http://www.reinvanhaaren.nl/)<br />[🌍](#translation-reinvanhaaren "Translation") | [<img src="https://avatars1.githubusercontent.com/u/386672?v=4" width="110px;"/><br /><sub>Teguh Dwicaksana</sub>](http://dheche.songolimo.net)<br />[🌍](#translation-dheche "Translation") | [<img src="https://avatars2.githubusercontent.com/u/2572552?v=4" width="110px;"/><br /><sub>fraccie</sub>](https://github.com/FRaccie)<br />[🌍](#translation-FRaccie "Translation") | [<img src="https://avatars0.githubusercontent.com/u/35182720?v=4" width="110px;"/><br /><sub>vinzruzell</sub>](https://github.com/vinzruzell)<br />[🌍](#translation-vinzruzell "Translation") | [<img src="https://avatars1.githubusercontent.com/u/7883603?v=4" width="110px;"/><br /><sub>Kevin Austin</sub>](http://kevinaustin.com)<br />[🌍](#translation-vipsystem "Translation") | [<img src="https://avatars3.githubusercontent.com/u/3861828?v=4" width="110px;"/><br /><sub>Wira Sandy</sub>](http://azuraweb.xyz)<br />[🌍](#translation-wira-sandy "Translation") |
|
||||
| [<img src="https://avatars2.githubusercontent.com/u/8663789?v=4" width="110px;"/><br /><sub>Илья</sub>](https://github.com/GrayHoax)<br />[🌍](#translation-GrayHoax "Translation") | [<img src="https://avatars3.githubusercontent.com/u/30119111?v=4" width="110px;"/><br /><sub>GodUseVPN</sub>](https://github.com/godusevpn)<br />[🌍](#translation-godusevpn "Translation") | [<img src="https://avatars1.githubusercontent.com/u/745576?v=4" width="110px;"/><br /><sub>周周</sub>](https://github.com/EngrZhou)<br />[🌍](#translation-EngrZhou "Translation") | [<img src="https://avatars3.githubusercontent.com/u/1631095?v=4" width="110px;"/><br /><sub>Sam</sub>](https://github.com/takuy)<br />[💻](https://github.com/snipe/snipe-it/commits?author=takuy "Code") | [<img src="https://avatars1.githubusercontent.com/u/264022?v=4" width="110px;"/><br /><sub>Azerothian</sub>](https://www.illisian.com.au)<br />[💻](https://github.com/snipe/snipe-it/commits?author=Azerothian "Code") |
|
||||
| [<img src="https://avatars2.githubusercontent.com/u/8663789?v=4" width="110px;"/><br /><sub>Илья</sub>](https://github.com/GrayHoax)<br />[🌍](#translation-GrayHoax "Translation") | [<img src="https://avatars3.githubusercontent.com/u/30119111?v=4" width="110px;"/><br /><sub>GodUseVPN</sub>](https://github.com/godusevpn)<br />[🌍](#translation-godusevpn "Translation") | [<img src="https://avatars1.githubusercontent.com/u/745576?v=4" width="110px;"/><br /><sub>周周</sub>](https://github.com/EngrZhou)<br />[🌍](#translation-EngrZhou "Translation") | [<img src="https://avatars3.githubusercontent.com/u/1631095?v=4" width="110px;"/><br /><sub>Sam</sub>](https://github.com/takuy)<br />[💻](https://github.com/snipe/snipe-it/commits?author=takuy "Code") | [<img src="https://avatars1.githubusercontent.com/u/264022?v=4" width="110px;"/><br /><sub>Azerothian</sub>](https://www.illisian.com.au)<br />[💻](https://github.com/snipe/snipe-it/commits?author=Azerothian "Code") | [<img src="https://avatars1.githubusercontent.com/u/7632599?v=4" width="110px;"/><br /><sub>Tim Farmer</sub>](https://github.com/timothyfarmer)<br />[💻](https://github.com/snipe/snipe-it/commits?author=timothyfarmer "Code") |
|
||||
<!-- ALL-CONTRIBUTORS-LIST:END -->
|
||||
|
||||
This project follows the [all-contributors](https://github.com/kentcdodds/all-contributors) specification. Contributions of any kind welcome!
|
||||
|
||||
@@ -61,7 +61,7 @@ class LdapSync extends Command
|
||||
$json_summary = [ "error" => true, "error_message" => $e->getMessage(), "summary" => [] ];
|
||||
$this->info(json_encode($json_summary));
|
||||
}
|
||||
LOG::error($e);
|
||||
LOG::info($e);
|
||||
return [];
|
||||
}
|
||||
|
||||
@@ -80,7 +80,7 @@ class LdapSync extends Command
|
||||
$json_summary = [ "error" => true, "error_message" => $e->getMessage(), "summary" => [] ];
|
||||
$this->info(json_encode($json_summary));
|
||||
}
|
||||
LOG::error($e);
|
||||
LOG::info($e);
|
||||
return [];
|
||||
}
|
||||
|
||||
|
||||
@@ -74,6 +74,7 @@ class ObjectImportCommand extends Command
|
||||
$importer->setCallbacks([$this, 'log'], [$this, 'progress'], [$this, 'errorCallback'])
|
||||
->setUserId($this->option('user_id'))
|
||||
->setUpdating($this->option('update'))
|
||||
->setShouldNotify($this->option('send-welcome'))
|
||||
->setUsernameFormat($this->option('username_format'));
|
||||
|
||||
$logFile = $this->option('logfile');
|
||||
@@ -172,6 +173,7 @@ class ObjectImportCommand extends Command
|
||||
array('web-importer', null, InputOption::VALUE_NONE, 'Internal: packages output for use with the web importer'),
|
||||
array('user_id', null, InputOption::VALUE_REQUIRED, 'ID of user creating items', 1),
|
||||
array('update', null, InputOption::VALUE_NONE, 'If a matching item is found, update item information'),
|
||||
array('send-welcome', null, InputOption::VALUE_NONE, 'Whether to send a welcome email to any new users that are created.'),
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
@@ -63,6 +63,8 @@ class ResetDemoSettings extends Command
|
||||
$settings->time_display_format = 'g:iA';
|
||||
$settings->thumbnail_max_h = '30';
|
||||
$settings->locale = 'en';
|
||||
$settings->version_footer = 'on';
|
||||
$settings->support_footer = 'on';
|
||||
$settings->save();
|
||||
|
||||
if ($user = User::where('username', '=', 'admin')->first()) {
|
||||
|
||||
@@ -62,6 +62,7 @@ class SendExpirationAlerts extends Command
|
||||
if ($assets->count() > 0) {
|
||||
$this->info(trans_choice('mail.assets_warrantee_alert', $assets->count(),
|
||||
['count' => $assets->count(), 'threshold' => $threshold]));
|
||||
\Notification::send($recipients, new ExpiringAssetsNotification($assets, $threshold));
|
||||
}
|
||||
|
||||
// Expiring licenses
|
||||
|
||||
@@ -46,7 +46,7 @@ class AccessoriesController extends Controller
|
||||
$accessories->where('supplier_id','=',$request->input('supplier_id'));
|
||||
}
|
||||
|
||||
$offset = $request->input('offset', 0);
|
||||
$offset = (($accessories) && (request('offset') > $accessories->count())) ? 0 : request('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';
|
||||
|
||||
@@ -44,7 +44,7 @@ class AssetMaintenancesController extends Controller
|
||||
$maintenances->where('asset_id', '=', $request->input('asset_id'));
|
||||
}
|
||||
|
||||
$offset = request('offset', 0);
|
||||
$offset = (($maintenances) && (request('offset') > $maintenances->count())) ? 0 : request('offset', 0);
|
||||
$limit = request('limit', 50);
|
||||
|
||||
$allowed_columns = [
|
||||
|
||||
@@ -60,7 +60,7 @@ class AssetModelsController extends Controller
|
||||
$assetmodels->TextSearch($request->input('search'));
|
||||
}
|
||||
|
||||
$offset = $request->input('offset', 0);
|
||||
$offset = (($assetmodels) && (request('offset') > $assetmodels->count())) ? 0 : request('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') : 'models.created_at';
|
||||
@@ -179,7 +179,7 @@ class AssetModelsController extends Controller
|
||||
try {
|
||||
unlink(public_path().'/uploads/models/'.$assetmodel->image);
|
||||
} catch (\Exception $e) {
|
||||
\Log::error($e);
|
||||
\Log::info($e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -95,7 +95,7 @@ class AssetsController extends Controller
|
||||
|
||||
$assets = Company::scopeCompanyables(Asset::select('assets.*'),"company_id","assets")
|
||||
->with('location', 'assetstatus', 'assetlog', 'company', 'defaultLoc','assignedTo',
|
||||
'model.category', 'model.manufacturer', 'model.fieldset','supplier');
|
||||
'model.category', 'model.manufacturer', 'model.fieldset','supplier');
|
||||
|
||||
|
||||
// These are used by the API to query against specific ID numbers.
|
||||
@@ -127,7 +127,7 @@ class AssetsController extends Controller
|
||||
|
||||
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'));
|
||||
->where('assets.assigned_type', '=', $request->input('assigned_type'));
|
||||
}
|
||||
|
||||
if ($request->has('company_id')) {
|
||||
@@ -144,7 +144,7 @@ class AssetsController extends Controller
|
||||
|
||||
$request->has('order_number') ? $assets = $assets->where('assets.order_number', '=', e($request->get('order_number'))) : '';
|
||||
|
||||
$offset = request('offset', 0);
|
||||
$offset = (($assets) && (request('offset') > $assets->count())) ? 0 : request('offset', 0);
|
||||
$limit = $request->input('limit', 50);
|
||||
$order = $request->input('order') === 'asc' ? 'asc' : 'desc';
|
||||
|
||||
@@ -167,12 +167,12 @@ class AssetsController extends Controller
|
||||
break;
|
||||
case '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);
|
||||
});
|
||||
->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();
|
||||
@@ -188,11 +188,11 @@ class AssetsController extends Controller
|
||||
case 'Requestable':
|
||||
$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);
|
||||
});
|
||||
$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':
|
||||
@@ -207,8 +207,8 @@ class AssetsController extends Controller
|
||||
$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
|
||||
|
||||
// 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");
|
||||
@@ -233,8 +233,8 @@ class AssetsController extends Controller
|
||||
// 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);
|
||||
@@ -291,7 +291,7 @@ class AssetsController extends Controller
|
||||
$this->authorize('view', $asset);
|
||||
return (new AssetsTransformer)->transformAsset($asset);
|
||||
}
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, 'Asset not found'), 404);
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, 'Asset not found'), 200);
|
||||
|
||||
}
|
||||
|
||||
@@ -305,17 +305,18 @@ class AssetsController extends Controller
|
||||
*/
|
||||
public function showBySerial($serial)
|
||||
{
|
||||
$this->authorize('index', Asset::class);
|
||||
if ($assets = Asset::with('assetstatus')->with('assignedTo')
|
||||
->withTrashed()->where('serial',$serial)->get()) {
|
||||
$this->authorize('view', $assets);
|
||||
return (new AssetsTransformer)->transformAssets($assets, $assets->count());
|
||||
|
||||
return (new AssetsTransformer)->transformAssets($assets, $assets->count());
|
||||
}
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, 'Asset not found'), 404);
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, 'Asset not found'), 200);
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
/**
|
||||
* Returns JSON with information about an asset for detail view.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
@@ -353,7 +354,7 @@ class AssetsController extends Controller
|
||||
'assets.assigned_to',
|
||||
'assets.assigned_type',
|
||||
'assets.status_id'
|
||||
])->with('model', 'assetstatus', 'assignedTo')->NotArchived());
|
||||
])->with('model', 'assetstatus', 'assignedTo')->NotArchived(),'company_id', 'assets');
|
||||
|
||||
if ($request->has('assetStatusType') && $request->input('assetStatusType') === 'RTD') {
|
||||
$assets = $assets->RTD();
|
||||
@@ -378,7 +379,7 @@ class AssetsController extends Controller
|
||||
$asset->use_text .= ' → '.$asset->assigned->getFullNameAttribute();
|
||||
}
|
||||
|
||||
|
||||
|
||||
if ($asset->assetstatus->getStatuslabelType()=='pending') {
|
||||
$asset->use_text .= '('.$asset->assetstatus->getStatuslabelType().')';
|
||||
}
|
||||
@@ -468,43 +469,15 @@ class AssetsController extends Controller
|
||||
$this->authorize('update', Asset::class);
|
||||
|
||||
if ($asset = Asset::find($id)) {
|
||||
($request->has('model_id')) ?
|
||||
$asset->model()->associate(AssetModel::find($request->get('model_id'))) : '';
|
||||
($request->has('name')) ?
|
||||
$asset->name = $request->get('name') : '';
|
||||
($request->has('serial')) ?
|
||||
$asset->serial = $request->get('serial') : '';
|
||||
($request->has('model_id')) ?
|
||||
$asset->model_id = $request->get('model_id') : '';
|
||||
($request->has('order_number')) ?
|
||||
$asset->order_number = $request->get('order_number') : '';
|
||||
($request->has('notes')) ?
|
||||
$asset->notes = $request->get('notes') : '';
|
||||
($request->has('asset_tag')) ?
|
||||
$asset->asset_tag = $request->get('asset_tag') : '';
|
||||
($request->has('archived')) ?
|
||||
$asset->archived = $request->get('archived') : '';
|
||||
($request->has('status_id')) ?
|
||||
$asset->status_id = $request->get('status_id') : '';
|
||||
($request->has('warranty_months')) ?
|
||||
$asset->warranty_months = $request->get('warranty_months') : '';
|
||||
($request->has('purchase_cost')) ?
|
||||
$asset->purchase_cost = Helper::ParseFloat($request->get('purchase_cost')) : '';
|
||||
($request->has('purchase_date')) ?
|
||||
$asset->purchase_date = $request->get('purchase_date') : '';
|
||||
($request->has('assigned_to')) ?
|
||||
$asset->assigned_to = $request->get('assigned_to') : '';
|
||||
($request->has('supplier_id')) ?
|
||||
$asset->supplier_id = $request->get('supplier_id') : '';
|
||||
($request->has('requestable')) ?
|
||||
$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')) : '';
|
||||
|
||||
$asset->fill($request->all());
|
||||
|
||||
($request->has('model_id')) ?
|
||||
$asset->model()->associate(AssetModel::find($request->get('model_id'))) : null;
|
||||
($request->has('company_id')) ?
|
||||
$asset->company_id = Company::getIdForCurrentUser($request->get('company_id')) : null;
|
||||
($request->has('rtd_location_id')) ?
|
||||
$asset->location_id = $request->get('rtd_location_id') : null;
|
||||
|
||||
// Update custom fields
|
||||
if (($model = AssetModel::find($asset->model_id)) && (isset($model->fieldset))) {
|
||||
@@ -519,9 +492,9 @@ class AssetsController extends Controller
|
||||
if ($asset->save()) {
|
||||
|
||||
if (($request->has('assigned_user')) && ($target = User::find($request->get('assigned_user')))) {
|
||||
$location = $target->location_id;
|
||||
$location = $target->location_id;
|
||||
} elseif (($request->has('assigned_asset')) && ($target = Asset::find($request->get('assigned_asset')))) {
|
||||
$location = $target->location_id;
|
||||
$location = $target->location_id;
|
||||
} elseif (($request->has('assigned_location')) && ($target = Location::find($request->get('assigned_location')))) {
|
||||
$location = $target->id;
|
||||
}
|
||||
@@ -631,7 +604,7 @@ class AssetsController extends Controller
|
||||
$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;
|
||||
@@ -639,7 +612,7 @@ class AssetsController extends Controller
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
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')));
|
||||
|
||||
@@ -30,7 +30,7 @@ class CategoriesController extends Controller
|
||||
$categories = $categories->TextSearch($request->input('search'));
|
||||
}
|
||||
|
||||
$offset = $request->input('offset', 0);
|
||||
$offset = (($categories) && (request('offset') > $categories->count())) ? 0 : request('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') : 'assets_count';
|
||||
|
||||
@@ -41,7 +41,7 @@ class CompaniesController extends Controller
|
||||
$companies->TextSearch($request->input('search'));
|
||||
}
|
||||
|
||||
$offset = $request->input('offset', 0);
|
||||
$offset = (($companies) && (request('offset') > $companies->count())) ? 0 : request('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';
|
||||
|
||||
@@ -43,7 +43,7 @@ class ComponentsController extends Controller
|
||||
$components->where('location_id','=',$request->input('location_id'));
|
||||
}
|
||||
|
||||
$offset = request('offset', 0);
|
||||
$offset = (($components) && (request('offset') > $components->count())) ? 0 : request('offset', 0);
|
||||
$limit = request('limit', 50);
|
||||
|
||||
$allowed_columns = ['id','name','min_amt','order_number','serial','purchase_date','purchase_cost','company','category','qty','location','image'];
|
||||
|
||||
@@ -35,12 +35,16 @@ class ConsumablesController extends Controller
|
||||
$consumables->where('company_id','=',$request->input('company_id'));
|
||||
}
|
||||
|
||||
if ($request->has('category_id')) {
|
||||
$consumables->where('category_id','=',$request->input('category_id'));
|
||||
}
|
||||
|
||||
if ($request->has('manufacturer_id')) {
|
||||
$consumables->where('manufacturer_id','=',$request->input('manufacturer_id'));
|
||||
}
|
||||
|
||||
|
||||
$offset = request('offset', 0);
|
||||
$offset = (($consumables) && (request('offset') > $consumables->count())) ? 0 : 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','image'];
|
||||
$order = $request->input('order') === 'asc' ? 'asc' : 'desc';
|
||||
|
||||
@@ -39,7 +39,7 @@ class DepartmentsController extends Controller
|
||||
$departments = $departments->TextSearch($request->input('search'));
|
||||
}
|
||||
|
||||
$offset = $request->input('offset', 0);
|
||||
$offset = (($departments) && (request('offset') > $departments->count())) ? 0 : request('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';
|
||||
|
||||
@@ -28,7 +28,7 @@ class DepreciationsController extends Controller
|
||||
$depreciations = $depreciations->TextSearch($request->input('search'));
|
||||
}
|
||||
|
||||
$offset = $request->input('offset', 0);
|
||||
$offset = (($depreciations) && (request('offset') > $depreciations->count())) ? 0 : request('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';
|
||||
|
||||
@@ -28,7 +28,7 @@ class GroupsController extends Controller
|
||||
$groups = $groups->TextSearch($request->input('search'));
|
||||
}
|
||||
|
||||
$offset = $request->input('offset', 0);
|
||||
$offset = (($groups) && (request('offset') > $groups->count())) ? 0 : request('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';
|
||||
|
||||
@@ -25,7 +25,7 @@ class ImportController extends Controller
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
//
|
||||
$this->authorize('import');
|
||||
$imports = Import::latest()->get();
|
||||
return (new ImportsTransformer)->transformImports($imports);
|
||||
|
||||
@@ -39,10 +39,8 @@ class ImportController extends Controller
|
||||
*/
|
||||
public function store()
|
||||
{
|
||||
//
|
||||
if (!Company::isCurrentUserAuthorized()) {
|
||||
return redirect()->route('hardware.index')->with('error', trans('general.insufficient_permissions'));
|
||||
} elseif (!config('app.lock_passwords')) {
|
||||
$this->authorize('import');
|
||||
if (!config('app.lock_passwords')) {
|
||||
$files = Input::file('files');
|
||||
$path = config('app.private_uploads').'/imports';
|
||||
$results = [];
|
||||
@@ -119,7 +117,7 @@ class ImportController extends Controller
|
||||
*/
|
||||
public function process(ItemImportRequest $request, $import_id)
|
||||
{
|
||||
$this->authorize('create', Asset::class);
|
||||
$this->authorize('import');
|
||||
// Run a backup immediately before processing
|
||||
Artisan::call('backup:run');
|
||||
$errors = $request->import(Import::find($import_id));
|
||||
@@ -162,7 +160,7 @@ class ImportController extends Controller
|
||||
*/
|
||||
public function destroy($import_id)
|
||||
{
|
||||
$this->authorize('create', Asset::class);
|
||||
$this->authorize('import');
|
||||
$import = Import::find($import_id);
|
||||
try {
|
||||
unlink(config('app.private_uploads').'/imports/'.$import->file_path);
|
||||
|
||||
@@ -82,7 +82,7 @@ class LicensesController extends Controller
|
||||
}
|
||||
|
||||
|
||||
$offset = request('offset', 0);
|
||||
$offset = (($licenses) && (request('offset') > $licenses->count())) ? 0 : request('offset', 0);
|
||||
$limit = request('limit', 50);
|
||||
$order = $request->input('order') === 'asc' ? 'asc' : 'desc';
|
||||
|
||||
|
||||
@@ -51,7 +51,7 @@ class LocationsController extends Controller
|
||||
|
||||
|
||||
|
||||
$offset = $request->input('offset', 0);
|
||||
$offset = (($locations) && (request('offset') > $locations->count())) ? 0 : request('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';
|
||||
|
||||
@@ -39,7 +39,7 @@ class ManufacturersController extends Controller
|
||||
|
||||
|
||||
|
||||
$offset = request('offset', 0);
|
||||
$offset = (($manufacturers) && (request('offset') > $manufacturers->count())) ? 0 : request('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';
|
||||
|
||||
@@ -27,15 +27,20 @@ class ProfileController extends Controller
|
||||
|
||||
|
||||
foreach ($checkoutRequests as $checkoutRequest) {
|
||||
$results['rows'][] = [
|
||||
'image' => $checkoutRequest->itemRequested()->present()->getImageUrl(),
|
||||
'name' => $checkoutRequest->itemRequested()->present()->name(),
|
||||
'type' => $checkoutRequest->itemType(),
|
||||
'qty' => $checkoutRequest->quantity,
|
||||
'location' => ($checkoutRequest->location()) ? $checkoutRequest->location()->name : null,
|
||||
'expected_checkin' => Helper::getFormattedDateObject($checkoutRequest->itemRequested()->expected_checkin, 'datetime'),
|
||||
'request_date' => Helper::getFormattedDateObject($checkoutRequest->created_at, 'datetime'),
|
||||
];
|
||||
|
||||
// Make sure the asset and request still exist
|
||||
if ($checkoutRequest && $checkoutRequest->itemRequested()) {
|
||||
$results['rows'][] = [
|
||||
'image' => $checkoutRequest->itemRequested()->present()->getImageUrl(),
|
||||
'name' => $checkoutRequest->itemRequested()->present()->name(),
|
||||
'type' => $checkoutRequest->itemType(),
|
||||
'qty' => $checkoutRequest->quantity,
|
||||
'location' => ($checkoutRequest->location()) ? $checkoutRequest->location()->name : null,
|
||||
'expected_checkin' => Helper::getFormattedDateObject($checkoutRequest->itemRequested()->expected_checkin, 'datetime'),
|
||||
'request_date' => Helper::getFormattedDateObject($checkoutRequest->created_at, 'datetime'),
|
||||
];
|
||||
}
|
||||
|
||||
}
|
||||
return $results;
|
||||
}
|
||||
|
||||
@@ -30,7 +30,7 @@ class StatuslabelsController extends Controller
|
||||
$statuslabels = $statuslabels->TextSearch($request->input('search'));
|
||||
}
|
||||
|
||||
$offset = $request->input('offset', 0);
|
||||
$offset = (($statuslabels) && (request('offset') > $statuslabels->count())) ? 0 : request('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';
|
||||
@@ -238,8 +238,7 @@ class StatuslabelsController extends Controller
|
||||
*/
|
||||
public function checkIfDeployable($id) {
|
||||
$statuslabel = Statuslabel::findOrFail($id);
|
||||
|
||||
$this->authorize('view', $statuslabel);
|
||||
$this->authorize('view', Asset::class);
|
||||
|
||||
if ($statuslabel->getStatuslabelType()=='deployable') {
|
||||
return '1';
|
||||
|
||||
@@ -33,7 +33,7 @@ class SuppliersController extends Controller
|
||||
$suppliers = $suppliers->TextSearch($request->input('search'));
|
||||
}
|
||||
|
||||
$offset = request('offset', 0);
|
||||
$offset = (($suppliers) && (request('offset') > $suppliers->count())) ? 0 : request('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';
|
||||
|
||||
@@ -12,6 +12,7 @@ use App\Http\Requests\SaveUserRequest;
|
||||
use App\Models\Asset;
|
||||
use App\Http\Transformers\AssetsTransformer;
|
||||
use App\Http\Transformers\SelectlistTransformer;
|
||||
use App\Http\Transformers\AccessoriesTransformer;
|
||||
|
||||
class UsersController extends Controller
|
||||
{
|
||||
@@ -51,6 +52,7 @@ class UsersController extends Controller
|
||||
'users.phone',
|
||||
'users.state',
|
||||
'users.two_factor_enrolled',
|
||||
'users.two_factor_optin',
|
||||
'users.updated_at',
|
||||
'users.username',
|
||||
'users.zip',
|
||||
@@ -85,7 +87,7 @@ class UsersController extends Controller
|
||||
}
|
||||
|
||||
$order = $request->input('order') === 'asc' ? 'asc' : 'desc';
|
||||
$offset = request('offset', 0);
|
||||
$offset = (($users) && (request('offset') > $users->count())) ? 0 : request('offset', 0);
|
||||
$limit = request('limit', 20);
|
||||
|
||||
switch ($request->input('sort')) {
|
||||
@@ -147,8 +149,7 @@ class UsersController extends Controller
|
||||
$users = Company::scopeCompanyables($users);
|
||||
|
||||
if ($request->has('search')) {
|
||||
$users = $users->where('first_name', 'LIKE', '%'.$request->get('search').'%')
|
||||
->orWhere('last_name', 'LIKE', '%'.$request->get('search').'%')
|
||||
$users = $users->SimpleNameSearch($request->get('search'))
|
||||
->orWhere('username', 'LIKE', '%'.$request->get('search').'%')
|
||||
->orWhere('employee_num', 'LIKE', '%'.$request->get('search').'%');
|
||||
}
|
||||
@@ -302,6 +303,23 @@ class UsersController extends Controller
|
||||
return (new AssetsTransformer)->transformAssets($assets, $assets->count());
|
||||
}
|
||||
|
||||
/**
|
||||
* Return JSON containing a list of accessories assigned to a user.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @since [v4.6.14]
|
||||
* @param $userId
|
||||
* @return string JSON
|
||||
*/
|
||||
public function accessories($id)
|
||||
{
|
||||
$this->authorize('view', User::class);
|
||||
$user = User::findOrFail($id);
|
||||
$this->authorize('view', Accessory::class);
|
||||
$accessories = $user->accessories;
|
||||
return (new AccessoriesTransformer)->transformAccessories($accessories, $accessories->count());
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset the user's two-factor status
|
||||
*
|
||||
|
||||
@@ -162,6 +162,9 @@ class AssetMaintenancesController extends Controller
|
||||
// Redirect to the improvement management page
|
||||
return redirect()->route('maintenances.index')
|
||||
->with('error', trans('admin/asset_maintenances/message.not_found'));
|
||||
} elseif (!$assetMaintenance->asset) {
|
||||
return redirect()->route('maintenances.index')
|
||||
->with('error', 'The asset associated with this maintenance does not exist.');
|
||||
} elseif (!Company::isCurrentUserHasAccess($assetMaintenance->asset)) {
|
||||
return static::getInsufficientPermissionsRedirect();
|
||||
}
|
||||
|
||||
@@ -209,7 +209,7 @@ class AssetModelsController extends Controller
|
||||
try {
|
||||
unlink(app('models_upload_path').$old_image);
|
||||
} catch (\Exception $e) {
|
||||
\Log::error($e);
|
||||
\Log::info($e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -246,7 +246,7 @@ class AssetModelsController extends Controller
|
||||
try {
|
||||
unlink(public_path().'/uploads/models/'.$model->image);
|
||||
} catch (\Exception $e) {
|
||||
\Log::error($e);
|
||||
\Log::info($e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -143,7 +143,7 @@ class AssetsController extends Controller
|
||||
}
|
||||
|
||||
// Create the image (if one was chosen.)
|
||||
if ($request->hasFile('image')) {
|
||||
if ($request->has('image')) {
|
||||
$image = $request->input('image');
|
||||
|
||||
// After modification, the image is prefixed by mime info like the following:
|
||||
@@ -326,7 +326,7 @@ class AssetsController extends Controller
|
||||
unlink(public_path().'/uploads/assets/'.$asset->image);
|
||||
$asset->image = '';
|
||||
} catch (\Exception $e) {
|
||||
\Log::error($e);
|
||||
\Log::info($e);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -781,7 +781,7 @@ class AssetsController extends Controller
|
||||
$filename = 'audit-'.$asset->id.'-'.str_slug(basename($file->getClientOriginalName(), '.'.$extension)).'.'.$extension;
|
||||
$file->move($destinationPath, $filename);
|
||||
} catch (\Exception $e) {
|
||||
\Log::error($e);
|
||||
\Log::info($e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -80,7 +80,7 @@ class LoginController extends Controller
|
||||
Log::debug("Remote user auth lookup complete");
|
||||
if(!is_null($user)) Auth::login($user, true);
|
||||
} catch(Exception $e) {
|
||||
Log::error("There was an error authenticating the Remote user: " . $e->getMessage());
|
||||
Log::debug("There was an error authenticating the Remote user: " . $e->getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -169,7 +169,7 @@ class LoginController extends Controller
|
||||
// If the user was unable to login via LDAP, log the error and let them fall through to
|
||||
// local authentication.
|
||||
} catch (\Exception $e) {
|
||||
Log::error("There was an error authenticating the LDAP user: ".$e->getMessage());
|
||||
Log::debug("There was an error authenticating the LDAP user: ".$e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -209,26 +209,33 @@ class LoginController extends Controller
|
||||
public function getTwoFactorEnroll()
|
||||
{
|
||||
|
||||
// Make sure the user is logged in
|
||||
if (!Auth::check()) {
|
||||
return redirect()->route('login')->with('error', 'You must be logged in.');
|
||||
return redirect()->route('login')->with('error', trans('auth/general.login_prompt'));
|
||||
}
|
||||
|
||||
|
||||
$settings = Setting::getSettings();
|
||||
$user = Auth::user();
|
||||
$google2fa = app()->make('PragmaRX\Google2FA\Contracts\Google2FA');
|
||||
|
||||
if ($user->two_factor_secret=='') {
|
||||
$user->two_factor_secret = $google2fa->generateSecretKey(32);
|
||||
$user->save();
|
||||
// We wouldn't normally see this page if 2FA isn't enforced via the
|
||||
// \App\Http\Middleware\CheckForTwoFactor middleware AND if a device isn't enrolled,
|
||||
// but let's check check anyway in case there's a browser history or back button thing.
|
||||
// While you can access this page directly, enrolling a device when 2FA isn't enforced
|
||||
// won't cause any harm.
|
||||
|
||||
if (($user->two_factor_secret!='') && ($user->two_factor_enrolled==1)) {
|
||||
return redirect()->route('two-factor')->with('error', trans('auth/message.two_factor.already_enrolled'));
|
||||
}
|
||||
|
||||
$google2fa = new Google2FA();
|
||||
$secret = $google2fa->generateSecretKey();
|
||||
$user->two_factor_secret = $secret;
|
||||
$user->save();
|
||||
|
||||
$google2fa_url = $google2fa->getQRCodeGoogleUrl(
|
||||
urlencode(Setting::getSettings()->site_name),
|
||||
urlencode($user->username),
|
||||
$user->two_factor_secret
|
||||
);
|
||||
|
||||
return view('auth.two_factor_enroll')->with('google2fa_url', $google2fa_url);
|
||||
$barcode = new \Com\Tecnick\Barcode\Barcode();
|
||||
$barcode_obj = $barcode->getBarcodeObj('QRCODE', 'otpauth://totp/'.urlencode($settings->site_name).':'.urlencode($user->username).'?secret='.urlencode($secret).'&issuer=Snipe-IT&period=30', 300, 300, 'black', array(-2, -2, -2, -2));
|
||||
return view('auth.two_factor_enroll')->with('barcode_obj', $barcode_obj);
|
||||
|
||||
}
|
||||
|
||||
@@ -240,6 +247,20 @@ class LoginController extends Controller
|
||||
*/
|
||||
public function getTwoFactorAuth()
|
||||
{
|
||||
// Check that the user is logged in
|
||||
if (!Auth::check()) {
|
||||
return redirect()->route('login')->with('error', trans('auth/general.login_prompt'));
|
||||
}
|
||||
|
||||
$user = Auth::user();
|
||||
|
||||
// Check whether there is a device enrolled.
|
||||
// This *should* be handled via the \App\Http\Middleware\CheckForTwoFactor middleware
|
||||
// but we're just making sure (in case someone edited the database directly, etc)
|
||||
if (($user->two_factor_secret=='') || ($user->two_factor_enrolled!=1)) {
|
||||
return redirect()->route('two-factor-enroll');
|
||||
}
|
||||
|
||||
return view('auth.two_factor');
|
||||
}
|
||||
|
||||
@@ -252,22 +273,25 @@ class LoginController extends Controller
|
||||
{
|
||||
|
||||
if (!Auth::check()) {
|
||||
return redirect()->route('login')->with('error', 'You must be logged in.');
|
||||
return redirect()->route('login')->with('error', trans('auth/general.login_prompt'));
|
||||
}
|
||||
|
||||
if (!$request->has('two_factor_secret')) {
|
||||
return redirect()->route('two-factor')->with('error', trans('auth/message.two_factor.code_required'));
|
||||
}
|
||||
|
||||
$user = Auth::user();
|
||||
$secret = $request->get('two_factor_secret');
|
||||
$google2fa = app()->make('PragmaRX\Google2FA\Contracts\Google2FA');
|
||||
$valid = $google2fa->verifyKey($user->two_factor_secret, $secret);
|
||||
$google2fa = new Google2FA();
|
||||
$secret = $request->input('two_factor_secret');
|
||||
|
||||
if ($valid) {
|
||||
if ($google2fa->verifyKey($user->two_factor_secret, $secret)) {
|
||||
$user->two_factor_enrolled = 1;
|
||||
$user->save();
|
||||
$request->session()->put('2fa_authed', 'true');
|
||||
return redirect()->route('home')->with('success', 'You are logged in!');
|
||||
}
|
||||
|
||||
return redirect()->route('two-factor')->with('error', 'Invalid two-factor code');
|
||||
return redirect()->route('two-factor')->with('error', trans('auth/message.two_factor.invalid_code'));
|
||||
|
||||
|
||||
}
|
||||
@@ -290,7 +314,7 @@ class LoginController extends Controller
|
||||
return redirect()->away($customLogoutUrl);
|
||||
}
|
||||
|
||||
return redirect()->route('login')->with('success', 'You have successfully logged out!');
|
||||
return redirect()->route('login')->with('success', trans('auth/general.logout.success'));
|
||||
}
|
||||
|
||||
|
||||
@@ -315,11 +339,11 @@ class LoginController extends Controller
|
||||
}
|
||||
|
||||
/**
|
||||
* Redirect the user after determining they are locked out.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
* Redirect the user after determining they are locked out.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
protected function sendLockoutResponse(Request $request)
|
||||
{
|
||||
$seconds = $this->limiter()->availableIn(
|
||||
@@ -330,18 +354,18 @@ class LoginController extends Controller
|
||||
|
||||
$message = \Lang::get('auth/message.throttle', ['minutes' => $minutes]);
|
||||
|
||||
return redirect()->back()
|
||||
return redirect()->back()
|
||||
->withInput($request->only($this->username(), 'remember'))
|
||||
->withErrors([$this->username() => $message]);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Override the lockout time and duration
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
* Override the lockout time and duration
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return bool
|
||||
*/
|
||||
protected function hasTooManyLoginAttempts(Request $request)
|
||||
{
|
||||
$lockoutTime = config('auth.throttle.lockout_duration');
|
||||
|
||||
@@ -179,7 +179,7 @@ class CategoriesController extends Controller
|
||||
try {
|
||||
unlink(app('categories_upload_path').$old_image);
|
||||
} catch (\Exception $e) {
|
||||
\Log::error($e);
|
||||
\Log::info($e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@ final class CompaniesController extends Controller
|
||||
{
|
||||
$this->authorize('view', Company::class);
|
||||
|
||||
return view('companies/index')->with('companies', Company::all());
|
||||
return view('companies/index');
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -148,7 +148,7 @@ final class CompaniesController extends Controller
|
||||
try {
|
||||
unlink(app('companies_upload_path').$old_image);
|
||||
} catch (\Exception $e) {
|
||||
\Log::error($e);
|
||||
\Log::info($e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -191,7 +191,7 @@ class DepartmentsController extends Controller
|
||||
try {
|
||||
unlink(app('departments_upload_path').$old_image);
|
||||
} catch (\Exception $e) {
|
||||
\Log::error($e);
|
||||
\Log::info($e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@ class DepreciationsController extends Controller
|
||||
$this->authorize('view', Depreciation::class);
|
||||
|
||||
// Show the page
|
||||
return view('depreciations/index', compact('depreciations'));
|
||||
return view('depreciations/index');
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@ class GroupsController extends Controller
|
||||
public function index()
|
||||
{
|
||||
// Show the page
|
||||
return view('groups/index', compact('groups'));
|
||||
return view('groups/index');
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -72,7 +72,7 @@ class GroupsController extends Controller
|
||||
if ($group->save()) {
|
||||
return redirect()->route("groups.index")->with('success', trans('admin/groups/message.success.create'));
|
||||
}
|
||||
return redirect(route('groups.create'))->withInput()->withErrors($group->getErrors());
|
||||
return redirect()->back()->withInput()->withErrors($group->getErrors());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -111,7 +111,7 @@ class GroupsController extends Controller
|
||||
{
|
||||
$permissions = config('permissions');
|
||||
if (!$group = Group::find($id)) {
|
||||
return redirect()->route('groups')->with('error', trans('admin/groups/message.group_not_found', compact('id')));
|
||||
return redirect()->route('groups.index')->with('error', trans('admin/groups/message.group_not_found', compact('id')));
|
||||
}
|
||||
$group->name = e(Input::get('name'));
|
||||
$group->permissions = json_encode(Input::get('permission'));
|
||||
@@ -138,7 +138,7 @@ class GroupsController extends Controller
|
||||
{
|
||||
if (!config('app.lock_passwords')) {
|
||||
if (!$group = Group::find($id)) {
|
||||
return redirect()->route('groups')->with('error', trans('admin/groups/message.group_not_found', compact('id')));
|
||||
return redirect()->route('groups.index')->with('error', trans('admin/groups/message.group_not_found', compact('id')));
|
||||
}
|
||||
$group->delete();
|
||||
// Redirect to the group management page
|
||||
|
||||
@@ -12,7 +12,7 @@ class ImportsController extends Controller
|
||||
{
|
||||
public function index()
|
||||
{
|
||||
$this->authorize('create', Asset::class);
|
||||
$this->authorize('import');
|
||||
$imports = Import::latest()->get();
|
||||
$imports = (new ImportsTransformer)->transformImports($imports);
|
||||
return view('importer/import')->with('imports', $imports);
|
||||
|
||||
@@ -44,7 +44,7 @@ class LocationsController extends Controller
|
||||
$locations = Location::orderBy('created_at', 'DESC')->with('parent', 'assets', 'assignedassets')->get();
|
||||
|
||||
// Show the page
|
||||
return view('locations/index', compact('locations'));
|
||||
return view('locations/index');
|
||||
}
|
||||
|
||||
|
||||
@@ -200,7 +200,7 @@ class LocationsController extends Controller
|
||||
try {
|
||||
unlink(app('locations_upload_path').$old_image);
|
||||
} catch (\Exception $e) {
|
||||
\Log::error($e);
|
||||
\Log::info($e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -36,7 +36,7 @@ class ManufacturersController extends Controller
|
||||
public function index()
|
||||
{
|
||||
$this->authorize('index', Manufacturer::class);
|
||||
return view('manufacturers/index', compact('manufacturers'));
|
||||
return view('manufacturers/index');
|
||||
}
|
||||
|
||||
|
||||
@@ -170,7 +170,7 @@ class ManufacturersController extends Controller
|
||||
try {
|
||||
unlink(app('manufacturers_upload_path').$old_image);
|
||||
} catch (\Exception $e) {
|
||||
\Log::error($e);
|
||||
\Log::info($e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -207,7 +207,7 @@ class ManufacturersController extends Controller
|
||||
try {
|
||||
unlink(public_path().'/uploads/manufacturers/'.$manufacturer->image);
|
||||
} catch (\Exception $e) {
|
||||
\Log::error($e);
|
||||
\Log::info($e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -125,8 +125,7 @@ class ProfileController extends Controller
|
||||
|
||||
$rules = array(
|
||||
'current_password' => 'required',
|
||||
'password' => Setting::passwordComplexityRulesSaving('store'),
|
||||
'password_confirm' => 'required|same:password',
|
||||
'password' => Setting::passwordComplexityRulesSaving('store').'|confirmed',
|
||||
);
|
||||
|
||||
$validator = \Validator::make($request->all(), $rules);
|
||||
|
||||
@@ -603,8 +603,8 @@ class ReportsController extends Controller
|
||||
|
||||
|
||||
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());
|
||||
$row[] = ($asset->checkedOutToUser() && $asset->assigned) ? $asset->assigned->getFullNameAttribute() : ($asset->assigned ? $asset->assigned->display_name : '');
|
||||
$row[] = ($asset->checkedOutToUser() && $asset->assigned) ? 'user' : $asset->assignedType();
|
||||
}
|
||||
|
||||
if ($request->has('username')) {
|
||||
|
||||
@@ -482,13 +482,12 @@ class SettingsController extends Controller
|
||||
$setting->two_factor_enabled = null;
|
||||
} else {
|
||||
$setting->two_factor_enabled = $request->input('two_factor_enabled');
|
||||
|
||||
# remote user login
|
||||
$setting->login_remote_user_enabled = (int)$request->input('login_remote_user_enabled');
|
||||
$setting->login_common_disabled= (int)$request->input('login_common_disabled');
|
||||
$setting->login_remote_user_custom_logout_url = $request->input('login_remote_user_custom_logout_url');
|
||||
}
|
||||
|
||||
# remote user login
|
||||
$setting->login_remote_user_enabled = (int)$request->input('login_remote_user_enabled');
|
||||
$setting->login_common_disabled = (int)$request->input('login_common_disabled');
|
||||
$setting->login_remote_user_custom_logout_url = $request->input('login_remote_user_custom_logout_url');
|
||||
}
|
||||
|
||||
$setting->pwd_secure_uncommon = (int) $request->input('pwd_secure_uncommon');
|
||||
|
||||
@@ -33,7 +33,7 @@ class StatuslabelsController extends Controller
|
||||
public function index()
|
||||
{
|
||||
$this->authorize('view', Statuslabel::class);
|
||||
return view('statuslabels.index', compact('statuslabels'));
|
||||
return view('statuslabels.index');
|
||||
}
|
||||
|
||||
public function show($id)
|
||||
|
||||
@@ -34,10 +34,9 @@ class SuppliersController extends Controller
|
||||
{
|
||||
// Grab all the suppliers
|
||||
$this->authorize('view', Supplier::class);
|
||||
$suppliers = Supplier::orderBy('created_at', 'DESC')->get();
|
||||
|
||||
// Show the page
|
||||
return view('suppliers/index', compact('suppliers'));
|
||||
return view('suppliers/index');
|
||||
}
|
||||
|
||||
|
||||
@@ -175,7 +174,7 @@ class SuppliersController extends Controller
|
||||
try {
|
||||
unlink(app('suppliers_upload_path').$old_image);
|
||||
} catch (\Exception $e) {
|
||||
\Log::error($e);
|
||||
\Log::info($e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -259,9 +259,7 @@ class UsersController extends Controller
|
||||
|
||||
// Only save groups if the user is a super user
|
||||
if (Auth::user()->isSuperUser()) {
|
||||
if ($request->has('groups')) {
|
||||
$user->groups()->sync($request->input('groups'));
|
||||
}
|
||||
$user->groups()->sync($request->input('groups'));
|
||||
}
|
||||
|
||||
|
||||
@@ -984,7 +982,7 @@ class UsersController extends Controller
|
||||
*/
|
||||
public function printInventory($id)
|
||||
{
|
||||
|
||||
$this->authorize('view', User::class);
|
||||
$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();
|
||||
|
||||
@@ -73,7 +73,7 @@ class ViewAssetsController extends Controller
|
||||
$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'));
|
||||
return view('account/requestable-assets', compact('assets', 'models'));
|
||||
}
|
||||
|
||||
|
||||
|
||||
+1
-1
@@ -25,7 +25,7 @@ class Kernel extends HttpKernel
|
||||
\Fideloper\Proxy\TrustProxies::class,
|
||||
\App\Http\Middleware\CheckForSetup::class,
|
||||
\App\Http\Middleware\CheckForDebug::class,
|
||||
// \Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class,
|
||||
\Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class,
|
||||
];
|
||||
|
||||
/**
|
||||
|
||||
@@ -43,6 +43,20 @@ class ItemImportRequest extends FormRequest
|
||||
$import->save();
|
||||
$fieldMappings=[];
|
||||
if ($import->field_map) {
|
||||
|
||||
// This checks to make sure the field header has been mapped.
|
||||
// If it hasn't been, it will throw an array_flip error
|
||||
foreach ($import->field_map as $field => $fieldValue) {
|
||||
$errorMessage = null;
|
||||
|
||||
if(is_null($fieldValue)){
|
||||
$errorMessage = 'All import fields must be mapped.';
|
||||
$this->errorCallback($import, $field, $errorMessage);
|
||||
|
||||
return $this->errors;
|
||||
}
|
||||
}
|
||||
|
||||
// We submit as csv field: column, but the importer is happier if we flip it here.
|
||||
$fieldMappings = array_change_key_case(array_flip($import->field_map), CASE_LOWER);
|
||||
// dd($fieldMappings);
|
||||
@@ -50,6 +64,7 @@ class ItemImportRequest extends FormRequest
|
||||
$importer->setCallbacks([$this, 'log'], [$this, 'progress'], [$this, 'errorCallback'])
|
||||
->setUserId(Auth::id())
|
||||
->setUpdating($this->has('import-update'))
|
||||
->setShouldNotify($this->has('send-welcome'))
|
||||
->setUsernameFormat('firstname.lastname')
|
||||
->setFieldMappings($fieldMappings);
|
||||
// $logFile = storage_path('logs/importer.log');
|
||||
@@ -60,7 +75,7 @@ class ItemImportRequest extends FormRequest
|
||||
|
||||
public function log($string)
|
||||
{
|
||||
// \Log::Info($string);
|
||||
\Log::Info($string);
|
||||
}
|
||||
|
||||
public function progress($count)
|
||||
|
||||
@@ -37,7 +37,7 @@ class SaveUserRequest extends Request
|
||||
$rules['username'] = 'required_unless:ldap_import,1|string|min:1';
|
||||
if ($this->request->get('ldap_import') == false)
|
||||
{
|
||||
$rules['password'] = Setting::passwordComplexityRulesSaving('store');
|
||||
$rules['password'] = Setting::passwordComplexityRulesSaving('store').'|confirmed';
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -46,7 +46,7 @@ class SaveUserRequest extends Request
|
||||
case 'PUT':
|
||||
$rules['first_name'] = 'required|string|min:1';
|
||||
$rules['username'] = 'required_unless:ldap_import,1|string|min:1';
|
||||
$rules['password'] = Setting::passwordComplexityRulesSaving('update');
|
||||
$rules['password'] = Setting::passwordComplexityRulesSaving('update').'|confirmed';
|
||||
break;
|
||||
|
||||
// Save only what's passed
|
||||
@@ -58,9 +58,7 @@ class SaveUserRequest extends Request
|
||||
|
||||
default:break;
|
||||
}
|
||||
|
||||
$rules['password_confirm'] = 'sometimes|required_with:password';
|
||||
|
||||
|
||||
return $rules;
|
||||
|
||||
}
|
||||
|
||||
@@ -29,8 +29,7 @@ class SetupUserRequest extends Request
|
||||
'last_name' => 'required|string|min:1',
|
||||
'username' => 'required|string|min:2|unique:users,username,NULL,deleted_at',
|
||||
'email' => 'email|unique:users,email',
|
||||
'password' => 'required|min:6',
|
||||
'password_confirm' => 'required|min:6|same:password',
|
||||
'password' => 'required|min:6|confirmed',
|
||||
'email_domain' => 'required|min:4',
|
||||
];
|
||||
}
|
||||
|
||||
@@ -26,6 +26,18 @@ class ActionlogsTransformer
|
||||
if ($actionlog->filename!='') {
|
||||
$icon = e(\App\Helpers\Helper::filetype_icon($actionlog->filename));
|
||||
}
|
||||
|
||||
// This is necessary since we can't escape special characters within a JSON object
|
||||
if (($actionlog->log_meta) && ($actionlog->log_meta!='')) {
|
||||
$meta_array = json_decode($actionlog->log_meta);
|
||||
foreach ($meta_array as $key => $value) {
|
||||
foreach ($value as $meta_key => $meta_value) {
|
||||
$clean_meta[$key][$meta_key] = e($meta_value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
$array = [
|
||||
'id' => (int) $actionlog->id,
|
||||
'icon' => $icon,
|
||||
@@ -64,7 +76,7 @@ class ActionlogsTransformer
|
||||
|
||||
'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,
|
||||
'log_meta' => ((isset($clean_meta)) && (is_array($clean_meta))) ? $clean_meta: null,
|
||||
|
||||
|
||||
];
|
||||
|
||||
@@ -27,6 +27,11 @@ class AssetMaintenancesTransformer
|
||||
'name'=> ($assetmaintenance->asset->name) ? e($assetmaintenance->asset->name) : null,
|
||||
'asset_tag'=> e($assetmaintenance->asset->asset_tag)
|
||||
|
||||
] : null,
|
||||
'company' => (($assetmaintenance->asset) && ($assetmaintenance->asset->company)) ? [
|
||||
'id' => (int) $assetmaintenance->asset->company->id,
|
||||
'name'=> ($assetmaintenance->asset->company->name) ? e($assetmaintenance->asset->company->name) : null,
|
||||
|
||||
] : null,
|
||||
'title' => ($assetmaintenance->title) ? e($assetmaintenance->title) : null,
|
||||
'location' => (($assetmaintenance->asset) && ($assetmaintenance->asset->location)) ? [
|
||||
|
||||
@@ -24,7 +24,7 @@ class UsersTransformer
|
||||
$array = [
|
||||
'id' => (int) $user->id,
|
||||
'avatar' => e($user->present()->gravatar),
|
||||
'name' => e($user->first_name).' '.($user->last_name),
|
||||
'name' => e($user->first_name).' '.e($user->last_name),
|
||||
'first_name' => e($user->first_name),
|
||||
'last_name' => e($user->last_name),
|
||||
'username' => e($user->username),
|
||||
@@ -53,6 +53,8 @@ class UsersTransformer
|
||||
'permissions' => $user->decodePermissions(),
|
||||
'activated' => ($user->activated =='1') ? true : false,
|
||||
'two_factor_activated' => ($user->two_factor_active()) ? true : false,
|
||||
'two_factor_enrolled' => ($user->two_factor_active_and_enrolled()) ? true : false,
|
||||
|
||||
'assets_count' => (int) $user->assets_count,
|
||||
'licenses_count' => (int) $user->licenses_count,
|
||||
'accessories_count' => (int) $user->accessories_count,
|
||||
|
||||
@@ -4,6 +4,7 @@ namespace App\Importer;
|
||||
use App\Models\CustomField;
|
||||
use App\Models\Setting;
|
||||
use App\Models\User;
|
||||
use App\Models\Department;
|
||||
use ForceUTF8\Encoding;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
@@ -29,6 +30,7 @@ abstract class Importer
|
||||
*/
|
||||
private $defaultFieldMap = [
|
||||
'asset_tag' => 'asset tag',
|
||||
'activated' => 'activated',
|
||||
'category' => 'category',
|
||||
'checkout_class' => 'checkout type', // Supports Location or User for assets. Using checkout_class instead of checkout_type because type exists on asset already.
|
||||
'checkout_location' => 'checkout location',
|
||||
@@ -66,6 +68,9 @@ abstract class Importer
|
||||
'phone_number' => 'phone number',
|
||||
'first_name' => 'first name',
|
||||
'last_name' => 'last name',
|
||||
'department' => 'department',
|
||||
'manager_first_name' => 'manager first name',
|
||||
'manager_last_name' => 'manager last name',
|
||||
];
|
||||
/**
|
||||
* Map of item fields->csv names
|
||||
@@ -176,10 +181,9 @@ abstract class Importer
|
||||
{
|
||||
|
||||
$val = $default;
|
||||
|
||||
$key = $this->lookupCustomKey($key);
|
||||
|
||||
$this->log("Custom Key: ${key}");
|
||||
// $this->log("Custom Key: ${key}");
|
||||
if (array_key_exists($key, $array)) {
|
||||
$val = Encoding::toUTF8(trim($array[ $key ]));
|
||||
}
|
||||
@@ -198,7 +202,6 @@ abstract class Importer
|
||||
public function lookupCustomKey($key)
|
||||
{
|
||||
if (array_key_exists($key, $this->fieldMap)) {
|
||||
// $this->log("Found a match in our custom map: {$key} is " . $this->fieldMap[$key]);
|
||||
return $this->fieldMap[$key];
|
||||
}
|
||||
// Otherwise no custom key, return original.
|
||||
@@ -248,7 +251,10 @@ abstract class Importer
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the user matching given data, or creates a new one if there is no match
|
||||
* Finds the user matching given data, or creates a new one if there is no match.
|
||||
* This is NOT used by the User Import, only for Asset/Accessory/etc where
|
||||
* there are users listed and we have to create them and associate them at
|
||||
* the same time. [ALG]
|
||||
*
|
||||
* @author Daniel Melzter
|
||||
* @since 3.0
|
||||
@@ -261,8 +267,13 @@ abstract class Importer
|
||||
$user_array = [
|
||||
'full_name' => $this->findCsvMatch($row, "full_name"),
|
||||
'email' => $this->findCsvMatch($row, "email"),
|
||||
'username' => $this->findCsvMatch($row, "username")
|
||||
'manager_id'=> '',
|
||||
'department_id' => '',
|
||||
'username' => $this->findCsvMatch($row, "username"),
|
||||
'activated' => $this->fetchHumanBoolean($this->findCsvMatch($row, 'activated')),
|
||||
];
|
||||
\Log::debug('Importer.php Activated: '.$this->findCsvMatch($row, 'activated'));
|
||||
|
||||
// If the full name is empty, bail out--we need this to extract first name (at the very least)
|
||||
if(empty($user_array['full_name'])) {
|
||||
$this->log('Insufficient user data provided (Full name is required)- skipping user creation, just adding asset');
|
||||
@@ -283,6 +294,7 @@ abstract class Importer
|
||||
$user_formatted_array = User::generateFormattedNameFromFullName(Setting::getSettings()->username_format, $user_array['full_name']);
|
||||
$user_array['first_name'] = $user_formatted_array['first_name'];
|
||||
$user_array['last_name'] = $user_formatted_array['last_name'];
|
||||
|
||||
if (empty($user_array['username'])) {
|
||||
$user_array['username'] = $user_formatted_array['username'];
|
||||
if ($this->usernameFormat =='email') {
|
||||
@@ -290,8 +302,9 @@ abstract class Importer
|
||||
}
|
||||
}
|
||||
|
||||
// Does this ever actually fire??
|
||||
// Check for a matching user after trying to guess username.
|
||||
if($user = User::where('username', $user_array['username'])->first()) {
|
||||
if ($user = User::where('username', $user_array['username'])->first()) {
|
||||
$this->log('User '.$user_array['username'].' already exists');
|
||||
return $user;
|
||||
}
|
||||
@@ -307,10 +320,15 @@ abstract class Importer
|
||||
$user->last_name = $user_array['last_name'];
|
||||
$user->username = $user_array['username'];
|
||||
$user->email = $user_array['email'];
|
||||
$user->activated = 1;
|
||||
$user->manager_id = (isset($user_array['manager_id']) ? $user_array['manager_id'] : null);
|
||||
$user->department_id = (isset($user_array['department_id']) ? $user_array['department_id']: null);
|
||||
$user->activated = $user_array['activated'];
|
||||
$user->password = $this->tempPassword;
|
||||
|
||||
\Log::debug('Creating a user with the following attributes: '.print_r($user_array, true));
|
||||
|
||||
if ($user->save()) {
|
||||
\Log::debug('Importer.php Name: '.$user->first_name.' '.$user->last_name.' ('.$user->username.')');
|
||||
$this->log('User '.$user_array['username'].' created');
|
||||
return $user;
|
||||
}
|
||||
@@ -360,6 +378,20 @@ abstract class Importer
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the Are we updating items in the import.
|
||||
*
|
||||
* @param bool $updating the updating
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function setShouldNotify($send_welcome)
|
||||
{
|
||||
$this->send_welcome = $send_welcome;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines mappings of csv fields
|
||||
*
|
||||
@@ -407,4 +439,64 @@ abstract class Importer
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function fetchHumanBoolean($value)
|
||||
{
|
||||
if (($value =='1') || (strtolower($value) =='true') || (strtolower($value) =='yes'))
|
||||
{
|
||||
return '1';
|
||||
}
|
||||
return '0';
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch an existing department, or create new if it doesn't exist
|
||||
*
|
||||
* @author A. Gianotto
|
||||
* @since 4.6.5
|
||||
* @param $user_department string
|
||||
* @return int id of company created/found
|
||||
*/
|
||||
public function createOrFetchDepartment($user_department_name)
|
||||
{
|
||||
if ($user_department_name!='') {
|
||||
$department = Department::where('name', '=', $user_department_name)->first();
|
||||
|
||||
if ($department) {
|
||||
$this->log('A matching Department ' . $user_department_name . ' already exists');
|
||||
return $department->id;
|
||||
}
|
||||
|
||||
$department = new Department();
|
||||
$department->name = $user_department_name;
|
||||
|
||||
if ($department->save()) {
|
||||
$this->log('Department ' . $user_department_name . ' was created');
|
||||
return $department->id;
|
||||
}
|
||||
$this->logError($department, 'Department');
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch an existing manager
|
||||
*
|
||||
* @author A. Gianotto
|
||||
* @since 4.6.5
|
||||
* @param $user_manager string
|
||||
* @return int id of company created/found
|
||||
*/
|
||||
public function fetchManager($user_manager_first_name, $user_manager_last_name)
|
||||
{
|
||||
$manager = User::where('first_name', '=', $user_manager_first_name)
|
||||
->where('last_name', '=', $user_manager_last_name)->first();
|
||||
if ($manager) {
|
||||
$this->log('A matching Manager ' . $user_manager_first_name . ' '. $user_manager_last_name . ' already exists');
|
||||
return $manager->id;
|
||||
}
|
||||
$this->log('No matching Manager ' . $user_manager_first_name . ' '. $user_manager_last_name . ' found. If their user account is being created through this import, you should re-process this file again. ');
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ use App\Models\Location;
|
||||
use App\Models\Manufacturer;
|
||||
use App\Models\Statuslabel;
|
||||
use App\Models\Supplier;
|
||||
use App\Models\Department;
|
||||
use App\Models\User;
|
||||
|
||||
class ItemImporter extends Importer
|
||||
@@ -54,6 +55,18 @@ class ItemImporter extends Importer
|
||||
if ($this->shouldUpdateField($item_supplier)) {
|
||||
$this->item['supplier_id'] = $this->createOrFetchSupplier($item_supplier);
|
||||
}
|
||||
|
||||
$item_department = $this->findCsvMatch($row, "department");
|
||||
if ($this->shouldUpdateField($item_department)) {
|
||||
$this->item['department_id'] = $this->createOrFetchDepartment($item_department);
|
||||
}
|
||||
|
||||
$item_manager_first_name = $this->findCsvMatch($row, "manager_first_name");
|
||||
$item_manager_last_name = $this->findCsvMatch($row, "manager_last_name");
|
||||
if ($this->shouldUpdateField($item_manager_first_name)) {
|
||||
$this->item['manager_id'] = $this->fetchManager($item_manager_first_name, $item_manager_last_name);
|
||||
}
|
||||
|
||||
$this->item["name"] = $this->findCsvMatch($row, "item_name");
|
||||
$this->item["notes"] = $this->findCsvMatch($row, "notes");
|
||||
$this->item["order_number"] = $this->findCsvMatch($row, "order_number");
|
||||
@@ -84,7 +97,7 @@ class ItemImporter extends Importer
|
||||
*/
|
||||
protected function determineCheckout($row)
|
||||
{
|
||||
// We only support checkout-to-location for asset, so short circuit otherw.
|
||||
// We only support checkout-to-location for asset, so short circuit otherwise.
|
||||
if(get_class($this) != AssetImporter::class) {
|
||||
return $this->createOrFetchUser($row);
|
||||
}
|
||||
@@ -161,7 +174,7 @@ class ItemImporter extends Importer
|
||||
* @since 3.0
|
||||
* @param array
|
||||
* @param $category Category
|
||||
* @param $manufacturer Manufacturer
|
||||
* @param $row Manufacturer
|
||||
* @return int Id of asset model created/found
|
||||
* @internal param $asset_modelno string
|
||||
*/
|
||||
@@ -279,6 +292,8 @@ class ItemImporter extends Importer
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Fetch the existing status label or create new if it doesn't exist.
|
||||
*
|
||||
|
||||
@@ -6,13 +6,21 @@ use App\Helpers\Helper;
|
||||
use App\Models\User;
|
||||
use App\Notifications\WelcomeNotification;
|
||||
|
||||
/**
|
||||
* This is ONLY used for the User Import. When we are importing users
|
||||
* via an Asset/etc import, we use createOrFetchUser() in
|
||||
* App\Importer.php. [ALG]
|
||||
*
|
||||
* Class UserImporter
|
||||
* @package App\Importer
|
||||
*
|
||||
*/
|
||||
class UserImporter extends ItemImporter
|
||||
{
|
||||
protected $users;
|
||||
public function __construct($filename)
|
||||
{
|
||||
parent::__construct($filename);
|
||||
// $this->users = User::all();
|
||||
}
|
||||
|
||||
protected function handle($row)
|
||||
@@ -31,25 +39,40 @@ class UserImporter extends ItemImporter
|
||||
*/
|
||||
public function createUserIfNotExists(array $row)
|
||||
{
|
||||
// User Specific Bits
|
||||
// Pull the records from the CSV to determine their values
|
||||
$this->item['username'] = $this->findCsvMatch($row, 'username');
|
||||
$this->item['first_name'] = $this->findCsvMatch($row, 'first_name');
|
||||
$this->item['last_name'] = $this->findCsvMatch($row, 'last_name');
|
||||
\Log::debug('UserImporter.php Name: '.$this->item['first_name'].' '.$this->item['last_name'].' ('.$this->item['username'].')');
|
||||
$this->item['email'] = $this->findCsvMatch($row, 'email');
|
||||
$this->item['phone'] = $this->findCsvMatch($row, 'phone_number');
|
||||
$this->item['jobtitle'] = $this->findCsvMatch($row, 'jobtitle');
|
||||
$this->item['activated'] = ($this->fetchHumanBoolean($this->findCsvMatch($row, 'activated')) == 1) ? '1' : 0;
|
||||
|
||||
\Log::debug('UserImporter.php Activated: '.$this->findCsvMatch($row, 'activated'));
|
||||
\Log::debug('UserImporter.php Activated fetchHumanBoolean: '. $this->fetchHumanBoolean($this->findCsvMatch($row, 'activated')));
|
||||
|
||||
$this->item['employee_num'] = $this->findCsvMatch($row, 'employee_num');
|
||||
$this->item['department_id'] = $this->createOrFetchDepartment($this->findCsvMatch($row, 'department')) ? $this->createOrFetchDepartment($this->findCsvMatch($row, 'department')) : null;
|
||||
$this->item['manager_id'] = $this->fetchManager($this->findCsvMatch($row, 'manager_first_name'), $this->findCsvMatch($row, 'manager_last_name')) ? $this->fetchManager($this->findCsvMatch($row, 'manager_first_name'), $this->findCsvMatch($row, 'manager_last_name')) : null;
|
||||
|
||||
|
||||
$user = User::where('username', $this->item['username'])->first();
|
||||
if ($user) {
|
||||
if (!$this->updating) {
|
||||
$this->log('A matching User ' . $this->item["name"] . ' already exists. ');
|
||||
\Log::debug('A matching User ' . $this->item["name"] . ' already exists. ');
|
||||
return;
|
||||
}
|
||||
$this->log('Updating User');
|
||||
$user->update($this->sanitizeItemForUpdating($user));
|
||||
$user->save();
|
||||
// \Log::debug('UserImporter.php Updated User ' . print_r($user, true));
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// This needs to be applied after the update logic, otherwise we'll overwrite user passwords
|
||||
// Issue #5408
|
||||
$this->item['password'] = $this->tempPassword;
|
||||
@@ -57,10 +80,11 @@ class UserImporter extends ItemImporter
|
||||
$this->log("No matching user, creating one");
|
||||
$user = new User();
|
||||
$user->fill($this->sanitizeItemForStoring($user));
|
||||
|
||||
if ($user->save()) {
|
||||
// $user->logCreate('Imported using CSV Importer');
|
||||
$this->log("User " . $this->item["name"] . ' was created');
|
||||
if($user->email) {
|
||||
|
||||
if(($user->email) && ($user->activated=='1')) {
|
||||
$data = [
|
||||
'email' => $user->email,
|
||||
'username' => $user->username,
|
||||
@@ -69,8 +93,10 @@ class UserImporter extends ItemImporter
|
||||
'password' => $this->tempPassword,
|
||||
];
|
||||
|
||||
// UNCOMMENT this to re-enable sending email notifications on user import
|
||||
// $user->notify(new WelcomeNotification($data));
|
||||
if ($this->send_welcome) {
|
||||
$user->notify(new WelcomeNotification($data));
|
||||
}
|
||||
|
||||
}
|
||||
$user = null;
|
||||
$this->item = null;
|
||||
|
||||
@@ -1,16 +1,20 @@
|
||||
| CSV | Item | Applicable Types |
|
||||
|---------------------|------------------|-------------------------------------------|
|
||||
| activated | | User |
|
||||
| asset tag | asset_tag | Asset |
|
||||
| category | category | All |
|
||||
| company | company | All |
|
||||
| department_id | | User ? All |
|
||||
| item name | item_name | All |
|
||||
| image | image | asset |
|
||||
| image | image | Asset |
|
||||
| email | | |
|
||||
| expiration date | expiration_date | License |
|
||||
| location | location | All |
|
||||
| notes | notes | All |
|
||||
| licensed to email | license_email | License |
|
||||
| licensed to name | license_name | License |
|
||||
| maintained | maintained | License |
|
||||
| manager_id | | User |
|
||||
| manufacturer | manufacturer | All |
|
||||
| model name | asset_model | Asset |
|
||||
| model number | model_number | Asset |
|
||||
@@ -22,12 +26,12 @@
|
||||
| reassignable | reassignable | License |
|
||||
| requestable | requestable | Asset, Accessory? |
|
||||
| seats | seats | License |
|
||||
| serial number | serial | asset, license |
|
||||
| status | status | asset ? All |
|
||||
| serial number | serial | Asset, license |
|
||||
| status | status | Asset ? All |
|
||||
| supplier | supplier | Asset ? All |
|
||||
| termination date | termination_date | License |
|
||||
| warranty months | warranty_months | asset |
|
||||
| warranty months | warranty_months | Asset |
|
||||
| User Related Fields | assigned_to | Asset |
|
||||
| name | | |
|
||||
| email | | |
|
||||
| username | | |
|
||||
| username | | |
|
||||
|
||||
|
||||
@@ -72,6 +72,8 @@ class AssetMaintenance extends Model implements ICompanyableChild
|
||||
trans('admin/asset_maintenances/general.repair') => trans('admin/asset_maintenances/general.repair'),
|
||||
trans('admin/asset_maintenances/general.upgrade') => trans('admin/asset_maintenances/general.upgrade'),
|
||||
'PAT test' => 'PAT test',
|
||||
trans('admin/asset_maintenances/general.calibration') => trans('admin/asset_maintenances/general.calibration'),
|
||||
'PAT test' => 'PAT test',
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
@@ -35,7 +35,7 @@ class Consumable extends SnipeModel
|
||||
'qty' => 'required|integer|min:0',
|
||||
'category_id' => 'required|integer',
|
||||
'company_id' => 'integer|nullable',
|
||||
'min_amt' => 'integer|min:1|nullable',
|
||||
'min_amt' => 'integer|min:0|nullable',
|
||||
'purchase_cost' => 'numeric|nullable',
|
||||
);
|
||||
|
||||
@@ -76,7 +76,7 @@ class Consumable extends SnipeModel
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $searchableAttributes = ['name', 'order_number', 'purchase_cost', 'purchase_date'];
|
||||
protected $searchableAttributes = ['name', 'order_number', 'purchase_cost', 'purchase_date', 'item_no'];
|
||||
|
||||
/**
|
||||
* The relations and their attributes that should be included when searching the model.
|
||||
|
||||
@@ -25,11 +25,11 @@ class Department extends SnipeModel
|
||||
use ValidatingTrait, UniqueUndeletedTrait;
|
||||
|
||||
protected $rules = [
|
||||
'name' => 'required|max:255',
|
||||
'user_id' => 'required',
|
||||
'location_id' => 'numeric|nullable',
|
||||
'company_id' => 'numeric|nullable',
|
||||
'manager_id' => 'numeric|nullable',
|
||||
'name' => 'required|max:255',
|
||||
'user_id' => 'nullable|exists:users,id',
|
||||
'location_id' => 'numeric|nullable',
|
||||
'company_id' => 'numeric|nullable',
|
||||
'manager_id' => 'numeric|nullable',
|
||||
];
|
||||
|
||||
/**
|
||||
|
||||
+5
-2
@@ -96,8 +96,11 @@ class Ldap extends Model
|
||||
|
||||
$filterQuery = $settings->ldap_auth_filter_query . $username;
|
||||
|
||||
|
||||
if (!$ldapbind = @ldap_bind($connection, $userDn, $password)) {
|
||||
return false;
|
||||
if(!$ldapbind = Ldap::bindAdminToLdap($connection)){
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!$results = ldap_search($connection, $baseDn, $filterQuery)) {
|
||||
@@ -112,7 +115,7 @@ class Ldap extends Model
|
||||
return false;
|
||||
}
|
||||
|
||||
return $user;
|
||||
return array_change_key_case($user);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -110,6 +110,7 @@ class License extends Depreciable
|
||||
protected $searchableRelations = [
|
||||
'manufacturer' => ['name'],
|
||||
'company' => ['name'],
|
||||
'category' => ['name'],
|
||||
];
|
||||
|
||||
public static function boot()
|
||||
|
||||
@@ -41,7 +41,8 @@ trait Loggable
|
||||
$settings = Setting::getSettings();
|
||||
$log = new Actionlog;
|
||||
$log = $this->determineLogItemType($log);
|
||||
$log->user_id = Auth::user()->id;
|
||||
if(Auth::user())
|
||||
$log->user_id = Auth::user()->id;
|
||||
|
||||
if (!isset($target)) {
|
||||
throw new Exception('All checkout logs require a target');
|
||||
|
||||
+67
-8
@@ -47,6 +47,7 @@ class User extends SnipeModel implements AuthenticatableContract, CanResetPasswo
|
||||
'manager_id',
|
||||
'password',
|
||||
'phone',
|
||||
'notes',
|
||||
'state',
|
||||
'username',
|
||||
'zip',
|
||||
@@ -269,7 +270,7 @@ class User extends SnipeModel implements AuthenticatableContract, CanResetPasswo
|
||||
**/
|
||||
public function managedLocations()
|
||||
{
|
||||
return $this->hasMany('\App\Models\Location', 'manager_id')->withTrashed();
|
||||
return $this->hasMany('\App\Models\Location', 'manager_id');
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -328,7 +329,7 @@ class User extends SnipeModel implements AuthenticatableContract, CanResetPasswo
|
||||
|
||||
public function scopeGetDeleted($query)
|
||||
{
|
||||
return $query->withTrashed()->whereNotNull('deleted_at');
|
||||
return $query->withTrashed()->whereNotNull('users.deleted_at');
|
||||
}
|
||||
|
||||
public function scopeGetNotDeleted($query)
|
||||
@@ -388,7 +389,11 @@ class User extends SnipeModel implements AuthenticatableContract, CanResetPasswo
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether two-factor authorization is required and the user has activated it
|
||||
* Check whether two-factor authorization is requiredfor this user
|
||||
*
|
||||
* 0 = 2FA disabled
|
||||
* 1 = 2FA optional
|
||||
* 2 = 2FA universally required
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @since [v4.0]
|
||||
@@ -397,10 +402,45 @@ class User extends SnipeModel implements AuthenticatableContract, CanResetPasswo
|
||||
*/
|
||||
public function two_factor_active () {
|
||||
|
||||
if (Setting::getSettings()->two_factor_enabled !='0') {
|
||||
if (($this->two_factor_optin =='1') && ($this->two_factor_enrolled)) {
|
||||
return true;
|
||||
}
|
||||
// If the 2FA is optional and the user has opted in
|
||||
if ((Setting::getSettings()->two_factor_enabled =='1') && ($this->two_factor_optin =='1'))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
// If the 2FA is required for everyone so is implicitly active
|
||||
elseif (Setting::getSettings()->two_factor_enabled =='2')
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether two-factor authorization is required and the user has activated it
|
||||
* and enrolled a device
|
||||
*
|
||||
* 0 = 2FA disabled
|
||||
* 1 = 2FA optional
|
||||
* 2 = 2FA universally required
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @since [v4.6.14]
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function two_factor_active_and_enrolled () {
|
||||
|
||||
// If the 2FA is optional and the user has opted in and is enrolled
|
||||
if ((Setting::getSettings()->two_factor_enabled =='1') && ($this->two_factor_optin =='1') && ($this->two_factor_enrolled =='1'))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
// If the 2FA is required for everyone and the user has enrolled
|
||||
elseif ((Setting::getSettings()->two_factor_enabled =='2') && ($this->two_factor_enrolled))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
||||
@@ -412,6 +452,25 @@ class User extends SnipeModel implements AuthenticatableContract, CanResetPasswo
|
||||
return json_decode($this->permissions, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Query builder scope to search user by name with spaces in it.
|
||||
* We don't use the advancedTextSearch() scope because that searches
|
||||
* all of the relations as well, which is more than what we need.
|
||||
*
|
||||
* @param \Illuminate\Database\Query\Builder $query Query builder instance
|
||||
* @param array $terms The search terms
|
||||
* @return \Illuminate\Database\Query\Builder
|
||||
*/
|
||||
public function scopeSimpleNameSearch($query, $search) {
|
||||
|
||||
$query = $query->where('first_name', 'LIKE', '%'.$search.'%')
|
||||
->orWhere('last_name', 'LIKE', '%'.$search.'%')
|
||||
->orWhereRaw('CONCAT('.DB::getTablePrefix().'users.first_name," ",'.DB::getTablePrefix().'users.last_name) LIKE ?', ["%$search%", "%$search%"]);
|
||||
return $query;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Run additional, advanced searches.
|
||||
*
|
||||
@@ -445,7 +504,7 @@ class User extends SnipeModel implements AuthenticatableContract, CanResetPasswo
|
||||
|
||||
public function scopeDeleted($query)
|
||||
{
|
||||
return $query->whereNotNull('deleted_at');
|
||||
return $query->whereNotNull('users.deleted_at');
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -53,7 +53,7 @@ abstract class SnipePermissionsPolicy
|
||||
/**
|
||||
* Determine whether the user can view the accessory.
|
||||
*
|
||||
* @param \App\User $user
|
||||
* @param \App\Models\User $user
|
||||
* @return mixed
|
||||
*/
|
||||
public function view(User $user, $item = null)
|
||||
@@ -64,7 +64,7 @@ abstract class SnipePermissionsPolicy
|
||||
/**
|
||||
* Determine whether the user can create accessories.
|
||||
*
|
||||
* @param \App\User $user
|
||||
* @param \App\Models\User $user
|
||||
* @return mixed
|
||||
*/
|
||||
public function create(User $user)
|
||||
@@ -75,7 +75,7 @@ abstract class SnipePermissionsPolicy
|
||||
/**
|
||||
* Determine whether the user can update the accessory.
|
||||
*
|
||||
* @param \App\User $user
|
||||
* @param \App\Models\User $user
|
||||
* @return mixed
|
||||
*/
|
||||
public function update(User $user, $item = null)
|
||||
@@ -86,7 +86,7 @@ abstract class SnipePermissionsPolicy
|
||||
/**
|
||||
* Determine whether the user can delete the accessory.
|
||||
*
|
||||
* @param \App\User $user
|
||||
* @param \App\Models\User $user
|
||||
* @return mixed
|
||||
*/
|
||||
public function delete(User $user, $item = null)
|
||||
@@ -97,11 +97,13 @@ abstract class SnipePermissionsPolicy
|
||||
/**
|
||||
* Determine whether the user can manage the accessory.
|
||||
*
|
||||
* @param \App\User $user
|
||||
* @param \App\Models\User $user
|
||||
* @return mixed
|
||||
*/
|
||||
public function manage(User $user, $item = null)
|
||||
{
|
||||
return $user->hasAccess($this->columnName().'.edit');
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -226,14 +226,14 @@ class UserPresenter extends Presenter
|
||||
[
|
||||
"field" => "two_factor_enrolled",
|
||||
"searchable" => false,
|
||||
"sortable" => false,
|
||||
"sortable" => true,
|
||||
"switchable" => true,
|
||||
"title" => trans('admin/users/general.two_factor_enrolled'),
|
||||
"visible" => false,
|
||||
'formatter' => 'trueFalseFormatter'
|
||||
],
|
||||
[
|
||||
"field" => "two_factor_active",
|
||||
"field" => "two_factor_activated",
|
||||
"searchable" => false,
|
||||
"sortable" => false,
|
||||
"switchable" => true,
|
||||
@@ -246,7 +246,7 @@ class UserPresenter extends Presenter
|
||||
"searchable" => false,
|
||||
"sortable" => true,
|
||||
"switchable" => true,
|
||||
"title" => trans('general.activated'),
|
||||
"title" => trans('general.login_enabled'),
|
||||
"visible" => true,
|
||||
'formatter' => 'trueFalseFormatter'
|
||||
],
|
||||
|
||||
@@ -58,7 +58,7 @@ class AppServiceProvider extends ServiceProvider
|
||||
if (($this->app->environment('production')) && (config('services.rollbar.access_token'))){
|
||||
$this->app->register(\Rollbar\Laravel\RollbarServiceProvider::class);
|
||||
}
|
||||
|
||||
|
||||
foreach ($monolog->getHandlers() as $handler) {
|
||||
$handler->setLevel($log_level);
|
||||
}
|
||||
|
||||
@@ -113,6 +113,14 @@ class AuthServiceProvider extends ServiceProvider
|
||||
});
|
||||
|
||||
|
||||
// Can the user import CSVs?
|
||||
Gate::define('import', function ($user) {
|
||||
if ($user->hasAccess('import') ) {
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
# -----------------------------------------
|
||||
# Reports
|
||||
# -----------------------------------------
|
||||
|
||||
+5
-4
@@ -12,8 +12,9 @@
|
||||
"doctrine/dbal": "^2.5.13",
|
||||
"doctrine/inflector": "1.1.*",
|
||||
"doctrine/instantiator": "1.0.*",
|
||||
"eduardokum/laravel-mail-auto-embed": "^1.0",
|
||||
"erusev/parsedown": "^1.6",
|
||||
"fideloper/proxy": "^3.1",
|
||||
"fideloper/proxy": "^3.3",
|
||||
"intervention/image": "^2.3",
|
||||
"javiereguiluz/easyslugger": "^1.0",
|
||||
"laravel/framework": "5.4.35",
|
||||
@@ -26,9 +27,10 @@
|
||||
"patchwork/utf8": "~1.2",
|
||||
"phpdocumentor/reflection-docblock": "3.2.2",
|
||||
"phpspec/prophecy": "1.6.2",
|
||||
"pragmarx/google2fa": "^1.0",
|
||||
"pragmarx/google2fa": "^5.0",
|
||||
"pragmarx/google2fa-laravel": "^0.3.0",
|
||||
"predis/predis": "^1.1",
|
||||
"rollbar/rollbar-laravel": "^2.2",
|
||||
"rollbar/rollbar-laravel": "2.4.1",
|
||||
"schuppo/password-strength": "~1.5",
|
||||
"spatie/laravel-backup": "3.11.0",
|
||||
"tecnickcom/tc-lib-barcode": "^1.15",
|
||||
@@ -41,7 +43,6 @@
|
||||
"fzaninotto/faker": "~1.4",
|
||||
"phpunit/php-token-stream": "1.4.11",
|
||||
"phpunit/phpunit": "~5.7",
|
||||
"roave/security-advisories": "dev-master",
|
||||
"squizlabs/php_codesniffer": "*",
|
||||
"symfony/css-selector": "3.1.*",
|
||||
"symfony/dom-crawler": "3.1.*"
|
||||
|
||||
Generated
+541
-345
File diff suppressed because it is too large
Load Diff
+2
-1
@@ -291,12 +291,13 @@ return [
|
||||
Collective\Html\HtmlServiceProvider::class,
|
||||
Spatie\Backup\BackupServiceProvider::class,
|
||||
Fideloper\Proxy\TrustedProxyServiceProvider::class,
|
||||
PragmaRX\Google2FA\Vendor\Laravel\ServiceProvider::class,
|
||||
PragmaRX\Google2FALaravel\ServiceProvider::class,
|
||||
Laravel\Passport\PassportServiceProvider::class,
|
||||
Laravel\Tinker\TinkerServiceProvider::class,
|
||||
Unicodeveloper\DumbPassword\DumbPasswordServiceProvider::class,
|
||||
Schuppo\PasswordStrength\PasswordStrengthServiceProvider::class,
|
||||
Tightenco\Ziggy\ZiggyServiceProvider::class, // Laravel routes in vue
|
||||
Eduardokum\LaravelMailAutoEmbed\ServiceProvider::class,
|
||||
|
||||
/*
|
||||
* Application Service Providers...
|
||||
|
||||
+1
-1
@@ -86,6 +86,6 @@ return [
|
||||
|
|
||||
*/
|
||||
|
||||
'prefix' => 'snipeit',
|
||||
'prefix' => env('CACHE_PREFIX', 'snipeit'),
|
||||
|
||||
];
|
||||
|
||||
@@ -27,6 +27,15 @@ return array(
|
||||
)
|
||||
),
|
||||
|
||||
'CSV Import' => array(
|
||||
array(
|
||||
'permission' => 'import',
|
||||
'label' => '',
|
||||
'note' => 'This will allow users to import even if access to users, assets, etc is denied elsewhere.',
|
||||
'display' => true,
|
||||
)
|
||||
),
|
||||
|
||||
'Reports' => array(
|
||||
array(
|
||||
'permission' => 'reports.view',
|
||||
|
||||
@@ -63,11 +63,12 @@ return [
|
||||
* We may also want to add something like:
|
||||
* \Illuminate\Http\Request::HEADER_CLIENT_PROTO => 'X_FORWARDED_SCHEME',
|
||||
*/
|
||||
// These are defaults already set in the config:
|
||||
'headers' => [
|
||||
(defined('Illuminate\Http\Request::HEADER_FORWARDED') ? Illuminate\Http\Request::HEADER_FORWARDED : 'forwarded') => 'FORWARDED',
|
||||
\Illuminate\Http\Request::HEADER_CLIENT_IP => 'X_FORWARDED_FOR',
|
||||
\Illuminate\Http\Request::HEADER_CLIENT_HOST => 'X_FORWARDED_HOST',
|
||||
\Illuminate\Http\Request::HEADER_CLIENT_PROTO => 'X_FORWARDED_PROTO',
|
||||
\Illuminate\Http\Request::HEADER_CLIENT_PORT => 'X_FORWARDED_PORT',
|
||||
|
||||
]
|
||||
];
|
||||
|
||||
+5
-5
@@ -1,10 +1,10 @@
|
||||
<?php
|
||||
return array (
|
||||
'app_version' => 'v4.6.5',
|
||||
'full_app_version' => 'v4.6.5 - build 3897-gff824ec4d',
|
||||
'build_version' => '3897',
|
||||
'app_version' => 'v4.6.15',
|
||||
'full_app_version' => 'v4.6.15 - build 4011-gd1e9fbfa2',
|
||||
'build_version' => '4011',
|
||||
'prerelease_version' => '',
|
||||
'hash_version' => 'gff824ec4d',
|
||||
'full_hash' => 'v4.6.5-15-gff824ec4d',
|
||||
'hash_version' => 'gd1e9fbfa2',
|
||||
'full_hash' => 'v4.6.15-2-gd1e9fbfa2',
|
||||
'branch' => 'master',
|
||||
);
|
||||
|
||||
@@ -15,7 +15,7 @@ class AddPrefixToSettings extends Migration {
|
||||
//
|
||||
Schema::table('settings', function(Blueprint $table) {
|
||||
|
||||
$table->string('auto_increment_prefix')->default(0);
|
||||
$table->string('auto_increment_prefix')->nullable()->default(NULL);
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
|
||||
class ChangeAutoIncrementPrefixToNullable extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::table('settings', function (Blueprint $table) {
|
||||
$table->string('auto_increment_prefix')->nullable()->default(null)->change();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
//
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
|
||||
class AutoIncrementBackToString extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::table('settings', function (Blueprint $table) {
|
||||
$table->string('auto_increment_prefix')->nullable()->default(null)->change();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
//
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
|
||||
class MakeSerialNullable extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
$platform = Schema::getConnection()->getDoctrineSchemaManager()->getDatabasePlatform();
|
||||
$platform->registerDoctrineTypeMapping('enum', 'string');
|
||||
|
||||
Schema::table('assets', function (Blueprint $table) {
|
||||
$table->string('serial')->nullable()->default(null)->change();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
//
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
|
||||
class MakeFieldsNullableForIntegrity extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
|
||||
|
||||
Schema::table('locations', function (Blueprint $table) {
|
||||
$table->string('city')->nullable()->default(null)->change();
|
||||
$table->string('state')->nullable()->default(null)->change();
|
||||
$table->string('country')->nullable()->default(null)->change();
|
||||
$table->integer('user_id')->nullable()->default(null)->change();
|
||||
$table->string('address')->nullable()->default(null)->change();
|
||||
$table->string('address2')->nullable()->default(null)->change();
|
||||
});
|
||||
|
||||
Schema::table('users', function (Blueprint $table) {
|
||||
$table->string('last_name')->nullable()->default(null)->change();
|
||||
});
|
||||
|
||||
Schema::table('suppliers', function (Blueprint $table) {
|
||||
$table->integer('user_id')->nullable()->default(null)->change();
|
||||
});
|
||||
|
||||
Schema::table('status_labels', function (Blueprint $table) {
|
||||
$table->integer('user_id')->nullable()->default(null)->change();
|
||||
});
|
||||
|
||||
Schema::table('models', function (Blueprint $table) {
|
||||
$table->integer('user_id')->nullable()->default(null)->change();
|
||||
$table->integer('manufacturer_id')->nullable()->default(null)->change();
|
||||
$table->integer('category_id')->nullable()->default(null)->change();
|
||||
});
|
||||
|
||||
Schema::table('licenses', function (Blueprint $table) {
|
||||
$table->integer('user_id')->nullable()->default(null)->change();
|
||||
$table->boolean('maintained')->nullable()->default(null)->change();
|
||||
});
|
||||
|
||||
Schema::table('depreciations', function (Blueprint $table) {
|
||||
$table->integer('user_id')->nullable()->default(null)->change();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
//
|
||||
}
|
||||
}
|
||||
@@ -5,7 +5,7 @@ if [ -z "$APP_KEY" ]
|
||||
then
|
||||
echo "Please re-run this container with an environment variable \$APP_KEY"
|
||||
echo "An example APP_KEY you could use is: "
|
||||
php artisan key:generate --show
|
||||
/var/www/html/artisan key:generate --show
|
||||
exit
|
||||
fi
|
||||
|
||||
@@ -47,5 +47,4 @@ then
|
||||
cp -ax /var/www/html/vendor/laravel/passport/database/migrations/* /var/www/html/database/migrations/
|
||||
fi
|
||||
|
||||
. /etc/apache2/envvars
|
||||
exec apache2 -DNO_DETACH < /dev/null
|
||||
exec supervisord -c /supervisord.conf
|
||||
@@ -0,0 +1,19 @@
|
||||
#!/usr/bin/env python
|
||||
# A supervisor event listener which terminates supervisord if any of its child
|
||||
# processes enter the FATAL state.
|
||||
# https://stackoverflow.com/a/37527488/119527
|
||||
import os
|
||||
import signal
|
||||
|
||||
from supervisor import childutils
|
||||
|
||||
def main():
|
||||
while True:
|
||||
headers, payload = childutils.listener.wait()
|
||||
childutils.listener.ok()
|
||||
if headers['eventname'] != 'PROCESS_STATE_FATAL':
|
||||
continue
|
||||
os.kill(os.getppid(), signal.SIGTERM)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -0,0 +1,27 @@
|
||||
[supervisord]
|
||||
nodaemon=true
|
||||
|
||||
[program:apache]
|
||||
; https://advancedweb.hu/2018/07/03/supervisor_docker/
|
||||
command=apache2ctl -DFOREGROUND
|
||||
killasgroup=true
|
||||
stopasgroup=true
|
||||
stdout_logfile=/dev/stdout
|
||||
stdout_logfile_maxbytes=0
|
||||
stderr_logfile=/dev/stderr
|
||||
stderr_logfile_maxbytes=0
|
||||
|
||||
[program:run_schedule]
|
||||
; Simply run the Laravel command scheduler every minute
|
||||
command=/bin/bash -c "while true; do /var/www/html/artisan schedule:run; sleep 1m; done"
|
||||
user=docker
|
||||
stdout_logfile=/dev/stdout
|
||||
stdout_logfile_maxbytes=0
|
||||
stderr_logfile=/dev/stderr
|
||||
stderr_logfile_maxbytes=0
|
||||
|
||||
|
||||
; https://stackoverflow.com/a/37527488/119527
|
||||
[eventlistener:exit_on_any_fatal]
|
||||
command=supervisor-exit-event-listener
|
||||
events=PROCESS_STATE_FATAL
|
||||
+600
-5
File diff suppressed because one or more lines are too long
Vendored
+1
-1
File diff suppressed because one or more lines are too long
+8044
-26
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Vendored
+26
-26
File diff suppressed because one or more lines are too long
@@ -1,14 +1,14 @@
|
||||
{
|
||||
"/js/build/vue.js": "/js/build/vue.js?id=832c22cb5b66ac81ed06",
|
||||
"/js/build/vue.js": "/js/build/vue.js?id=96f90510b797ac27a94b",
|
||||
"/css/AdminLTE.css": "/css/AdminLTE.css?id=5e72463a66acbcc740d5",
|
||||
"/css/app.css": "/css/app.css?id=407edb63cc6b6dc62405",
|
||||
"/css/overrides.css": "/css/overrides.css?id=2d81c3704393bac77011",
|
||||
"/js/build/vue.js.map": "/js/build/vue.js.map?id=0deaf852882fe2d65263",
|
||||
"/js/build/vue.js.map": "/js/build/vue.js.map?id=423f16f63b86abd6b196",
|
||||
"/css/AdminLTE.css.map": "/css/AdminLTE.css.map?id=0be7790b84909dca6a0a",
|
||||
"/css/app.css.map": "/css/app.css.map?id=96b5c985e860716e6a16",
|
||||
"/css/overrides.css.map": "/css/overrides.css.map?id=f7ce9ca49027594ac402",
|
||||
"/css/dist/all.css": "/css/dist/all.css?id=98db4e9b7650453c8b00",
|
||||
"/js/dist/all.js": "/js/dist/all.js?id=9d02373ef452329336d3",
|
||||
"/js/dist/all.js": "/js/dist/all.js?id=114f1025a1b3e8975476",
|
||||
"/css/build/all.css": "/css/build/all.css?id=98db4e9b7650453c8b00",
|
||||
"/js/build/all.js": "/js/build/all.js?id=9d02373ef452329336d3"
|
||||
}
|
||||
"/js/build/all.js": "/js/build/all.js?id=114f1025a1b3e8975476"
|
||||
}
|
||||
|
||||
@@ -6,29 +6,49 @@ tr {
|
||||
|
||||
<template>
|
||||
<tr v-show="processDetail">
|
||||
<td colspan="3">
|
||||
<td colspan="5">
|
||||
<div class="col-md-2 text-left">
|
||||
</div>
|
||||
<div class="col-md-8 col-md-offset-2 text-center" style="padding-top: 30px; margin: 0 auto;">
|
||||
<div class="col-md-12 text-left">
|
||||
|
||||
<h4 class="modal-title">Import File:</h4>
|
||||
<div class="dynamic-form-row">
|
||||
<div class="col-md-4 col-xs-12">
|
||||
<div class="col-md-5 col-xs-12">
|
||||
<label for="import-type">Import Type:</label>
|
||||
</div>
|
||||
<div class="col-md-4 col-xs-12">
|
||||
<div class="col-md-7 col-xs-12">
|
||||
<select2 :options="options.importTypes" v-model="options.importType" required>
|
||||
<option disabled value="0"></option>
|
||||
</select2>
|
||||
</div>
|
||||
</div>
|
||||
<div class="dynamic-form-row">
|
||||
<div class="col-md-4 col-xs-12">
|
||||
<div class="col-md-5 col-xs-12">
|
||||
<label for="import-update">Update Existing Values?:</label>
|
||||
</div>
|
||||
<div class="col-md-4 col-xs-12">
|
||||
<div class="col-md-7 col-xs-12">
|
||||
<input type="checkbox" name="import-update" v-model="options.update">
|
||||
</div>
|
||||
</div>
|
||||
<div class="dynamic-form-row">
|
||||
<div class="col-md-5 col-xs-12">
|
||||
<label for="send-welcome">Send Welcome Email for new Users?</label>
|
||||
</div>
|
||||
<div class="col-md-7 col-xs-12">
|
||||
<input type="checkbox" name="send-welcome" v-model="options.send_welcome">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="alert col-md-12" style="text-align:left"
|
||||
:class="alertClass"
|
||||
v-if="statusText">
|
||||
{{ this.statusText }}
|
||||
</div>
|
||||
|
||||
<div class="col-md-12" style="padding-top: 30px;">
|
||||
<table class="table">
|
||||
|
||||
<div class="text-left" style="padding-top: 30px;">
|
||||
<table class="table table-striped snipe-table">
|
||||
<thead>
|
||||
<th>Header Field</th>
|
||||
<th>Import Field</th>
|
||||
@@ -54,21 +74,24 @@ tr {
|
||||
</template>
|
||||
</tbody>
|
||||
</table>
|
||||
<br>
|
||||
<div class="col-md-8 col-md-offset-2 text-right">
|
||||
<button type="button" class="btn btn-sm btn-default" @click="processDetail = false">Cancel</button>
|
||||
<button type="submit" class="btn btn-sm btn-primary" @click="postSave">Import</button>
|
||||
<br><br>
|
||||
</div>
|
||||
|
||||
<div class="alert col-md-12" style="padding-top: 20px;"
|
||||
:class="alertClass"
|
||||
v-if="statusText">
|
||||
{{ this.statusText }}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</td>
|
||||
|
||||
<td>
|
||||
<button type="button" class="btn btn-sm btn-default" @click="processDetail = false">Cancel</button>
|
||||
<button type="submit" class="btn btn-sm btn-primary" @click="postSave">Import</button>
|
||||
<div
|
||||
class="alert col-md-5 col-md-offset-1"
|
||||
:class="alertClass"
|
||||
style="text-align:left"
|
||||
v-if="statusText"
|
||||
>
|
||||
{{ this.statusText }}
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</template>
|
||||
|
||||
@@ -113,6 +136,7 @@ tr {
|
||||
{id: 'serial', text: 'Serial Number' },
|
||||
{id: 'supplier', text: 'Supplier' },
|
||||
{id: 'username', text: 'Username' },
|
||||
{id: 'department', text: 'Department' },
|
||||
],
|
||||
assets: [
|
||||
{id: 'asset_tag', text: 'Asset Tag' },
|
||||
@@ -143,6 +167,9 @@ tr {
|
||||
{id: 'jobtitle', text: 'Job Title' },
|
||||
{id: 'last_name', text: 'Last Name' },
|
||||
{id: 'phone_number', text: 'Phone Number' },
|
||||
{id: 'manager_first_name', text: 'Manager First Name' },
|
||||
{id: 'manager_last_name', text: 'Manager Last Name' },
|
||||
{id: 'activated', text: 'Activated' },
|
||||
|
||||
],
|
||||
customFields: this.customFields,
|
||||
@@ -211,6 +238,7 @@ tr {
|
||||
this.statusText = "Processing...";
|
||||
this.$http.post(route('api.imports.importFile', this.file.id), {
|
||||
'import-update': this.options.update,
|
||||
'send-welcome': this.options.send_welcome,
|
||||
'import-type': this.options.importType,
|
||||
'column-mappings': this.columnMappings
|
||||
}).then( ({body}) => {
|
||||
|
||||
@@ -260,7 +260,18 @@ $(document).ready(function () {
|
||||
}
|
||||
|
||||
function formatDataSelection (datalist) {
|
||||
return datalist.text;
|
||||
// This a heinous workaround for a known bug in Select2.
|
||||
// Without this, the rich selectlists are vulnerable to XSS.
|
||||
// Many thanks to @uberbrady for this fix. It ain't pretty,
|
||||
// but it resolves the issue until Select2 addresses it on their end.
|
||||
//
|
||||
// Bug was reported in 2016 :{
|
||||
// https://github.com/select2/select2/issues/4587
|
||||
|
||||
return datalist.text.replace(/>/g, '>')
|
||||
.replace(/</g, '<')
|
||||
.replace(/"/g, '"')
|
||||
.replace(/'/g, ''');
|
||||
}
|
||||
|
||||
// This handles the radio button selectors for the checkout-to-foo options
|
||||
|
||||
@@ -42,7 +42,7 @@ return array(
|
||||
'alt_barcode_type' => '1D نوع الباركود',
|
||||
'eula_settings' => 'إعدادات اتفاقية ترخيص المستخدم النهائي',
|
||||
'eula_markdown' => 'تسمح اتفاقية ترخيص المستخدم هذه <a href="https://help.github.com/articles/github-flavored-markdown/">بتطبيق نمط الكتابة من Github</a>.',
|
||||
'footer_text' => 'Additional Footer Text ',
|
||||
'footer_text' => 'إضافة نص لتذييل الصفحة ',
|
||||
'footer_text_help' => 'This text will appear in the right-side footer. Links are allowed using <a href="https://help.github.com/articles/github-flavored-markdown/">Github flavored markdown</a>. Line breaks, headers, images, etc may result in unpredictable results.',
|
||||
'general_settings' => 'الاعدادات العامة',
|
||||
'generate_backup' => 'إنشاء النسخ الاحتياطي',
|
||||
@@ -75,7 +75,7 @@ return array(
|
||||
'ldap_active_flag' => 'لداب العلم النشط',
|
||||
'ldap_emp_num' => 'رقم موظف لداب',
|
||||
'ldap_email' => 'بريد لداب',
|
||||
'license' => 'Software License',
|
||||
'license' => 'ترخيص البرنامج',
|
||||
'load_remote_text' => 'المخطوطات عن بعد',
|
||||
'load_remote_help_text' => 'هذا قنص إيت تثبيت يمكن تحميل البرامج النصية من العالم الخارجي.',
|
||||
'login_note' => 'تسجيل الدخول ملاحظة',
|
||||
@@ -83,16 +83,16 @@ return array(
|
||||
'login_remote_user_text' => 'Remote User login options',
|
||||
'login_remote_user_enabled_text' => 'Enable Login with Remote User Header',
|
||||
'login_remote_user_enabled_help' => 'This option enables Authentication via the REMOTE_USER header according to the "Common Gateway Interface (rfc3875)"',
|
||||
'login_common_disabled_text' => 'Disable other authentication mechanisms',
|
||||
'login_common_disabled_text' => 'تعطيل آليات المصادقة الأخرى',
|
||||
'login_common_disabled_help' => 'This option disables other authentication mechanisms. Just enable this option if you are sure that your REMOTE_USER login is already working',
|
||||
'login_remote_user_custom_logout_url_text' => 'عنوان صفحة مخصص لتسجيل الخروج',
|
||||
'login_remote_user_custom_logout_url_help' => 'If a url is provided here, users will get redirected to this URL after the user logs out of Snipe-IT. This is useful to close the user sessions of your Authentication provider correctly.',
|
||||
'logo' => 'شعار',
|
||||
'logo_print_assets' => 'Use in Print',
|
||||
'logo_print_assets_help' => 'Use branding on printable asset lists ',
|
||||
'logo_print_assets' => 'الاستخدام في الطباعة',
|
||||
'logo_print_assets_help' => 'استخدم العلامة التجارية في قوائم الأصول القابلة للطباعة ',
|
||||
'full_multiple_companies_support_help_text' => 'تقييد المستخدمين (بما في ذلك المشرفون) المعينون للشركات إلى أصول شركاتهم.',
|
||||
'full_multiple_companies_support_text' => 'كامل دعم الشركات المتعددة',
|
||||
'show_in_model_list' => 'Show in Model Dropdowns',
|
||||
'show_in_model_list' => 'إظهار في القوائم المنسدلة للنماذج',
|
||||
'optional' => 'اختياري',
|
||||
'per_page' => 'النتائج لكل صفحة',
|
||||
'php' => 'نسخة فب',
|
||||
@@ -108,10 +108,10 @@ return array(
|
||||
'qr_text' => 'نص رمز الاستجابة السريعة',
|
||||
'setting' => 'ضبط',
|
||||
'settings' => 'إعدادات',
|
||||
'show_alerts_in_menu' => 'Show alerts in top menu',
|
||||
'show_archived_in_list' => 'Archived Assets',
|
||||
'show_archived_in_list_text' => 'Show archived assets in the "all assets" listing',
|
||||
'show_images_in_email' => 'Show images in emails',
|
||||
'show_alerts_in_menu' => 'عرض التنبيهات في القائمة العلوية',
|
||||
'show_archived_in_list' => 'الأصول المحفوظة',
|
||||
'show_archived_in_list_text' => 'عرض الأصول المحفوظة في قائمة "جميع الأصول"',
|
||||
'show_images_in_email' => 'إظهار الصور في رسائل البريد الإلكتروني',
|
||||
'show_images_in_email_help' => 'Uncheck this box if your Snipe-IT installation is behind a VPN or closed network and users outside the network will not be able to load images served from this installation in their emails.',
|
||||
'site_name' => 'اسم الموقع',
|
||||
'slack_botname' => 'سلاك بوتنام',
|
||||
@@ -136,7 +136,7 @@ return array(
|
||||
'label_dimensions' => 'أبعاد التسمية (بوصة)',
|
||||
'next_auto_tag_base' => 'الزيادة التلقائية التالية',
|
||||
'page_padding' => 'هوامش الصفحة (بوصة)',
|
||||
'privacy_policy_link' => 'Link to Privacy Policy',
|
||||
'privacy_policy_link' => 'رابط سياسة الخصوصية',
|
||||
'privacy_policy' => 'سياسة الخصوصية',
|
||||
'privacy_policy_link_help' => 'If a url is included here, a link to your privacy policy will be included in the app footer and in any emails that the system sends out, in compliance with GDPR. ',
|
||||
'purge' => 'تطهير السجلات المحذوفة',
|
||||
|
||||
@@ -20,7 +20,7 @@ return array(
|
||||
'field_element_short' => 'Typ',
|
||||
'field_format' => 'Formát',
|
||||
'field_custom_format' => 'Vlastní formát',
|
||||
'field_custom_format_help' => 'This field allows you to use a regex expression for validation. It should start with "regex:" - for example, to validate that a custom field value contains a valid IMEI (15 numeric digits), you would use <code>regex:/^[0-9]{15}$/</code>.',
|
||||
'field_custom_format_help' => 'Toto pole umožňuje použít pro validaci regulární výrazy. Mělo by začínat slovem "regex:" - například pro ověření, že zadaná hodnota pole obsahuje platný IMEI (15 číslic), použijte <code>regex:/^[0-9]{15}$/</code>.',
|
||||
'required' => 'Povinné',
|
||||
'req' => 'Pov.',
|
||||
'used_by_models' => 'Užito u modelů',
|
||||
|
||||
@@ -5,7 +5,7 @@ return array(
|
||||
'ad_domain' => 'Doména služby Active Directory',
|
||||
'ad_domain_help' => 'Toto je někdy stejné jako vaše emailová doména, ale ne vždy.',
|
||||
'admin_cc_email' => 'Ve skryté kopii',
|
||||
'admin_cc_email_help' => 'If you would like to send a copy of checkin/checkout emails that are sent to users to an additional email account, enter it here. Otherwise leave this field blank.',
|
||||
'admin_cc_email_help' => 'Chcete-li poslat kopii e-mailů pro check-in / checkout, které jsou uživatelům zaslány na další e-mailový účet, zadejte je zde. V opačném případě nechte toto pole prázdné.',
|
||||
'is_ad' => 'Toto je server služby Active Directory',
|
||||
'alert_email' => 'Zasílat upozornění na',
|
||||
'alerts_enabled' => 'Upozornění zapnutá',
|
||||
@@ -26,9 +26,9 @@ return array(
|
||||
'custom_css' => 'Vlastní CSS',
|
||||
'custom_css_help' => 'Zadejte libovolné vlastní CSS, které chcete použít. Nezahrnujte <style></style> tagy.',
|
||||
'custom_forgot_pass_url' => 'Uživatelem určená URL adresa pro resetování hesla',
|
||||
'custom_forgot_pass_url_help' => 'This replaces the built-in forgotten password URL on the login screen, useful to direct people to internal or hosted LDAP password reset functionality. It will effectively disable local user forgotten password functionality.',
|
||||
'custom_forgot_pass_url_help' => 'Nahrazuje vestavěnou URL pro změnu zapomenutého hesla na přihlašovací obrazovce, slouží k přesměrování uživatelů na interní nebo hostované funkce obnovení hesla LDAP. Zablokuje přístup k funkci změny hesla lokálního uživatele.',
|
||||
'dashboard_message' => 'Hlášení na nástěnce',
|
||||
'dashboard_message_help' => 'This text will appear on the dashboard for anyone with permission to view the dashboard.',
|
||||
'dashboard_message_help' => 'Tento text se objeví na nástěnce každému, kdo má oprávnění k zobrazení nástěnky.',
|
||||
'default_currency' => 'Výchozí měna',
|
||||
'default_eula_text' => 'Výchozí EULA',
|
||||
'default_language' => 'Výchozí jazyk',
|
||||
@@ -43,7 +43,7 @@ return array(
|
||||
'eula_settings' => 'Nastavení EULA',
|
||||
'eula_markdown' => 'Tato EULA umožňuje <a href="https://help.github.com/articles/github-flavored-markdown/">Github markdown</a>.',
|
||||
'footer_text' => 'Další text do zápatí ',
|
||||
'footer_text_help' => 'This text will appear in the right-side footer. Links are allowed using <a href="https://help.github.com/articles/github-flavored-markdown/">Github flavored markdown</a>. Line breaks, headers, images, etc may result in unpredictable results.',
|
||||
'footer_text_help' => 'Tento text se zobrazí v pravém zápatí. Odkazy jsou povoleny pomocí <a href="https://help.github.com/articles/github-flavored-markdown/">Github flavored markdown</a>. Zalamování řádků, záhlaví, obrázky atd. mohou mít za následek nepředvídatelné výsledky.',
|
||||
'general_settings' => 'Obecné nastavení',
|
||||
'generate_backup' => 'Vytvořit zálohu',
|
||||
'header_color' => 'Barva záhlaví',
|
||||
@@ -53,7 +53,7 @@ return array(
|
||||
'ldap_integration' => 'LDAP integrace',
|
||||
'ldap_settings' => 'Nastavení LDAP',
|
||||
'ldap_login_test_help' => 'Zadejte platné LDAP uživatelské jméno a heslo ze základu rozlišeného názvu který jste určili výše a vyzkoušejte zda je LDAP přihlašování správně nastavené. NEJPRVE JE TŘEBA ULOŽIT ZMĚNĚNÉ NASTAVENÍ LDAP.',
|
||||
'ldap_login_sync_help' => 'This only tests that LDAP can sync correctly. If your LDAP Authentication query is not correct, users may still not be able to login. YOU MUST SAVE YOUR UPDATED LDAP SETTINGS FIRST.',
|
||||
'ldap_login_sync_help' => 'Otestujte, že LDAP může správně synchronizovat. Pokud ověřovací LDAP dotaz není správný, uživatelé se nemusí být schopni přihlásit. JE NUTNÉ NEJPRVE NEJDŘÍVE ULOŽIT NASTAVENÍ LDAP POKUD BYLO ZMĚNĚNO.',
|
||||
'ldap_server' => 'LDAP server',
|
||||
'ldap_server_help' => 'Toto by mělo začít s ldap: // (pro nešifrované nebo TLS) nebo ldaps: // (pro SSL)',
|
||||
'ldap_server_cert' => 'Validace certifikátů LDAP SSL',
|
||||
@@ -86,10 +86,10 @@ return array(
|
||||
'login_common_disabled_text' => 'Vypnout ostatní způsoby ověřování',
|
||||
'login_common_disabled_help' => 'Tato volba vypne ostatní způsoby ověřování. Použijte ji pouze pokud jste si jistí, že už funguje přihlašování REMOTE_USER',
|
||||
'login_remote_user_custom_logout_url_text' => 'Uživatelsky určená URL adresa odhlašování',
|
||||
'login_remote_user_custom_logout_url_help' => 'If a url is provided here, users will get redirected to this URL after the user logs out of Snipe-IT. This is useful to close the user sessions of your Authentication provider correctly.',
|
||||
'login_remote_user_custom_logout_url_help' => 'Pokud je zde uvedena adresa URL, uživatelé budou po odhlášení ze Snipe-IT přesměrování na tuto URL. To je užitečné pro správné ukončení relací Authentication providera.',
|
||||
'logo' => 'Logo',
|
||||
'logo_print_assets' => 'Use in Print',
|
||||
'logo_print_assets_help' => 'Use branding on printable asset lists ',
|
||||
'logo_print_assets' => 'Použijte v tisku',
|
||||
'logo_print_assets_help' => 'Používat branding na seznamech k tisku ',
|
||||
'full_multiple_companies_support_help_text' => 'Omezení uživatelů (včetně správců) jsou přiřazená ke společnostem s majetkem společnosti.',
|
||||
'full_multiple_companies_support_text' => 'Plná podpora více společností',
|
||||
'show_in_model_list' => 'Zobrazit v rozbalovacích nabídkách modelu',
|
||||
@@ -120,10 +120,10 @@ return array(
|
||||
'slack_integration' => 'Nastavení Slack',
|
||||
'slack_integration_help' => 'Slack integrace je dobrovolná, nicméně pokud ho chcete používat jsou vyžadovány koncový bod a kanál. Chcete-li nakonfigurovat integraci Slack, nejprve <a href=":slack_link" target="_new"> ytvořte příchozí webhook</a> na vašem Slack účtu.',
|
||||
'slack_integration_help_button' => 'Po uložení informací ke Slack se zobrazí tlačítko pro vyzkoušení.',
|
||||
'slack_test_help' => 'Test whether your Slack integration is configured correctly. YOU MUST SAVE YOUR UPDATED SLACK SETTINGS FIRST.',
|
||||
'slack_test_help' => 'Zkontrolujte, zda je správně nakonfigurována integrace Slack. MUSÍTE NEJDŘÍVE ULOŽIT NASTAVENÍ SLACK POKUD BYLO ZMĚNĚNO.',
|
||||
'snipe_version' => 'Verze Snipe-IT',
|
||||
'support_footer' => 'Odkazy v zápatí na podporu ',
|
||||
'support_footer_help' => 'Specify who sees the links to the Snipe-IT Support info and Users Manual',
|
||||
'support_footer_help' => 'Určete, kdo uvidí odkazy na Snipe-IT podporu a uživatelskou příručku',
|
||||
'version_footer' => 'Verze v zápatí ',
|
||||
'version_footer_help' => 'Určete kdo uvidí verzi Snipe-IT a číslo sestavení.',
|
||||
'system' => 'Systémové informace',
|
||||
@@ -182,6 +182,6 @@ return array(
|
||||
'vertical' => 'svislé',
|
||||
'horizontal' => 'vodorovné',
|
||||
'unique_serial' => 'Neopakující se sériová čísla',
|
||||
'unique_serial_help_text' => 'Checking this box will enforce a uniqueness constraint on asset serials',
|
||||
'unique_serial_help_text' => 'Zaškrtnutím tohoto políčka bude vynucena jedinečnost seriových čísel položek majetku',
|
||||
'zerofill_count' => 'Délka značek majetku včetně zerofill',
|
||||
);
|
||||
|
||||
@@ -6,7 +6,7 @@ return array(
|
||||
'create' => 'Vytvořit označení stavu',
|
||||
'color' => 'Barva grafu',
|
||||
'default_label' => 'Výchozí štítek',
|
||||
'default_label_help' => 'This is used to ensure your most commonly used status labels appear at the top of the select box when creating/editing assets.',
|
||||
'default_label_help' => 'Toto se používá k zajištění zobrazení nejčastěji používaných štítků v horní části rozbalovacího pole, při vytváření nebo úpravách položek majetku.',
|
||||
'deployable' => 'Připraveno k nasazení',
|
||||
'info' => 'Označení stavu se používá k popisu různých stavů majetku. Můžou být v opravě, ztracení atd. Lze vytvořit nové stavy pro další možné stavy.',
|
||||
'name' => 'Název stavu',
|
||||
|
||||
@@ -19,9 +19,9 @@ return array(
|
||||
'confirm' => 'Opravdu si přejete odstranit tohoto dodavatele?',
|
||||
'error' => 'Vyskytl se problém při mazání dodavatele. Zkuste to prosím znovu.',
|
||||
'success' => 'Dodavatel byl úspěšně smazán.',
|
||||
'assoc_assets' => 'This supplier is currently associated with :asset_count asset(s) and cannot be deleted. Please update your assets to no longer reference this supplier and try again. ',
|
||||
'assoc_licenses' => 'This supplier is currently associated with :licenses_count licences(s) and cannot be deleted. Please update your licenses to no longer reference this supplier and try again. ',
|
||||
'assoc_maintenances' => 'This supplier is currently associated with :asset_maintenances_count asset maintenances(s) and cannot be deleted. Please update your asset maintenances to no longer reference this supplier and try again. ',
|
||||
'assoc_assets' => 'Tento dodavatel je v současné době přiřazen k :asset_count položkám majetku a nelze jej smazat. Aktualizujte svůj majetek tak, aby již tento dodavatel nebyl přiřazen a zkuste to znovu. ',
|
||||
'assoc_licenses' => 'Tento dodavatel je v současné době spojen s :licenses_count licencemi a nelze jej smazat. Aktualizujte prosím své licence, abyste již tento dodavatel nebyl přiřazen a zkuste to znovu. ',
|
||||
'assoc_maintenances' => 'Tento dodavatel je v současné době spojen s údržbou :asset_maintenances_count položek majetku a nemůže být smazán. Aktualizujte prosím údržbu vašeho majetku, aby již tento dodavatel nebyl přiřazen a zkuste to znovu. ',
|
||||
)
|
||||
|
||||
);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user