Compare commits
177 Commits
v3.5.2
...
v4.0-alpha
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
08ef78356d | ||
|
|
47ac59abef | ||
|
|
265a896211 | ||
|
|
f7e4fca70d | ||
|
|
bb4c443cd9 | ||
|
|
7b1d2ee050 | ||
|
|
b3f70a046f | ||
|
|
734e87f85f | ||
|
|
f371c5fd62 | ||
|
|
4b3edbd2f5 | ||
|
|
1f3106b9da | ||
|
|
9fd3a9a82d | ||
|
|
a6e6991a2d | ||
|
|
93ba0717d8 | ||
|
|
a8839e0ef4 | ||
|
|
3e4152c966 | ||
|
|
1bf34d73f5 | ||
|
|
d1e360d64d | ||
|
|
3b5b19848c | ||
|
|
93ba90e837 | ||
|
|
dd28c5709e | ||
|
|
fc70d79a17 | ||
|
|
42fe481f71 | ||
|
|
95f1a98b96 | ||
|
|
6f1e0d6d9f | ||
|
|
ae66bba0f1 | ||
|
|
32c5a258a7 | ||
|
|
e7ac860f77 | ||
|
|
899a991a3b | ||
|
|
f26d86dff2 | ||
|
|
84317f7f50 | ||
|
|
65016a2383 | ||
|
|
eb48e5ed1c | ||
|
|
dbcb2ccb46 | ||
|
|
927a12f78d | ||
|
|
dd52b4828c | ||
|
|
6273e313bc | ||
|
|
2afcfcc87c | ||
|
|
1afef9416a | ||
|
|
77685fd52b | ||
|
|
f532abebd4 | ||
|
|
6f9a82f4ea | ||
|
|
4049143ebf | ||
|
|
4df53bdf8d | ||
|
|
d49a1ea304 | ||
|
|
521f4facd5 | ||
|
|
b4653dfc15 | ||
|
|
659d9c10ca | ||
|
|
2ab0594530 | ||
|
|
8a81b29901 | ||
|
|
93d9a6e4bb | ||
|
|
99e79a02d6 | ||
|
|
47c77fe042 | ||
|
|
e42da293ee | ||
|
|
a2ffe77d55 | ||
|
|
a7a9f027fb | ||
|
|
e587b2dcee | ||
|
|
c3b4342df4 | ||
|
|
5a7ea0e908 | ||
|
|
59617cc7d3 | ||
|
|
1be22cf051 | ||
|
|
e62f3f9fb4 | ||
|
|
7ccef51a4f | ||
|
|
4c418bf622 | ||
|
|
16cfdbaa93 | ||
|
|
3f8f6ad981 | ||
|
|
d8d800bb7a | ||
|
|
5bca1ed2b6 | ||
|
|
68b9ffb908 | ||
|
|
d03c167d3b | ||
|
|
2ec7c0bf1d | ||
|
|
7513c99dd0 | ||
|
|
6c366eb112 | ||
|
|
820d37cabb | ||
|
|
b614470b21 | ||
|
|
ce056c39e5 | ||
|
|
b6ffb8b3df | ||
|
|
f5e100a6a5 | ||
|
|
abcc01f5e0 | ||
|
|
4dbe8fad30 | ||
|
|
7bf1664b8f | ||
|
|
92ace8582d | ||
|
|
507040976a | ||
|
|
b0d8711002 | ||
|
|
227ac94aa2 | ||
|
|
53404f3d1c | ||
|
|
f605821143 | ||
|
|
cab331f3f8 | ||
|
|
eb340b0fa9 | ||
|
|
3acc4065ce | ||
|
|
2ce67e9443 | ||
|
|
263f19bdad | ||
|
|
4fc88f673d | ||
|
|
c72954b671 | ||
|
|
dbb2b62223 | ||
|
|
7393f0bbea | ||
|
|
2603488bd6 | ||
|
|
81a0e06c40 | ||
|
|
0d6b160b61 | ||
|
|
16a24b7fb8 | ||
|
|
ba23952852 | ||
|
|
4c08331c9d | ||
|
|
cc943e22db | ||
|
|
6bb5555a73 | ||
|
|
3592bdb2e1 | ||
|
|
b8cbf0022e | ||
|
|
dd3718489a | ||
|
|
7214920563 | ||
|
|
8c549c47e4 | ||
|
|
45c789021e | ||
|
|
1d2ae84572 | ||
|
|
54dec2147c | ||
|
|
bc84f80e20 | ||
|
|
ac9fd3b3bb | ||
|
|
d8eb68af83 | ||
|
|
dcc000284f | ||
|
|
d0d9d82579 | ||
|
|
54848b5edf | ||
|
|
eb4562a28b | ||
|
|
e8f45555ff | ||
|
|
554a6e4fd6 | ||
|
|
7efe3a3207 | ||
|
|
f77cb3d0f5 | ||
|
|
55ccc000eb | ||
|
|
19592814d9 | ||
|
|
5c70898dbf | ||
|
|
08c7701f17 | ||
|
|
d722ed3823 | ||
|
|
84e06f4642 | ||
|
|
2ef4b58a8c | ||
|
|
91caba05b7 | ||
|
|
37a6599978 | ||
|
|
cbabcb9197 | ||
|
|
369715b7c7 | ||
|
|
e74a0171a6 | ||
|
|
b854689d3d | ||
|
|
1543c03624 | ||
|
|
7667fca691 | ||
|
|
9db28cf6d6 | ||
|
|
2ddee9b44c | ||
|
|
49ce630bb8 | ||
|
|
10d37abe6c | ||
|
|
2f05b83e0b | ||
|
|
f4fc783026 | ||
|
|
96ad5fb77b | ||
|
|
4747a4c03f | ||
|
|
af97d8ed24 | ||
|
|
a914dacf8e | ||
|
|
a182d8c924 | ||
|
|
6400557901 | ||
|
|
26d14b2338 | ||
|
|
3dac20c20f | ||
|
|
429afc6b3f | ||
|
|
8323ed27c2 | ||
|
|
c47d391946 | ||
|
|
25bd1acab5 | ||
|
|
7c6bdcb6b2 | ||
|
|
13450aa961 | ||
|
|
0595867500 | ||
|
|
a4ae3b0091 | ||
|
|
cbfcf959f9 | ||
|
|
e065d18227 | ||
|
|
adc3ebee41 | ||
|
|
41defb312b | ||
|
|
10ea5daabd | ||
|
|
140bac2b53 | ||
|
|
dce5afde78 | ||
|
|
38b188f6ff | ||
|
|
fe041b66c6 | ||
|
|
32c439d979 | ||
|
|
62f5a1b2c7 | ||
|
|
2fe71f3ebc | ||
|
|
9b714a5af5 | ||
|
|
408aab112b | ||
|
|
2f6fcadd05 | ||
|
|
cea255995c | ||
|
|
3a8edfdf58 |
15
.env.example
15
.env.example
@@ -20,6 +20,16 @@ DB_PASSWORD=null
|
||||
DB_PREFIX=null
|
||||
DB_DUMP_PATH='/usr/bin'
|
||||
|
||||
# --------------------------------------------
|
||||
# OPTIONAL: SSL DATABASE SETTINGS
|
||||
# --------------------------------------------
|
||||
DB_SSL=false
|
||||
DB_SSL_KEY_PATH=null
|
||||
DB_SSL_CERT_PATH=null
|
||||
DB_SSL_CA_PATH=null
|
||||
DB_SSL_CIPHER=null
|
||||
|
||||
|
||||
# --------------------------------------------
|
||||
# REQUIRED: OUTGOING MAIL SERVER SETTINGS
|
||||
# --------------------------------------------
|
||||
@@ -69,6 +79,11 @@ AWS_KEY=null
|
||||
AWS_REGION=null
|
||||
AWS_BUCKET=null
|
||||
|
||||
# --------------------------------------------
|
||||
# OPTIONAL: LOGIN THROTTLING
|
||||
# --------------------------------------------
|
||||
LOGIN_MAX_ATTEMPTS=5
|
||||
LOGIN_LOCKOUT_DURATION=60
|
||||
|
||||
# --------------------------------------------
|
||||
# OPTIONAL: MISC
|
||||
|
||||
9
.env.tests
Normal file
9
.env.tests
Normal file
@@ -0,0 +1,9 @@
|
||||
APP_ENV=local
|
||||
APP_DEBUG=true
|
||||
APP_URL=http://snipe-it.localapp
|
||||
DB_CONNECTION=mysql
|
||||
DB_HOST=localhost
|
||||
DB_DATABASE=snipeittests
|
||||
DB_USERNAME=snipeit
|
||||
DB_PASSWORD=snipe
|
||||
APP_KEY=base64:tu9NRh/a6+dCXBDGvg0Gv/0TcABnFsbT4AKxrr8mwQo=
|
||||
4
.github/ISSUE_TEMPLATE.md
vendored
4
.github/ISSUE_TEMPLATE.md
vendored
@@ -13,7 +13,7 @@
|
||||
#### Please confirm you have done the following before posting your bug report:
|
||||
|
||||
- [ ] I have enabled debug mode
|
||||
- [ ] I have read [checked the Common Issues page](http://docs.snipeitapp.com/common-issues.html)
|
||||
- [ ] I have read [checked the Common Issues page](https://snipe-it.readme.io/docs/common-issues)
|
||||
|
||||
-----
|
||||
#### Please provide answers to these questions before posting your bug report:
|
||||
@@ -21,7 +21,7 @@
|
||||
- Version of Snipe-IT you're running
|
||||
- What OS and web server you're running Snipe-IT on
|
||||
- What method you used to install Snipe-IT (install.sh, manual installation, docker, etc)
|
||||
- If you're getting an error in your browser, include that error
|
||||
- WITH DEBUG TURNED ON, if you're getting an error in your browser, include that error
|
||||
- What specific Snipe-IT page you're on, and what specific element you're interacting with to trigger the error
|
||||
- If a stacktrace is provided in the error, include that too.
|
||||
- Any errors that appear in your browser's error console.
|
||||
|
||||
3
.gitignore
vendored
3
.gitignore
vendored
@@ -37,3 +37,6 @@ storage/private_uploads/users/*
|
||||
tests/_data/scenarios
|
||||
tests/_output/*
|
||||
tests/_support/_generated/*
|
||||
/npm-debug.log
|
||||
/storage/oauth-private.key
|
||||
/storage/oauth-public.key
|
||||
|
||||
74
CODE_OF_CONDUCT.md
Normal file
74
CODE_OF_CONDUCT.md
Normal file
@@ -0,0 +1,74 @@
|
||||
# Contributor Covenant Code of Conduct
|
||||
|
||||
## Our Pledge
|
||||
|
||||
In the interest of fostering an open and welcoming environment, we as
|
||||
contributors and maintainers pledge to making participation in our project and
|
||||
our community a harassment-free experience for everyone, regardless of age, body
|
||||
size, disability, ethnicity, gender identity and expression, level of experience,
|
||||
nationality, personal appearance, race, religion, or sexual identity and
|
||||
orientation.
|
||||
|
||||
## Our Standards
|
||||
|
||||
Examples of behavior that contributes to creating a positive environment
|
||||
include:
|
||||
|
||||
* Using welcoming and inclusive language
|
||||
* Being respectful of differing viewpoints and experiences
|
||||
* Gracefully accepting constructive criticism
|
||||
* Focusing on what is best for the community
|
||||
* Showing empathy towards other community members
|
||||
|
||||
Examples of unacceptable behavior by participants include:
|
||||
|
||||
* The use of sexualized language or imagery and unwelcome sexual attention or
|
||||
advances
|
||||
* Trolling, insulting/derogatory comments, and personal or political attacks
|
||||
* Public or private harassment
|
||||
* Publishing others' private information, such as a physical or electronic
|
||||
address, without explicit permission
|
||||
* Other conduct which could reasonably be considered inappropriate in a
|
||||
professional setting
|
||||
|
||||
## Our Responsibilities
|
||||
|
||||
Project maintainers are responsible for clarifying the standards of acceptable
|
||||
behavior and are expected to take appropriate and fair corrective action in
|
||||
response to any instances of unacceptable behavior.
|
||||
|
||||
Project maintainers have the right and responsibility to remove, edit, or
|
||||
reject comments, commits, code, wiki edits, issues, and other contributions
|
||||
that are not aligned to this Code of Conduct, or to ban temporarily or
|
||||
permanently any contributor for other behaviors that they deem inappropriate,
|
||||
threatening, offensive, or harmful.
|
||||
|
||||
## Scope
|
||||
|
||||
This Code of Conduct applies both within project spaces and in public spaces
|
||||
when an individual is representing the project or its community. Examples of
|
||||
representing a project or community include using an official project e-mail
|
||||
address, posting via an official social media account, or acting as an appointed
|
||||
representative at an online or offline event. Representation of a project may be
|
||||
further defined and clarified by project maintainers.
|
||||
|
||||
## Enforcement
|
||||
|
||||
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
||||
reported by contacting the project team at [INSERT EMAIL ADDRESS]. All
|
||||
complaints will be reviewed and investigated and will result in a response that
|
||||
is deemed necessary and appropriate to the circumstances. The project team is
|
||||
obligated to maintain confidentiality with regard to the reporter of an incident.
|
||||
Further details of specific enforcement policies may be posted separately.
|
||||
|
||||
Project maintainers who do not follow or enforce the Code of Conduct in good
|
||||
faith may face temporary or permanent repercussions as determined by other
|
||||
members of the project's leadership.
|
||||
|
||||
## Attribution
|
||||
|
||||
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
|
||||
available at [http://contributor-covenant.org/version/1/4][version]
|
||||
|
||||
[homepage]: http://contributor-covenant.org
|
||||
[version]: http://contributor-covenant.org/version/1/4/
|
||||
15
Dockerfile
15
Dockerfile
@@ -1,4 +1,4 @@
|
||||
FROM ubuntu:trusty
|
||||
FROM debian:jessie-slim
|
||||
MAINTAINER Brady Wetherington <uberbrady@gmail.com>
|
||||
|
||||
RUN apt-get update && apt-get install -y \
|
||||
@@ -13,7 +13,9 @@ patch \
|
||||
curl \
|
||||
vim \
|
||||
git \
|
||||
mysql-client
|
||||
mysql-client \
|
||||
&& apt-get clean \
|
||||
&& rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
|
||||
|
||||
RUN php5enmod mcrypt
|
||||
RUN php5enmod gd
|
||||
@@ -54,12 +56,9 @@ COPY docker/docker.env /var/www/html/.env
|
||||
RUN chown -R docker /var/www/html
|
||||
|
||||
RUN \
|
||||
rm -r "/var/www/html/storage/private_uploads" && ln -fs "/var/lib/snipeit/data/private_uploads" "/var/www/html/storage/private_uploads" && \
|
||||
mkdir -p "/var/www/html/public/uploads" && \
|
||||
rm -rf "/var/www/html/public/uploads/avatars" && ln -fs "/var/lib/snipeit/data/uploads/avatars" "/var/www/html/public/uploads/avatars" && \
|
||||
rm -rf "/var/www/html/public/uploads/models" && ln -fs "/var/lib/snipeit/data/uploads/models" "/var/www/html/public/uploads/models" && \
|
||||
rm -rf "/var/www/html/public/uploads/suppliers" && ln -fs "/var/lib/snipeit/data/uploads/suppliers" "/var/www/html/public/uploads/suppliers" && \
|
||||
rm -r "/var/www/html/storage/app/backups" && ln -fs "/var/lib/snipeit/dumps" "/var/www/html/storage/app/backups"
|
||||
rm -r "/var/www/html/storage/private_uploads" && ln -fs "/var/lib/snipeit/data/private_uploads" "/var/www/html/storage/private_uploads" \
|
||||
&& rm -rf "/var/www/html/public/uploads" && ln -fs "/var/lib/snipeit/data/uploads" "/var/www/html/public/uploads" \
|
||||
&& rm -r "/var/www/html/storage/app/backups" && ln -fs "/var/lib/snipeit/dumps" "/var/www/html/storage/app/backups"
|
||||
|
||||
############## DEPENDENCIES via COMPOSER ###################
|
||||
|
||||
|
||||
@@ -53,3 +53,7 @@ Please see the documentation on [contributing and developing for Snipe-IT](https
|
||||
|
||||
|
||||
Please note that this project is released with a [Contributor Code of Conduct](CODE_OF_CONDUCT.md). By participating in this project you agree to abide by its terms.
|
||||
|
||||
### Security
|
||||
|
||||
To report a security vulnerability, please email security@snipeitapp.com instead of using the issue tracker.
|
||||
|
||||
164
app/Console/Commands/LdapSync.php
Normal file
164
app/Console/Commands/LdapSync.php
Normal file
@@ -0,0 +1,164 @@
|
||||
<?php
|
||||
|
||||
namespace App\Console\Commands;
|
||||
|
||||
use Illuminate\Console\Command;
|
||||
use App\Models\Setting;
|
||||
use App\Models\Ldap;
|
||||
use App\Models\User;
|
||||
use App\Models\Location;
|
||||
use Log;
|
||||
|
||||
class LdapSync extends Command
|
||||
{
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'snipeit:ldap-sync {--location=} {--location_id=} {--summary}';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Command line LDAP sync';
|
||||
|
||||
/**
|
||||
* Create a new command instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
ini_set('max_execution_time', 600); //600 seconds = 10 minutes
|
||||
ini_set('memory_limit', '500M');
|
||||
|
||||
$ldap_result_username = Setting::getSettings()->ldap_username_field;
|
||||
$ldap_result_last_name = Setting::getSettings()->ldap_lname_field;
|
||||
$ldap_result_first_name = Setting::getSettings()->ldap_fname_field;
|
||||
|
||||
$ldap_result_active_flag = Setting::getSettings()->ldap_active_flag_field;
|
||||
$ldap_result_emp_num = Setting::getSettings()->ldap_emp_num;
|
||||
$ldap_result_email = Setting::getSettings()->ldap_email;
|
||||
|
||||
try {
|
||||
$ldapconn = Ldap::connectToLdap();
|
||||
} catch (\Exception $e) {
|
||||
LOG::error($e);
|
||||
}
|
||||
|
||||
try {
|
||||
Ldap::bindAdminToLdap($ldapconn);
|
||||
} catch (\Exception $e) {
|
||||
LOG::error($e);
|
||||
}
|
||||
|
||||
$summary = array();
|
||||
|
||||
$results = Ldap::findLdapUsers();
|
||||
|
||||
if ($this->option('location')!='') {
|
||||
$location = Location::where('name','=',$this->option('location'))->first();
|
||||
LOG::debug('Location name '.$this->option('location').' passed');
|
||||
LOG::debug('Importing to '.$location->name.' ('.$location->id.')');
|
||||
} elseif ($this->option('location_id')!='') {
|
||||
$location = Location::where('id','=',$this->option('location_id'))->first();
|
||||
LOG::debug('Location ID '.$this->option('location_id').' passed');
|
||||
LOG::debug('Importing to '.$location->name.' ('.$location->id.')');
|
||||
} else {
|
||||
$location = new Location;
|
||||
}
|
||||
|
||||
if (!isset($location)) {
|
||||
LOG::debug('That location is invalid, so no location will be assigned.');
|
||||
}
|
||||
|
||||
|
||||
$tmp_pass = substr(str_shuffle("0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"), 0, 20);
|
||||
$pass = bcrypt($tmp_pass);
|
||||
|
||||
|
||||
for ($i = 0; $i < $results["count"]; $i++) {
|
||||
if (empty($ldap_result_active_flag) || $results[$i][$ldap_result_active_flag][0] == "TRUE") {
|
||||
|
||||
$item = array();
|
||||
$item["username"] = isset($results[$i][$ldap_result_username][0]) ? $results[$i][$ldap_result_username][0] : "";
|
||||
$item["employee_number"] = isset($results[$i][$ldap_result_emp_num][0]) ? $results[$i][$ldap_result_emp_num][0] : "";
|
||||
$item["lastname"] = isset($results[$i][$ldap_result_last_name][0]) ? $results[$i][$ldap_result_last_name][0] : "";
|
||||
$item["firstname"] = isset($results[$i][$ldap_result_first_name][0]) ? $results[$i][$ldap_result_first_name][0] : "";
|
||||
$item["email"] = isset($results[$i][$ldap_result_email][0]) ? $results[$i][$ldap_result_email][0] : "" ;
|
||||
|
||||
// User exists
|
||||
$item["createorupdate"] = 'updated';
|
||||
if (!$user = User::where('username', $item["username"])->first()) {
|
||||
$user = new User;
|
||||
$user->password = $pass;
|
||||
$item["createorupdate"] = 'created';
|
||||
}
|
||||
|
||||
// Create the user if they don't exist.
|
||||
|
||||
|
||||
$user->first_name = e($item["firstname"]);
|
||||
$user->last_name = e($item["lastname"]);
|
||||
$user->username = e($item["username"]);
|
||||
$user->email = e($item["email"]);
|
||||
$user->employee_num = e($item["employee_number"]);
|
||||
$user->activated = 1;
|
||||
|
||||
if ($location) {
|
||||
$user->location_id = e($location->id);
|
||||
}
|
||||
|
||||
$user->notes = 'Imported from LDAP';
|
||||
$user->ldap_import = 1;
|
||||
|
||||
$errors = '';
|
||||
|
||||
if ($user->save()) {
|
||||
$item["note"] = $item["createorupdate"];
|
||||
$item["status"]='success';
|
||||
} else {
|
||||
foreach ($user->getErrors()->getMessages() as $key => $err) {
|
||||
$errors .= $err[0];
|
||||
}
|
||||
$item["note"] = $errors;
|
||||
$item["status"]='error';
|
||||
}
|
||||
|
||||
array_push($summary, $item);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if ($this->option('summary')) {
|
||||
for ($x = 0; $x < count($summary); $x++) {
|
||||
if ($summary[$x]['status']=='error') {
|
||||
$this->error('ERROR: '.$summary[$x]['firstname'].' '.$summary[$x]['lastname'].' (username: '.$summary[$x]['username'].' was not imported: '.$summary[$x]['note'] );
|
||||
} else {
|
||||
$this->info('User '.$summary[$x]['firstname'].' '.$summary[$x]['lastname'].' (username: '.$summary[$x]['username'].' was '.strtoupper($summary[$x]['createorupdate']).'.');
|
||||
}
|
||||
|
||||
}
|
||||
} else {
|
||||
return $summary;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -100,7 +100,7 @@ class ObjectImportCommand extends Command
|
||||
$this->locations = Location::All(['name', 'id']);
|
||||
$this->categories = Category::All(['name', 'category_type', 'id']);
|
||||
$this->manufacturers = Manufacturer::All(['name', 'id']);
|
||||
$this->asset_models = AssetModel::All(['name','modelno','category_id','manufacturer_id', 'id']);
|
||||
$this->asset_models = AssetModel::All(['name','model_number','category_id','manufacturer_id', 'id']);
|
||||
$this->companies = Company::All(['name', 'id']);
|
||||
$this->status_labels = Statuslabel::All(['name', 'id']);
|
||||
$this->suppliers = Supplier::All(['name', 'id']);
|
||||
@@ -348,7 +348,7 @@ class ObjectImportCommand extends Command
|
||||
$editingModel = false;
|
||||
foreach ($this->asset_models as $tempmodel) {
|
||||
if (strcasecmp($tempmodel->name, $asset_model_name) == 0
|
||||
&& $tempmodel->modelno == $asset_modelno) {
|
||||
&& $tempmodel->model_number == $asset_modelno) {
|
||||
$this->log('A matching model ' . $asset_model_name . ' already exists');
|
||||
if (!$this->option('update')) {
|
||||
return $tempmodel;
|
||||
@@ -366,7 +366,7 @@ class ObjectImportCommand extends Command
|
||||
$asset_model->name = $asset_model_name;
|
||||
}
|
||||
isset($manufacturer) && $manufacturer->exists && $asset_model->manufacturer_id = $manufacturer->id;
|
||||
isset($asset_modelno) && $asset_model->modelno = $asset_modelno;
|
||||
isset($asset_modelno) && $asset_model->model_number = $asset_modelno;
|
||||
if (isset($category) && $category->exists) {
|
||||
$asset_model->category_id = $category->id;
|
||||
}
|
||||
|
||||
@@ -40,20 +40,19 @@ class Versioning extends Command
|
||||
*/
|
||||
public function fire()
|
||||
{
|
||||
// Path to the file containing your version
|
||||
// This will be overwritten everything you commit a message
|
||||
|
||||
$versionFile = 'config/version.php';
|
||||
$hash_version = str_replace("\n",'',shell_exec('git describe --tags'));
|
||||
|
||||
// The git's output
|
||||
// get the argument passed in the git command
|
||||
$hash_version = $this->argument('app_version');
|
||||
$version = explode('-', $hash_version);
|
||||
|
||||
// discard the commit hash
|
||||
$version = explode('-', $hash_version);
|
||||
$realVersion = $version[0];
|
||||
|
||||
// save the version array to a variable
|
||||
$array = var_export(array('app_version' => $realVersion,'hash_version' => $hash_version), true);
|
||||
$array = var_export(
|
||||
array(
|
||||
'app_version' => $version[0],
|
||||
'build_version' => $version[1],
|
||||
'hash_version' => $version[2],
|
||||
'full_hash' => $hash_version),
|
||||
true);
|
||||
|
||||
|
||||
// Construct our file content
|
||||
@@ -64,7 +63,7 @@ CON;
|
||||
|
||||
// And finally write the file and output the current version
|
||||
\File::put($versionFile, $content);
|
||||
$this->line('Setting version: '. \config('version.latest'));
|
||||
$this->line('Setting version: '. config('version.app_version').' build '.config('version.build_version').' ('.config('version.hash_version').')');
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -75,7 +74,6 @@ CON;
|
||||
protected function getArguments()
|
||||
{
|
||||
return array(
|
||||
array('app_version', InputArgument::REQUIRED, 'version number is required.'),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -23,6 +23,7 @@ class Kernel extends ConsoleKernel
|
||||
Commands\SystemBackup::class,
|
||||
Commands\DisableLDAP::class,
|
||||
Commands\Purge::class,
|
||||
Commands\LdapSync::class,
|
||||
];
|
||||
|
||||
/**
|
||||
|
||||
@@ -434,8 +434,8 @@ class Helper
|
||||
foreach ($consumables as $consumable) {
|
||||
$avail = $consumable->numRemaining();
|
||||
if ($avail < ($consumable->min_amt) + \App\Models\Setting::getSettings()->alert_threshold) {
|
||||
if ($consumable->total_qty > 0) {
|
||||
$percent = number_format((($consumable->numRemaining() / $consumable->total_qty) * 100), 0);
|
||||
if ($consumable->qty > 0) {
|
||||
$percent = number_format((($consumable->numRemaining() / $consumable->qty) * 100), 0);
|
||||
} else {
|
||||
$percent = 100;
|
||||
}
|
||||
@@ -456,8 +456,8 @@ class Helper
|
||||
$avail = $accessory->numRemaining();
|
||||
if ($avail < ($accessory->min_amt) + \App\Models\Setting::getSettings()->alert_threshold) {
|
||||
|
||||
if ($accessory->total_qty > 0) {
|
||||
$percent = number_format((($accessory->numRemaining() / $accessory->total_qty) * 100), 0);
|
||||
if ($accessory->qty > 0) {
|
||||
$percent = number_format((($accessory->numRemaining() / $accessory->qty) * 100), 0);
|
||||
} else {
|
||||
$percent = 100;
|
||||
}
|
||||
@@ -476,8 +476,8 @@ class Helper
|
||||
foreach ($components as $component) {
|
||||
$avail = $component->numRemaining();
|
||||
if ($avail < ($component->min_amt) + \App\Models\Setting::getSettings()->alert_threshold) {
|
||||
if ($component->total_qty > 0) {
|
||||
$percent = number_format((($component->numRemaining() / $component->total_qty) * 100), 0);
|
||||
if ($component->qty > 0) {
|
||||
$percent = number_format((($component->numRemaining() / $component->qty) * 100), 0);
|
||||
} else {
|
||||
$percent = 100;
|
||||
}
|
||||
|
||||
@@ -7,19 +7,19 @@ use App\Models\Actionlog;
|
||||
use App\Models\Company;
|
||||
use App\Models\Setting;
|
||||
use App\Models\User;
|
||||
use Auth;
|
||||
use Carbon\Carbon;
|
||||
use Config;
|
||||
use DB;
|
||||
use Gate;
|
||||
use Input;
|
||||
use Lang;
|
||||
use Mail;
|
||||
use Redirect;
|
||||
use Request;
|
||||
use Slack;
|
||||
use Str;
|
||||
use View;
|
||||
use Auth;
|
||||
use Request;
|
||||
use Gate;
|
||||
|
||||
/** This controller handles all actions related to Accessories for
|
||||
* the Snipe-IT Asset Management application.
|
||||
@@ -54,7 +54,7 @@ class AccessoriesController extends Controller
|
||||
{
|
||||
// Show the page
|
||||
return View::make('accessories/edit')
|
||||
->with('accessory', new Accessory)
|
||||
->with('item', new Accessory)
|
||||
->with('category_list', Helper::categoryList('accessory'))
|
||||
->with('company_list', Helper::companyList())
|
||||
->with('location_list', Helper::locationsList())
|
||||
@@ -82,6 +82,7 @@ class AccessoriesController extends Controller
|
||||
$accessory->company_id = Company::getIdForCurrentUser(Input::get('company_id'));
|
||||
$accessory->order_number = e(Input::get('order_number'));
|
||||
$accessory->manufacturer_id = e(Input::get('manufacturer_id'));
|
||||
$accessory->model_number = e(Input::get('model_number'));
|
||||
|
||||
if (e(Input::get('purchase_date')) == '') {
|
||||
$accessory->purchase_date = null;
|
||||
@@ -119,14 +120,14 @@ class AccessoriesController extends Controller
|
||||
public function getEdit(Request $request, $accessoryId = null)
|
||||
{
|
||||
// Check if the accessory exists
|
||||
if (is_null($accessory = Accessory::find($accessoryId))) {
|
||||
if (is_null($item = Accessory::find($accessoryId))) {
|
||||
// Redirect to the blogs management page
|
||||
return redirect()->to('admin/accessories')->with('error', trans('admin/accessories/message.does_not_exist'));
|
||||
} elseif (!Company::isCurrentUserHasAccess($accessory)) {
|
||||
} elseif (!Company::isCurrentUserHasAccess($item)) {
|
||||
return redirect()->to('admin/accessories')->with('error', trans('general.insufficient_permissions'));
|
||||
}
|
||||
|
||||
return View::make('accessories/edit', compact('accessory'))
|
||||
return View::make('accessories/edit', compact('item'))
|
||||
->with('category_list', Helper::categoryList('accessory'))
|
||||
->with('company_list', Helper::companyList())
|
||||
->with('location_list', Helper::locationsList())
|
||||
@@ -164,6 +165,7 @@ class AccessoriesController extends Controller
|
||||
$accessory->company_id = Company::getIdForCurrentUser(Input::get('company_id'));
|
||||
$accessory->manufacturer_id = e(Input::get('manufacturer_id'));
|
||||
$accessory->order_number = e(Input::get('order_number'));
|
||||
$accessory->model_number = e(Input::get('model_number'));
|
||||
|
||||
if (e(Input::get('purchase_date')) == '') {
|
||||
$accessory->purchase_date = null;
|
||||
@@ -427,8 +429,8 @@ class AccessoriesController extends Controller
|
||||
return redirect()->to('admin/accessories')->with('error', trans('general.insufficient_permissions'));
|
||||
}
|
||||
|
||||
$logaction = $accessory->logCheckin(e(Input::get('note')));
|
||||
$return_to = e($accessory_user->assigned_to);
|
||||
$logaction = $accessory->logCheckin(User::find($return_to), e(Input::get('note')));
|
||||
$admin_user = Auth::user();
|
||||
|
||||
|
||||
@@ -530,9 +532,11 @@ class AccessoriesController extends Controller
|
||||
**/
|
||||
public function getDatatable(Request $request)
|
||||
{
|
||||
$accessories = Company::scopeCompanyables(Accessory::select('accessories.*')->with('category', 'company'))
|
||||
->whereNull('accessories.deleted_at');
|
||||
|
||||
$accessories = Company::scopeCompanyables(
|
||||
Accessory::select('accessories.*')
|
||||
->whereNull('accessories.deleted_at')
|
||||
->with('category', 'company', 'manufacturer', 'users', 'location')
|
||||
);
|
||||
if (Input::has('search')) {
|
||||
$accessories = $accessories->TextSearch(e(Input::get('search')));
|
||||
}
|
||||
@@ -550,7 +554,7 @@ class AccessoriesController extends Controller
|
||||
}
|
||||
|
||||
|
||||
$allowed_columns = ['name','min_amt','order_number','purchase_date','purchase_cost','companyName','category'];
|
||||
$allowed_columns = ['name','min_amt','order_number','purchase_date','purchase_cost','companyName','category','model_number'];
|
||||
$order = Input::get('order') === 'asc' ? 'asc' : 'desc';
|
||||
$sort = in_array(Input::get('sort'), $allowed_columns) ? e(Input::get('sort')) : 'created_at';
|
||||
|
||||
@@ -592,6 +596,7 @@ class AccessoriesController extends Controller
|
||||
$rows[] = array(
|
||||
'name' => '<a href="'.url('admin/accessories/'.$accessory->id).'/view">'. $accessory->name.'</a>',
|
||||
'category' => ($accessory->category) ? (string)link_to('admin/settings/categories/'.$accessory->category->id.'/view', $accessory->category->name) : '',
|
||||
'model_number' => e($accessory->model_number),
|
||||
'qty' => e($accessory->qty),
|
||||
'order_number' => e($accessory->order_number),
|
||||
'min_amt' => e($accessory->min_amt),
|
||||
|
||||
18
app/Http/Controllers/ActionlogController.php
Normal file
18
app/Http/Controllers/ActionlogController.php
Normal file
@@ -0,0 +1,18 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Helpers\Helper;
|
||||
use Response;
|
||||
|
||||
class ActionlogController extends Controller
|
||||
{
|
||||
public function displaySig($filename)
|
||||
{
|
||||
|
||||
$file = config('app.private_uploads') . '/signatures/' . $filename;
|
||||
$filetype = Helper::checkUploadIsImage($file);
|
||||
$contents = file_get_contents($file);
|
||||
return Response::make($contents)->header('Content-Type', $filetype);
|
||||
}
|
||||
}
|
||||
@@ -21,6 +21,7 @@ use App\Models\Setting;
|
||||
use App\Models\Asset;
|
||||
use App\Helpers\Helper;
|
||||
use Auth;
|
||||
use Gate;
|
||||
|
||||
/**
|
||||
* This controller handles all actions related to Asset Maintenance for
|
||||
@@ -75,8 +76,7 @@ class AssetMaintenancesController extends Controller
|
||||
*/
|
||||
public function getDatatable()
|
||||
{
|
||||
$maintenances = AssetMaintenance::with('asset', 'supplier', 'asset.company','admin')
|
||||
->withTrashed();
|
||||
$maintenances = AssetMaintenance::with('asset', 'supplier', 'asset.company','admin');
|
||||
|
||||
if (Input::has('search')) {
|
||||
$maintenances = $maintenances->TextSearch(e(Input::get('search')));
|
||||
@@ -119,8 +119,12 @@ class AssetMaintenancesController extends Controller
|
||||
$settings = Setting::getSettings();
|
||||
|
||||
foreach ($maintenances as $maintenance) {
|
||||
|
||||
$actions = '<nobr><a href="'.route('update/asset_maintenance', $maintenance->id).'" class="btn btn-warning btn-sm" style="margin-right:5px;"><i class="fa fa-pencil icon-white"></i></a><a data-html="false" class="btn delete-asset btn-danger btn-sm" data-toggle="modal" href="'.route('delete/asset_maintenance', $maintenance->id).'" data-content="'.trans('admin/asset_maintenances/message.delete.confirm').'" data-title="'.trans('general.delete').' '.htmlspecialchars($maintenance->title).'?" onClick="return false;"><i class="fa fa-trash icon-white"></i></a></nobr>';
|
||||
$actions = '';
|
||||
if (Gate::allows('assets.edit')) {
|
||||
$actions .= '<nobr><a href="' . route('update/asset_maintenance',
|
||||
$maintenance->id) . '" class="btn btn-warning btn-sm" style="margin-right:5px;"><i class="fa fa-pencil icon-white"></i></a><a data-html="false" class="btn delete-asset btn-danger btn-sm" data-toggle="modal" href="' . route('delete/asset_maintenance',
|
||||
$maintenance->id) . '" data-content="' . trans('admin/asset_maintenances/message.delete.confirm') . '" data-title="' . trans('general.delete') . ' ' . htmlspecialchars($maintenance->title) . '?" onClick="return false;"><i class="fa fa-trash icon-white"></i></a></nobr>';
|
||||
}
|
||||
|
||||
if (($maintenance->cost) && (isset($maintenance->asset)) && ($maintenance->asset->assetloc) && ($maintenance->asset->assetloc->currency!='')) {
|
||||
$maintenance_cost = $maintenance->asset->assetloc->currency.$maintenance->cost;
|
||||
@@ -178,7 +182,7 @@ class AssetMaintenancesController extends Controller
|
||||
->with('selectedAsset', $selectedAsset)
|
||||
->with('supplier_list', $supplier_list)
|
||||
->with('assetMaintenanceType', $assetMaintenanceType)
|
||||
->with('assetMaintenance', new AssetMaintenance);
|
||||
->with('item', new AssetMaintenance);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -317,7 +321,7 @@ class AssetMaintenancesController extends Controller
|
||||
->with('selectedAsset', null)
|
||||
->with('supplier_list', $supplier_list)
|
||||
->with('assetMaintenanceType', $assetMaintenanceType)
|
||||
->with('assetMaintenance', $assetMaintenance);
|
||||
->with('item', $assetMaintenance);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -6,11 +6,8 @@ use Input;
|
||||
use Lang;
|
||||
use App\Models\AssetModel;
|
||||
use Redirect;
|
||||
use App\Models\Setting;
|
||||
use Auth;
|
||||
use DB;
|
||||
use App\Models\Depreciation;
|
||||
use App\Models\Manufacturer;
|
||||
use Str;
|
||||
use Validator;
|
||||
use View;
|
||||
@@ -62,7 +59,7 @@ class AssetModelsController extends Controller
|
||||
->with('category_list', $category_list)
|
||||
->with('depreciation_list', $depreciation_list)
|
||||
->with('manufacturer_list', $manufacturer_list)
|
||||
->with('model', new AssetModel);
|
||||
->with('item', new AssetModel);
|
||||
}
|
||||
|
||||
|
||||
@@ -94,10 +91,10 @@ class AssetModelsController extends Controller
|
||||
|
||||
// Save the model data
|
||||
$model->name = e(Input::get('name'));
|
||||
$model->modelno = e(Input::get('modelno'));
|
||||
$model->model_number = e(Input::get('model_number'));
|
||||
$model->manufacturer_id = e(Input::get('manufacturer_id'));
|
||||
$model->category_id = e(Input::get('category_id'));
|
||||
$model->note = e(Input::get('note'));
|
||||
$model->notes = e(Input::get('notes'));
|
||||
$model->user_id = Auth::user()->id;
|
||||
$model->requestable = Input::has('requestable');
|
||||
|
||||
@@ -146,9 +143,9 @@ class AssetModelsController extends Controller
|
||||
$model->name=e(Input::get('name'));
|
||||
$model->manufacturer_id = e(Input::get('manufacturer_id'));
|
||||
$model->category_id = e(Input::get('category_id'));
|
||||
$model->modelno = e(Input::get('modelno'));
|
||||
$model->model_number = e(Input::get('model_number'));
|
||||
$model->user_id = Auth::user()->id;
|
||||
$model->note = e(Input::get('note'));
|
||||
$model->notes = e(Input::get('notes'));
|
||||
$model->eol= null;
|
||||
|
||||
if (Input::get('fieldset_id')=='') {
|
||||
@@ -176,7 +173,7 @@ class AssetModelsController extends Controller
|
||||
public function getEdit($modelId = null)
|
||||
{
|
||||
// Check if the model exists
|
||||
if (is_null($model = AssetModel::find($modelId))) {
|
||||
if (is_null($item = AssetModel::find($modelId))) {
|
||||
// Redirect to the model management page
|
||||
return redirect()->to('assets/models')->with('error', trans('admin/models/message.does_not_exist'));
|
||||
}
|
||||
@@ -184,7 +181,8 @@ class AssetModelsController extends Controller
|
||||
$depreciation_list = Helper::depreciationList();
|
||||
$manufacturer_list = Helper::manufacturerList();
|
||||
$category_list = Helper::categoryList('asset');
|
||||
$view = View::make('models/edit', compact('model'));
|
||||
|
||||
$view = View::make('models/edit', compact('item'));
|
||||
$view->with('category_list', $category_list);
|
||||
$view->with('depreciation_list', $depreciation_list);
|
||||
$view->with('manufacturer_list', $manufacturer_list);
|
||||
@@ -221,13 +219,12 @@ class AssetModelsController extends Controller
|
||||
} else {
|
||||
$model->eol = e(Input::get('eol'));
|
||||
}
|
||||
|
||||
// Update the model data
|
||||
$model->name = e(Input::get('name'));
|
||||
$model->modelno = e(Input::get('modelno'));
|
||||
$model->model_number = e(Input::get('model_number'));
|
||||
$model->manufacturer_id = e(Input::get('manufacturer_id'));
|
||||
$model->category_id = e(Input::get('category_id'));
|
||||
$model->note = e(Input::get('note'));
|
||||
$model->notes = e(Input::get('notes'));
|
||||
|
||||
$model->requestable = Input::has('requestable');
|
||||
|
||||
@@ -381,7 +378,7 @@ class AssetModelsController extends Controller
|
||||
$view->with('category_list', $category_list);
|
||||
$view->with('depreciation_list', $depreciation_list);
|
||||
$view->with('manufacturer_list', $manufacturer_list);
|
||||
$view->with('model', $model);
|
||||
$view->with('item', $model);
|
||||
$view->with('clone_model', $model_to_clone);
|
||||
return $view;
|
||||
|
||||
@@ -398,7 +395,7 @@ class AssetModelsController extends Controller
|
||||
*/
|
||||
public function getCustomFields($modelId)
|
||||
{
|
||||
$model=AssetModel::find($modelId);
|
||||
$model = AssetModel::find($modelId);
|
||||
return View::make("models.custom_fields_form")->with("model", $model);
|
||||
}
|
||||
|
||||
@@ -416,7 +413,7 @@ class AssetModelsController extends Controller
|
||||
|
||||
public function getDatatable($status = null)
|
||||
{
|
||||
$models = AssetModel::with('category', 'assets', 'depreciation');
|
||||
$models = AssetModel::with('category', 'assets', 'depreciation', 'manufacturer');
|
||||
|
||||
switch ($status) {
|
||||
case 'Deleted':
|
||||
@@ -442,7 +439,7 @@ class AssetModelsController extends Controller
|
||||
}
|
||||
|
||||
|
||||
$allowed_columns = ['id','name','modelno'];
|
||||
$allowed_columns = ['id','name','model_number'];
|
||||
$order = Input::get('order') === 'asc' ? 'asc' : 'desc';
|
||||
$sort = in_array(Input::get('sort'), $allowed_columns) ? e(Input::get('sort')) : 'created_at';
|
||||
|
||||
@@ -465,12 +462,13 @@ class AssetModelsController extends Controller
|
||||
'manufacturer' => (string)link_to('/admin/settings/manufacturers/'.$model->manufacturer->id.'/view', $model->manufacturer->name),
|
||||
'name' => (string)link_to('/hardware/models/'.$model->id.'/view', $model->name),
|
||||
'image' => ($model->image!='') ? '<img src="'.config('app.url').'/uploads/models/'.$model->image.'" height=50 width=50>' : '',
|
||||
'modelnumber' => $model->modelno,
|
||||
'modelnumber' => $model->model_number,
|
||||
'numassets' => $model->assets->count(),
|
||||
'depreciation' => (($model->depreciation)&&($model->depreciation->id > 0)) ? $model->depreciation->name.' ('.$model->depreciation->months.')' : trans('general.no_depreciation'),
|
||||
'category' => ($model->category) ? $model->category->name : '',
|
||||
'depreciation' => (($model->depreciation) && ($model->depreciation->id > 0)) ? $model->depreciation->name.' ('.$model->depreciation->months.')' : trans('general.no_depreciation'),
|
||||
'category' => ($model->category) ? (string)link_to('admin/settings/categories/'.$model->category->id.'/view', $model->category->name) : '',
|
||||
'eol' => ($model->eol) ? $model->eol.' '.trans('general.months') : '',
|
||||
'note' => $model->getNote(),
|
||||
'note' => $model->getNote(),
|
||||
'fieldset' => ($model->fieldset) ? (string)link_to('admin/custom_fields/'.$model->fieldset->id, $model->fieldset->name) : '',
|
||||
'actions' => $actions
|
||||
);
|
||||
}
|
||||
@@ -491,7 +489,7 @@ class AssetModelsController extends Controller
|
||||
*/
|
||||
public function getDataView($modelID)
|
||||
{
|
||||
$assets = Asset::where('model_id', '=', $modelID)->with('company');
|
||||
$assets = Asset::where('model_id', '=', $modelID)->with('company', 'assetstatus');
|
||||
|
||||
if (Input::has('search')) {
|
||||
$assets = $assets->TextSearch(e(Input::get('search')));
|
||||
|
||||
@@ -124,7 +124,7 @@ class AssetsController extends Controller
|
||||
$view->with('statuslabel_list', $statuslabel_list);
|
||||
$view->with('assigned_to', $assigned_to);
|
||||
$view->with('location_list', $location_list);
|
||||
$view->with('asset', new Asset);
|
||||
$view->with('item', new Asset);
|
||||
$view->with('manufacturer', $manufacturer_list);
|
||||
$view->with('category', $category_list);
|
||||
$view->with('statuslabel_types', $statuslabel_types);
|
||||
@@ -290,10 +290,10 @@ class AssetsController extends Controller
|
||||
{
|
||||
|
||||
// Check if the asset exists
|
||||
if (!$asset = Asset::find($assetId)) {
|
||||
if (!$item = Asset::find($assetId)) {
|
||||
// Redirect to the asset management page
|
||||
return redirect()->to('hardware')->with('error', trans('admin/hardware/message.does_not_exist'));
|
||||
} elseif (!Company::isCurrentUserHasAccess($asset)) {
|
||||
} elseif (!Company::isCurrentUserHasAccess($item)) {
|
||||
return redirect()->to('hardware')->with('error', trans('general.insufficient_permissions'));
|
||||
}
|
||||
|
||||
@@ -308,7 +308,7 @@ class AssetsController extends Controller
|
||||
$assigned_to = Helper::usersList();
|
||||
$statuslabel_types =Helper::statusTypeList();
|
||||
|
||||
return View::make('hardware/edit', compact('asset'))
|
||||
return View::make('hardware/edit', compact('item'))
|
||||
->with('model_list', $model_list)
|
||||
->with('supplier_list', $supplier_list)
|
||||
->with('company_list', $company_list)
|
||||
@@ -1038,7 +1038,7 @@ class AssetsController extends Controller
|
||||
->with('statuslabel_list', $statuslabel_list)
|
||||
->with('statuslabel_types', $statuslabel_types)
|
||||
->with('assigned_to', $assigned_to)
|
||||
->with('asset', $asset)
|
||||
->with('item', $asset)
|
||||
->with('location_list', $location_list)
|
||||
->with('manufacturer', $manufacturer_list)
|
||||
->with('category', $category_list)
|
||||
@@ -1798,7 +1798,7 @@ class AssetsController extends Controller
|
||||
'asset_tag' => '<a title="'.e($asset->asset_tag).'" href="hardware/'.$asset->id.'/view">'.e($asset->asset_tag).'</a>',
|
||||
'serial' => e($asset->serial),
|
||||
'model' => ($asset->model) ? (string)link_to('/hardware/models/'.$asset->model->id.'/view', e($asset->model->name)) : 'No model',
|
||||
'model_number' => ($asset->model && $asset->model->modelno) ? (string)$asset->model->modelno : '',
|
||||
'model_number' => ($asset->model && $asset->model->model_number) ? (string)$asset->model->model_number : '',
|
||||
'status_label' => ($asset->assigneduser) ? 'Deployed' : ((e($asset->assetstatus)) ? e($asset->assetstatus->name) : ''),
|
||||
'assigned_to' => ($asset->assigneduser) ? (string)link_to(config('app.url').'/admin/users/'.$asset->assigned_to.'/view', e($asset->assigneduser->fullName())) : '',
|
||||
'location' => (($asset->assigneduser) && ($asset->assigneduser->userloc!='')) ? (string)link_to('admin/settings/locations/'.$asset->assigneduser->userloc->id.'/view', e($asset->assigneduser->userloc->name)) : (($asset->defaultLoc!='') ? (string)link_to('admin/settings/locations/'.$asset->defaultLoc->id.'/view', e($asset->defaultLoc->name)) : ''),
|
||||
|
||||
@@ -5,6 +5,7 @@ namespace App\Http\Controllers\Auth;
|
||||
use Validator;
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Foundation\Auth\ThrottlesLogins;
|
||||
use Illuminate\Foundation\Auth\AuthenticatesAndRegistersUsers;
|
||||
use App\Models\Setting;
|
||||
use App\Models\Ldap;
|
||||
use App\Models\User;
|
||||
@@ -15,6 +16,7 @@ use Input;
|
||||
use Redirect;
|
||||
use Log;
|
||||
use View;
|
||||
use PragmaRX\Google2FA\Google2FA;
|
||||
|
||||
|
||||
|
||||
@@ -29,7 +31,7 @@ use View;
|
||||
class AuthController extends Controller
|
||||
{
|
||||
|
||||
use ThrottlesLogins;
|
||||
use AuthenticatesAndRegistersUsers, ThrottlesLogins;
|
||||
|
||||
// This tells the auth controller to use username instead of email address
|
||||
protected $username = 'username';
|
||||
@@ -48,22 +50,65 @@ class AuthController extends Controller
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->middleware('guest', ['except' => 'logout']);
|
||||
$this->middleware('guest', ['except' => ['logout','postTwoFactorAuth','getTwoFactorAuth','getTwoFactorEnroll']]);
|
||||
}
|
||||
|
||||
|
||||
function showLoginForm()
|
||||
{
|
||||
// Is the user logged in?
|
||||
if (Auth::check()) {
|
||||
return redirect()->intended('dashboard');
|
||||
}
|
||||
|
||||
// Show the page
|
||||
return View::make('auth.login');
|
||||
}
|
||||
|
||||
|
||||
private function login_via_ldap(Request $request)
|
||||
{
|
||||
LOG::debug("Binding user to LDAP.");
|
||||
$ldap_user = Ldap::findAndBindUserLdap($request->input('username'), $request->input('password'));
|
||||
if(!$ldap_user) {
|
||||
LOG::debug("LDAP user ".$request->input('username')." not found in LDAP or could not bind");
|
||||
throw new \Exception("Could not find user in LDAP directory");
|
||||
} else {
|
||||
LOG::debug("LDAP user ".$request->input('username')." successfully bound to LDAP");
|
||||
}
|
||||
|
||||
// Check if the user already exists in the database and was imported via LDAP
|
||||
$user = User::where('username', '=', Input::get('username'))->whereNull('deleted_at')->where('ldap_import','=',1)->first();
|
||||
LOG::debug("Local auth lookup complete");
|
||||
|
||||
// The user does not exist in the database. Try to get them from LDAP.
|
||||
// If user does not exist and authenticates successfully with LDAP we
|
||||
// will create it on the fly and sign in with default permissions
|
||||
if (!$user) {
|
||||
LOG::debug("Local user ".Input::get('username')." does not exist");
|
||||
LOG::debug("Creating local user ".Input::get('username'));
|
||||
|
||||
if ($user = Ldap::createUserFromLdap($ldap_user)) { //this handles passwords on its own
|
||||
LOG::debug("Local user created.");
|
||||
} else {
|
||||
LOG::debug("Could not create local user.");
|
||||
throw new \Exception("Could not create local user");
|
||||
}
|
||||
// If the user exists and they were imported from LDAP already
|
||||
} else {
|
||||
LOG::debug("Local user ".$request->input('username')." exists in database. Updating existing user against LDAP.");
|
||||
|
||||
$ldap_attr = Ldap::parseAndMapLdapAttributes($ldap_user);
|
||||
|
||||
if (Setting::getSettings()->ldap_pw_sync=='1') {
|
||||
$user->password = bcrypt($request->input('password'));
|
||||
}
|
||||
|
||||
$user->email = $ldap_attr['email'];
|
||||
$user->first_name = $ldap_attr['firstname'];
|
||||
$user->last_name = $ldap_attr['lastname'];
|
||||
$user->save();
|
||||
} // End if(!user)
|
||||
return $user;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Account sign in form processing.
|
||||
@@ -78,94 +123,54 @@ class AuthController extends Controller
|
||||
return redirect()->back()->withInput()->withErrors($validator);
|
||||
}
|
||||
|
||||
// If the class is using the ThrottlesLogins trait, we can automatically throttle
|
||||
// the login attempts for this application. We'll key this by the username and
|
||||
// the IP address of the client making these requests into this application.
|
||||
$throttles = $this->isUsingThrottlesLoginsTrait();
|
||||
$this->maxLoginAttempts = config('auth.throttle.max_attempts');
|
||||
$this->lockoutTime = config('auth.throttle.lockout_duration');
|
||||
|
||||
if ($throttles && $lockedOut = $this->hasTooManyLoginAttempts($request)) {
|
||||
$this->fireLockoutEvent($request);
|
||||
|
||||
return $this->sendLockoutResponse($request);
|
||||
}
|
||||
|
||||
$user = null;
|
||||
|
||||
// Should we even check for LDAP users?
|
||||
if (Setting::getSettings()->ldap_enabled=='1') {
|
||||
|
||||
LOG::debug("LDAP is enabled.");
|
||||
// Check if the user exists in the database
|
||||
$user = User::where('username', '=', Input::get('username'))->whereNull('deleted_at')->first();
|
||||
LOG::debug("Local auth lookup complete");
|
||||
|
||||
try {
|
||||
Ldap::findAndBindUserLdap($request->input('username'), $request->input('password'));
|
||||
LOG::debug("Binding user to LDAP.");
|
||||
$user = $this->login_via_ldap($request);
|
||||
Auth::login($user, true);
|
||||
|
||||
// If the user was unable to login via LDAP, log the error and let them fall through to
|
||||
// local authentication.
|
||||
} catch (\Exception $e) {
|
||||
LOG::debug("User ".Input::get('username').' did not authenticate successfully against LDAP.');
|
||||
//$ldap_error = $e->getMessage();
|
||||
// return redirect()->back()->withInput()->with('error',$e->getMessage());
|
||||
LOG::error("There was an error authenticating the LDAP user: ".$e->getMessage());
|
||||
}
|
||||
|
||||
|
||||
// The user does not exist in the database. Try to get them from LDAP.
|
||||
// If user does not exist and authenticates sucessfully with LDAP we
|
||||
// will create it on the fly and sign in with default permissions
|
||||
if (!$user) {
|
||||
LOG::debug("Local user ".Input::get('username')." does not exist");
|
||||
|
||||
try {
|
||||
|
||||
if ($userattr = Ldap::findAndBindUserLdap($request->input('username'), $request->input('password'))) {
|
||||
LOG::debug("Creating local user ".Input::get('username'));
|
||||
|
||||
if ($newuser = Ldap::createUserFromLdap($userattr)) {
|
||||
LOG::debug("Local user created.");
|
||||
} else {
|
||||
LOG::debug("Could not create local user.");
|
||||
}
|
||||
|
||||
} else {
|
||||
LOG::debug("User did not authenticate correctly against LDAP. No local user was created.");
|
||||
}
|
||||
|
||||
} catch (\Exception $e) {
|
||||
return redirect()->back()->withInput()->with('error',$e->getMessage());
|
||||
}
|
||||
|
||||
// If the user exists and they were imported from LDAP already
|
||||
} else {
|
||||
|
||||
LOG::debug("Local user ".Input::get('username')." exists in database. Authenticating existing user against LDAP.");
|
||||
|
||||
if ($ldap_user = Ldap::findAndBindUserLdap($request->input('username'), $request->input('password'))) {
|
||||
$ldap_attr = Ldap::parseAndMapLdapAttributes($ldap_user);
|
||||
|
||||
LOG::debug("Valid LDAP login. Updating the local data.");
|
||||
|
||||
if (Setting::getSettings()->ldap_pw_sync=='1') {
|
||||
$user->password = bcrypt($request->input('password'));
|
||||
}
|
||||
|
||||
$user->email = $ldap_attr['email'];
|
||||
$user->first_name = $ldap_attr['firstname'];
|
||||
$user->last_name = $ldap_attr['lastname'];
|
||||
$user->save();
|
||||
|
||||
if (Setting::getSettings()->ldap_pw_sync!='1') {
|
||||
Auth::login($user, true);
|
||||
// Redirect to the users page
|
||||
return redirect()->to('/home')->with('success', trans('auth/message.signin.success'));
|
||||
}
|
||||
|
||||
} else {
|
||||
LOG::debug("User ".Input::get('username')." did not authenticate correctly against LDAP. Local user was not updated.");
|
||||
}// End LDAP auth
|
||||
|
||||
} // End if(!user)
|
||||
|
||||
// NO LDAP enabled - just try to login the user normally
|
||||
}
|
||||
|
||||
// If the user wasn't authenticated via LDAP, skip to local auth
|
||||
if(!$user) {
|
||||
LOG::debug("Authenticating user against database.");
|
||||
// Try to log the user in
|
||||
if (!Auth::attempt(Input::only('username', 'password'), Input::get('remember-me', 0))) {
|
||||
|
||||
LOG::debug("Authenticating user against database.");
|
||||
// Try to log the user in
|
||||
if (!Auth::attempt(Input::only('username', 'password'), Input::get('remember-me', 0))) {
|
||||
LOG::debug("Local authentication failed.");
|
||||
// throw new Cartalyst\Sentry\Users\UserNotFoundException();
|
||||
return redirect()->back()->withInput()->with('error', trans('auth/message.account_not_found'));
|
||||
if ($throttles && ! $lockedOut) {
|
||||
$this->incrementLoginAttempts($request);
|
||||
}
|
||||
|
||||
LOG::debug("Local authentication failed.");
|
||||
return redirect()->back()->withInput()->with('error', trans('auth/message.account_not_found'));
|
||||
} else {
|
||||
if ($throttles) {
|
||||
$this->clearLoginAttempts($request);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Get the page we were before
|
||||
$redirect = \Session::get('loginRedirect', 'home');
|
||||
|
||||
@@ -174,23 +179,89 @@ class AuthController extends Controller
|
||||
|
||||
// Redirect to the users page
|
||||
return redirect()->to($redirect)->with('success', trans('auth/message.signin.success'));
|
||||
|
||||
// Ooops.. something went wrong
|
||||
return redirect()->back()->withInput()->withErrors($this->messageBag);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Two factor enrollment page
|
||||
*
|
||||
* @return Redirect
|
||||
*/
|
||||
public function getTwoFactorEnroll()
|
||||
{
|
||||
|
||||
if (!Auth::check()) {
|
||||
return redirect()->route('login')->with('error', 'You must be logged in.');
|
||||
}
|
||||
|
||||
$user = Auth::user();
|
||||
$google2fa = app()->make('PragmaRX\Google2FA\Contracts\Google2FA');
|
||||
|
||||
if ($user->two_factor_secret=='') {
|
||||
$user->two_factor_secret = $google2fa->generateSecretKey(32);
|
||||
$user->save();
|
||||
}
|
||||
|
||||
|
||||
$google2fa_url = $google2fa->getQRCodeGoogleUrl(
|
||||
urlencode(Setting::getSettings()->site_name),
|
||||
urlencode($user->username),
|
||||
$user->two_factor_secret
|
||||
);
|
||||
|
||||
return View::make('auth.two_factor_enroll')->with('google2fa_url',$google2fa_url);
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Two factor code form page
|
||||
*
|
||||
* @return Redirect
|
||||
*/
|
||||
public function getTwoFactorAuth() {
|
||||
return View::make('auth.two_factor');
|
||||
}
|
||||
|
||||
/**
|
||||
* Two factor code submission
|
||||
*
|
||||
* @return Redirect
|
||||
*/
|
||||
public function postTwoFactorAuth(Request $request) {
|
||||
|
||||
if (!Auth::check()) {
|
||||
return redirect()->route('login')->with('error', 'You must be logged in.');
|
||||
}
|
||||
|
||||
$user = Auth::user();
|
||||
$secret = $request->get('two_factor_secret');
|
||||
$google2fa = app()->make('PragmaRX\Google2FA\Contracts\Google2FA');
|
||||
$valid = $google2fa->verifyKey($user->two_factor_secret, $secret);
|
||||
|
||||
if ($valid) {
|
||||
$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');
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Logout page.
|
||||
*
|
||||
* @return Redirect
|
||||
*/
|
||||
public function logout()
|
||||
public function logout(Request $request)
|
||||
{
|
||||
// Log the user out
|
||||
$request->session()->forget('2fa_authed');
|
||||
Auth::logout();
|
||||
|
||||
// Redirect to the users page
|
||||
return redirect()->route('home')->with('success', 'You have successfully logged out!');
|
||||
return redirect()->route('login')->with('success', 'You have successfully logged out!');
|
||||
}
|
||||
|
||||
|
||||
@@ -207,4 +278,19 @@ class AuthController extends Controller
|
||||
'password' => 'required',
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the login lockout error message.
|
||||
*
|
||||
* @param int $seconds
|
||||
* @return string
|
||||
*/
|
||||
protected function getLockoutErrorMessage($seconds)
|
||||
{
|
||||
return \Lang::has('auth/message.throttle')
|
||||
? \Lang::get('auth/message.throttle', ['seconds' => $seconds])
|
||||
: 'Too many login attempts. Please try again in '.$seconds.' seconds.';
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -46,4 +46,15 @@ class PasswordController extends Controller
|
||||
public function getEmailSubject(){
|
||||
return property_exists($this, 'subject') ? $this->subject : \Lang::get('mail.reset_link');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the response for after the reset link has been successfully sent.
|
||||
*
|
||||
* @param string $response
|
||||
* @return \Symfony\Component\HttpFoundation\Response
|
||||
*/
|
||||
protected function getSendResetLinkEmailSuccessResponse($response)
|
||||
{
|
||||
return redirect()->route('login')->with('status', trans($response));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -53,7 +53,7 @@ class CategoriesController extends Controller
|
||||
{
|
||||
// Show the page
|
||||
$category_types= Helper::categoryTypeList();
|
||||
return View::make('categories/edit')->with('category', new Category)
|
||||
return View::make('categories/edit')->with('item', new Category)
|
||||
->with('category_types', $category_types);
|
||||
}
|
||||
|
||||
@@ -109,7 +109,7 @@ class CategoriesController extends Controller
|
||||
public function getEdit($categoryId = null)
|
||||
{
|
||||
// Check if the category exists
|
||||
if (is_null($category = Category::find($categoryId))) {
|
||||
if (is_null($item = Category::find($categoryId))) {
|
||||
// Redirect to the blogs management page
|
||||
return redirect()->to('admin/settings/categories')->with('error', trans('admin/categories/message.does_not_exist'));
|
||||
}
|
||||
@@ -120,7 +120,7 @@ class CategoriesController extends Controller
|
||||
$category_options = array('' => 'Top Level') + DB::table('categories')->where('id', '!=', $categoryId)->lists('name', 'id');
|
||||
$category_types= Helper::categoryTypeList();
|
||||
|
||||
return View::make('categories/edit', compact('category'))
|
||||
return View::make('categories/edit', compact('item'))
|
||||
->with('category_options', $category_options)
|
||||
->with('category_types', $category_types);
|
||||
}
|
||||
@@ -293,7 +293,6 @@ class CategoriesController extends Controller
|
||||
'category_type' => ucwords($category->category_type),
|
||||
'count' => $category->itemCount(),
|
||||
'acceptance' => ($category->require_acceptance=='1') ? '<i class="fa fa-check"></i>' : '',
|
||||
//EULA is still not working correctly
|
||||
'eula' => ($category->getEula()) ? '<i class="fa fa-check"></i>' : '',
|
||||
'actions' => $actions
|
||||
);
|
||||
@@ -307,9 +306,9 @@ class CategoriesController extends Controller
|
||||
public function getDataViewAssets($categoryID)
|
||||
{
|
||||
|
||||
$category = Category::with('assets.company')->find($categoryID);
|
||||
$category = Category::find($categoryID);
|
||||
$category = $category->load('assets.company', 'assets.model', 'assets.assetstatus', 'assets.assigneduser');
|
||||
$category_assets = $category->assets();
|
||||
|
||||
if (Input::has('search')) {
|
||||
$category_assets = $category_assets->TextSearch(e(Input::get('search')));
|
||||
}
|
||||
@@ -333,7 +332,6 @@ class CategoriesController extends Controller
|
||||
$count = $category_assets->count();
|
||||
$category_assets = $category_assets->skip($offset)->take($limit)->get();
|
||||
$rows = array();
|
||||
|
||||
foreach ($category_assets as $asset) {
|
||||
|
||||
$actions = '';
|
||||
@@ -358,13 +356,13 @@ class CategoriesController extends Controller
|
||||
$rows[] = array(
|
||||
'id' => $asset->id,
|
||||
'name' => (string)link_to('/hardware/'.$asset->id.'/view', $asset->showAssetName()),
|
||||
'model' => $asset->model->name,
|
||||
'model' => ($asset->model) ? (string)link_to('hardware/models/'.$asset->model->id.'/view', $asset->model->name) : '',
|
||||
'asset_tag' => $asset->asset_tag,
|
||||
'serial' => $asset->serial,
|
||||
'assigned_to' => ($asset->assigneduser) ? (string)link_to('/admin/users/'.$asset->assigneduser->id.'/view', $asset->assigneduser->fullName()): '',
|
||||
'change' => $inout,
|
||||
'actions' => $actions,
|
||||
'companyName' => Company::getName($asset),
|
||||
'companyName' => is_null($asset->company) ? '' : e($asset->company->name)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -38,7 +38,7 @@ final class CompaniesController extends Controller
|
||||
*/
|
||||
public function getCreate()
|
||||
{
|
||||
return View::make('companies/edit')->with('company', new Company);
|
||||
return View::make('companies/edit')->with('item', new Company);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -74,11 +74,11 @@ final class CompaniesController extends Controller
|
||||
*/
|
||||
public function getEdit($companyId)
|
||||
{
|
||||
if (is_null($company = Company::find($companyId))) {
|
||||
if (is_null($item = Company::find($companyId))) {
|
||||
return redirect()->to('admin/settings/companies')
|
||||
->with('error', trans('admin/companies/message.does_not_exist'));
|
||||
} else {
|
||||
return View::make('companies/edit')->with('company', $company);
|
||||
return View::make('companies/edit')->with('item', $item);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -61,7 +61,7 @@ class ComponentsController extends Controller
|
||||
$location_list = Helper::locationsList();
|
||||
|
||||
return View::make('components/edit')
|
||||
->with('component', new Component)
|
||||
->with('item', new Component)
|
||||
->with('category_list', $category_list)
|
||||
->with('company_list', $company_list)
|
||||
->with('location_list', $location_list);
|
||||
@@ -89,7 +89,7 @@ class ComponentsController extends Controller
|
||||
$component->company_id = Company::getIdForCurrentUser(Input::get('company_id'));
|
||||
$component->order_number = e(Input::get('order_number'));
|
||||
$component->min_amt = e(Input::get('min_amt'));
|
||||
$component->serial_number = e(Input::get('serial_number'));
|
||||
$component->serial = e(Input::get('serial'));
|
||||
|
||||
if (e(Input::get('purchase_date')) == '') {
|
||||
$component->purchase_date = null;
|
||||
@@ -103,7 +103,7 @@ class ComponentsController extends Controller
|
||||
$component->purchase_cost = Helper::ParseFloat(e(Input::get('purchase_cost')));
|
||||
}
|
||||
|
||||
$component->total_qty = e(Input::get('total_qty'));
|
||||
$component->qty = e(Input::get('qty'));
|
||||
$component->user_id = Auth::user()->id;
|
||||
|
||||
// Was the component created?
|
||||
@@ -130,10 +130,10 @@ class ComponentsController extends Controller
|
||||
public function getEdit($componentId = null)
|
||||
{
|
||||
// Check if the component exists
|
||||
if (is_null($component = Component::find($componentId))) {
|
||||
if (is_null($item = Component::find($componentId))) {
|
||||
// Redirect to the blogs management page
|
||||
return redirect()->to('admin/components')->with('error', trans('admin/components/message.does_not_exist'));
|
||||
} elseif (!Company::isCurrentUserHasAccess($component)) {
|
||||
} elseif (!Company::isCurrentUserHasAccess($item)) {
|
||||
return redirect()->to('admin/components')->with('error', trans('general.insufficient_permissions'));
|
||||
}
|
||||
|
||||
@@ -141,7 +141,7 @@ class ComponentsController extends Controller
|
||||
$company_list = Helper::companyList();
|
||||
$location_list = Helper::locationsList();
|
||||
|
||||
return View::make('components/edit', compact('component'))
|
||||
return View::make('components/edit', compact('item'))
|
||||
->with('category_list', $category_list)
|
||||
->with('company_list', $company_list)
|
||||
->with('location_list', $location_list);
|
||||
@@ -174,8 +174,8 @@ class ComponentsController extends Controller
|
||||
$component->location_id = e(Input::get('location_id'));
|
||||
$component->company_id = Company::getIdForCurrentUser(Input::get('company_id'));
|
||||
$component->order_number = e(Input::get('order_number'));
|
||||
$component->min_amt = e(Input::get('min_amt'));
|
||||
$component->serial_number = e(Input::get('serial_number'));
|
||||
$component->min_amt = e(Input::get('min_amt'));
|
||||
$component->serial = e(Input::get('serial'));
|
||||
|
||||
if (e(Input::get('purchase_date')) == '') {
|
||||
$component->purchase_date = null;
|
||||
@@ -189,7 +189,7 @@ class ComponentsController extends Controller
|
||||
$component->purchase_cost = Helper::ParseFloat(e(Input::get('purchase_cost')));
|
||||
}
|
||||
|
||||
$component->total_qty = e(Input::get('total_qty'));
|
||||
$component->qty = e(Input::get('qty'));
|
||||
|
||||
// Was the component created?
|
||||
if ($component->save()) {
|
||||
@@ -424,7 +424,7 @@ class ComponentsController extends Controller
|
||||
$limit = 50;
|
||||
}
|
||||
|
||||
$allowed_columns = ['id','name','min_amt','order_number','serial_number','purchase_date','purchase_cost','companyName','category','total_qty'];
|
||||
$allowed_columns = ['id','name','min_amt','order_number','serial','purchase_date','purchase_cost','companyName','category','total_qty'];
|
||||
$order = Input::get('order') === 'asc' ? 'asc' : 'desc';
|
||||
$sort = in_array(Input::get('sort'), $allowed_columns) ? Input::get('sort') : 'created_at';
|
||||
|
||||
@@ -472,9 +472,9 @@ class ComponentsController extends Controller
|
||||
'checkbox' =>'<div class="text-center"><input type="checkbox" name="component['.$component->id.']" class="one_required"></div>',
|
||||
'id' => $component->id,
|
||||
'name' => (string)link_to('admin/components/'.$component->id.'/view', e($component->name)),
|
||||
'serial_number' => $component->serial_number,
|
||||
'serial_number' => $component->serial,
|
||||
'location' => ($component->location) ? e($component->location->name) : '',
|
||||
'total_qty' => e($component->total_qty),
|
||||
'qty' => e($component->qty),
|
||||
'min_amt' => e($component->min_amt),
|
||||
'category' => ($component->category) ? e($component->category->name) : 'Missing category',
|
||||
'order_number' => e($component->order_number),
|
||||
|
||||
@@ -59,7 +59,7 @@ class ConsumablesController extends Controller
|
||||
$manufacturer_list = Helper::manufacturerList();
|
||||
|
||||
return View::make('consumables/edit')
|
||||
->with('consumable', new Consumable)
|
||||
->with('item', new Consumable)
|
||||
->with('category_list', $category_list)
|
||||
->with('company_list', $company_list)
|
||||
->with('location_list', $location_list)
|
||||
@@ -85,7 +85,7 @@ class ConsumablesController extends Controller
|
||||
$consumable->order_number = e(Input::get('order_number'));
|
||||
$consumable->min_amt = e(Input::get('min_amt'));
|
||||
$consumable->manufacturer_id = e(Input::get('manufacturer_id'));
|
||||
$consumable->model_no = e(Input::get('model_no'));
|
||||
$consumable->model_number = e(Input::get('model_number'));
|
||||
$consumable->item_no = e(Input::get('item_no'));
|
||||
|
||||
if (e(Input::get('purchase_date')) == '') {
|
||||
@@ -127,10 +127,10 @@ class ConsumablesController extends Controller
|
||||
public function getEdit($consumableId = null)
|
||||
{
|
||||
// Check if the consumable exists
|
||||
if (is_null($consumable = Consumable::find($consumableId))) {
|
||||
if (is_null($item = Consumable::find($consumableId))) {
|
||||
// Redirect to the blogs management page
|
||||
return redirect()->to('admin/consumables')->with('error', trans('admin/consumables/message.does_not_exist'));
|
||||
} elseif (!Company::isCurrentUserHasAccess($consumable)) {
|
||||
} elseif (!Company::isCurrentUserHasAccess($item)) {
|
||||
return redirect()->to('admin/consumables')->with('error', trans('general.insufficient_permissions'));
|
||||
}
|
||||
|
||||
@@ -139,7 +139,7 @@ class ConsumablesController extends Controller
|
||||
$location_list = Helper::locationsList();
|
||||
$manufacturer_list = Helper::manufacturerList();
|
||||
|
||||
return View::make('consumables/edit', compact('consumable'))
|
||||
return View::make('consumables/edit', compact('item'))
|
||||
->with('category_list', $category_list)
|
||||
->with('company_list', $company_list)
|
||||
->with('location_list', $location_list)
|
||||
@@ -171,7 +171,7 @@ class ConsumablesController extends Controller
|
||||
$consumable->order_number = e(Input::get('order_number'));
|
||||
$consumable->min_amt = e(Input::get('min_amt'));
|
||||
$consumable->manufacturer_id = e(Input::get('manufacturer_id'));
|
||||
$consumable->model_no = e(Input::get('model_no'));
|
||||
$consumable->model_number = e(Input::get('model_number'));
|
||||
$consumable->item_no = e(Input::get('item_no'));
|
||||
|
||||
if (e(Input::get('purchase_date')) == '') {
|
||||
@@ -390,8 +390,11 @@ class ConsumablesController extends Controller
|
||||
*/
|
||||
public function getDatatable()
|
||||
{
|
||||
$consumables = Company::scopeCompanyables(Consumable::select('consumables.*')->whereNull('consumables.deleted_at')
|
||||
->with('company', 'location', 'category', 'users'));
|
||||
$consumables = Company::scopeCompanyables(
|
||||
Consumable::select('consumables.*')
|
||||
->whereNull('consumables.deleted_at')
|
||||
->with('company', 'location', 'category', 'users', 'manufacturer')
|
||||
);
|
||||
|
||||
if (Input::has('search')) {
|
||||
$consumables = $consumables->TextSearch(e(Input::get('search')));
|
||||
@@ -409,7 +412,7 @@ class ConsumablesController extends Controller
|
||||
$limit = 50;
|
||||
}
|
||||
|
||||
$allowed_columns = ['id','name','order_number','min_amt','purchase_date','purchase_cost','companyName','category','model_no', 'item_no', 'manufacturer'];
|
||||
$allowed_columns = ['id','name','order_number','min_amt','purchase_date','purchase_cost','companyName','category','model_number', 'item_no', 'manufacturer'];
|
||||
$order = Input::get('order') === 'asc' ? 'asc' : 'desc';
|
||||
$sort = in_array(Input::get('sort'), $allowed_columns) ? Input::get('sort') : 'created_at';
|
||||
|
||||
@@ -463,7 +466,7 @@ class ConsumablesController extends Controller
|
||||
'min_amt' => e($consumable->min_amt),
|
||||
'qty' => e($consumable->qty),
|
||||
'manufacturer' => ($consumable->manufacturer) ? (string) link_to('/admin/settings/manufacturers/'.$consumable->manufacturer_id.'/view', $consumable->manufacturer->name): '',
|
||||
'model_no' => e($consumable->model_no),
|
||||
'model_number' => e($consumable->model_number),
|
||||
'item_no' => e($consumable->item_no),
|
||||
'category' => ($consumable->category) ? (string) link_to('/admin/settings/categories/'.$consumable->category_id.'/view', $consumable->category->name) : 'Missing category',
|
||||
'order_number' => e($consumable->order_number),
|
||||
|
||||
@@ -11,6 +11,7 @@ use App\Models\AssetModel;
|
||||
use Lang;
|
||||
use Auth;
|
||||
use Illuminate\Http\Request;
|
||||
use Log;
|
||||
|
||||
/**
|
||||
* This controller handles all actions related to Custom Asset Fields for
|
||||
@@ -210,21 +211,15 @@ class CustomFieldsController extends Controller
|
||||
*/
|
||||
public function show($id)
|
||||
{
|
||||
//$id=$parameters[0];
|
||||
$cfset=CustomFieldset::find($id);
|
||||
$cfset = CustomFieldset::with('fields')->where('id','=',$id)->orderBy('id','ASC')->first();
|
||||
$custom_fields_list = ["" => "Add New Field to Fieldset"] + CustomField::lists("name", "id")->toArray();
|
||||
|
||||
//print_r($parameters);
|
||||
//
|
||||
$custom_fields_list=["" => "Add New Field to Fieldset"] + CustomField::lists("name", "id")->toArray();
|
||||
// print_r($custom_fields_list);
|
||||
$maxid=0;
|
||||
foreach ($cfset->fields as $field) {
|
||||
// print "Looking for: ".$field->id;
|
||||
$maxid = 0;
|
||||
foreach ($cfset->fields() as $field) {
|
||||
if ($field->pivot->order > $maxid) {
|
||||
$maxid=$field->pivot->order;
|
||||
}
|
||||
if (isset($custom_fields_list[$field->id])) {
|
||||
// print "Found ".$field->id.", so removing it.<br>";
|
||||
unset($custom_fields_list[$field->id]);
|
||||
}
|
||||
}
|
||||
@@ -274,14 +269,14 @@ class CustomFieldsController extends Controller
|
||||
public function destroy($id)
|
||||
{
|
||||
//
|
||||
$fieldset=CustomFieldset::find($id);
|
||||
$fieldset = CustomFieldset::find($id);
|
||||
|
||||
$models = AssetModel::where("fieldset_id", "=", $id);
|
||||
if ($models->count()==0) {
|
||||
if ($models->count() == 0) {
|
||||
$fieldset->delete();
|
||||
return redirect()->route("admin.custom_fields.index")->with("success", trans('admin/custom_fields/message.fieldset.delete.success'));
|
||||
} else {
|
||||
return redirect()->route("admin.custom_fields.index")->with("error", trans('admin/custom_fields/message.fieldset.delete.in_use')); //->with("models",$models);
|
||||
return redirect()->route("admin.custom_fields.index")->with("error", trans('admin/custom_fields/message.fieldset.delete.in_use'));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -294,18 +289,23 @@ class CustomFieldsController extends Controller
|
||||
* @since [v3.0]
|
||||
* @return Array
|
||||
*/
|
||||
public function postReorder($id)
|
||||
public function postReorder(Request $request, $id)
|
||||
{
|
||||
$fieldset=CustomFieldset::find($id);
|
||||
$fieldset = CustomFieldset::find($id);
|
||||
$fields = array();
|
||||
$order_array = array();
|
||||
|
||||
$items = Input::get('item');
|
||||
foreach ($fieldset->fields as $field) {
|
||||
$value = array_shift($items);
|
||||
$fields[$field->id] = ['required' => $field->pivot->required, 'order' => $value];
|
||||
$items = $request->input('item');
|
||||
|
||||
foreach ($items as $order => $field_id) {
|
||||
$order_array[$field_id] = $order;
|
||||
}
|
||||
return $fieldset->fields()->sync($fields);
|
||||
|
||||
foreach ($fieldset->fields as $field) {
|
||||
$fields[$field->id] = ['required' => $field->pivot->required, 'order' => $order_array[$field->id]];
|
||||
}
|
||||
|
||||
return $fieldset->fields()->sync($fields);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -79,7 +79,7 @@ class DashboardController extends Controller
|
||||
return View::make('dashboard')->with('asset_stats', $asset_stats);
|
||||
} else {
|
||||
// Redirect to the profile page
|
||||
return redirect()->route('view-assets');
|
||||
return redirect()->intended('account/view-assets');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,7 +46,7 @@ class DepreciationsController extends Controller
|
||||
public function getCreate()
|
||||
{
|
||||
// Show the page
|
||||
return View::make('depreciations/edit')->with('depreciation', new Depreciation);
|
||||
return View::make('depreciations/edit')->with('item', new Depreciation);
|
||||
}
|
||||
|
||||
|
||||
@@ -94,12 +94,12 @@ class DepreciationsController extends Controller
|
||||
public function getEdit($depreciationId = null)
|
||||
{
|
||||
// Check if the depreciation exists
|
||||
if (is_null($depreciation = Depreciation::find($depreciationId))) {
|
||||
if (is_null($item = Depreciation::find($depreciationId))) {
|
||||
// Redirect to the blogs management page
|
||||
return redirect()->to('admin/settings/depreciations')->with('error', trans('admin/depreciations/message.does_not_exist'));
|
||||
}
|
||||
|
||||
return View::make('depreciations/edit', compact('depreciation'));
|
||||
return View::make('depreciations/edit', compact('item'));
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -70,7 +70,7 @@ class LicensesController extends Controller
|
||||
->with('maintained_list', $maintained_list)
|
||||
->with('company_list', Helper::companyList())
|
||||
->with('manufacturer_list', Helper::manufacturerList())
|
||||
->with('license', new License);
|
||||
->with('item', new License);
|
||||
|
||||
}
|
||||
|
||||
@@ -139,6 +139,7 @@ class LicensesController extends Controller
|
||||
$license->depreciation_id = e(Input::get('depreciation_id'));
|
||||
$license->company_id = Company::getIdForCurrentUser(Input::get('company_id'));
|
||||
$license->expiration_date = e(Input::get('expiration_date'));
|
||||
$license->termination_date = e(Input::get('termination_date'));
|
||||
$license->user_id = Auth::user()->id;
|
||||
|
||||
if (($license->purchase_date == "") || ($license->purchase_date == "0000-00-00")) {
|
||||
@@ -190,26 +191,26 @@ class LicensesController extends Controller
|
||||
public function getEdit($licenseId = null)
|
||||
{
|
||||
// Check if the license exists
|
||||
if (is_null($license = License::find($licenseId))) {
|
||||
if (is_null($item = License::find($licenseId))) {
|
||||
// Redirect to the blogs management page
|
||||
return redirect()->to('admin/licenses')->with('error', trans('admin/licenses/message.does_not_exist'));
|
||||
} elseif (!Company::isCurrentUserHasAccess($license)) {
|
||||
} elseif (!Company::isCurrentUserHasAccess($item)) {
|
||||
return redirect()->to('admin/licenses')->with('error', trans('general.insufficient_permissions'));
|
||||
}
|
||||
|
||||
if ($license->purchase_date == "0000-00-00") {
|
||||
$license->purchase_date = null;
|
||||
if ($item->purchase_date == "0000-00-00") {
|
||||
$item->purchase_date = null;
|
||||
}
|
||||
|
||||
if ($license->purchase_cost == "0.00") {
|
||||
$license->purchase_cost = null;
|
||||
if ($item->purchase_cost == "0.00") {
|
||||
$item->purchase_cost = null;
|
||||
}
|
||||
|
||||
// Show the page
|
||||
$license_options = array('' => 'Top Level') + DB::table('assets')->where('id', '!=', $licenseId)->pluck('name', 'id');
|
||||
$maintained_list = array('' => 'Maintained', '1' => 'Yes', '0' => 'No');
|
||||
|
||||
return View::make('licenses/edit', compact('license'))
|
||||
return View::make('licenses/edit', compact('item'))
|
||||
->with('license_options', $license_options)
|
||||
->with('depreciation_list', Helper::depreciationList())
|
||||
->with('supplier_list', Helper::suppliersList())
|
||||
@@ -395,7 +396,7 @@ class LicensesController extends Controller
|
||||
return redirect()->to('admin/licenses')->with('error', trans('general.insufficient_permissions'));
|
||||
}
|
||||
|
||||
if (($license->assignedcount()) && ($license->assignedcount() > 0)) {
|
||||
if ($license->assigned_seats_count > 0) {
|
||||
|
||||
// Redirect to the license management page
|
||||
return redirect()->to('admin/licenses')->with('error', trans('admin/licenses/message.assoc_users'));
|
||||
@@ -669,8 +670,10 @@ class LicensesController extends Controller
|
||||
// Ooops.. something went wrong
|
||||
return redirect()->back()->withInput()->withErrors($validator);
|
||||
}
|
||||
$return_to = $licenseseat->assigned_to;
|
||||
|
||||
$return_to = User::find($licenseseat->assigned_to);
|
||||
if (!$return_to) {
|
||||
$return_to = Asset::find($licenseseat->asset_id);
|
||||
}
|
||||
// Update the asset data
|
||||
$licenseseat->assigned_to = null;
|
||||
$licenseseat->asset_id = null;
|
||||
@@ -679,7 +682,7 @@ class LicensesController extends Controller
|
||||
|
||||
// Was the asset updated?
|
||||
if ($licenseseat->save()) {
|
||||
$licenseseat->logCheckin(e(Input::get('note')));
|
||||
$licenseseat->logCheckin($return_to, e(Input::get('note')));
|
||||
|
||||
$settings = Setting::getSettings();
|
||||
|
||||
@@ -719,7 +722,7 @@ class LicensesController extends Controller
|
||||
|
||||
|
||||
if ($backto=='user') {
|
||||
return redirect()->to("admin/users/".$return_to.'/view')->with('success', trans('admin/licenses/message.checkin.success'));
|
||||
return redirect()->to("admin/users/".$return_to->id.'/view')->with('success', trans('admin/licenses/message.checkin.success'));
|
||||
} else {
|
||||
return redirect()->to("admin/licenses/".$licenseseat->license_id."/view")->with('success', trans('admin/licenses/message.checkin.success'));
|
||||
}
|
||||
@@ -742,6 +745,7 @@ class LicensesController extends Controller
|
||||
{
|
||||
|
||||
$license = License::find($licenseId);
|
||||
$license = $license->load('assignedusers', 'licenseSeats.user', 'licenseSeats.asset');
|
||||
|
||||
if (isset($license->id)) {
|
||||
|
||||
@@ -785,7 +789,7 @@ class LicensesController extends Controller
|
||||
->with('license_options', $license_options)
|
||||
->with('depreciation_list', $depreciation_list)
|
||||
->with('supplier_list', $supplier_list)
|
||||
->with('license', $license)
|
||||
->with('item', $license)
|
||||
->with('maintained_list', $maintained_list)
|
||||
->with('company_list', $company_list)
|
||||
->with('manufacturer_list', Helper::manufacturerList());
|
||||
@@ -821,7 +825,7 @@ class LicensesController extends Controller
|
||||
foreach (Input::file('licensefile') as $file) {
|
||||
|
||||
$rules = array(
|
||||
'licensefile' => 'required|mimes:png,gif,jpg,jpeg,doc,docx,pdf,txt,zip,rar,rtf|max:2000'
|
||||
'licensefile' => 'required|mimes:png,gif,jpg,jpeg,doc,docx,pdf,txt,zip,rar,rtf,xml,lic|max:2000'
|
||||
);
|
||||
$validator = Validator::make(array('licensefile'=> $file), $rules);
|
||||
|
||||
@@ -947,17 +951,28 @@ class LicensesController extends Controller
|
||||
*/
|
||||
public function getDatatable()
|
||||
{
|
||||
$licenses = Company::scopeCompanyables(License::with('company'));
|
||||
$licenses = Company::scopeCompanyables(License::with('company', 'licenseSeatsRelation', 'manufacturer'));
|
||||
|
||||
if (Input::has('search')) {
|
||||
$licenses = $licenses->TextSearch(Input::get('search'));
|
||||
}
|
||||
|
||||
$allowed_columns = ['id','name','purchase_cost','expiration_date','purchase_order','order_number','notes','purchase_date','serial'];
|
||||
$allowed_columns = ['id','name','purchase_cost','expiration_date','purchase_order','order_number','notes','purchase_date','serial','manufacturer','company'];
|
||||
$order = Input::get('order') === 'asc' ? 'asc' : 'desc';
|
||||
$sort = in_array(Input::get('sort'), $allowed_columns) ? e(Input::get('sort')) : 'created_at';
|
||||
|
||||
$licenses = $licenses->orderBy($sort, $order);
|
||||
switch ($sort) {
|
||||
case 'manufacturer':
|
||||
$licenses = $licenses->OrderManufacturer($order);
|
||||
break;
|
||||
case 'company':
|
||||
$licenses = $licenses->OrderCompany($order);
|
||||
break;
|
||||
default:
|
||||
$licenses = $licenses->orderBy($sort, $order);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
$licenseCount = $licenses->count();
|
||||
$licenses = $licenses->skip(Input::get('offset'))->take(Input::get('limit'))->get();
|
||||
@@ -991,7 +1006,7 @@ class LicensesController extends Controller
|
||||
'id' => $license->id,
|
||||
'name' => (string) link_to('/admin/licenses/'.$license->id.'/view', $license->name),
|
||||
'serial' => (string) link_to('/admin/licenses/'.$license->id.'/view', mb_strimwidth($license->serial, 0, 50, "...")),
|
||||
'totalSeats' => $license->totalSeatsByLicenseID(),
|
||||
'totalSeats' => $license->licenseSeatsCount,
|
||||
'remaining' => $license->remaincount(),
|
||||
'license_name' => e($license->license_name),
|
||||
'license_email' => e($license->license_email),
|
||||
@@ -1002,7 +1017,7 @@ class LicensesController extends Controller
|
||||
'order_number' => ($license->order_number) ? e($license->order_number) : '',
|
||||
'notes' => ($license->notes) ? e($license->notes) : '',
|
||||
'actions' => $actions,
|
||||
'companyName' => is_null($license->company) ? '' : e($license->company->name),
|
||||
'company' => is_null($license->company) ? '' : e($license->company->name),
|
||||
'manufacturer' => $license->manufacturer ? (string) link_to('/admin/settings/manufacturers/'.$license->manufacturer_id.'/view', $license->manufacturer->name) : ''
|
||||
);
|
||||
}
|
||||
|
||||
@@ -61,7 +61,7 @@ class LocationsController extends Controller
|
||||
|
||||
return View::make('locations/edit')
|
||||
->with('location_options', $location_options)
|
||||
->with('location', new Location);
|
||||
->with('item', new Location);
|
||||
}
|
||||
|
||||
|
||||
@@ -159,7 +159,7 @@ class LocationsController extends Controller
|
||||
public function getEdit($locationId = null)
|
||||
{
|
||||
// Check if the location exists
|
||||
if (is_null($location = Location::find($locationId))) {
|
||||
if (is_null($item = Location::find($locationId))) {
|
||||
return redirect()->to('admin/settings/locations')->with('error', trans('admin/locations/message.does_not_exist'));
|
||||
}
|
||||
|
||||
@@ -169,7 +169,7 @@ class LocationsController extends Controller
|
||||
$location_options = Location::flattenLocationsArray($location_options_array);
|
||||
$location_options = array('' => 'Top Level') + $location_options;
|
||||
|
||||
return View::make('locations/edit', compact('location'))->with('location_options', $location_options);
|
||||
return View::make('locations/edit', compact('item'))->with('location_options', $location_options);
|
||||
}
|
||||
|
||||
|
||||
@@ -318,7 +318,7 @@ class LocationsController extends Controller
|
||||
$locations = $locations->OrderParent($order);
|
||||
break;
|
||||
default:
|
||||
$allowed_columns = ['id','name','address','city','state','country','currency'];
|
||||
$allowed_columns = ['id','name','address','city','state','country','currency','zip'];
|
||||
|
||||
$sort = in_array(Input::get('sort'), $allowed_columns) ? Input::get('sort') : 'created_at';
|
||||
$locations = $locations->orderBy($sort, $order);
|
||||
@@ -344,6 +344,7 @@ class LocationsController extends Controller
|
||||
'address' => ($location->address) ? e($location->address): '',
|
||||
'city' => e($location->city),
|
||||
'state' => e($location->state),
|
||||
'zip' => e($location->zip),
|
||||
'country' => e($location->country),
|
||||
'currency' => e($location->currency),
|
||||
'actions' => $actions
|
||||
|
||||
@@ -46,7 +46,7 @@ class ManufacturersController extends Controller
|
||||
*/
|
||||
public function getCreate()
|
||||
{
|
||||
return View::make('manufacturers/edit')->with('manufacturer', new Manufacturer);
|
||||
return View::make('manufacturers/edit')->with('item', new Manufacturer);
|
||||
}
|
||||
|
||||
|
||||
@@ -84,13 +84,13 @@ class ManufacturersController extends Controller
|
||||
public function getEdit($manufacturerId = null)
|
||||
{
|
||||
// Check if the manufacturer exists
|
||||
if (is_null($manufacturer = Manufacturer::find($manufacturerId))) {
|
||||
if (is_null($item = Manufacturer::find($manufacturerId))) {
|
||||
// Redirect to the manufacturer page
|
||||
return redirect()->to('admin/settings/manufacturers')->with('error', trans('admin/manufacturers/message.does_not_exist'));
|
||||
}
|
||||
|
||||
// Show the page
|
||||
return View::make('manufacturers/edit', compact('manufacturer'));
|
||||
return View::make('manufacturers/edit', compact('item'));
|
||||
}
|
||||
|
||||
|
||||
@@ -257,7 +257,7 @@ class ManufacturersController extends Controller
|
||||
*/
|
||||
public function getDataView($manufacturerId, $itemtype = null)
|
||||
{
|
||||
$manufacturer = Manufacturer::with('assets.company')->find($manufacturerId);
|
||||
$manufacturer = Manufacturer::find($manufacturerId);
|
||||
|
||||
switch ($itemtype) {
|
||||
case "assets":
|
||||
@@ -276,6 +276,7 @@ class ManufacturersController extends Controller
|
||||
|
||||
protected function getDataAssetsView(Manufacturer $manufacturer)
|
||||
{
|
||||
$manufacturer = $manufacturer->load('assets.model', 'assets.assigneduser', 'assets.assetstatus', 'assets.company');
|
||||
$manufacturer_assets = $manufacturer->assets;
|
||||
|
||||
if (Input::has('search')) {
|
||||
@@ -329,20 +330,22 @@ class ManufacturersController extends Controller
|
||||
'serial' => e($asset->serial),
|
||||
'assigned_to' => ($asset->assigneduser) ? (string)link_to('/admin/users/'.$asset->assigneduser->id.'/view', e($asset->assigneduser->fullName())): '',
|
||||
'actions' => $actions,
|
||||
'companyName' => e(Company::getName($asset)),
|
||||
// 'companyName' => e(Company::getName($asset)),
|
||||
'companyName' => is_null($asset->company) ? '' : $asset->company->name
|
||||
);
|
||||
|
||||
if (isset($inout)) {
|
||||
$row['change'] = $inout;
|
||||
}
|
||||
if (isset($inout)) {
|
||||
$row['change'] = $inout;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
$data = array('total' => $count, 'rows' => $rows);
|
||||
return $data;
|
||||
}
|
||||
|
||||
protected function getDataLicensesView(Manufacturer $manufacturer)
|
||||
{
|
||||
$manufacturer = $manufacturer->load('licenses.company', 'licenses.manufacturer', 'licenses.licenseSeatsRelation');
|
||||
$licenses = $manufacturer->licenses;
|
||||
|
||||
if (Input::has('search')) {
|
||||
@@ -380,7 +383,7 @@ class ManufacturersController extends Controller
|
||||
'id' => $license->id,
|
||||
'name' => (string) link_to('/admin/licenses/'.$license->id.'/view', $license->name),
|
||||
'serial' => (string) link_to('/admin/licenses/'.$license->id.'/view', mb_strimwidth($license->serial, 0, 50, "...")),
|
||||
'totalSeats' => $license->totalSeatsByLicenseID(),
|
||||
'totalSeats' => $license->licenseSeatCount,
|
||||
'remaining' => $license->remaincount(),
|
||||
'license_name' => e($license->license_name),
|
||||
'license_email' => e($license->license_email),
|
||||
@@ -403,6 +406,13 @@ class ManufacturersController extends Controller
|
||||
|
||||
public function getDataAccessoriesView(Manufacturer $manufacturer)
|
||||
{
|
||||
$manufacturer = $manufacturer->load(
|
||||
'accessories.location',
|
||||
'accessories.company',
|
||||
'accessories.category',
|
||||
'accessories.manufacturer',
|
||||
'accessories.users'
|
||||
);
|
||||
$accessories = $manufacturer->accessories;
|
||||
|
||||
if (Input::has('search')) {
|
||||
@@ -461,6 +471,13 @@ class ManufacturersController extends Controller
|
||||
|
||||
public function getDataConsumablesView($manufacturer)
|
||||
{
|
||||
$manufacturer = $manufacturer->load(
|
||||
'consumables.location',
|
||||
'consumables.company',
|
||||
'consumables.category',
|
||||
'consumables.manufacturer',
|
||||
'consumables.users'
|
||||
);
|
||||
$consumables = $manufacturer->consumables;
|
||||
|
||||
if (Input::has('search')) {
|
||||
@@ -504,7 +521,7 @@ class ManufacturersController extends Controller
|
||||
'min_amt' => e($consumable->min_amt),
|
||||
'qty' => e($consumable->qty),
|
||||
'manufacturer' => ($consumable->manufacturer) ? (string) link_to('/admin/settings/manufacturers/'.$consumable->manufacturer_id.'/view', $consumable->manufacturer->name): '',
|
||||
'model_no' => e($consumable->model_no),
|
||||
'model_number' => e($consumable->model_number),
|
||||
'item_no' => e($consumable->item_no),
|
||||
'category' => ($consumable->category) ? (string) link_to('/admin/settings/categories/'.$consumable->category_id.'/view', $consumable->category->name) : 'Missing category',
|
||||
'order_number' => e($consumable->order_number),
|
||||
|
||||
@@ -8,6 +8,8 @@ use App\Models\Location;
|
||||
use View;
|
||||
use Auth;
|
||||
use App\Helpers\Helper;
|
||||
use App\Models\Setting;
|
||||
use Gate;
|
||||
|
||||
/**
|
||||
* This controller handles all actions related to User Profiles for
|
||||
@@ -53,6 +55,11 @@ class ProfileController extends Controller
|
||||
$user->gravatar = e(Input::get('gravatar'));
|
||||
$user->locale = e(Input::get('locale'));
|
||||
|
||||
|
||||
if ((Gate::allows('self.two_factor')) && ((Setting::getSettings()->two_factor_enabled=='1') && (!config('app.lock_passwords')))) {
|
||||
$user->two_factor_optin = e(Input::get('two_factor_optin', '0'));
|
||||
}
|
||||
|
||||
if (Input::file('avatar')) {
|
||||
$image = Input::file('avatar');
|
||||
$file_name = str_slug($user->first_name."-".$user->last_name).".".$image->getClientOriginalExtension();
|
||||
|
||||
@@ -152,7 +152,7 @@ class ReportsController extends Controller
|
||||
$asset->asset_tag,
|
||||
($asset->model->manufacturer) ? $asset->model->manufacturer->name : '',
|
||||
($asset->model) ? $asset->model->name : '',
|
||||
($asset->model->modelno) ? $asset->model->modelno : '',
|
||||
($asset->model->model_number) ? $asset->model->model_number : '',
|
||||
($asset->name) ? $asset->name : '',
|
||||
($asset->serial) ? $asset->serial : '',
|
||||
($asset->assetstatus) ? e($asset->assetstatus->name) : '',
|
||||
@@ -311,7 +311,7 @@ class ReportsController extends Controller
|
||||
$activitylogs = Company::scopeCompanyables(Actionlog::with('item', 'user', 'target'))->orderBy('created_at', 'DESC');
|
||||
|
||||
if (Input::has('search')) {
|
||||
$activity = $activity->TextSearch(e(Input::get('search')));
|
||||
$activitylogs = $activitylogs->TextSearch(e(Input::get('search')));
|
||||
}
|
||||
|
||||
if (Input::has('offset')) {
|
||||
@@ -356,10 +356,12 @@ class ReportsController extends Controller
|
||||
$activity_item = '<a href="'.route('view/hardware', $activity->item_id).'">'.e($activity->item->asset_tag).' - '. e($activity->item->showAssetName()).'</a>';
|
||||
$item_type = 'asset';
|
||||
} elseif ($activity->item) {
|
||||
$activity_item = '<a href="'.route('view/'. $activity->itemType(), $activity->item_id).'">'.e($activity->item->name).'</a>';
|
||||
$activity_item = '<a href="' . route('view/' . $activity->itemType(),
|
||||
$activity->item_id) . '">' . e($activity->item->name) . '</a>';
|
||||
$item_type = $activity->itemType();
|
||||
|
||||
} else {
|
||||
$activity_item = "unkonwn";
|
||||
$activity_item = "unknown (deleted)";
|
||||
$item_type = "null";
|
||||
}
|
||||
|
||||
@@ -378,6 +380,9 @@ class ReportsController extends Controller
|
||||
} else {
|
||||
$activity_target = '';
|
||||
}
|
||||
} elseif (($activity->action_type=='accepted') || ($activity->action_type=='declined')) {
|
||||
$activity_target = '<a href="' . route('view/user', $activity->item->assigneduser->id) . '">' . e($activity->item->assigneduser->fullName()) . '</a>';
|
||||
|
||||
} elseif ($activity->action_type=='requested') {
|
||||
if ($activity->user) {
|
||||
$activity_target = '<a href="'.route('view/user', $activity->user_id).'">'.$activity->user->fullName().'</a>';
|
||||
@@ -448,9 +453,9 @@ class ReportsController extends Controller
|
||||
trans('admin/licenses/form.seats'),
|
||||
trans('admin/licenses/form.remaining_seats'),
|
||||
trans('admin/licenses/form.expiration'),
|
||||
trans('admin/licenses/form.date'),
|
||||
trans('admin/licenses/form.depreciation'),
|
||||
trans('admin/licenses/form.cost')
|
||||
trans('general.purchase_date'),
|
||||
trans('general.depreciation'),
|
||||
trans('general.purchase_cost')
|
||||
];
|
||||
|
||||
$header = array_map('trim', $header);
|
||||
@@ -556,6 +561,9 @@ class ReportsController extends Controller
|
||||
if (e(Input::get('username')) == '1') {
|
||||
$header[] = 'Username';
|
||||
}
|
||||
if (e(Input::get('employee_num')) == '1') {
|
||||
$header[] = 'Employee No.';
|
||||
}
|
||||
if (e(Input::get('status')) == '1') {
|
||||
$header[] = 'Status';
|
||||
}
|
||||
@@ -568,6 +576,14 @@ class ReportsController extends Controller
|
||||
$header[] = 'Value';
|
||||
$header[] = 'Diff';
|
||||
}
|
||||
if (e(Input::get('expected_checkin')) == '1') {
|
||||
$header[] = trans('admin/hardware/form.expected_checkin');
|
||||
}
|
||||
|
||||
if (e(Input::get('notes')) == '1') {
|
||||
$header[] = trans('general.notes');
|
||||
}
|
||||
|
||||
|
||||
foreach ($customfields as $customfield) {
|
||||
if (e(Input::get($customfield->db_column_name())) == '1') {
|
||||
@@ -601,7 +617,7 @@ class ReportsController extends Controller
|
||||
}
|
||||
if (e(Input::get('model')) == '1') {
|
||||
$row[] = '"' . e($asset->model->name) . '"';
|
||||
$row[] = '"' . e($asset->model->modelno) . '"';
|
||||
$row[] = '"' . e($asset->model->model_number) . '"';
|
||||
}
|
||||
if (e(Input::get('category')) == '1') {
|
||||
$row[] = '"' .e($asset->model->category->name) . '"';
|
||||
@@ -670,6 +686,14 @@ class ReportsController extends Controller
|
||||
}
|
||||
}
|
||||
|
||||
if (e(Input::get('employee_num')) == '1') {
|
||||
if ($asset->assigneduser) {
|
||||
$row[] = '"' .e($asset->assigneduser->employee_num). '"';
|
||||
} else {
|
||||
$row[] = ''; // Empty string if unassigned
|
||||
}
|
||||
}
|
||||
|
||||
if (e(Input::get('status')) == '1') {
|
||||
if (( $asset->status_id == '0' ) && ( $asset->assigned_to == '0' )) {
|
||||
$row[] = trans('general.ready_to_deploy');
|
||||
@@ -696,6 +720,21 @@ class ReportsController extends Controller
|
||||
$row[] = '"' . Helper::formatCurrencyOutput($depreciation) . '"';
|
||||
$row[] = '"' . Helper::formatCurrencyOutput($asset->purchase_cost) . '"';
|
||||
}
|
||||
if (e(Input::get('expected_checkin')) == '1') {
|
||||
if ($asset->expected_checkin) {
|
||||
$row[] = '"' .e($asset->expected_checkin). '"';
|
||||
} else {
|
||||
$row[] = ''; // Empty string if blankd
|
||||
}
|
||||
}
|
||||
|
||||
if (e(Input::get('notes')) == '1') {
|
||||
if ($asset->notes) {
|
||||
$row[] = '"' .$asset->notes . '"';
|
||||
} else {
|
||||
$row[] = '';
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($customfields as $customfield) {
|
||||
$column_name = $customfield->db_column_name();
|
||||
@@ -760,7 +799,7 @@ class ReportsController extends Controller
|
||||
$header = [
|
||||
trans('admin/hardware/table.asset_tag'),
|
||||
trans('admin/asset_maintenances/table.asset_name'),
|
||||
trans('admin/asset_maintenances/table.supplier_name'),
|
||||
trans('general.supplier'),
|
||||
trans('admin/asset_maintenances/form.asset_maintenance_type'),
|
||||
trans('admin/asset_maintenances/form.title'),
|
||||
trans('admin/asset_maintenances/form.start_date'),
|
||||
|
||||
@@ -15,6 +15,7 @@ use Response;
|
||||
use Artisan;
|
||||
use Crypt;
|
||||
use Mail;
|
||||
use Auth;
|
||||
use App\Models\User;
|
||||
use App\Http\Requests\SetupUserRequest;
|
||||
|
||||
@@ -184,6 +185,7 @@ class SettingsController extends Controller
|
||||
return redirect()->back()->withInput()->withErrors($user->getErrors())->withErrors($settings->getErrors());
|
||||
} else {
|
||||
$user->save();
|
||||
Auth::login($user, true);
|
||||
$settings->save();
|
||||
|
||||
if (Input::get('email_creds')=='1') {
|
||||
@@ -195,6 +197,7 @@ class SettingsController extends Controller
|
||||
}
|
||||
|
||||
|
||||
|
||||
return redirect()->route('setup.done');
|
||||
}
|
||||
|
||||
@@ -224,6 +227,7 @@ class SettingsController extends Controller
|
||||
*/
|
||||
public function getSetupDone()
|
||||
{
|
||||
|
||||
return View::make('setup/done')
|
||||
->with('step', 4)
|
||||
->with('section', 'Done!');
|
||||
@@ -260,10 +264,7 @@ class SettingsController extends Controller
|
||||
*/
|
||||
public function getIndex()
|
||||
{
|
||||
// Grab all the settings
|
||||
$settings = Setting::all();
|
||||
|
||||
// Show the page
|
||||
return View::make('settings/index', compact('settings'));
|
||||
}
|
||||
|
||||
@@ -316,10 +317,17 @@ class SettingsController extends Controller
|
||||
}
|
||||
|
||||
|
||||
if (config('app.lock_passwords')==false) {
|
||||
if (!config('app.lock_passwords')) {
|
||||
$setting->site_name = e(Input::get('site_name'));
|
||||
$setting->brand = e(Input::get('brand'));
|
||||
$setting->custom_css = e(Input::get('custom_css'));
|
||||
|
||||
if (Input::get('two_factor_enabled')=='') {
|
||||
$setting->two_factor_enabled = null;
|
||||
} else {
|
||||
$setting->two_factor_enabled = e(Input::get('two_factor_enabled'));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (Input::get('per_page')!='') {
|
||||
@@ -345,6 +353,7 @@ class SettingsController extends Controller
|
||||
$setting->email_domain = e(Input::get('email_domain'));
|
||||
$setting->email_format = e(Input::get('email_format'));
|
||||
$setting->username_format = e(Input::get('username_format'));
|
||||
$setting->require_accept_signature = e(Input::get('require_accept_signature'));
|
||||
|
||||
|
||||
$setting->labels_per_page = e(Input::get('labels_per_page'));
|
||||
@@ -360,6 +369,7 @@ class SettingsController extends Controller
|
||||
$setting->labels_pagewidth = e(Input::get('labels_pagewidth'));
|
||||
$setting->labels_pageheight = e(Input::get('labels_pageheight'));
|
||||
|
||||
|
||||
if (Input::has('labels_display_name')) {
|
||||
$setting->labels_display_name = 1;
|
||||
} else {
|
||||
@@ -379,7 +389,7 @@ class SettingsController extends Controller
|
||||
}
|
||||
|
||||
$alert_email = rtrim(Input::get('alert_email'), ',');
|
||||
$alert_email = trim(Input::get('alert_email'));
|
||||
$alert_email = trim($alert_email);
|
||||
|
||||
$setting->alert_email = e($alert_email);
|
||||
$setting->alerts_enabled = e(Input::get('alerts_enabled', '0'));
|
||||
@@ -410,10 +420,8 @@ class SettingsController extends Controller
|
||||
$setting->ldap_tls = e(Input::get('ldap_tls', '0'));
|
||||
$setting->ldap_pw_sync = e(Input::get('ldap_pw_sync', '0'));
|
||||
|
||||
// If validation fails, we'll exit the operation now.
|
||||
if ($setting->save()) {
|
||||
return redirect()->to("admin/settings/app")->with('success', trans('admin/settings/message.update.success'));
|
||||
|
||||
} else {
|
||||
return redirect()->back()->withInput()->withErrors($setting->getErrors());
|
||||
}
|
||||
|
||||
@@ -87,11 +87,11 @@ class StatuslabelsController extends Controller
|
||||
public function getCreate()
|
||||
{
|
||||
// Show the page
|
||||
$statuslabel = new Statuslabel;
|
||||
$use_statuslabel_type = $statuslabel->getStatuslabelType();
|
||||
$item = new Statuslabel;
|
||||
$use_statuslabel_type = $item->getStatuslabelType();
|
||||
$statuslabel_types = Helper::statusTypeList();
|
||||
|
||||
return View::make('statuslabels/edit', compact('statuslabel_types', 'statuslabel'))->with('use_statuslabel_type', $use_statuslabel_type);
|
||||
return View::make('statuslabels/edit', compact('statuslabel_types', 'item'))->with('use_statuslabel_type', $use_statuslabel_type);
|
||||
}
|
||||
|
||||
|
||||
@@ -169,16 +169,16 @@ class StatuslabelsController extends Controller
|
||||
public function getEdit($statuslabelId = null)
|
||||
{
|
||||
// Check if the Statuslabel exists
|
||||
if (is_null($statuslabel = Statuslabel::find($statuslabelId))) {
|
||||
if (is_null($item = Statuslabel::find($statuslabelId))) {
|
||||
// Redirect to the blogs management page
|
||||
return redirect()->to('admin/settings/statuslabels')->with('error', trans('admin/statuslabels/message.does_not_exist'));
|
||||
}
|
||||
|
||||
$use_statuslabel_type = $statuslabel->getStatuslabelType();
|
||||
$use_statuslabel_type = $item->getStatuslabelType();
|
||||
|
||||
$statuslabel_types = array('' => trans('admin/hardware/form.select_statustype')) + array('undeployable' => trans('admin/hardware/general.undeployable')) + array('pending' => trans('admin/hardware/general.pending')) + array('archived' => trans('admin/hardware/general.archived')) + array('deployable' => trans('admin/hardware/general.deployable'));
|
||||
|
||||
return View::make('statuslabels/edit', compact('statuslabel', 'statuslabel_types'))->with('use_statuslabel_type', $use_statuslabel_type);
|
||||
return View::make('statuslabels/edit', compact('item', 'statuslabel_types'))->with('use_statuslabel_type', $use_statuslabel_type);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -45,7 +45,7 @@ class SuppliersController extends Controller
|
||||
*/
|
||||
public function getCreate()
|
||||
{
|
||||
return View::make('suppliers/edit')->with('supplier', new Supplier);
|
||||
return View::make('suppliers/edit')->with('item', new Supplier);
|
||||
}
|
||||
|
||||
|
||||
@@ -125,13 +125,13 @@ class SuppliersController extends Controller
|
||||
public function getEdit($supplierId = null)
|
||||
{
|
||||
// Check if the supplier exists
|
||||
if (is_null($supplier = Supplier::find($supplierId))) {
|
||||
if (is_null($item = Supplier::find($supplierId))) {
|
||||
// Redirect to the supplier page
|
||||
return redirect()->to('admin/settings/suppliers')->with('error', trans('admin/suppliers/message.does_not_exist'));
|
||||
}
|
||||
|
||||
// Show the page
|
||||
return View::make('suppliers/edit', compact('supplier'));
|
||||
return View::make('suppliers/edit', compact('item'));
|
||||
}
|
||||
|
||||
|
||||
@@ -242,7 +242,7 @@ class SuppliersController extends Controller
|
||||
|
||||
public function getDatatable()
|
||||
{
|
||||
$suppliers = Supplier::select(array('id','name','address','address2','city','state','country','fax', 'phone','email','contact'))
|
||||
$suppliers = Supplier::with('assets', 'licenses')->select(array('id','name','address','address2','city','state','country','fax', 'phone','email','contact'))
|
||||
->whereNull('deleted_at');
|
||||
|
||||
if (Input::has('search')) {
|
||||
@@ -283,8 +283,8 @@ class SuppliersController extends Controller
|
||||
'phone' => e($supplier->phone),
|
||||
'fax' => e($supplier->fax),
|
||||
'email' => ($supplier->email!='') ? '<a href="mailto:'.e($supplier->email).'">'.e($supplier->email).'</a>' : '',
|
||||
'assets' => $supplier->num_assets(),
|
||||
'licenses' => $supplier->num_licenses(),
|
||||
'assets' => $supplier->assets->count(),
|
||||
'licenses' => $supplier->licenses->count(),
|
||||
'actions' => $actions
|
||||
);
|
||||
}
|
||||
|
||||
@@ -125,7 +125,16 @@ class UsersController extends Controller
|
||||
$user->company_id = e(Company::getIdForUser($request->input('company_id')));
|
||||
$user->manager_id = e($request->input('manager_id'));
|
||||
$user->notes = e($request->input('notes'));
|
||||
$user->permissions = json_encode($request->input('permission'));
|
||||
|
||||
// Strip out the superuser permission if the user isn't a superadmin
|
||||
$permissions_array = $request->input('permission');
|
||||
|
||||
if (!Auth::user()->isSuperUser()) {
|
||||
unset($permissions_array['superuser']);
|
||||
}
|
||||
|
||||
$user->permissions = json_encode($permissions_array);
|
||||
|
||||
|
||||
|
||||
if ($user->manager_id == "") {
|
||||
@@ -301,26 +310,42 @@ class UsersController extends Controller
|
||||
}
|
||||
|
||||
try {
|
||||
// Get the user information
|
||||
|
||||
$user = User::find($id);
|
||||
|
||||
// Figure out of this user was an admin before this edit
|
||||
$orig_permissions_array = $user->decodePermissions();
|
||||
|
||||
if (is_array($orig_permissions_array)) {
|
||||
if (array_key_exists('superuser', $orig_permissions_array)) {
|
||||
$orig_superuser = $orig_permissions_array['superuser'];
|
||||
} else {
|
||||
$orig_superuser = '0';
|
||||
}
|
||||
} else {
|
||||
$orig_superuser = '0';
|
||||
}
|
||||
|
||||
|
||||
if (!Company::isCurrentUserHasAccess($user)) {
|
||||
return redirect()->route('users')->with('error', trans('general.insufficient_permissions'));
|
||||
}
|
||||
|
||||
} catch (UserNotFoundException $e) {
|
||||
// Prepare the error message
|
||||
$error = trans('admin/users/message.user_not_found', compact('id'));
|
||||
|
||||
// Redirect to the user management page
|
||||
return redirect()->route('users')->with('error', $error);
|
||||
}
|
||||
|
||||
// First handle anything exclusive to editing.
|
||||
if ($request->has('groups')) {
|
||||
$user->groups()->sync($request->input('groups'));
|
||||
} else {
|
||||
$user->groups()->sync(array());
|
||||
|
||||
// Only save groups if the user is a super user
|
||||
if (Auth::user()->isSuperUser()) {
|
||||
if ($request->has('groups')) {
|
||||
$user->groups()->sync($request->input('groups'));
|
||||
} else {
|
||||
$user->groups()->sync(array());
|
||||
}
|
||||
}
|
||||
|
||||
// Do we want to update the user password?
|
||||
if ($request->has('password')) {
|
||||
$user->password = bcrypt($request->input('password'));
|
||||
@@ -334,6 +359,7 @@ class UsersController extends Controller
|
||||
// Update the user
|
||||
$user->first_name = e($request->input('first_name'));
|
||||
$user->last_name = e($request->input('last_name'));
|
||||
$user->two_factor_optin = e($request->input('two_factor_optin'));
|
||||
$user->locale = e($request->input('locale'));
|
||||
$user->employee_num = e($request->input('employee_num'));
|
||||
$user->activated = e($request->input('activated', $user->activated));
|
||||
@@ -343,7 +369,17 @@ class UsersController extends Controller
|
||||
$user->company_id = e(Company::getIdForUser($request->input('company_id')));
|
||||
$user->manager_id = e($request->input('manager_id'));
|
||||
$user->notes = e($request->input('notes'));
|
||||
$user->permissions = json_encode($request->input('permission'));
|
||||
|
||||
// Strip out the superuser permission if the user isn't a superadmin
|
||||
$permissions_array = $request->input('permission');
|
||||
|
||||
if (!Auth::user()->isSuperUser()) {
|
||||
unset($permissions_array['superuser']);
|
||||
$permissions_array['superuser'] = $orig_superuser;
|
||||
}
|
||||
|
||||
|
||||
$user->permissions = json_encode($permissions_array);
|
||||
|
||||
if ($user->manager_id == "") {
|
||||
$user->manager_id = null;
|
||||
@@ -389,17 +425,12 @@ class UsersController extends Controller
|
||||
|
||||
// Check if we are not trying to delete ourselves
|
||||
if ($user->id === Auth::user()->id) {
|
||||
// Prepare the error message
|
||||
$error = trans('admin/users/message.error.delete');
|
||||
|
||||
// Redirect to the user management page
|
||||
return redirect()->route('users')->with('error', $error);
|
||||
return redirect()->route('users')->with('error', trans('admin/users/message.error.delete'));
|
||||
}
|
||||
|
||||
|
||||
// Do we have permission to delete this user?
|
||||
if ((!Auth::user()->isSuperUser()) || (config('app.lock_passwords'))) {
|
||||
// Redirect to the user management page
|
||||
if ((Gate::denies('users.delete') || (config('app.lock_passwords')))) {
|
||||
return redirect()->route('users')->with('error', 'Insufficient permissions!');
|
||||
}
|
||||
|
||||
@@ -423,18 +454,11 @@ class UsersController extends Controller
|
||||
|
||||
// Delete the user
|
||||
$user->delete();
|
||||
|
||||
// Prepare the success message
|
||||
$success = trans('admin/users/message.success.delete');
|
||||
|
||||
// Redirect to the user management page
|
||||
return redirect()->route('users')->with('success', $success);
|
||||
} catch (UserNotFoundException $e) {
|
||||
// Prepare the error message
|
||||
$error = trans('admin/users/message.user_not_found', compact('id'));
|
||||
|
||||
// Redirect to the user management page
|
||||
return redirect()->route('users')->with('error', $error);
|
||||
} catch (UserNotFoundException $e) {
|
||||
return redirect()->route('users')->with('error', trans('admin/users/message.user_not_found', compact('id')));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -486,10 +510,7 @@ class UsersController extends Controller
|
||||
if (($key = array_search(Auth::user()->id, $user_raw_array)) !== false) {
|
||||
unset($user_raw_array[$key]);
|
||||
}
|
||||
|
||||
if (!Auth::user()->isSuperUser()) {
|
||||
return redirect()->route('users')->with('error', trans('admin/users/message.insufficient_permissions'));
|
||||
}
|
||||
|
||||
|
||||
if (!config('app.lock_passwords')) {
|
||||
|
||||
@@ -829,7 +850,6 @@ class UsersController extends Controller
|
||||
'permissions' => '{"user":1}',
|
||||
'notes' => 'Imported user'
|
||||
);
|
||||
//dd($newuser);
|
||||
|
||||
DB::table('users')->insert($newuser);
|
||||
|
||||
@@ -892,7 +912,7 @@ class UsersController extends Controller
|
||||
$sort = e(Input::get('sort'));
|
||||
}
|
||||
|
||||
$users = User::select(array('users.id','users.employee_num','users.jobtitle','users.email','users.username','users.location_id','users.manager_id','users.first_name','users.last_name','users.created_at','users.notes','users.company_id', 'users.deleted_at','users.activated'))
|
||||
$users = User::select(array('users.id','users.employee_num','users.two_factor_enrolled','users.jobtitle','users.email','users.username','users.location_id','users.manager_id','users.first_name','users.last_name','users.created_at','users.notes','users.company_id', 'users.deleted_at','users.activated'))
|
||||
->with('assets', 'accessories', 'consumables', 'licenses', 'manager', 'groups', 'userloc', 'company','throttle');
|
||||
$users = Company::scopeCompanyables($users);
|
||||
|
||||
@@ -919,7 +939,8 @@ class UsersController extends Controller
|
||||
$allowed_columns =
|
||||
[
|
||||
'last_name','first_name','email','jobtitle','username','employee_num',
|
||||
'assets','accessories', 'consumables','licenses','groups','activated','created_at'
|
||||
'assets','accessories', 'consumables','licenses','groups','activated','created_at',
|
||||
'two_factor_enrolled','two_factor_optin'
|
||||
];
|
||||
|
||||
$sort = in_array($sort, $allowed_columns) ? $sort : 'first_name';
|
||||
@@ -969,7 +990,7 @@ class UsersController extends Controller
|
||||
$actions .= ' <span class="btn delete-asset btn-danger btn-sm disabled"><i class="fa fa-trash icon-white"></i></span>';
|
||||
}
|
||||
} else {
|
||||
$actions.='foo';
|
||||
$actions.='';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -978,7 +999,7 @@ class UsersController extends Controller
|
||||
$rows[] = array(
|
||||
'id' => $user->id,
|
||||
'checkbox' => ($status!='deleted') ? '<div class="text-center hidden-xs hidden-sm"><input type="checkbox" name="edit_user['.e($user->id).']" class="one_required"></div>' : '',
|
||||
'name' => '<a title="'.e($user->fullName()).'" href="../admin/users/'.e($user->id).'/view">'.e($user->fullName()).'</a>',
|
||||
'name' => '<a title="'.e($user->fullName()).'" href="'.config('app.url').'/admin/users/'.e($user->id).'/view">'.e($user->fullName()).'</a>',
|
||||
'jobtitle' => e($user->jobtitle),
|
||||
'email' => ($user->email!='') ?
|
||||
'<a href="mailto:'.e($user->email).'" class="hidden-md hidden-lg">'.e($user->email).'</a>'
|
||||
@@ -986,7 +1007,7 @@ class UsersController extends Controller
|
||||
.'</span>' : '',
|
||||
'username' => e($user->username),
|
||||
'location' => ($user->userloc) ? e($user->userloc->name) : '',
|
||||
'manager' => ($user->manager) ? '<a title="' . e($user->manager->fullName()) . '" href="users/' . e($user->manager->id) . '/view">' . e($user->manager->fullName()) . '</a>' : '',
|
||||
'manager' => ($user->manager) ? '<a title="' . e($user->manager->fullName()) . '" href="'.config('app.url').'/' . e($user->manager->id) . '/view">' . e($user->manager->fullName()) . '</a>' : '',
|
||||
'assets' => $user->assets->count(),
|
||||
'employee_num' => e($user->employee_num),
|
||||
'licenses' => $user->licenses->count(),
|
||||
@@ -994,8 +1015,10 @@ class UsersController extends Controller
|
||||
'consumables' => $user->consumables->count(),
|
||||
'groups' => $group_names,
|
||||
'notes' => e($user->notes),
|
||||
'two_factor_enrolled' => ($user->two_factor_enrolled=='1') ? '<i class="fa fa-check text-success"></i>' : '<i class="fa fa-times text-danger"></i>',
|
||||
'two_factor_optin' => (($user->two_factor_optin=='1') || (Setting::getSettings()->two_factor_enabled=='2') ) ? '<i class="fa fa-check text-success"></i>' : '<i class="fa fa-times text-danger"></i>',
|
||||
'created_at' => ($user->created_at!='') ? e($user->created_at->format('F j, Y h:iA')) : '',
|
||||
'activated' => ($user->activated=='1') ? '<i class="fa fa-check"></i>' : '<i class="fa fa-times"></i>',
|
||||
'activated' => ($user->activated=='1') ? '<i class="fa fa-check text-success"></i>' : '<i class="fa fa-times text-danger"></i>',
|
||||
'actions' => ($actions) ? $actions : '',
|
||||
'companyName' => is_null($user->company) ? '' : e($user->company->name)
|
||||
);
|
||||
@@ -1068,7 +1091,6 @@ class UsersController extends Controller
|
||||
$user = User::find($userId);
|
||||
$destinationPath = config('app.private_uploads').'/users';
|
||||
|
||||
// the license is valid
|
||||
if (isset($user->id)) {
|
||||
|
||||
if (!Company::isCurrentUserHasAccess($user)) {
|
||||
@@ -1365,4 +1387,25 @@ class UsersController extends Controller
|
||||
return $response;
|
||||
|
||||
}
|
||||
|
||||
|
||||
public function postTwoFactorReset(Request $request)
|
||||
{
|
||||
if (Gate::denies('users.edit')) {
|
||||
return response()->json(['message' => trans('general.insufficient_permissions')], 500);
|
||||
}
|
||||
|
||||
try {
|
||||
$user = User::find($request->get('id'));
|
||||
$user->two_factor_secret = null;
|
||||
$user->two_factor_enrolled = 0;
|
||||
$user->save();
|
||||
return response()->json(['message' => trans('admin/settings/general.two_factor_reset_success')], 200);
|
||||
} catch (\Exception $e) {
|
||||
return response()->json(['message' => trans('admin/settings/general.two_factor_reset_error')], 500);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@ use Redirect;
|
||||
use Slack;
|
||||
use Validator;
|
||||
use View;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
/**
|
||||
* This controller handles all actions related to the ability for users
|
||||
@@ -294,10 +295,14 @@ class ViewAssetsController extends Controller
|
||||
//return redirect()->to('account')->with('error', trans('admin/hardware/message.does_not_exist'));
|
||||
}
|
||||
|
||||
if ($findlog->accepted_id!='') {
|
||||
return redirect()->to('account/view-assets')->with('error', trans('admin/users/message.error.asset_already_accepted'));
|
||||
}
|
||||
|
||||
$user = Auth::user();
|
||||
|
||||
if ($user->id != $findlog->checkedout_to) {
|
||||
|
||||
if ($user->id != $findlog->item->assigned_to) {
|
||||
return redirect()->to('account/view-assets')->with('error', trans('admin/users/message.error.incorrect_user_accepted'));
|
||||
}
|
||||
|
||||
@@ -310,12 +315,12 @@ class ViewAssetsController extends Controller
|
||||
} elseif (!Company::isCurrentUserHasAccess($item)) {
|
||||
return redirect()->route('requestable-assets')->with('error', trans('general.insufficient_permissions'));
|
||||
} else {
|
||||
return View::make('account/accept-asset', compact('item'))->with('findlog', $findlog);
|
||||
return View::make('account/accept-asset', compact('item'))->with('findlog', $findlog)->with('item',$item);
|
||||
}
|
||||
}
|
||||
|
||||
// Save the acceptance
|
||||
public function postAcceptAsset($logID = null)
|
||||
public function postAcceptAsset(Request $request, $logID = null)
|
||||
{
|
||||
|
||||
// Check if the asset exists
|
||||
@@ -331,15 +336,25 @@ class ViewAssetsController extends Controller
|
||||
}
|
||||
|
||||
if (!Input::has('asset_acceptance')) {
|
||||
return redirect()->to('account/view-assets')->with('error', trans('admin/users/message.error.accept_or_decline'));
|
||||
return redirect()->back()->with('error', trans('admin/users/message.error.accept_or_decline'));
|
||||
}
|
||||
|
||||
$user = Auth::user();
|
||||
|
||||
if ($user->id != $findlog->checkedout_to) {
|
||||
if ($user->id != $findlog->item->assigned_to) {
|
||||
return redirect()->to('account/view-assets')->with('error', trans('admin/users/message.error.incorrect_user_accepted'));
|
||||
}
|
||||
|
||||
if ($request->has('signature_output')) {
|
||||
$path = config('app.private_uploads').'/signatures';
|
||||
$sig_filename = "siglog-".$findlog->id.'-'.date('Y-m-d-his').".png";
|
||||
$data_uri = e($request->get('signature_output'));
|
||||
$encoded_image = explode(",", $data_uri);
|
||||
$decoded_image = base64_decode($encoded_image[1]);
|
||||
file_put_contents($path."/".$sig_filename, $decoded_image);
|
||||
}
|
||||
|
||||
|
||||
$logaction = new Actionlog();
|
||||
|
||||
if (Input::get('asset_acceptance')=='accepted') {
|
||||
@@ -353,6 +368,7 @@ class ViewAssetsController extends Controller
|
||||
}
|
||||
$logaction->item_id = $findlog->item_id;
|
||||
$logaction->item_type = $findlog->item_type;
|
||||
|
||||
// Asset
|
||||
if (($findlog->item_id!='') && ($findlog->item_type==Asset::class)) {
|
||||
if (Input::get('asset_acceptance')!='accepted') {
|
||||
@@ -361,19 +377,24 @@ class ViewAssetsController extends Controller
|
||||
->update(array('assigned_to' => null));
|
||||
}
|
||||
}
|
||||
$logaction->target_id = $findlog->target_id;
|
||||
|
||||
$logaction->target_id = $findlog->target_id;
|
||||
$logaction->target_type = User::class;
|
||||
$logaction->note = e(Input::get('note'));
|
||||
$logaction->user_id = $user->id;
|
||||
$logaction->accepted_at = date("Y-m-d H:i:s");
|
||||
$logaction->updated_at = date("Y-m-d H:i:s");
|
||||
|
||||
|
||||
if (isset($sig_filename)) {
|
||||
$logaction->accept_signature = $sig_filename;
|
||||
}
|
||||
$log = $logaction->logaction($logaction_msg);
|
||||
|
||||
$update_checkout = DB::table('action_logs')
|
||||
->where('id', $findlog->id)
|
||||
->update(array('accepted_id' => $logaction->id));
|
||||
|
||||
$affected_asset=$logaction->assetlog;
|
||||
$affected_asset->accepted=$accepted;
|
||||
$affected_asset = $logaction->item;
|
||||
$affected_asset->accepted = $accepted;
|
||||
$affected_asset->save();
|
||||
|
||||
if ($update_checkout) {
|
||||
|
||||
@@ -22,6 +22,7 @@ class Kernel extends HttpKernel
|
||||
\App\Http\Middleware\NosniffGuard::class,
|
||||
\App\Http\Middleware\CheckForSetup::class,
|
||||
\Fideloper\Proxy\TrustProxies::class,
|
||||
\App\Http\Middleware\CheckForDebug::class,
|
||||
];
|
||||
|
||||
/**
|
||||
@@ -35,6 +36,7 @@ class Kernel extends HttpKernel
|
||||
\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
|
||||
\App\Http\Middleware\VerifyCsrfToken::class,
|
||||
\App\Http\Middleware\CheckLocale::class,
|
||||
\App\Http\Middleware\CheckForTwoFactor::class,
|
||||
],
|
||||
|
||||
'api' => [
|
||||
|
||||
27
app/Http/Middleware/CheckForDebug.php
Normal file
27
app/Http/Middleware/CheckForDebug.php
Normal file
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Middleware;
|
||||
|
||||
use Closure;
|
||||
use Auth;
|
||||
|
||||
class CheckForDebug
|
||||
{
|
||||
/**
|
||||
* Handle an incoming request.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \Closure $next
|
||||
* @return mixed
|
||||
*/
|
||||
public function handle($request, Closure $next)
|
||||
{
|
||||
view()->share('debug_in_production', false);
|
||||
|
||||
if (((Auth::check() && (Auth::user()->isSuperUser()))) && (app()->environment()=='production') && (config('app.warn_debug')===true) && (config('app.debug')===true)) {
|
||||
view()->share('debug_in_production', true);
|
||||
}
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
}
|
||||
@@ -14,6 +14,11 @@ class CheckForSetup
|
||||
public function handle($request, Closure $next, $guard = null)
|
||||
{
|
||||
|
||||
// This is dumb
|
||||
if ($request->is('_debugbar*')) {
|
||||
return $next($request);
|
||||
}
|
||||
|
||||
if (Setting::setupCompleted()) {
|
||||
|
||||
if ($request->is('setup*')) {
|
||||
|
||||
52
app/Http/Middleware/CheckForTwoFactor.php
Normal file
52
app/Http/Middleware/CheckForTwoFactor.php
Normal file
@@ -0,0 +1,52 @@
|
||||
<?php
|
||||
namespace App\Http\Middleware;
|
||||
|
||||
use App\Models\Setting;
|
||||
use Auth;
|
||||
use Closure;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
use Log;
|
||||
|
||||
class CheckForTwoFactor
|
||||
{
|
||||
/**
|
||||
* Handle an incoming request.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \Closure $next
|
||||
* @return mixed
|
||||
*/
|
||||
public function handle($request, Closure $next)
|
||||
{
|
||||
|
||||
// Skip the logic if the user is on the two factor pages or the setup pages
|
||||
if (($request->route()->getName()=='two-factor') || ($request->route()->getName()=='two-factor-enroll') || ($request->route()->getPrefix()=='setup') || ($request->route()->getName()=='logout')) {
|
||||
return $next($request);
|
||||
}
|
||||
|
||||
// Two-factor is enabled (either optional or required)
|
||||
if (Setting::getSettings()) {
|
||||
if (Auth::check() && (Setting::getSettings()->two_factor_enabled!='')) {
|
||||
|
||||
// This user is already 2fa-authed
|
||||
if ($request->session()->get('2fa_authed')) {
|
||||
return $next($request);
|
||||
}
|
||||
|
||||
// Two-factor is optional and the user has NOT opted in, let them through
|
||||
if ((Setting::getSettings()->two_factor_enabled=='1') && (Auth::user()->two_factor_optin!='1')) {
|
||||
return $next($request);
|
||||
}
|
||||
|
||||
// Otherwise make sure they're enrolled and show them the 2FA code screen
|
||||
if ((Auth::user()->two_factor_secret!='') && (Auth::user()->two_factor_enrolled=='1')) {
|
||||
return redirect()->route('two-factor')->with('info', 'Please enter your two-factor authentication code.');
|
||||
}
|
||||
|
||||
return redirect()->route('two-factor-enroll')->with('success', 'Please enroll a device in two-factor authentication.');
|
||||
}
|
||||
}
|
||||
return $next($request);
|
||||
|
||||
}
|
||||
}
|
||||
@@ -21,7 +21,9 @@ class CheckLocale
|
||||
|
||||
public function handle($request, Closure $next, $guard = null)
|
||||
{
|
||||
if (Schema::hasTable('settings')) {
|
||||
|
||||
|
||||
if (Setting::getSettings()) {
|
||||
// User's preference
|
||||
if (($request->user()) && ($request->user()->locale)) {
|
||||
\App::setLocale($request->user()->locale);
|
||||
|
||||
@@ -22,7 +22,8 @@ class CheckPermissions
|
||||
*/
|
||||
public function handle($request, Closure $next, $section = null)
|
||||
{
|
||||
|
||||
|
||||
|
||||
if (Gate::allows($section)) {
|
||||
return $next($request);
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@ class RedirectIfAuthenticated
|
||||
public function handle($request, Closure $next, $guard = null)
|
||||
{
|
||||
if (Auth::guard($guard)->check()) {
|
||||
return redirect('/');
|
||||
return redirect()->intended('/');
|
||||
}
|
||||
|
||||
return $next($request);
|
||||
|
||||
@@ -90,6 +90,7 @@ Route::group([ 'prefix' => 'api', 'middleware' => 'auth' ], function () {
|
||||
/*---Users API---*/
|
||||
Route::group([ 'prefix' => 'users' ], function () {
|
||||
Route::post('/', [ 'as' => 'api.users.store', 'uses' => 'UsersController@store' ]);
|
||||
Route::post('two_factor_reset', [ 'as' => 'api.users.two_factor_reset', 'uses' => 'UsersController@postTwoFactorReset' ]);
|
||||
Route::get('list/{status?}', [ 'as' => 'api.users.list', 'uses' => 'UsersController@getDatatable' ]);
|
||||
Route::get('{userId}/assets', [ 'as' => 'api.users.assetlist', 'uses' => 'UsersController@getAssetList' ]);
|
||||
Route::post('{userId}/upload', [ 'as' => 'upload/user', 'uses' => 'UsersController@postUpload' ]);
|
||||
@@ -378,6 +379,30 @@ Route::group(
|
||||
}
|
||||
);
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Log Routes
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Register all the admin routes.
|
||||
|
|
||||
*/
|
||||
|
||||
Route::group(['middleware' => 'auth'], function () {
|
||||
|
||||
Route::get(
|
||||
'display-sig/{filename}',
|
||||
[
|
||||
'as' => 'log.signature.view',
|
||||
'middleware' => 'authorize:assets.view',
|
||||
'uses' => 'ActionlogController@displaySig' ]
|
||||
);
|
||||
|
||||
|
||||
});
|
||||
|
||||
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Admin Routes
|
||||
@@ -456,17 +481,30 @@ Route::group([ 'prefix' => 'admin','middleware' => ['web','auth']], function ()
|
||||
# Asset Maintenances
|
||||
Route::group([ 'prefix' => 'asset_maintenances', 'middleware'=>'authorize:assets.view' ], function () {
|
||||
|
||||
Route::get(
|
||||
'create/{assetId?}',
|
||||
[ 'as' => 'create/asset_maintenances', 'uses' => 'AssetMaintenancesController@getCreate' ]
|
||||
);
|
||||
Route::post('create/{assetId?}', 'AssetMaintenancesController@postCreate');
|
||||
Route::get('/', [ 'as' => 'asset_maintenances', 'uses' => 'AssetMaintenancesController@getIndex' ]);
|
||||
Route::get(
|
||||
'{assetMaintenanceId}/edit',
|
||||
[ 'as' => 'update/asset_maintenance', 'uses' => 'AssetMaintenancesController@getEdit' ]
|
||||
);
|
||||
Route::post('{assetMaintenanceId}/edit', 'AssetMaintenancesController@postEdit');
|
||||
Route::get('create/{assetId?}',
|
||||
[ 'as' => 'create/asset_maintenances',
|
||||
'middleware' => 'authorize:assets.edit',
|
||||
'uses' => 'AssetMaintenancesController@getCreate'
|
||||
]);
|
||||
|
||||
Route::post('create/{assetId?}',
|
||||
[ 'as' => 'create/asset_maintenances.save',
|
||||
'middleware' => 'authorize:assets.edit',
|
||||
'uses' => 'AssetMaintenancesController@postCreate'
|
||||
]);
|
||||
|
||||
Route::get('{assetMaintenanceId}/edit',
|
||||
[ 'as' => 'update/asset_maintenance',
|
||||
'middleware' => 'authorize:assets.edit',
|
||||
'uses' => 'AssetMaintenancesController@getEdit'
|
||||
]);
|
||||
|
||||
Route::post('{assetMaintenanceId}/edit',
|
||||
[ 'as' => 'update/asset_maintenance.save',
|
||||
'middleware' => 'authorize:assets.edit',
|
||||
'uses' => 'AssetMaintenancesController@postEdit'
|
||||
]);
|
||||
|
||||
Route::get(
|
||||
'{assetMaintenanceId}/delete',
|
||||
[ 'as' => 'delete/asset_maintenance', 'uses' => 'AssetMaintenancesController@getDelete' ]
|
||||
@@ -475,6 +513,8 @@ Route::group([ 'prefix' => 'admin','middleware' => ['web','auth']], function ()
|
||||
'{assetMaintenanceId}/view',
|
||||
[ 'as' => 'view/asset_maintenance', 'uses' => 'AssetMaintenancesController@getView' ]
|
||||
);
|
||||
|
||||
Route::get('/', [ 'as' => 'asset_maintenances', 'uses' => 'AssetMaintenancesController@getIndex' ]);
|
||||
});
|
||||
|
||||
# Accessories
|
||||
@@ -779,7 +819,7 @@ Route::group([ 'prefix' => 'admin','middleware' => ['web','auth']], function ()
|
||||
Route::post('{userId}/edit', [ 'uses' => 'UsersController@postEdit', 'middleware' => ['authorize:users.edit'] ]);
|
||||
Route::get('{userId}/clone', [ 'as' => 'clone/user', 'uses' => 'UsersController@getClone', 'middleware' => ['authorize:users.edit'] ]);
|
||||
Route::post('{userId}/clone', [ 'uses' => 'UsersController@postCreate', 'middleware' => ['authorize:users.edit'] ]);
|
||||
Route::get('{userId}/delete', [ 'as' => 'delete/user', 'uses' => 'UsersController@getDelete', 'middleware' => ['authorize:users.edit'] ]);
|
||||
Route::get('{userId}/delete', [ 'as' => 'delete/user', 'uses' => 'UsersController@getDelete', 'middleware' => ['authorize:users.delete'] ]);
|
||||
Route::get('{userId}/restore', [ 'as' => 'restore/user', 'uses' => 'UsersController@getRestore', 'middleware' => ['authorize:users.edit'] ]);
|
||||
Route::get('{userId}/view', [ 'as' => 'view/user', 'uses' => 'UsersController@getView' , 'middleware' => ['authorize:users.view'] ]);
|
||||
Route::get('{userId}/unsuspend', [ 'as' => 'unsuspend/user', 'uses' => 'UsersController@getUnsuspend', 'middleware' => ['authorize:users.edit'] ]);
|
||||
@@ -997,6 +1037,29 @@ Route::group([ 'prefix' => 'setup', 'middleware' => 'web'], function () {
|
||||
|
||||
});
|
||||
|
||||
Route::get(
|
||||
'two-factor-enroll',
|
||||
[
|
||||
'as' => 'two-factor-enroll',
|
||||
'middleware' => ['web'],
|
||||
'uses' => 'Auth\AuthController@getTwoFactorEnroll' ]
|
||||
);
|
||||
|
||||
Route::get(
|
||||
'two-factor',
|
||||
[
|
||||
'as' => 'two-factor',
|
||||
'middleware' => ['web'],
|
||||
'uses' => 'Auth\AuthController@getTwoFactorAuth' ]
|
||||
);
|
||||
|
||||
Route::post(
|
||||
'two-factor',
|
||||
[
|
||||
'as' => 'two-factor',
|
||||
'middleware' => ['web'],
|
||||
'uses' => 'Auth\AuthController@postTwoFactorAuth' ]
|
||||
);
|
||||
|
||||
Route::get(
|
||||
'/',
|
||||
@@ -1006,8 +1069,24 @@ Route::get(
|
||||
'uses' => 'DashboardController@getIndex' ]
|
||||
);
|
||||
|
||||
|
||||
|
||||
Route::group(['middleware' => 'web'], function () {
|
||||
Route::auth();
|
||||
Route::get(
|
||||
'login',
|
||||
[
|
||||
'as' => 'login',
|
||||
'middleware' => ['web'],
|
||||
'uses' => 'Auth\AuthController@showLoginForm' ]
|
||||
);
|
||||
Route::get(
|
||||
'logout',
|
||||
[
|
||||
'as' => 'logout',
|
||||
'uses' => 'Auth\AuthController@logout' ]
|
||||
);
|
||||
|
||||
});
|
||||
|
||||
Route::get('home', function () {
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
namespace App\Models;
|
||||
|
||||
use App\Models\Loggable;
|
||||
use App\Models\SnipeModel;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
use Watson\Validating\ValidatingTrait;
|
||||
@@ -11,7 +12,7 @@ use Watson\Validating\ValidatingTrait;
|
||||
*
|
||||
* @version v1.0
|
||||
*/
|
||||
class Accessory extends Model
|
||||
class Accessory extends SnipeModel
|
||||
{
|
||||
use CompanyableTrait;
|
||||
use Loggable;
|
||||
@@ -28,7 +29,7 @@ class Accessory extends Model
|
||||
'qty' => 'required|integer|min:1',
|
||||
'category_id' => 'required|integer',
|
||||
'company_id' => 'integer',
|
||||
'min_amt' => 'integer|min:1',
|
||||
'min_amt' => 'integer|min:0',
|
||||
'purchase_cost' => 'numeric',
|
||||
);
|
||||
|
||||
@@ -153,6 +154,7 @@ class Accessory extends Model
|
||||
$query->where('locations.name', 'LIKE', '%'.$search.'%');
|
||||
});
|
||||
})->orWhere('accessories.name', 'LIKE', '%'.$search.'%')
|
||||
->orWhere('accessories.model_number', 'LIKE', '%'.$search.'%')
|
||||
->orWhere('accessories.order_number', 'LIKE', '%'.$search.'%')
|
||||
->orWhere('accessories.purchase_cost', 'LIKE', '%'.$search.'%')
|
||||
->orWhere('accessories.purchase_date', 'LIKE', '%'.$search.'%');
|
||||
|
||||
@@ -4,8 +4,7 @@ namespace App\Models;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Response;
|
||||
|
||||
/**
|
||||
* Model for the Actionlog (the table that keeps a historical log of
|
||||
@@ -46,6 +45,10 @@ class Actionlog extends Model
|
||||
return $this->morphTo('item')->withTrashed();
|
||||
}
|
||||
|
||||
public function company() {
|
||||
return $this->hasMany('\App\Models\Company', 'id','company_id');
|
||||
}
|
||||
|
||||
public function itemType()
|
||||
{
|
||||
|
||||
@@ -91,15 +94,14 @@ class Actionlog extends Model
|
||||
/**
|
||||
* Check if the file exists, and if it does, force a download
|
||||
**/
|
||||
public function get_src($type = 'assets')
|
||||
public function get_src($type = 'assets', $fieldname = 'filename')
|
||||
{
|
||||
|
||||
$file = config('app.private_uploads') . '/' . $type . '/' . $this->filename;
|
||||
|
||||
$file = config('app.private_uploads') . '/' . $type . '/' . $this->{$fieldname};
|
||||
return $file;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Get the parent category name
|
||||
*/
|
||||
@@ -131,4 +133,30 @@ class Actionlog extends Model
|
||||
->orderBy('created_at', 'asc')
|
||||
->get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Query builder scope to search on text for complex Bootstrap Tables API
|
||||
*
|
||||
* @param Illuminate\Database\Query\Builder $query Query builder instance
|
||||
* @param text $search Search term
|
||||
*
|
||||
* @return Illuminate\Database\Query\Builder Modified query builder
|
||||
*/
|
||||
public function scopeTextSearch($query, $search)
|
||||
{
|
||||
$search = explode(' OR ', $search);
|
||||
|
||||
return $query->where(function ($query) use ($search) {
|
||||
|
||||
foreach ($search as $search) {
|
||||
$query->where(function ($query) use ($search) {
|
||||
$query->whereHas('company', function ($query) use ($search) {
|
||||
$query->where('companies.name', 'LIKE', '%'.$search.'%');
|
||||
});
|
||||
})->orWhere('action_type', 'LIKE', '%'.$search.'%')
|
||||
->orWhere('note', 'LIKE', '%'.$search.'%');
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -217,7 +217,8 @@ class Asset extends Depreciable
|
||||
$logaction->item_type = Asset::class;
|
||||
$logaction->item_id = $this->id;
|
||||
$logaction->target_type = User::class;
|
||||
$logaction->target_id = $this->assigned_to;
|
||||
// On Checkin, this is the user that previously had the asset.
|
||||
$logaction->target_id = $user->id;
|
||||
$logaction->note = $note;
|
||||
$logaction->user_id = $admin->id;
|
||||
if ($checkout_at!='') {
|
||||
@@ -232,7 +233,6 @@ class Asset extends Depreciable
|
||||
}
|
||||
} else {
|
||||
// Update the asset data to null, since it's being checked in
|
||||
$logaction->target_id = '';
|
||||
$logaction->location_id = null;
|
||||
}
|
||||
$logaction->user()->associate($admin);
|
||||
@@ -329,8 +329,7 @@ class Asset extends Depreciable
|
||||
{
|
||||
|
||||
return $this->hasMany('\App\Models\AssetMaintenance', 'asset_id')
|
||||
->orderBy('created_at', 'desc')
|
||||
->withTrashed();
|
||||
->orderBy('created_at', 'desc');
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -400,6 +399,11 @@ class Asset extends Depreciable
|
||||
}
|
||||
}
|
||||
|
||||
public function getDisplayNameAttribute()
|
||||
{
|
||||
return $this->showAssetName();
|
||||
}
|
||||
|
||||
public function warrantee_expires()
|
||||
{
|
||||
$date = date_create($this->purchase_date);
|
||||
@@ -481,9 +485,12 @@ class Asset extends Depreciable
|
||||
$settings = \App\Models\Setting::getSettings();
|
||||
|
||||
if ($settings->auto_increment_assets == '1') {
|
||||
$asset_tag = \DB::table('assets')
|
||||
$temp_asset_tag = \DB::table('assets')
|
||||
->where('physical', '=', '1')
|
||||
->max('id');
|
||||
->max('asset_tag');
|
||||
|
||||
$asset_tag_digits = preg_replace('/\D/', '', $temp_asset_tag);
|
||||
$asset_tag = preg_replace('/^0*/', '', $asset_tag_digits);
|
||||
|
||||
if ($settings->zerofill_count > 0) {
|
||||
return $settings->auto_increment_prefix.Asset::zerofill(($asset_tag + 1),$settings->zerofill_count);
|
||||
@@ -788,7 +795,7 @@ public function checkin_email()
|
||||
$query->where(function ($query) use ($search) {
|
||||
$query->where('categories.name', 'LIKE', '%'.$search.'%')
|
||||
->orWhere('models.name', 'LIKE', '%'.$search.'%')
|
||||
->orWhere('models.modelno', 'LIKE', '%'.$search.'%');
|
||||
->orWhere('models.model_number', 'LIKE', '%'.$search.'%');
|
||||
});
|
||||
});
|
||||
})->orWhereHas('model', function ($query) use ($search) {
|
||||
@@ -856,21 +863,21 @@ public function checkin_email()
|
||||
*/
|
||||
public function scopeOrderModelNumber($query, $order)
|
||||
{
|
||||
return $query->join('models', 'assets.model_id', '=', 'models.id')->orderBy('models.modelno', $order);
|
||||
return $query->join('models', 'assets.model_id', '=', 'models.id')->orderBy('models.model_number', $order);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Query builder scope to order on assigned user
|
||||
*
|
||||
* @param Illuminate\Database\Query\Builder $query Query builder instance
|
||||
* @param text $order Order
|
||||
*
|
||||
* @return Illuminate\Database\Query\Builder Modified query builder
|
||||
*/
|
||||
/**
|
||||
* Query builder scope to order on assigned user
|
||||
*
|
||||
* @param Illuminate\Database\Query\Builder $query Query builder instance
|
||||
* @param text $order Order
|
||||
*
|
||||
* @return Illuminate\Database\Query\Builder Modified query builder
|
||||
*/
|
||||
public function scopeOrderAssigned($query, $order)
|
||||
{
|
||||
return $query->join('users', 'assets.assigned_to', '=', 'users.id')->orderBy('users.first_name', $order)->orderBy('users.last_name', $order);
|
||||
return $query->leftJoin('users', 'assets.assigned_to', '=', 'users.id')->select('assets.*')->orderBy('users.first_name', $order)->orderBy('users.last_name', $order);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
namespace App\Models;
|
||||
|
||||
use App\Models\Requestable;
|
||||
use App\Models\SnipeModel;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
use Watson\Validating\ValidatingTrait;
|
||||
@@ -12,7 +13,7 @@ use Watson\Validating\ValidatingTrait;
|
||||
*
|
||||
* @version v1.0
|
||||
*/
|
||||
class AssetModel extends Model
|
||||
class AssetModel extends SnipeModel
|
||||
{
|
||||
use SoftDeletes;
|
||||
use Requestable;
|
||||
@@ -22,7 +23,7 @@ class AssetModel extends Model
|
||||
// Declare the rules for the model validation
|
||||
protected $rules = array(
|
||||
'name' => 'required|min:1|max:255',
|
||||
'modelno' => 'min:1|max:255',
|
||||
'model_number' => 'min:1|max:255',
|
||||
'category_id' => 'required|integer',
|
||||
'manufacturer_id' => 'required|integer',
|
||||
'eol' => 'integer:min:0|max:240',
|
||||
@@ -92,8 +93,8 @@ class AssetModel extends Model
|
||||
public function displayModelName()
|
||||
{
|
||||
$name = $this->manufacturer->name.' '.$this->name;
|
||||
if ($this->modelno) {
|
||||
$name .=" / ".$this->modelno;
|
||||
if ($this->model_number) {
|
||||
$name .=" / ".$this->model_number;
|
||||
}
|
||||
return $name;
|
||||
}
|
||||
@@ -161,7 +162,7 @@ class AssetModel extends Model
|
||||
{
|
||||
|
||||
return $query->where('name', 'LIKE', "%$search%")
|
||||
->orWhere('modelno', 'LIKE', "%$search%")
|
||||
->orWhere('model_number', 'LIKE', "%$search%")
|
||||
->orWhere(function ($query) use ($search) {
|
||||
$query->whereHas('depreciation', function ($query) use ($search) {
|
||||
$query->where('name', 'LIKE', '%'.$search.'%');
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
<?php
|
||||
namespace App\Models;
|
||||
|
||||
use App\Http\Traits\UniqueUndeletedTrait;
|
||||
use App\Models\SnipeModel;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
use Watson\Validating\ValidatingTrait;
|
||||
use App\Http\Traits\UniqueUndeletedTrait;
|
||||
|
||||
/**
|
||||
* Model for Categories. Categories are a higher-level group
|
||||
@@ -14,7 +15,7 @@ use App\Http\Traits\UniqueUndeletedTrait;
|
||||
*
|
||||
* @version v1.0
|
||||
*/
|
||||
class Category extends Model
|
||||
class Category extends SnipeModel
|
||||
{
|
||||
|
||||
use SoftDeletes;
|
||||
|
||||
@@ -1,17 +1,18 @@
|
||||
<?php
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Watson\Validating\ValidatingTrait;
|
||||
use App\Models\SnipeModel;
|
||||
use Auth;
|
||||
use DB;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Watson\Validating\ValidatingTrait;
|
||||
|
||||
/**
|
||||
* Model for Companies.
|
||||
*
|
||||
* @version v1.8
|
||||
*/
|
||||
final class Company extends Model
|
||||
final class Company extends SnipeModel
|
||||
{
|
||||
protected $table = 'companies';
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@ use App\Models\Company;
|
||||
use App\Models\ConsumableAssignment;
|
||||
use App\Models\Location;
|
||||
use App\Models\Loggable;
|
||||
use App\Models\SnipeModel;
|
||||
use App\Models\User;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
@@ -17,7 +18,7 @@ use Watson\Validating\ValidatingTrait;
|
||||
*
|
||||
* @version v1.0
|
||||
*/
|
||||
class Component extends Model
|
||||
class Component extends SnipeModel
|
||||
{
|
||||
use CompanyableTrait;
|
||||
use Loggable;
|
||||
@@ -32,7 +33,7 @@ class Component extends Model
|
||||
*/
|
||||
public $rules = array(
|
||||
'name' => 'required|min:3|max:255',
|
||||
'total_qty' => 'required|integer|min:1',
|
||||
'qty' => 'required|integer|min:1',
|
||||
'category_id' => 'required|integer',
|
||||
'company_id' => 'integer',
|
||||
'purchase_date' => 'date',
|
||||
@@ -100,7 +101,7 @@ class Component extends Model
|
||||
}
|
||||
|
||||
|
||||
$total = $this->total_qty;
|
||||
$total = $this->qty;
|
||||
$remaining = $total - $checkedout;
|
||||
return $remaining;
|
||||
}
|
||||
@@ -141,7 +142,7 @@ class Component extends Model
|
||||
});
|
||||
})->orWhere('components.name', 'LIKE', '%'.$search.'%')
|
||||
->orWhere('components.order_number', 'LIKE', '%'.$search.'%')
|
||||
->orWhere('components.serial_number', 'LIKE', '%'.$search.'%')
|
||||
->orWhere('components.serial', 'LIKE', '%'.$search.'%')
|
||||
->orWhere('components.purchase_cost', 'LIKE', '%'.$search.'%')
|
||||
->orWhere('components.purchase_date', 'LIKE', '%'.$search.'%');
|
||||
}
|
||||
|
||||
@@ -7,12 +7,13 @@ use App\Models\Company;
|
||||
use App\Models\ConsumableAssignment;
|
||||
use App\Models\Location;
|
||||
use App\Models\Loggable;
|
||||
use App\Models\SnipeModel;
|
||||
use App\Models\User;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
use Watson\Validating\ValidatingTrait;
|
||||
|
||||
class Consumable extends Model
|
||||
class Consumable extends SnipeModel
|
||||
{
|
||||
use CompanyableTrait;
|
||||
use Loggable;
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Schema;
|
||||
|
||||
class CustomField extends Model
|
||||
{
|
||||
@@ -22,7 +23,7 @@ class CustomField extends Model
|
||||
];
|
||||
|
||||
public $rules=[
|
||||
"name" => "required|unique:custom_fields"
|
||||
"name" => "required|unique:custom_fields"
|
||||
];
|
||||
|
||||
public static $table_name="assets";
|
||||
@@ -36,12 +37,12 @@ class CustomField extends Model
|
||||
{
|
||||
self::creating(function ($custom_field) {
|
||||
|
||||
if (in_array($custom_field->db_column_name(), \Schema::getColumnListing(\DB::getTablePrefix().CustomField::$table_name))) {
|
||||
if (Schema::hasColumn(CustomField::$table_name,$custom_field->db_column_name())) {
|
||||
//field already exists when making a new custom field; fail.
|
||||
return false;
|
||||
}
|
||||
|
||||
\Schema::table(\DB::getTablePrefix().\App\Models\CustomField::$table_name, function ($table) use ($custom_field) {
|
||||
Schema::table(CustomField::$table_name, function ($table) use ($custom_field) {
|
||||
$table->text($custom_field->db_column_name())->nullable();
|
||||
});
|
||||
|
||||
@@ -49,17 +50,21 @@ class CustomField extends Model
|
||||
|
||||
self::updating(function ($custom_field) {
|
||||
if ($custom_field->isDirty("name")) {
|
||||
if (in_array($custom_field->db_column_name(), \Schema::getColumnListing(CustomField::$table_name))) {
|
||||
if (Schema::hasColumn(CustomField::$table_name,$custom_field->db_column_name())) {
|
||||
//field already exists when renaming a custom field
|
||||
return false;
|
||||
}
|
||||
return \DB::statement("UPDATE ".CustomField::$table_name." RENAME ".self::name_to_db_name($custom_field->get_original("name"))." TO ".$custom_field->db_column_name());
|
||||
return Schema::table(CustomField::$table_name, function ($table) use ($custom_field) {
|
||||
$table->renameColumn(self::name_to_db_name($custom_field->getOriginal("name")),$custom_field->db_column_name());
|
||||
});
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
self::deleting(function ($custom_field) {
|
||||
return \DB::statement("ALTER TABLE ".CustomField::$table_name." DROP COLUMN ".$custom_field->db_column_name());
|
||||
return Schema::table(CustomField::$table_name,function ($table) use ($custom_field) {
|
||||
$table->dropColumn(self::name_to_db_name($custom_field->getOriginal("name")));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
<?php
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use App\Models\Depreciation;
|
||||
use App\Models\SnipeModel;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class Depreciable extends Model
|
||||
class Depreciable extends SnipeModel
|
||||
{
|
||||
/**
|
||||
* Depreciation Relation, and associated helper methods
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
<?php
|
||||
namespace App\Models;
|
||||
|
||||
use App\Models\SnipeModel;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Watson\Validating\ValidatingTrait;
|
||||
|
||||
class Depreciation extends Model
|
||||
class Depreciation extends SnipeModel
|
||||
{
|
||||
// Declare the rules for the form validation
|
||||
protected $rules = array(
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
<?php
|
||||
namespace App\Models;
|
||||
|
||||
use App\Models\SnipeModel;
|
||||
use Watson\Validating\ValidatingTrait;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class Group extends Model
|
||||
class Group extends SnipeModel
|
||||
{
|
||||
protected $table = 'groups';
|
||||
|
||||
|
||||
@@ -219,10 +219,10 @@ class Ldap extends Model
|
||||
$user->notes = 'Imported on first login from LDAP';
|
||||
|
||||
if ($user->save()) {
|
||||
return true;
|
||||
return $user;
|
||||
} else {
|
||||
LOG::debug('Could not create user.'.$user->getErrors());
|
||||
exit;
|
||||
throw new Exception("Could not create user: ".$user->getErrors());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -277,7 +277,7 @@ class Ldap extends Model
|
||||
$global_count += $results['count'];
|
||||
$result_set = array_merge($result_set, $results);
|
||||
|
||||
ldap_control_paged_result_response($ldapconn, $search_results, $cookie);
|
||||
@ldap_control_paged_result_response($ldapconn, $search_results, $cookie);
|
||||
|
||||
} while ($cookie !== null && $cookie != '');
|
||||
|
||||
|
||||
@@ -23,7 +23,6 @@ class License extends Depreciable
|
||||
protected $table = 'licenses';
|
||||
protected $rules = array(
|
||||
'name' => 'required|string|min:3|max:255',
|
||||
'serial' => 'required|min:5',
|
||||
'seats' => 'required|min:1|max:10000|integer',
|
||||
'license_email' => 'email|min:0|max:120',
|
||||
'license_name' => 'string|min:0|max:100',
|
||||
@@ -101,6 +100,20 @@ class License extends Depreciable
|
||||
->count();
|
||||
}
|
||||
|
||||
// We do this to eager load the "count" of seats from the controller. Otherwise calling "count()" on each model results in n+1
|
||||
public function licenseSeatsRelation()
|
||||
{
|
||||
return $this->hasMany(LicenseSeat::class)->whereNull('deleted_at')->selectRaw('license_id, count(*) as count')->groupBy('license_id');
|
||||
}
|
||||
|
||||
public function getLicenseSeatsCountAttribute()
|
||||
{
|
||||
if ($this->licenseSeatsRelation->first()) {
|
||||
return $this->licenseSeatsRelation->first()->count;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get total licenses not checked out
|
||||
@@ -116,37 +129,47 @@ class License extends Depreciable
|
||||
/**
|
||||
* Get the number of available seats
|
||||
*/
|
||||
public function availcount()
|
||||
public function availCount()
|
||||
{
|
||||
return LicenseSeat::whereNull('assigned_to')
|
||||
->whereNull('asset_id')
|
||||
->where('license_id', '=', $this->id)
|
||||
->whereNull('deleted_at')
|
||||
->count();
|
||||
return $this->licenseSeatsRelation()
|
||||
->whereNull('asset_id');
|
||||
}
|
||||
|
||||
public function getAvailSeatsCountAttribute()
|
||||
{
|
||||
if ($this->availCount->first()) {
|
||||
return $this->availCount->first()->count;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the number of assigned seats
|
||||
*
|
||||
*/
|
||||
public function assignedcount()
|
||||
public function assignedCount()
|
||||
{
|
||||
return $this->licenseSeatsRelation()->where(function ($query) {
|
||||
$query->whereNotNull('assigned_to')
|
||||
->orWhereNotNull('asset_id');
|
||||
});
|
||||
}
|
||||
|
||||
return \App\Models\LicenseSeat::where('license_id', '=', $this->id)
|
||||
->where(function ($query) {
|
||||
|
||||
$query->whereNotNull('assigned_to')
|
||||
->orWhereNotNull('asset_id');
|
||||
})
|
||||
->count();
|
||||
|
||||
public function getAssignedSeatsCountAttribute()
|
||||
{
|
||||
// dd($this->licenseSeatsRelation->first());
|
||||
if ($this->assignedCount->first()) {
|
||||
return $this->assignedCount->first()->count;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
public function remaincount()
|
||||
{
|
||||
$total = $this->totalSeatsByLicenseID();
|
||||
$taken = $this->assignedcount();
|
||||
$total = $this->licenseSeatsCount;
|
||||
$taken = $this->assigned_seats_count;
|
||||
$diff = ($total - $taken);
|
||||
return $diff;
|
||||
}
|
||||
@@ -156,7 +179,7 @@ class License extends Depreciable
|
||||
*/
|
||||
public function totalcount()
|
||||
{
|
||||
$avail = $this->availcount();
|
||||
$avail = $this->availSeatsCount;
|
||||
$taken = $this->assignedcount();
|
||||
$diff = ($avail + $taken);
|
||||
return $diff;
|
||||
@@ -210,13 +233,51 @@ class License extends Depreciable
|
||||
|
||||
return $query->where(function ($query) use ($search) {
|
||||
|
||||
$query->where('name', 'LIKE', '%'.$search.'%')
|
||||
->orWhere('serial', 'LIKE', '%'.$search.'%')
|
||||
->orWhere('notes', 'LIKE', '%'.$search.'%')
|
||||
->orWhere('order_number', 'LIKE', '%'.$search.'%')
|
||||
->orWhere('purchase_order', 'LIKE', '%'.$search.'%')
|
||||
->orWhere('purchase_date', 'LIKE', '%'.$search.'%')
|
||||
->orWhere('purchase_cost', 'LIKE', '%'.$search.'%');
|
||||
$query->where('licenses.name', 'LIKE', '%'.$search.'%')
|
||||
->orWhere('licenses.serial', 'LIKE', '%'.$search.'%')
|
||||
->orWhere('licenses.notes', 'LIKE', '%'.$search.'%')
|
||||
->orWhere('licenses.order_number', 'LIKE', '%'.$search.'%')
|
||||
->orWhere('licenses.purchase_order', 'LIKE', '%'.$search.'%')
|
||||
->orWhere('licenses.purchase_date', 'LIKE', '%'.$search.'%')
|
||||
->orWhere('licenses.purchase_cost', 'LIKE', '%'.$search.'%')
|
||||
->orWhereHas('manufacturer', function ($query) use ($search) {
|
||||
$query->where(function ($query) use ($search) {
|
||||
$query->where('manufacturers.name', 'LIKE', '%'.$search.'%');
|
||||
});
|
||||
})
|
||||
->orWhereHas('company', function ($query) use ($search) {
|
||||
$query->where(function ($query) use ($search) {
|
||||
$query->where('companies.name', 'LIKE', '%'.$search.'%');
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Query builder scope to order on manufacturer
|
||||
*
|
||||
* @param Illuminate\Database\Query\Builder $query Query builder instance
|
||||
* @param text $order Order
|
||||
*
|
||||
* @return Illuminate\Database\Query\Builder Modified query builder
|
||||
*/
|
||||
public function scopeOrderManufacturer($query, $order)
|
||||
{
|
||||
return $query->leftJoin('manufacturers', 'licenses.manufacturer_id', '=', 'manufacturers.id')->select('licenses.*')
|
||||
->orderBy('manufacturers.name', $order);
|
||||
}
|
||||
|
||||
/**
|
||||
* Query builder scope to order on company
|
||||
*
|
||||
* @param Illuminate\Database\Query\Builder $query Query builder instance
|
||||
* @param text $order Order
|
||||
*
|
||||
* @return Illuminate\Database\Query\Builder Modified query builder
|
||||
*/
|
||||
public function scopeOrderCompany($query, $order)
|
||||
{
|
||||
return $query->leftJoin('companies as companies', 'licenses.company_id', '=', 'companies.id')->select('licenses.*')
|
||||
->orderBy('companies.name', $order);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,14 +1,15 @@
|
||||
<?php
|
||||
namespace App\Models;
|
||||
|
||||
use App\Http\Traits\UniqueUndeletedTrait;
|
||||
use App\Models\Asset;
|
||||
use App\Models\SnipeModel;
|
||||
use App\Models\User;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
use App\Models\User;
|
||||
use App\Models\Asset;
|
||||
use Watson\Validating\ValidatingTrait;
|
||||
use App\Http\Traits\UniqueUndeletedTrait;
|
||||
|
||||
class Location extends Model
|
||||
class Location extends SnipeModel
|
||||
{
|
||||
use SoftDeletes;
|
||||
protected $dates = ['deleted_at'];
|
||||
@@ -16,8 +17,8 @@ class Location extends Model
|
||||
protected $rules = array(
|
||||
'name' => 'required|min:3|max:255|unique_undeleted',
|
||||
'city' => 'min:3|max:255',
|
||||
'state' => 'min:2|max:32',
|
||||
'country' => 'min:2|max:2|max:2',
|
||||
'state' => 'min:0|max:2',
|
||||
'country' => 'min:2|max:2',
|
||||
'address' => 'min:5|max:80',
|
||||
'address2' => 'min:2|max:80',
|
||||
'zip' => 'min:3|max:10',
|
||||
@@ -49,7 +50,7 @@ class Location extends Model
|
||||
|
||||
public function assets()
|
||||
{
|
||||
return $this->hasManyThrough('\App\Models\Asset', '\App\Models\Actionlog', 'location_id', 'id');
|
||||
return $this->hasManyThrough('\App\Models\Asset', '\App\Models\User', 'location_id', 'assigned_to', 'id');
|
||||
}
|
||||
|
||||
public function assignedassets()
|
||||
|
||||
@@ -63,9 +63,11 @@ trait Loggable
|
||||
* @since [v3.4]
|
||||
* @return \App\Models\Actionlog
|
||||
*/
|
||||
public function logCheckin($note)
|
||||
public function logCheckin($target, $note)
|
||||
{
|
||||
$log = new Actionlog;
|
||||
$log->target_type = get_class($target);
|
||||
$log->target_id = $target->id;
|
||||
if (static::class == LicenseSeat::class) {
|
||||
$log->item_type = License::class;
|
||||
$log->item_id = $this->license_id;
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
<?php
|
||||
namespace App\Models;
|
||||
|
||||
use App\Models\SnipeModel;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
use Watson\Validating\ValidatingTrait;
|
||||
|
||||
class Manufacturer extends Model
|
||||
class Manufacturer extends SnipeModel
|
||||
{
|
||||
use SoftDeletes;
|
||||
protected $dates = ['deleted_at'];
|
||||
@@ -46,6 +47,11 @@ class Manufacturer extends Model
|
||||
return $this->hasManyThrough('\App\Models\Asset', '\App\Models\AssetModel', 'manufacturer_id', 'model_id');
|
||||
}
|
||||
|
||||
public function models()
|
||||
{
|
||||
return $this->hasMany('\App\Models\AssetModel', 'manufacturer_id');
|
||||
}
|
||||
|
||||
public function licenses()
|
||||
{
|
||||
return $this->hasMany('\App\Models\License', 'manufacturer_id');
|
||||
|
||||
@@ -49,10 +49,14 @@ class Setting extends Model
|
||||
{
|
||||
static $static_cache = null;
|
||||
|
||||
if (!$static_cache) {
|
||||
$static_cache = Setting::first();
|
||||
}
|
||||
return $static_cache;
|
||||
if (!$static_cache) {
|
||||
if (Schema::hasTable('settings')) {
|
||||
$static_cache = Setting::first();
|
||||
}
|
||||
}
|
||||
|
||||
return $static_cache;
|
||||
|
||||
}
|
||||
|
||||
public static function setupCompleted()
|
||||
|
||||
14
app/Models/SnipeModel.php
Normal file
14
app/Models/SnipeModel.php
Normal file
@@ -0,0 +1,14 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class SnipeModel extends Model
|
||||
{
|
||||
//
|
||||
public function getDisplayNameAttribute()
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
}
|
||||
@@ -1,12 +1,13 @@
|
||||
<?php
|
||||
namespace App\Models;
|
||||
|
||||
use App\Http\Traits\UniqueUndeletedTrait;
|
||||
use App\Models\SnipeModel;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
use Watson\Validating\ValidatingTrait;
|
||||
use App\Http\Traits\UniqueUndeletedTrait;
|
||||
|
||||
class Statuslabel extends Model
|
||||
class Statuslabel extends SnipeModel
|
||||
{
|
||||
use SoftDeletes;
|
||||
use ValidatingTrait;
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
<?php
|
||||
namespace App\Models;
|
||||
|
||||
use App\Http\Traits\UniqueUndeletedTrait;
|
||||
use App\Models\SnipeModel;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
use Watson\Validating\ValidatingTrait;
|
||||
use App\Http\Traits\UniqueUndeletedTrait;
|
||||
|
||||
class Supplier extends Model
|
||||
class Supplier extends SnipeModel
|
||||
{
|
||||
use SoftDeletes;
|
||||
protected $dates = ['deleted_at'];
|
||||
@@ -14,14 +15,14 @@ class Supplier extends Model
|
||||
|
||||
protected $rules = array(
|
||||
'name' => 'required|min:3|max:255|unique_undeleted',
|
||||
'address' => 'min:3|max:255',
|
||||
'address2' => 'min:2|max:255',
|
||||
'address' => 'min:3|max:50',
|
||||
'address2' => 'min:2|max:50',
|
||||
'city' => 'min:3|max:255',
|
||||
'state' => 'min:0|max:32',
|
||||
'country' => 'min:0|max:2',
|
||||
'fax' => 'min:7|max:20',
|
||||
'phone' => 'min:7|max:20',
|
||||
'contact' => 'min:0|max:255',
|
||||
'contact' => 'min:0|max:100',
|
||||
'notes' => 'min:0|max:255',
|
||||
'email' => 'email|min:5|max:150',
|
||||
'zip' => 'min:0|max:10',
|
||||
@@ -47,6 +48,21 @@ class Supplier extends Model
|
||||
protected $fillable = ['name'];
|
||||
|
||||
|
||||
// Eager load counts.
|
||||
// We do this to eager load the "count" of seats from the controller. Otherwise calling "count()" on each model results in n+1
|
||||
public function assetsRelation()
|
||||
{
|
||||
return $this->hasMany(Asset::class)->whereNull('deleted_at')->selectRaw('supplier_id, count(*) as count')->groupBy('supplier_id');
|
||||
}
|
||||
|
||||
public function getLicenseSeatsCountAttribute()
|
||||
{
|
||||
if ($this->licenseSeatsRelation->first()) {
|
||||
return $this->licenseSeatsRelation->first()->count;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
public function assets()
|
||||
{
|
||||
return $this->hasMany('\App\Models\Asset', 'supplier_id');
|
||||
@@ -59,7 +75,11 @@ class Supplier extends Model
|
||||
|
||||
public function num_assets()
|
||||
{
|
||||
return $this->hasMany('\App\Models\Asset', 'supplier_id')->count();
|
||||
if ($this->assetsRelation->first()) {
|
||||
return $this->assetsRelation->first()->count;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
public function licenses()
|
||||
@@ -69,7 +89,7 @@ class Supplier extends Model
|
||||
|
||||
public function num_licenses()
|
||||
{
|
||||
return $this->hasMany('\App\Models\License', 'supplier_id')->count();
|
||||
return $this->licenses()->count();
|
||||
}
|
||||
|
||||
public function addhttp($url)
|
||||
|
||||
@@ -389,6 +389,11 @@ class User extends Model implements AuthenticatableContract, CanResetPasswordCon
|
||||
$query->where('locations.name', 'LIKE', '%'.$search.'%');
|
||||
});
|
||||
})
|
||||
->orWhere(function ($query) use ($search) {
|
||||
$query->whereHas('groups', function ($query) use ($search) {
|
||||
$query->where('groups.name', 'LIKE', '%'.$search.'%');
|
||||
});
|
||||
})
|
||||
|
||||
// Ugly, ugly code because Laravel sucks at self-joins
|
||||
->orWhere(function ($query) use ($search) {
|
||||
|
||||
@@ -4,6 +4,7 @@ namespace App\Providers;
|
||||
use Validator;
|
||||
use Illuminate\Support\ServiceProvider;
|
||||
use DB;
|
||||
use Log;
|
||||
|
||||
|
||||
/**
|
||||
@@ -64,6 +65,11 @@ class AppServiceProvider extends ServiceProvider
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
// Share common variables with all views.
|
||||
view()->composer('*', function ($view) {
|
||||
$view->with('snipeSettings', \App\Models\Setting::getSettings());
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -73,6 +79,20 @@ class AppServiceProvider extends ServiceProvider
|
||||
*/
|
||||
public function register()
|
||||
{
|
||||
//
|
||||
$monolog = Log::getMonolog();
|
||||
|
||||
if (config('app.debug')) {
|
||||
$log_level = 'debug';
|
||||
} else {
|
||||
if (config('log-level')) {
|
||||
$log_level = config('log-level');
|
||||
} else {
|
||||
$log_level = 'error';
|
||||
}
|
||||
}
|
||||
|
||||
foreach($monolog->getHandlers() as $handler) {
|
||||
$handler->setLevel($log_level);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -328,5 +328,15 @@ class AuthServiceProvider extends ServiceProvider
|
||||
});
|
||||
|
||||
|
||||
# -----------------------------------------
|
||||
# Self
|
||||
# -----------------------------------------
|
||||
$gate->define('self.two_factor', function ($user) {
|
||||
if (($user->hasAccess('self.two_factor')) || ($user->hasAccess('admin'))) {
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,13 +12,6 @@ settings:
|
||||
extensions:
|
||||
enabled:
|
||||
- Codeception\Extension\RunFailed
|
||||
modules:
|
||||
config:
|
||||
Db:
|
||||
dsn: ''
|
||||
user: ''
|
||||
password: ''
|
||||
dump: tests/_data/dump.sql
|
||||
coverage:
|
||||
enabled: true
|
||||
include:
|
||||
|
||||
@@ -23,7 +23,8 @@
|
||||
"barryvdh/laravel-debugbar": "^2.1",
|
||||
"spatie/laravel-backup": "3.8.1",
|
||||
"misterphilip/maintenance-mode": "1.0.*",
|
||||
"neitanod/forceutf8": "dev-master"
|
||||
"neitanod/forceutf8": "dev-master",
|
||||
"pragmarx/google2fa": "^1.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"fzaninotto/faker": "~1.4",
|
||||
|
||||
119
composer.lock
generated
119
composer.lock
generated
@@ -4,8 +4,8 @@
|
||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"hash": "ed9f8700f2dcd943ff662a82e4d8314f",
|
||||
"content-hash": "9c0251ddc1a110d83a762483abeea079",
|
||||
"hash": "a188b3cf19debb9f4ad80016cb02bacd",
|
||||
"content-hash": "d05155478c07249acdb2fed3d47189e6",
|
||||
"packages": [
|
||||
{
|
||||
"name": "aws/aws-sdk-php",
|
||||
@@ -197,6 +197,60 @@
|
||||
],
|
||||
"time": "2016-07-29 15:00:36"
|
||||
},
|
||||
{
|
||||
"name": "christian-riesen/base32",
|
||||
"version": "1.3.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/ChristianRiesen/base32.git",
|
||||
"reference": "0a31e50c0fa9b1692d077c86ac188eecdcbaf7fa"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/ChristianRiesen/base32/zipball/0a31e50c0fa9b1692d077c86ac188eecdcbaf7fa",
|
||||
"reference": "0a31e50c0fa9b1692d077c86ac188eecdcbaf7fa",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.3.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "4.*",
|
||||
"satooshi/php-coveralls": "0.*"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "1.1.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Base32\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Christian Riesen",
|
||||
"email": "chris.riesen@gmail.com",
|
||||
"homepage": "http://christianriesen.com",
|
||||
"role": "Developer"
|
||||
}
|
||||
],
|
||||
"description": "Base32 encoder/decoder according to RFC 4648",
|
||||
"homepage": "https://github.com/ChristianRiesen/base32",
|
||||
"keywords": [
|
||||
"base32",
|
||||
"decode",
|
||||
"encode",
|
||||
"rfc4648"
|
||||
],
|
||||
"time": "2016-05-05 11:49:03"
|
||||
},
|
||||
{
|
||||
"name": "classpreloader/classpreloader",
|
||||
"version": "3.0.0",
|
||||
@@ -2056,6 +2110,67 @@
|
||||
],
|
||||
"time": "2016-03-18 20:34:03"
|
||||
},
|
||||
{
|
||||
"name": "pragmarx/google2fa",
|
||||
"version": "v1.0.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/antonioribeiro/google2fa.git",
|
||||
"reference": "b346dc138339b745c5831405d00cff7c1351aa0d"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/antonioribeiro/google2fa/zipball/b346dc138339b745c5831405d00cff7c1351aa0d",
|
||||
"reference": "b346dc138339b745c5831405d00cff7c1351aa0d",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"christian-riesen/base32": "~1.3",
|
||||
"paragonie/random_compat": "~1.4|~2.0",
|
||||
"php": ">=5.4",
|
||||
"symfony/polyfill-php56": "~1.2"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpspec/phpspec": "~2.1"
|
||||
},
|
||||
"suggest": {
|
||||
"bacon/bacon-qr-code": "Required to generate inline QR Codes."
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"component": "package",
|
||||
"frameworks": [
|
||||
"Laravel"
|
||||
],
|
||||
"branch-alias": {
|
||||
"dev-master": "1.0-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"PragmaRX\\Google2FA\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"BSD-3-Clause"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Antonio Carlos Ribeiro",
|
||||
"email": "acr@antoniocarlosribeiro.com",
|
||||
"role": "Creator & Designer"
|
||||
}
|
||||
],
|
||||
"description": "A One Time Password Authentication package, compatible with Google Authenticator.",
|
||||
"keywords": [
|
||||
"Authentication",
|
||||
"Two Factor Authentication",
|
||||
"google2fa",
|
||||
"laravel"
|
||||
],
|
||||
"time": "2016-07-18 20:25:04"
|
||||
},
|
||||
{
|
||||
"name": "psr/http-message",
|
||||
"version": "1.0.1",
|
||||
|
||||
@@ -27,6 +27,7 @@ return [
|
||||
*/
|
||||
|
||||
'debug' => env('APP_DEBUG', false),
|
||||
'warn_debug' => env('WARN_DEBUG', true),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
@@ -109,6 +110,7 @@ return [
|
||||
*/
|
||||
|
||||
'log' => env('APP_LOG', 'single'),
|
||||
'log-level' => env('APP_LOG_LEVEL', 'error'),
|
||||
|
||||
|
||||
/*
|
||||
@@ -212,7 +214,7 @@ return [
|
||||
Fideloper\Proxy\TrustedProxyServiceProvider::class,
|
||||
MisterPhilip\MaintenanceMode\MaintenanceModeServiceProvider::class,
|
||||
MisterPhilip\MaintenanceMode\MaintenanceCommandServiceProvider::class,
|
||||
|
||||
PragmaRX\Google2FA\Vendor\Laravel\ServiceProvider::class,
|
||||
/*
|
||||
* Custom service provider
|
||||
*/
|
||||
@@ -269,6 +271,7 @@ return [
|
||||
'View' => Illuminate\Support\Facades\View::class,
|
||||
'Form' => 'Collective\Html\FormFacade',
|
||||
'Html' => 'Collective\Html\HtmlFacade',
|
||||
'Google2FA' => PragmaRX\Google2FA\Vendor\Laravel\Facade::class,
|
||||
],
|
||||
|
||||
];
|
||||
|
||||
@@ -104,4 +104,21 @@ return [
|
||||
],
|
||||
],
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Login throttling
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This handles the max failed login attempt throttling.
|
||||
| You should not change the values here, but should change them in your
|
||||
| application's .env file instead, as future changes to this file could
|
||||
| overwrite your changes here.
|
||||
|
|
||||
*/
|
||||
|
||||
'throttle' => [
|
||||
'max_attempts' => env('LOGIN_MAX_ATTEMPTS', 10),
|
||||
'lockout_duration' => env('LOGIN_LOCKOUT_DURATION', 60),
|
||||
],
|
||||
|
||||
];
|
||||
|
||||
@@ -73,6 +73,12 @@ return [
|
||||
'dump_command_path' => env('DB_DUMP_PATH', '/usr/local/bin'), // only the path, so without 'mysqldump'
|
||||
'dump_command_timeout' => 60 * 5, // 5 minute timeout
|
||||
'dump_using_single_transaction' => true, // perform dump using a single transaction
|
||||
'options' => (env('DB_SSL')) ? [
|
||||
PDO::MYSQL_ATTR_SSL_KEY => env('DB_SSL_KEY'), // /path/to/key.pem
|
||||
PDO::MYSQL_ATTR_SSL_CERT => env('DB_SSL_CERT'), // /path/to/cert.pem
|
||||
PDO::MYSQL_ATTR_SSL_CA => env('DB_SSL_CA'), // /path/to/ca.pem
|
||||
PDO::MYSQL_ATTR_SSL_CIPHER => env('DB_SSL_CIPHER')
|
||||
] : []
|
||||
],
|
||||
|
||||
'pgsql' => [
|
||||
|
||||
@@ -279,6 +279,16 @@ return array(
|
||||
|
||||
),
|
||||
|
||||
'Self' => array(
|
||||
array(
|
||||
'permission' => 'self.two_factor',
|
||||
'label' => 'Two-Factor Authentication',
|
||||
'note' => 'The user may disable/enable two-factor authentication themselves if two-factor is enabled and set to selective.',
|
||||
'display' => true,
|
||||
),
|
||||
|
||||
),
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
<?php
|
||||
return array (
|
||||
'app_version' => 'v3.5.2',
|
||||
'hash_version' => 'v3.5.2-11-g5a835a5',
|
||||
'app_version' => 'v3.6.4',
|
||||
'build_version' => '12',
|
||||
'hash_version' => 'gf7e4fca',
|
||||
'full_hash' => 'v3.6.4-12-gf7e4fca',
|
||||
);
|
||||
|
||||
3
crowdin.yml
Normal file
3
crowdin.yml
Normal file
@@ -0,0 +1,3 @@
|
||||
files:
|
||||
- source: /resources/lang/en/**/*.php
|
||||
translation: '**/%original_file_name%'
|
||||
@@ -11,6 +11,11 @@
|
||||
|
|
||||
*/
|
||||
|
||||
use App\Models\Company;
|
||||
use App\Models\Location;
|
||||
use App\Models\Manufacturer;
|
||||
use App\Models\Supplier;
|
||||
|
||||
$factory->defineAs(App\Models\Asset::class, 'asset', function (Faker\Generator $faker) {
|
||||
return [
|
||||
'name' => $faker->catchPhrase,
|
||||
@@ -22,10 +27,12 @@ $factory->defineAs(App\Models\Asset::class, 'asset', function (Faker\Generator $
|
||||
'asset_tag' => $faker->unixTime('now'),
|
||||
'notes' => $faker->sentence,
|
||||
'purchase_date' => $faker->dateTime(),
|
||||
'purchase_cost' => $faker->randomFloat(2),
|
||||
'order_number' => $faker->numberBetween(1000000,50000000),
|
||||
'supplier_id' => $faker->numberBetween(1,5),
|
||||
'requestable' => $faker->numberBetween(0,1),
|
||||
'company_id' => \App\Models\Company::inRandomOrder()->first()->id
|
||||
'company_id' => Company::inRandomOrder()->first()->id,
|
||||
'requestable' => $faker->boolean()
|
||||
];
|
||||
});
|
||||
|
||||
@@ -35,25 +42,33 @@ $factory->defineAs(App\Models\AssetModel::class, 'assetmodel', function (Faker\G
|
||||
'name' => $faker->catchPhrase,
|
||||
'manufacturer_id' => $faker->numberBetween(1,10),
|
||||
'category_id' => $faker->numberBetween(1,9),
|
||||
'modelno' => $faker->numberBetween(1000000,50000000),
|
||||
'model_number' => $faker->numberBetween(1000000,50000000),
|
||||
'eol' => 1,
|
||||
'notes' => $faker->paragraph(),
|
||||
'requestable' => $faker->boolean(),
|
||||
];
|
||||
});
|
||||
|
||||
$factory->defineAs(App\Models\Location::class, 'location', function (Faker\Generator $faker) {
|
||||
return [
|
||||
'name' => $faker->city,
|
||||
'city' => $faker->city,
|
||||
'state' => $faker->stateAbbr,
|
||||
'country' => $faker->countryCode,
|
||||
'currency' => $faker->currencyCode,
|
||||
];
|
||||
return [
|
||||
'name' => $faker->catchPhrase,
|
||||
'address' => $faker->streetAddress,
|
||||
'address2' => $faker->secondaryAddress,
|
||||
'city' => $faker->city,
|
||||
'state' => $faker->stateAbbr,
|
||||
'country' => $faker->countryCode,
|
||||
'currency' => $faker->currencyCode,
|
||||
'zip' => $faker->postcode
|
||||
];
|
||||
});
|
||||
|
||||
$factory->defineAs(App\Models\Category::class, 'asset-category', function (Faker\Generator $faker) {
|
||||
return [
|
||||
'name' => $faker->text(20),
|
||||
'category_type' => $faker->randomElement($array = array ('asset')),
|
||||
'eula_text' => $faker->paragraph(),
|
||||
'require_acceptance' => $faker->boolean(),
|
||||
'checkin_email' => $faker->boolean()
|
||||
];
|
||||
});
|
||||
|
||||
@@ -95,9 +110,14 @@ $factory->defineAs(App\Models\Component::class, 'component', function (Faker\Gen
|
||||
return [
|
||||
'name' => $faker->text(20),
|
||||
'category_id' => $faker->numberBetween(21,25),
|
||||
'total_qty' => $faker->numberBetween(3, 10),
|
||||
'location_id' => Location::inRandomOrder()->first()->id,
|
||||
'serial' => $faker->uuid,
|
||||
'qty' => $faker->numberBetween(3, 10),
|
||||
'order_number' => $faker->numberBetween(1000000,50000000),
|
||||
'purchase_date' => $faker->dateTime(),
|
||||
'purchase_cost' => $faker->randomFloat(2),
|
||||
'min_amt' => $faker->numberBetween($min = 1, $max = 2),
|
||||
'company_id' => \App\Models\Company::inRandomOrder()->first()->id
|
||||
'company_id' => Company::inRandomOrder()->first()->id
|
||||
];
|
||||
});
|
||||
|
||||
@@ -110,39 +130,52 @@ $factory->defineAs(App\Models\Depreciation::class, 'depreciation', function (Fak
|
||||
|
||||
$factory->defineAs(App\Models\Accessory::class, 'accessory', function (Faker\Generator $faker) {
|
||||
return [
|
||||
'company_id' => Company::inRandomOrder()->first()->id,
|
||||
'name' => $faker->text(20),
|
||||
'category_id' => $faker->numberBetween(11,15),
|
||||
'qty' => $faker->numberBetween(5, 10),
|
||||
'manufacturer_id' => Manufacturer::inRandomOrder()->first()->id,
|
||||
'location_id' => $faker->numberBetween(1,5),
|
||||
'order_number' => $faker->numberBetween(1000000,50000000),
|
||||
'purchase_date' => $faker->dateTime(),
|
||||
'purchase_cost' => $faker->randomFloat(2),
|
||||
'qty' => $faker->numberBetween(5, 10),
|
||||
'min_amt' => $faker->numberBetween($min = 1, $max = 2),
|
||||
'company_id' => \App\Models\Company::inRandomOrder()->first()->id
|
||||
];
|
||||
|
||||
});
|
||||
|
||||
|
||||
$factory->defineAs(App\Models\Supplier::class, 'supplier', function (Faker\Generator $faker) {
|
||||
return [
|
||||
'name' => $faker->company,
|
||||
'address' => $faker->streetAddress,
|
||||
'city' => $faker->city,
|
||||
'state' => $faker->stateAbbr,
|
||||
'country' => $faker->countryCode,
|
||||
'contact' => $faker->name,
|
||||
'phone' => $faker->phoneNumber,
|
||||
'email' => $faker->safeEmail,
|
||||
];
|
||||
return [
|
||||
'name' => $faker->company,
|
||||
'address' => $faker->streetAddress,
|
||||
'address2' => $faker->secondaryAddress,
|
||||
'city' => $faker->city,
|
||||
'state' => $faker->stateAbbr,
|
||||
'zip' => $faker->postCode,
|
||||
'country' => $faker->countryCode,
|
||||
'contact' => $faker->name,
|
||||
'phone' => $faker->phoneNumber,
|
||||
'fax' => $faker->phoneNumber,
|
||||
'email' => $faker->safeEmail,
|
||||
'url' => $faker->url,
|
||||
'notes' => $faker->paragraph
|
||||
];
|
||||
});
|
||||
|
||||
|
||||
$factory->defineAs(App\Models\Consumable::class, 'consumable', function (Faker\Generator $faker) {
|
||||
return [
|
||||
'name' => $faker->text(20),
|
||||
'company_id' => Company::inRandomOrder()->first()->id,
|
||||
'category_id' => $faker->numberBetween(16, 20),
|
||||
'company_id' => $faker->numberBetween(1, 10),
|
||||
'model_number' => $faker->numberBetween(1000000,50000000),
|
||||
'item_no' => $faker->numberBetween(1000000,50000000),
|
||||
'order_number' => $faker->numberBetween(1000000,50000000),
|
||||
'purchase_date' => $faker->dateTime(),
|
||||
'purchase_cost' => $faker->randomFloat(2),
|
||||
'qty' => $faker->numberBetween(5, 10),
|
||||
'min_amt' => $faker->numberBetween($min = 1, $max = 2),
|
||||
'company_id' => \App\Models\Company::inRandomOrder()->first()->id
|
||||
|
||||
];
|
||||
});
|
||||
|
||||
@@ -171,7 +204,7 @@ $factory->defineAs(App\Models\Statuslabel::class, 'pending', function (Faker\Gen
|
||||
'deployable' => 0,
|
||||
'pending' => 1,
|
||||
'archived' => 0,
|
||||
'notes' => ''
|
||||
'notes' => $faker->sentence
|
||||
];
|
||||
});
|
||||
|
||||
@@ -246,17 +279,20 @@ $factory->defineAs(App\Models\Statuslabel::class, 'lost', function (Faker\Genera
|
||||
});
|
||||
|
||||
$factory->defineAs(App\Models\License::class, 'license', function (Faker\Generator $faker) {
|
||||
return [
|
||||
'name' => $faker->catchPhrase,
|
||||
'serial' => $faker->uuid,
|
||||
'seats' => $faker->numberBetween(1, 10),
|
||||
'license_email' => $faker->safeEmail,
|
||||
'license_name' => $faker->name,
|
||||
'purchase_date' => $faker->dateTime(),
|
||||
'purchase_cost' => $faker->randomFloat(2),
|
||||
'notes' => $faker->sentence,
|
||||
'company_id' => \App\Models\Company::inRandomOrder()->first()->id
|
||||
];
|
||||
return [
|
||||
'name' => $faker->catchPhrase,
|
||||
'serial' => $faker->uuid,
|
||||
'seats' => $faker->numberBetween(1, 10),
|
||||
'license_email' => $faker->safeEmail,
|
||||
'license_name' => $faker->name,
|
||||
'order_number' => $faker->numberBetween(1500, 13250),
|
||||
'purchase_order' => $faker->numberBetween(1500, 13250),
|
||||
'purchase_date' => $faker->dateTime(),
|
||||
'purchase_cost' => $faker->randomFloat(2),
|
||||
'notes' => $faker->sentence,
|
||||
'supplier_id' => Supplier::inRandomOrder()->first()->id,
|
||||
'company_id' => Company::inRandomOrder()->first()->id
|
||||
];
|
||||
});
|
||||
|
||||
$factory->defineAs(App\Models\LicenseSeat::class, 'license-seat', function (Faker\Generator $faker) {
|
||||
@@ -270,7 +306,7 @@ $factory->defineAs(App\Models\LicenseSeat::class, 'license-seat', function (Fake
|
||||
});
|
||||
|
||||
$factory->defineAs(App\Models\Actionlog::class, 'asset-checkout', function (Faker\Generator $faker) {
|
||||
$company = \App\Models\Company::has('users')->has('assets')->inRandomOrder()->first();
|
||||
$company = Company::has('users')->has('assets')->inRandomOrder()->first();
|
||||
return [
|
||||
'user_id' => $company->users()->inRandomOrder()->first()->id,
|
||||
'action_type' => 'checkout',
|
||||
@@ -285,7 +321,7 @@ $factory->defineAs(App\Models\Actionlog::class, 'asset-checkout', function (Fake
|
||||
});
|
||||
|
||||
$factory->defineAs(App\Models\Actionlog::class, 'license-checkout-asset', function (Faker\Generator $faker) {
|
||||
$company = \App\Models\Company::has('users')->has('licenses')->inRandomOrder()->first();
|
||||
$company = Company::has('users')->has('licenses')->inRandomOrder()->first();
|
||||
|
||||
return [
|
||||
'user_id' => $company->users()->inRandomOrder()->first()->id,
|
||||
@@ -301,7 +337,7 @@ $factory->defineAs(App\Models\Actionlog::class, 'license-checkout-asset', functi
|
||||
});
|
||||
|
||||
$factory->defineAs(App\Models\Actionlog::class, 'accessory-checkout', function (Faker\Generator $faker) {
|
||||
$company = \App\Models\Company::has('users')->has('accessories')->inRandomOrder()->first();
|
||||
$company = Company::has('users')->has('accessories')->inRandomOrder()->first();
|
||||
return [
|
||||
'user_id' => $company->users()->inRandomOrder()->first()->id,
|
||||
'action_type' => 'checkout',
|
||||
@@ -316,7 +352,7 @@ $factory->defineAs(App\Models\Actionlog::class, 'accessory-checkout', function (
|
||||
});
|
||||
|
||||
$factory->defineAs(App\Models\Actionlog::class, 'consumable-checkout', function (Faker\Generator $faker) {
|
||||
$company = \App\Models\Company::has('users')->has('consumables')->inRandomOrder()->first();
|
||||
$company = Company::has('users')->has('consumables')->inRandomOrder()->first();
|
||||
|
||||
return [
|
||||
'user_id' => $company->users()->inRandomOrder()->first()->id,
|
||||
@@ -332,7 +368,7 @@ $factory->defineAs(App\Models\Actionlog::class, 'consumable-checkout', function
|
||||
});
|
||||
|
||||
$factory->defineAs(App\Models\Actionlog::class, 'component-checkout', function (Faker\Generator $faker) {
|
||||
$company = \App\Models\Company::has('users')->has('components')->inRandomOrder()->first();
|
||||
$company = Company::has('users')->has('components')->inRandomOrder()->first();
|
||||
|
||||
return [
|
||||
'user_id' => $company->users()->inRandomOrder()->first()->id,
|
||||
@@ -357,12 +393,17 @@ $factory->defineAs(App\Models\CustomField::class, 'customfield-ip', function (Fa
|
||||
|
||||
|
||||
$factory->defineAs(App\Models\User::class, 'valid-user', function (Faker\Generator $faker) {
|
||||
return [
|
||||
'first_name' => $faker->firstName,
|
||||
'last_name' => $faker->lastName,
|
||||
'email' => $faker->safeEmail,
|
||||
'password' => $faker->password,
|
||||
'username' => $faker->username,
|
||||
'company_id' => \App\Models\Company::inRandomOrder()->first()->id
|
||||
];
|
||||
return [
|
||||
'first_name' => $faker->firstName,
|
||||
'last_name' => $faker->lastName,
|
||||
'username' => $faker->username,
|
||||
'password' => $faker->password,
|
||||
'email' => $faker->safeEmail,
|
||||
'company_id' => Company::inRandomOrder()->first()->id,
|
||||
'locale' => $faker->locale,
|
||||
'employee_num' => $faker->numberBetween(3500, 35050),
|
||||
'jobtitle' => $faker->word,
|
||||
'phone' => $faker->phoneNumber,
|
||||
'notes' => $faker->sentence
|
||||
];
|
||||
});
|
||||
|
||||
@@ -59,6 +59,7 @@ class MigrateAssetLogToActionLog extends Migration
|
||||
$a->expected_checkin = $log->expected_checkin;
|
||||
$a->thread_id = $log->thread_id;
|
||||
$a->accepted_id = $log->accepted_id;
|
||||
$a->filename = $log->filename;
|
||||
|
||||
$a->save();
|
||||
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
|
||||
class RenameModelnoToModelNumber extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::table('models', function (Blueprint $table) {
|
||||
//
|
||||
$table->renameColumn('modelno', 'model_number');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::table('models', function (Blueprint $table) {
|
||||
//
|
||||
$table->renameColumn('model_number', 'modelno');
|
||||
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
|
||||
class RenameConsumableModelnoToModelNumber extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::table('consumables', function (Blueprint $table) {
|
||||
//
|
||||
$table->renameColumn('model_no', 'model_number');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::table('consumables', function (Blueprint $table) {
|
||||
//
|
||||
$table->renameColumn('model_number', 'model_no');
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
|
||||
class RenameModelNoteToNotes extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::table('models', function (Blueprint $table) {
|
||||
//
|
||||
$table->renameColumn('note', 'notes');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::table('models', function (Blueprint $table) {
|
||||
//
|
||||
$table->renameColumn('notes', 'note');
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
|
||||
class RenameComponentTotalQtyToQty extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::table('components', function (Blueprint $table) {
|
||||
//
|
||||
$table->renameColumn('total_qty', 'qty');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::table('components', function (Blueprint $table) {
|
||||
//
|
||||
$table->renameColumn('qty', 'total_qty');
|
||||
});
|
||||
}
|
||||
}
|
||||
43
database/migrations/2016_10_29_002724_enable_2fa_fields.php
Normal file
43
database/migrations/2016_10_29_002724_enable_2fa_fields.php
Normal file
@@ -0,0 +1,43 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
|
||||
class Enable2faFields extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::table('settings', function ($table) {
|
||||
$table->tinyInteger('two_factor_enabled')->nullable()->default(null);
|
||||
});
|
||||
|
||||
Schema::table('users', function ($table) {
|
||||
$table->string('two_factor_secret', 32)->nullable()->default(null);
|
||||
$table->boolean('two_factor_enrolled')->default(0);
|
||||
$table->boolean('two_factor_optin')->default(0);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::table('settings', function ($table) {
|
||||
$table->dropColumn('two_factor_enabled');
|
||||
});
|
||||
|
||||
Schema::table('users', function ($table) {
|
||||
$table->dropColumn('two_factor_secret');
|
||||
$table->dropColumn('two_factor_enrolled');
|
||||
$table->dropColumn('two_factor_optin');
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
|
||||
class AddSignatureToAcceptance extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::table('settings', function ($table) {
|
||||
$table->boolean('require_accept_signature')->default(0);
|
||||
});
|
||||
|
||||
Schema::table('action_logs', function ($table) {
|
||||
$table->string('accept_signature', 100)->nullable()->default(null);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::table('settings', function ($table) {
|
||||
$table->dropColumn('require_accept_signature');
|
||||
});
|
||||
|
||||
Schema::table('action_logs', function ($table) {
|
||||
$table->dropColumn('accept_signature');
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
<?php
|
||||
|
||||
use App\Models\Actionlog;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
|
||||
class FixForgottenFilenameInActionLogs extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::table('action_logs', function (Blueprint $table) {
|
||||
$logs = DB::table('asset_logs')->where('filename', '!=', null)->get();
|
||||
//
|
||||
foreach($logs as $log) {
|
||||
$matching_action_log = Actionlog::where('item_id', $log->asset_id)
|
||||
->where('created_at', $log->created_at)
|
||||
->where('note', $log->note)
|
||||
->where('filename', null)
|
||||
->withTrashed()
|
||||
->get()->first();
|
||||
|
||||
if($matching_action_log) {
|
||||
$matching_action_log->filename = $log->filename;
|
||||
$matching_action_log->save();
|
||||
}else{
|
||||
echo("Couldn't find matching Action log row when trying to migrate".
|
||||
" filename from asset log:\n".
|
||||
"LogDate{$log->created_at} LogForAsset:{$log->asset_id}".
|
||||
"LogNote:{$log->note} \n");
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::table('action_logs', function (Blueprint $table) {
|
||||
//
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
|
||||
class RenameComponentSerialNumberToSerial extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::table('components', function ($table) {
|
||||
$table->renameColumn('serial_number', 'serial');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::table('components', function ($table) {
|
||||
$table->renameColumn('serial', 'serial_number');
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
|
||||
class IncreasePurchaseCostSize extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
$platform = Schema::getConnection()->getDoctrineSchemaManager()->getDatabasePlatform();
|
||||
$platform->registerDoctrineTypeMapping('enum', 'string');
|
||||
|
||||
|
||||
Schema::table('assets', function ($table) {
|
||||
$table->decimal('purchase_cost', 20, 2)->nullable()->default(null)->change();
|
||||
});
|
||||
|
||||
Schema::table('accessories', function ($table) {
|
||||
$table->decimal('purchase_cost', 20, 2)->nullable()->default(null)->change();
|
||||
});
|
||||
|
||||
Schema::table('asset_maintenances', function ($table) {
|
||||
$table->decimal('cost', 20, 2)->nullable()->default(null)->change();
|
||||
});
|
||||
|
||||
Schema::table('components', function ($table) {
|
||||
$table->decimal('purchase_cost', 20, 2)->nullable()->default(null)->change();
|
||||
});
|
||||
|
||||
Schema::table('consumables', function ($table) {
|
||||
$table->decimal('purchase_cost', 20, 2)->nullable()->default(null)->change();
|
||||
});
|
||||
|
||||
Schema::table('licenses', function ($table) {
|
||||
$table->decimal('purchase_cost', 20, 2)->nullable()->default(null)->change();
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
$platform = Schema::getConnection()->getDoctrineSchemaManager()->getDatabasePlatform();
|
||||
$platform->registerDoctrineTypeMapping('enum', 'string');
|
||||
|
||||
Schema::table('assets', function ($table) {
|
||||
$table->decimal('purchase_cost', 8, 2)->nullable()->default(null)->change();
|
||||
});
|
||||
|
||||
Schema::table('accessories', function ($table) {
|
||||
$table->decimal('purchase_cost', 13, 4)->nullable()->default(null)->change();
|
||||
});
|
||||
|
||||
Schema::table('asset_maintenances', function ($table) {
|
||||
$table->decimal('cost', 10, 2)->nullable()->default(null)->change();
|
||||
});
|
||||
|
||||
Schema::table('components', function ($table) {
|
||||
$table->decimal('purchase_cost', 13, 4)->nullable()->default(null)->change();
|
||||
});
|
||||
|
||||
Schema::table('consumables', function ($table) {
|
||||
$table->decimal('purchase_cost', 13, 4)->nullable()->default(null)->change();
|
||||
});
|
||||
|
||||
Schema::table('licenses', function ($table) {
|
||||
$table->decimal('purchase_cost', 8, 2)->nullable()->default(null)->change();
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
|
||||
class LongerStateFieldInLocation extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::table('locations', function ($table) {
|
||||
$table->string('state', 32)->nullable()->default(null)->change();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::table('locations', function ($table) {
|
||||
$table->string('state', 2)->nullable()->default(null)->change();
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
|
||||
class AddModelNumberToAccessories extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::table('accessories', function ($table) {
|
||||
$table->string('model_number')->nullable()->default(null);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::table('accessories', function ($table) {
|
||||
$table->dropColumn('model_number');
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
class AddMissingTargetTypeToLogsTable extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
// Get list of action logs with a target id but not a target type. This fixes missing target_type in accept_asset
|
||||
DB::table('action_logs')->where('target_type', null)->where(function($query) {
|
||||
$query->where('action_type', 'accepted')
|
||||
->orWhere('action_type', 'declined');
|
||||
})->update(['target_type'=> 'App\Models\User']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
// Nothing to do.
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
|
||||
class IncreaseSizeOfStateInSuppliers extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::table('suppliers', function ($table) {
|
||||
$table->string('state', 32)->nullable()->default(null)->change();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::table('suppliers', function ($table) {
|
||||
$table->string('state', 2)->nullable()->default(null)->change();
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -16,6 +16,8 @@ class DatabaseSeeder extends Seeder
|
||||
|
||||
$this->call(CompanySeeder::class);
|
||||
$this->call(UserSeeder::class);
|
||||
$this->call(ManufacturerSeeder::class);
|
||||
$this->call(LocationSeeder::class);
|
||||
$this->call(AssetModelSeeder::class);
|
||||
$this->call(AccessorySeeder::class);
|
||||
$this->call(AssetSeeder::class);
|
||||
@@ -27,8 +29,6 @@ class DatabaseSeeder extends Seeder
|
||||
$this->call(LicenseSeeder::class);
|
||||
$this->call(ActionlogSeeder::class);
|
||||
$this->call(DepreciationSeeder::class);
|
||||
$this->call(ManufacturerSeeder::class);
|
||||
$this->call(LocationSeeder::class);
|
||||
$this->call(CustomFieldSeeder::class);
|
||||
|
||||
Model::reguard();
|
||||
|
||||
@@ -18,7 +18,7 @@ else
|
||||
fi
|
||||
|
||||
# create data directories
|
||||
for dir in 'data/private_uploads' 'data/uploads' 'data/uploads/avatars' 'data/uploads/models' 'data/uploads/suppliers' 'dumps'; do
|
||||
for dir in 'data/private_uploads' 'data/uploads' 'data/uploads/avatars' 'data/uploads/barcodes' 'data/uploads/models' 'data/uploads/suppliers' 'dumps'; do
|
||||
mkdir -p "/var/lib/snipeit/$dir"
|
||||
done
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
var elixir = require('laravel-elixir');
|
||||
require('laravel-elixir-codeception');
|
||||
require('laravel-elixir-codeception-standalone');
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Elixir Asset Management
|
||||
@@ -38,7 +38,7 @@ elixir(function(mix) {
|
||||
mix.version(['assets/css/app.css','assets/js/all.js']);
|
||||
|
||||
|
||||
mix.codeception();
|
||||
mix.codeception(null, { flags: '--report' });
|
||||
|
||||
|
||||
|
||||
|
||||
21
package.json
Normal file
21
package.json
Normal file
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"prod": "gulp --production",
|
||||
"dev": "gulp watch"
|
||||
},
|
||||
"devDependencies": {
|
||||
"bootstrap-sass": "^3.3.7",
|
||||
"gulp": "^3.9.1",
|
||||
"jquery": "^3.1.0",
|
||||
"laravel-elixir": "^6.0.0-11",
|
||||
"laravel-elixir-vue-2": "^0.2.0",
|
||||
"laravel-elixir-webpack-official": "^1.0.2",
|
||||
"lodash": "^4.16.2",
|
||||
"vue": "^2.0.1",
|
||||
"vue-resource": "^1.0.3"
|
||||
},
|
||||
"dependencies": {
|
||||
"laravel-elixir-codeception": "^0.2.0"
|
||||
}
|
||||
}
|
||||
136
public/assets/css/signature-pad.css
Executable file
136
public/assets/css/signature-pad.css
Executable file
@@ -0,0 +1,136 @@
|
||||
|
||||
#signature-pad {
|
||||
padding-top: 250px;
|
||||
margin: auto;
|
||||
}
|
||||
.m-signature-pad {
|
||||
|
||||
position: relative;
|
||||
font-size: 10px;
|
||||
width: 100%;
|
||||
height: 300px;
|
||||
border: 1px solid #e8e8e8;
|
||||
background-color: #fff;
|
||||
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.27), 0 0 40px rgba(0, 0, 0, 0.08) inset;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.m-signature-pad:before, .m-signature-pad:after {
|
||||
position: absolute;
|
||||
z-index: -1;
|
||||
content: "";
|
||||
width: 40%;
|
||||
height: 10px;
|
||||
left: 20px;
|
||||
bottom: 10px;
|
||||
background: transparent;
|
||||
-webkit-transform: skew(-3deg) rotate(-3deg);
|
||||
-moz-transform: skew(-3deg) rotate(-3deg);
|
||||
-ms-transform: skew(-3deg) rotate(-3deg);
|
||||
-o-transform: skew(-3deg) rotate(-3deg);
|
||||
transform: skew(-3deg) rotate(-3deg);
|
||||
box-shadow: 0 8px 12px rgba(0, 0, 0, 0.4);
|
||||
}
|
||||
|
||||
.m-signature-pad:after {
|
||||
left: auto;
|
||||
right: 20px;
|
||||
-webkit-transform: skew(3deg) rotate(3deg);
|
||||
-moz-transform: skew(3deg) rotate(3deg);
|
||||
-ms-transform: skew(3deg) rotate(3deg);
|
||||
-o-transform: skew(3deg) rotate(3deg);
|
||||
transform: skew(3deg) rotate(3deg);
|
||||
}
|
||||
|
||||
.m-signature-pad--body {
|
||||
position: absolute;
|
||||
left: 20px;
|
||||
right: 20px;
|
||||
top: 20px;
|
||||
bottom: 60px;
|
||||
border: 1px solid #f4f4f4;
|
||||
}
|
||||
|
||||
.m-signature-pad--body
|
||||
canvas {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border-radius: 4px;
|
||||
box-shadow: 0 0 5px rgba(0, 0, 0, 0.02) inset;
|
||||
}
|
||||
|
||||
.m-signature-pad--footer {
|
||||
position: absolute;
|
||||
left: 20px;
|
||||
right: 20px;
|
||||
bottom: 20px;
|
||||
height: 40px;
|
||||
}
|
||||
|
||||
.m-signature-pad--footer
|
||||
.description {
|
||||
color: #C3C3C3;
|
||||
text-align: center;
|
||||
font-size: 1.2em;
|
||||
margin-top: 1.8em;
|
||||
}
|
||||
|
||||
.m-signature-pad--footer
|
||||
.button {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
}
|
||||
|
||||
.m-signature-pad--footer
|
||||
.button.clear {
|
||||
left: 0;
|
||||
}
|
||||
|
||||
.m-signature-pad--footer
|
||||
.button.save {
|
||||
right: 0;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 1024px) {
|
||||
.m-signature-pad {
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
width: auto;
|
||||
height: auto;
|
||||
min-width: 250px;
|
||||
min-height: 140px;
|
||||
margin: 5%;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@media screen and (min-device-width: 768px) and (max-device-width: 1024px) {
|
||||
.m-signature-pad {
|
||||
margin: 10%;
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-height: 320px) {
|
||||
.m-signature-pad--body {
|
||||
left: 0;
|
||||
right: 0;
|
||||
top: 0;
|
||||
bottom: 32px;
|
||||
}
|
||||
.m-signature-pad--footer {
|
||||
left: 20px;
|
||||
right: 20px;
|
||||
bottom: 4px;
|
||||
height: 28px;
|
||||
}
|
||||
.m-signature-pad--footer
|
||||
.description {
|
||||
font-size: 1em;
|
||||
margin-top: 1em;
|
||||
}
|
||||
}
|
||||
389
public/assets/js/signature_pad.js
Executable file
389
public/assets/js/signature_pad.js
Executable file
@@ -0,0 +1,389 @@
|
||||
(function (root, factory) {
|
||||
if (typeof define === 'function' && define.amd) {
|
||||
// AMD. Register as an anonymous module unless amdModuleId is set
|
||||
define([], function () {
|
||||
return (root['SignaturePad'] = factory());
|
||||
});
|
||||
} else if (typeof exports === 'object') {
|
||||
// Node. Does not work with strict CommonJS, but
|
||||
// only CommonJS-like environments that support module.exports,
|
||||
// like Node.
|
||||
module.exports = factory();
|
||||
} else {
|
||||
root['SignaturePad'] = factory();
|
||||
}
|
||||
}(this, function () {
|
||||
|
||||
/*!
|
||||
* Signature Pad v1.5.3
|
||||
* https://github.com/szimek/signature_pad
|
||||
*
|
||||
* Copyright 2016 Szymon Nowak
|
||||
* Released under the MIT license
|
||||
*
|
||||
* The main idea and some parts of the code (e.g. drawing variable width Bézier curve) are taken from:
|
||||
* http://corner.squareup.com/2012/07/smoother-signatures.html
|
||||
*
|
||||
* Implementation of interpolation using cubic Bézier curves is taken from:
|
||||
* http://benknowscode.wordpress.com/2012/09/14/path-interpolation-using-cubic-bezier-and-control-point-estimation-in-javascript
|
||||
*
|
||||
* Algorithm for approximated length of a Bézier curve is taken from:
|
||||
* http://www.lemoda.net/maths/bezier-length/index.html
|
||||
*
|
||||
*/
|
||||
var SignaturePad = (function (document) {
|
||||
"use strict";
|
||||
|
||||
var SignaturePad = function (canvas, options) {
|
||||
var self = this,
|
||||
opts = options || {};
|
||||
|
||||
this.velocityFilterWeight = opts.velocityFilterWeight || 0.7;
|
||||
this.minWidth = opts.minWidth || 0.5;
|
||||
this.maxWidth = opts.maxWidth || 2.5;
|
||||
this.dotSize = opts.dotSize || function () {
|
||||
return (this.minWidth + this.maxWidth) / 2;
|
||||
};
|
||||
this.penColor = opts.penColor || "black";
|
||||
this.backgroundColor = opts.backgroundColor || "rgba(0,0,0,0)";
|
||||
this.onEnd = opts.onEnd;
|
||||
this.onBegin = opts.onBegin;
|
||||
|
||||
this._canvas = canvas;
|
||||
this._ctx = canvas.getContext("2d");
|
||||
this.clear();
|
||||
|
||||
// we need add these inline so they are available to unbind while still having
|
||||
// access to 'self' we could use _.bind but it's not worth adding a dependency
|
||||
this._handleMouseDown = function (event) {
|
||||
if (event.which === 1) {
|
||||
self._mouseButtonDown = true;
|
||||
self._strokeBegin(event);
|
||||
}
|
||||
};
|
||||
|
||||
this._handleMouseMove = function (event) {
|
||||
if (self._mouseButtonDown) {
|
||||
self._strokeUpdate(event);
|
||||
}
|
||||
};
|
||||
|
||||
this._handleMouseUp = function (event) {
|
||||
if (event.which === 1 && self._mouseButtonDown) {
|
||||
self._mouseButtonDown = false;
|
||||
self._strokeEnd(event);
|
||||
}
|
||||
};
|
||||
|
||||
this._handleTouchStart = function (event) {
|
||||
if (event.targetTouches.length == 1) {
|
||||
var touch = event.changedTouches[0];
|
||||
self._strokeBegin(touch);
|
||||
}
|
||||
};
|
||||
|
||||
this._handleTouchMove = function (event) {
|
||||
// Prevent scrolling.
|
||||
event.preventDefault();
|
||||
|
||||
var touch = event.targetTouches[0];
|
||||
self._strokeUpdate(touch);
|
||||
};
|
||||
|
||||
this._handleTouchEnd = function (event) {
|
||||
var wasCanvasTouched = event.target === self._canvas;
|
||||
if (wasCanvasTouched) {
|
||||
event.preventDefault();
|
||||
self._strokeEnd(event);
|
||||
}
|
||||
};
|
||||
|
||||
this._handleMouseEvents();
|
||||
this._handleTouchEvents();
|
||||
};
|
||||
|
||||
SignaturePad.prototype.clear = function () {
|
||||
var ctx = this._ctx,
|
||||
canvas = this._canvas;
|
||||
|
||||
ctx.fillStyle = this.backgroundColor;
|
||||
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
||||
ctx.fillRect(0, 0, canvas.width, canvas.height);
|
||||
this._reset();
|
||||
};
|
||||
|
||||
SignaturePad.prototype.toDataURL = function (imageType, quality) {
|
||||
var canvas = this._canvas;
|
||||
return canvas.toDataURL.apply(canvas, arguments);
|
||||
};
|
||||
|
||||
SignaturePad.prototype.fromDataURL = function (dataUrl) {
|
||||
var self = this,
|
||||
image = new Image(),
|
||||
ratio = window.devicePixelRatio || 1,
|
||||
width = this._canvas.width / ratio,
|
||||
height = this._canvas.height / ratio;
|
||||
|
||||
this._reset();
|
||||
image.src = dataUrl;
|
||||
image.onload = function () {
|
||||
self._ctx.drawImage(image, 0, 0, width, height);
|
||||
};
|
||||
this._isEmpty = false;
|
||||
};
|
||||
|
||||
SignaturePad.prototype._strokeUpdate = function (event) {
|
||||
var point = this._createPoint(event);
|
||||
this._addPoint(point);
|
||||
};
|
||||
|
||||
SignaturePad.prototype._strokeBegin = function (event) {
|
||||
this._reset();
|
||||
this._strokeUpdate(event);
|
||||
if (typeof this.onBegin === 'function') {
|
||||
this.onBegin(event);
|
||||
}
|
||||
};
|
||||
|
||||
SignaturePad.prototype._strokeDraw = function (point) {
|
||||
var ctx = this._ctx,
|
||||
dotSize = typeof(this.dotSize) === 'function' ? this.dotSize() : this.dotSize;
|
||||
|
||||
ctx.beginPath();
|
||||
this._drawPoint(point.x, point.y, dotSize);
|
||||
ctx.closePath();
|
||||
ctx.fill();
|
||||
};
|
||||
|
||||
SignaturePad.prototype._strokeEnd = function (event) {
|
||||
var canDrawCurve = this.points.length > 2,
|
||||
point = this.points[0];
|
||||
|
||||
if (!canDrawCurve && point) {
|
||||
this._strokeDraw(point);
|
||||
}
|
||||
if (typeof this.onEnd === 'function') {
|
||||
this.onEnd(event);
|
||||
}
|
||||
};
|
||||
|
||||
SignaturePad.prototype._handleMouseEvents = function () {
|
||||
this._mouseButtonDown = false;
|
||||
|
||||
this._canvas.addEventListener("mousedown", this._handleMouseDown);
|
||||
this._canvas.addEventListener("mousemove", this._handleMouseMove);
|
||||
document.addEventListener("mouseup", this._handleMouseUp);
|
||||
};
|
||||
|
||||
SignaturePad.prototype._handleTouchEvents = function () {
|
||||
// Pass touch events to canvas element on mobile IE11 and Edge.
|
||||
this._canvas.style.msTouchAction = 'none';
|
||||
this._canvas.style.touchAction = 'none';
|
||||
|
||||
this._canvas.addEventListener("touchstart", this._handleTouchStart);
|
||||
this._canvas.addEventListener("touchmove", this._handleTouchMove);
|
||||
this._canvas.addEventListener("touchend", this._handleTouchEnd);
|
||||
};
|
||||
|
||||
SignaturePad.prototype.on = function () {
|
||||
this._handleMouseEvents();
|
||||
this._handleTouchEvents();
|
||||
};
|
||||
|
||||
SignaturePad.prototype.off = function () {
|
||||
this._canvas.removeEventListener("mousedown", this._handleMouseDown);
|
||||
this._canvas.removeEventListener("mousemove", this._handleMouseMove);
|
||||
document.removeEventListener("mouseup", this._handleMouseUp);
|
||||
|
||||
this._canvas.removeEventListener("touchstart", this._handleTouchStart);
|
||||
this._canvas.removeEventListener("touchmove", this._handleTouchMove);
|
||||
this._canvas.removeEventListener("touchend", this._handleTouchEnd);
|
||||
};
|
||||
|
||||
SignaturePad.prototype.isEmpty = function () {
|
||||
return this._isEmpty;
|
||||
};
|
||||
|
||||
SignaturePad.prototype._reset = function () {
|
||||
this.points = [];
|
||||
this._lastVelocity = 0;
|
||||
this._lastWidth = (this.minWidth + this.maxWidth) / 2;
|
||||
this._isEmpty = true;
|
||||
this._ctx.fillStyle = this.penColor;
|
||||
};
|
||||
|
||||
SignaturePad.prototype._createPoint = function (event) {
|
||||
var rect = this._canvas.getBoundingClientRect();
|
||||
return new Point(
|
||||
event.clientX - rect.left,
|
||||
event.clientY - rect.top
|
||||
);
|
||||
};
|
||||
|
||||
SignaturePad.prototype._addPoint = function (point) {
|
||||
var points = this.points,
|
||||
c2, c3,
|
||||
curve, tmp;
|
||||
|
||||
points.push(point);
|
||||
|
||||
if (points.length > 2) {
|
||||
// To reduce the initial lag make it work with 3 points
|
||||
// by copying the first point to the beginning.
|
||||
if (points.length === 3) points.unshift(points[0]);
|
||||
|
||||
tmp = this._calculateCurveControlPoints(points[0], points[1], points[2]);
|
||||
c2 = tmp.c2;
|
||||
tmp = this._calculateCurveControlPoints(points[1], points[2], points[3]);
|
||||
c3 = tmp.c1;
|
||||
curve = new Bezier(points[1], c2, c3, points[2]);
|
||||
this._addCurve(curve);
|
||||
|
||||
// Remove the first element from the list,
|
||||
// so that we always have no more than 4 points in points array.
|
||||
points.shift();
|
||||
}
|
||||
};
|
||||
|
||||
SignaturePad.prototype._calculateCurveControlPoints = function (s1, s2, s3) {
|
||||
var dx1 = s1.x - s2.x, dy1 = s1.y - s2.y,
|
||||
dx2 = s2.x - s3.x, dy2 = s2.y - s3.y,
|
||||
|
||||
m1 = {x: (s1.x + s2.x) / 2.0, y: (s1.y + s2.y) / 2.0},
|
||||
m2 = {x: (s2.x + s3.x) / 2.0, y: (s2.y + s3.y) / 2.0},
|
||||
|
||||
l1 = Math.sqrt(dx1*dx1 + dy1*dy1),
|
||||
l2 = Math.sqrt(dx2*dx2 + dy2*dy2),
|
||||
|
||||
dxm = (m1.x - m2.x),
|
||||
dym = (m1.y - m2.y),
|
||||
|
||||
k = l2 / (l1 + l2),
|
||||
cm = {x: m2.x + dxm*k, y: m2.y + dym*k},
|
||||
|
||||
tx = s2.x - cm.x,
|
||||
ty = s2.y - cm.y;
|
||||
|
||||
return {
|
||||
c1: new Point(m1.x + tx, m1.y + ty),
|
||||
c2: new Point(m2.x + tx, m2.y + ty)
|
||||
};
|
||||
};
|
||||
|
||||
SignaturePad.prototype._addCurve = function (curve) {
|
||||
var startPoint = curve.startPoint,
|
||||
endPoint = curve.endPoint,
|
||||
velocity, newWidth;
|
||||
|
||||
velocity = endPoint.velocityFrom(startPoint);
|
||||
velocity = this.velocityFilterWeight * velocity
|
||||
+ (1 - this.velocityFilterWeight) * this._lastVelocity;
|
||||
|
||||
newWidth = this._strokeWidth(velocity);
|
||||
this._drawCurve(curve, this._lastWidth, newWidth);
|
||||
|
||||
this._lastVelocity = velocity;
|
||||
this._lastWidth = newWidth;
|
||||
};
|
||||
|
||||
SignaturePad.prototype._drawPoint = function (x, y, size) {
|
||||
var ctx = this._ctx;
|
||||
|
||||
ctx.moveTo(x, y);
|
||||
ctx.arc(x, y, size, 0, 2 * Math.PI, false);
|
||||
this._isEmpty = false;
|
||||
};
|
||||
|
||||
SignaturePad.prototype._drawCurve = function (curve, startWidth, endWidth) {
|
||||
var ctx = this._ctx,
|
||||
widthDelta = endWidth - startWidth,
|
||||
drawSteps, width, i, t, tt, ttt, u, uu, uuu, x, y;
|
||||
|
||||
drawSteps = Math.floor(curve.length());
|
||||
ctx.beginPath();
|
||||
for (i = 0; i < drawSteps; i++) {
|
||||
// Calculate the Bezier (x, y) coordinate for this step.
|
||||
t = i / drawSteps;
|
||||
tt = t * t;
|
||||
ttt = tt * t;
|
||||
u = 1 - t;
|
||||
uu = u * u;
|
||||
uuu = uu * u;
|
||||
|
||||
x = uuu * curve.startPoint.x;
|
||||
x += 3 * uu * t * curve.control1.x;
|
||||
x += 3 * u * tt * curve.control2.x;
|
||||
x += ttt * curve.endPoint.x;
|
||||
|
||||
y = uuu * curve.startPoint.y;
|
||||
y += 3 * uu * t * curve.control1.y;
|
||||
y += 3 * u * tt * curve.control2.y;
|
||||
y += ttt * curve.endPoint.y;
|
||||
|
||||
width = startWidth + ttt * widthDelta;
|
||||
this._drawPoint(x, y, width);
|
||||
}
|
||||
ctx.closePath();
|
||||
ctx.fill();
|
||||
};
|
||||
|
||||
SignaturePad.prototype._strokeWidth = function (velocity) {
|
||||
return Math.max(this.maxWidth / (velocity + 1), this.minWidth);
|
||||
};
|
||||
|
||||
|
||||
var Point = function (x, y, time) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.time = time || new Date().getTime();
|
||||
};
|
||||
|
||||
Point.prototype.velocityFrom = function (start) {
|
||||
return (this.time !== start.time) ? this.distanceTo(start) / (this.time - start.time) : 1;
|
||||
};
|
||||
|
||||
Point.prototype.distanceTo = function (start) {
|
||||
return Math.sqrt(Math.pow(this.x - start.x, 2) + Math.pow(this.y - start.y, 2));
|
||||
};
|
||||
|
||||
var Bezier = function (startPoint, control1, control2, endPoint) {
|
||||
this.startPoint = startPoint;
|
||||
this.control1 = control1;
|
||||
this.control2 = control2;
|
||||
this.endPoint = endPoint;
|
||||
};
|
||||
|
||||
// Returns approximated length.
|
||||
Bezier.prototype.length = function () {
|
||||
var steps = 10,
|
||||
length = 0,
|
||||
i, t, cx, cy, px, py, xdiff, ydiff;
|
||||
|
||||
for (i = 0; i <= steps; i++) {
|
||||
t = i / steps;
|
||||
cx = this._point(t, this.startPoint.x, this.control1.x, this.control2.x, this.endPoint.x);
|
||||
cy = this._point(t, this.startPoint.y, this.control1.y, this.control2.y, this.endPoint.y);
|
||||
if (i > 0) {
|
||||
xdiff = cx - px;
|
||||
ydiff = cy - py;
|
||||
length += Math.sqrt(xdiff * xdiff + ydiff * ydiff);
|
||||
}
|
||||
px = cx;
|
||||
py = cy;
|
||||
}
|
||||
return length;
|
||||
};
|
||||
|
||||
Bezier.prototype._point = function (t, start, c1, c2, end) {
|
||||
return start * (1.0 - t) * (1.0 - t) * (1.0 - t)
|
||||
+ 3.0 * c1 * (1.0 - t) * (1.0 - t) * t
|
||||
+ 3.0 * c2 * (1.0 - t) * t * t
|
||||
+ end * t * t * t;
|
||||
};
|
||||
|
||||
return SignaturePad;
|
||||
})(document);
|
||||
|
||||
return SignaturePad;
|
||||
|
||||
}));
|
||||
5
public/assets/js/signature_pad.min.js
vendored
Executable file
5
public/assets/js/signature_pad.min.js
vendored
Executable file
File diff suppressed because one or more lines are too long
0
public/uploads/.gitkeep
Normal file → Executable file
0
public/uploads/.gitkeep
Normal file → Executable file
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user