2017-01-12 19:40:20 -08:00
< ? php
namespace App\Http\Controllers\Api ;
use Illuminate\Http\Request ;
use App\Http\Controllers\Controller ;
2017-01-12 23:42:39 -08:00
use App\Http\Transformers\UsersTransformer ;
2017-01-13 04:50:20 -08:00
use App\Models\Company ;
2017-01-12 23:42:39 -08:00
use App\Models\User ;
2017-08-03 19:50:18 -07:00
use App\Helpers\Helper ;
2017-08-22 20:32:39 -07:00
use App\Http\Requests\SaveUserRequest ;
2017-08-26 15:21:38 -07:00
use App\Models\Asset ;
2017-10-24 19:18:20 -07:00
use App\Http\Transformers\AssetsTransformer ;
2017-10-26 21:50:01 -07:00
use App\Http\Transformers\SelectlistTransformer ;
2019-03-01 17:21:03 -08:00
use App\Http\Transformers\AccessoriesTransformer ;
2019-12-19 18:00:36 -08:00
use App\Http\Transformers\LicensesTransformer ;
2020-03-06 15:28:46 -08:00
use Auth ;
2017-01-12 19:40:20 -08:00
class UsersController extends Controller
{
/**
* Display a listing of the resource .
*
* @ author [ A . Gianotto ] [ < snipe @ snipe . net > ]
* @ since [ v4 . 0 ]
*
* @ return \Illuminate\Http\Response
*/
2017-01-13 04:50:20 -08:00
public function index ( Request $request )
2017-01-12 19:40:20 -08:00
{
2017-01-12 23:42:39 -08:00
$this -> authorize ( 'view' , User :: class );
2017-01-13 04:50:20 -08:00
$users = User :: select ([
2018-02-24 19:01:34 -08:00
'users.activated' ,
2017-10-30 18:57:00 -07:00
'users.address' ,
2018-02-24 19:01:34 -08:00
'users.avatar' ,
2017-10-30 18:57:00 -07:00
'users.city' ,
2018-02-24 19:01:34 -08:00
'users.company_id' ,
2017-10-30 18:57:00 -07:00
'users.country' ,
2017-01-13 04:50:20 -08:00
'users.created_at' ,
'users.deleted_at' ,
2017-05-23 02:46:55 -07:00
'users.department_id' ,
2018-02-24 19:01:34 -08:00
'users.email' ,
'users.employee_num' ,
'users.first_name' ,
'users.id' ,
'users.jobtitle' ,
'users.last_login' ,
'users.last_name' ,
'users.location_id' ,
'users.manager_id' ,
'users.notes' ,
'users.permissions' ,
'users.phone' ,
'users.state' ,
'users.two_factor_enrolled' ,
2019-03-18 11:59:02 -07:00
'users.two_factor_optin' ,
2018-02-24 19:01:34 -08:00
'users.updated_at' ,
'users.username' ,
'users.zip' ,
2017-10-24 09:51:07 -07:00
2017-11-02 11:06:15 -07:00
]) -> with ( 'manager' , 'groups' , 'userloc' , 'company' , 'department' , 'assets' , 'licenses' , 'accessories' , 'consumables' )
2019-05-22 00:52:51 -07:00
-> withCount ( 'assets as assets_count' , 'licenses as licenses_count' , 'accessories as accessories_count' , 'consumables as consumables_count' );
2017-01-13 04:50:20 -08:00
$users = Company :: scopeCompanyables ( $users );
2019-05-23 17:39:50 -07:00
if (( $request -> filled ( 'deleted' )) && ( $request -> input ( 'deleted' ) == 'true' )) {
2017-09-06 17:11:43 -07:00
$users = $users -> GetDeleted ();
}
2019-05-23 17:39:50 -07:00
if ( $request -> filled ( 'company_id' )) {
2017-12-11 22:50:55 -08:00
$users = $users -> where ( 'users.company_id' , '=' , $request -> input ( 'company_id' ));
2017-06-12 17:39:03 -07:00
}
2019-05-23 17:39:50 -07:00
if ( $request -> filled ( 'location_id' )) {
2017-12-11 22:50:55 -08:00
$users = $users -> where ( 'users.location_id' , '=' , $request -> input ( 'location_id' ));
2017-02-08 08:48:41 -08:00
}
2018-02-24 19:01:34 -08:00
2019-05-23 17:39:50 -07:00
if ( $request -> filled ( 'group_id' )) {
2017-10-24 04:39:47 -07:00
$users = $users -> ByGroup ( $request -> get ( 'group_id' ));
2017-10-17 21:43:57 -07:00
}
2017-02-08 08:48:41 -08:00
2019-05-23 17:39:50 -07:00
if ( $request -> filled ( 'department_id' )) {
2017-11-03 14:29:04 -07:00
$users = $users -> where ( 'users.department_id' , '=' , $request -> input ( 'department_id' ));
2017-05-23 01:09:03 -07:00
}
2019-05-23 17:39:50 -07:00
if ( $request -> filled ( 'search' )) {
2018-01-11 15:17:34 -08:00
$users = $users -> TextSearch ( $request -> input ( 'search' ));
}
2017-01-13 04:50:20 -08:00
$order = $request -> input ( 'order' ) === 'asc' ? 'asc' : 'desc' ;
2020-02-04 12:32:24 -08:00
// Set the offset to the API call's offset, unless the offset is higher than the actual count of items in which
// case we override with the actual count, so we should return 0 items.
$offset = (( $users ) && ( $request -> get ( 'offset' ) > $users -> count ())) ? $users -> count () : $request -> get ( 'offset' , 0 );
2019-09-03 14:02:08 -07:00
// Check to make sure the limit is not higher than the max allowed
2019-09-03 20:28:49 -07:00
(( config ( 'app.max_results' ) >= $request -> input ( 'limit' )) && ( $request -> filled ( 'limit' ))) ? $limit = $request -> input ( 'limit' ) : $limit = config ( 'app.max_results' );
2019-09-03 14:02:08 -07:00
2017-01-13 04:50:20 -08:00
switch ( $request -> input ( 'sort' )) {
case 'manager' :
$users = $users -> OrderManager ( $order );
break ;
case 'location' :
$users = $users -> OrderLocation ( $order );
break ;
2017-05-23 02:46:55 -07:00
case 'department' :
$users = $users -> OrderDepartment ( $order );
break ;
2019-05-24 13:37:20 -07:00
case 'company' :
$users = $users -> OrderCompany ( $order );
break ;
2017-01-13 04:50:20 -08:00
default :
$allowed_columns =
[
'last_name' , 'first_name' , 'email' , 'jobtitle' , 'username' , 'employee_num' ,
'assets' , 'accessories' , 'consumables' , 'licenses' , 'groups' , 'activated' , 'created_at' ,
2017-10-19 17:15:21 -07:00
'two_factor_enrolled' , 'two_factor_optin' , 'last_login' , 'assets_count' , 'licenses_count' ,
2017-10-30 18:57:00 -07:00
'consumables_count' , 'accessories_count' , 'phone' , 'address' , 'city' , 'state' ,
2018-07-23 06:46:50 -07:00
'country' , 'zip' , 'id'
2017-01-13 04:50:20 -08:00
];
$sort = in_array ( $request -> get ( 'sort' ), $allowed_columns ) ? $request -> get ( 'sort' ) : 'first_name' ;
$users = $users -> orderBy ( $sort , $order );
break ;
}
2018-01-11 15:17:34 -08:00
2017-05-23 14:30:07 -07:00
$total = $users -> count ();
2017-01-13 04:50:20 -08:00
$users = $users -> skip ( $offset ) -> take ( $limit ) -> get ();
2017-05-23 14:30:07 -07:00
return ( new UsersTransformer ) -> transformUsers ( $users , $total );
2017-01-12 19:40:20 -08:00
}
2017-10-24 19:24:35 -07:00
/**
2017-10-26 21:50:01 -07:00
* Gets a paginated collection for the select2 menus
2017-10-24 19:24:35 -07:00
*
* @ author [ A . Gianotto ] [ < snipe @ snipe . net > ]
2017-10-26 21:50:01 -07:00
* @ since [ v4 . 0.16 ]
* @ see \App\Http\Transformers\SelectlistTransformer
2017-10-24 19:24:35 -07:00
*
*/
public function selectlist ( Request $request )
{
$users = User :: select (
[
'users.id' ,
2018-01-19 23:47:37 -08:00
'users.username' ,
2017-10-24 19:24:35 -07:00
'users.employee_num' ,
'users.first_name' ,
'users.last_name' ,
'users.gravatar' ,
'users.avatar' ,
'users.email' ,
]
2018-07-18 03:59:02 -07:00
) -> where ( 'show_in_list' , '=' , '1' );
2017-10-24 19:24:35 -07:00
$users = Company :: scopeCompanyables ( $users );
2019-05-23 17:39:50 -07:00
if ( $request -> filled ( 'search' )) {
2019-03-05 21:13:39 -08:00
$users = $users -> SimpleNameSearch ( $request -> get ( 'search' ))
2017-10-24 19:24:35 -07:00
-> orWhere ( 'username' , 'LIKE' , '%' . $request -> get ( 'search' ) . '%' )
2017-10-28 11:17:52 -07:00
-> orWhere ( 'employee_num' , 'LIKE' , '%' . $request -> get ( 'search' ) . '%' );
2017-10-24 19:24:35 -07:00
}
2017-10-28 11:17:52 -07:00
$users = $users -> orderBy ( 'last_name' , 'asc' ) -> orderBy ( 'first_name' , 'asc' );
2017-10-24 19:24:35 -07:00
$users = $users -> paginate ( 50 );
2017-10-26 21:50:01 -07:00
2017-10-24 19:24:35 -07:00
foreach ( $users as $user ) {
$name_str = '' ;
if ( $user -> last_name != '' ) {
$name_str .= e ( $user -> last_name ) . ', ' ;
}
$name_str .= e ( $user -> first_name );
2018-01-19 23:47:37 -08:00
if ( $user -> username != '' ) {
$name_str .= ' (' . e ( $user -> username ) . ')' ;
}
2017-10-24 19:24:35 -07:00
if ( $user -> employee_num != '' ) {
2018-01-19 23:47:37 -08:00
$name_str .= ' - #' . e ( $user -> employee_num );
2017-10-24 19:24:35 -07:00
}
2017-10-26 21:50:01 -07:00
$user -> use_text = $name_str ;
$user -> use_image = ( $user -> present () -> gravatar ) ? $user -> present () -> gravatar : null ;
2017-10-24 19:24:35 -07:00
}
2017-10-26 03:43:28 -07:00
2017-10-26 21:50:01 -07:00
return ( new SelectlistTransformer ) -> transformSelectlist ( $users );
2017-10-24 19:24:35 -07:00
}
2017-01-12 19:40:20 -08:00
/**
* Store a newly created resource in storage .
*
* @ author [ A . Gianotto ] [ < snipe @ snipe . net > ]
* @ since [ v4 . 0 ]
* @ param \Illuminate\Http\Request $request
* @ return \Illuminate\Http\Response
*/
2017-08-22 20:32:39 -07:00
public function store ( SaveUserRequest $request )
2017-01-12 19:40:20 -08:00
{
2018-07-12 18:28:02 -07:00
$this -> authorize ( 'create' , User :: class );
2017-08-03 19:50:18 -07:00
$user = new User ;
$user -> fill ( $request -> all ());
2018-04-20 14:02:52 -07:00
2020-03-06 15:28:46 -08:00
if ( $request -> has ( 'permissions' )) {
$permissions_array = $request -> input ( 'permissions' );
// Strip out the superuser permission if the API user isn't a superadmin
if ( ! Auth :: user () -> isSuperUser ()) {
unset ( $permissions_array [ 'superuser' ]);
}
$user -> permissions = $permissions_array ;
}
2018-04-20 14:02:52 -07:00
$tmp_pass = substr ( str_shuffle ( " 0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ " ), 0 , 20 );
$user -> password = bcrypt ( $request -> get ( 'password' , $tmp_pass ));
2017-08-03 19:50:18 -07:00
if ( $user -> save ()) {
2019-05-23 17:39:50 -07:00
if ( $request -> filled ( 'groups' )) {
2018-09-07 18:25:58 -07:00
$user -> groups () -> sync ( $request -> input ( 'groups' ));
} else {
$user -> groups () -> sync ( array ());
}
2017-10-24 19:17:30 -07:00
return response () -> json ( Helper :: formatStandardApiResponse ( 'success' , ( new UsersTransformer ) -> transformUser ( $user ), trans ( 'admin/users/message.success.create' )));
2017-08-03 19:50:18 -07:00
}
return response () -> json ( Helper :: formatStandardApiResponse ( 'error' , null , $user -> getErrors ()));
2017-01-12 19:40:20 -08:00
}
/**
* Display the specified resource .
*
* @ author [ A . Gianotto ] [ < snipe @ snipe . net > ]
* @ param int $id
* @ return \Illuminate\Http\Response
*/
public function show ( $id )
{
2017-01-12 23:42:39 -08:00
$this -> authorize ( 'view' , User :: class );
2019-12-19 18:09:53 -08:00
$user = User :: withCount ( 'assets as assets_count' , 'licenses as licenses_count' , 'accessories as accessories_count' , 'consumables as consumables_count' ) -> findOrFail ( $id );
2017-01-12 23:42:39 -08:00
return ( new UsersTransformer ) -> transformUser ( $user );
2017-01-12 19:40:20 -08:00
}
/**
* Update the specified resource in storage .
*
* @ author [ A . Gianotto ] [ < snipe @ snipe . net > ]
* @ since [ v4 . 0 ]
* @ param \Illuminate\Http\Request $request
* @ param int $id
* @ return \Illuminate\Http\Response
*/
2017-08-22 20:32:39 -07:00
public function update ( SaveUserRequest $request , $id )
2017-01-12 19:40:20 -08:00
{
2018-07-12 18:28:02 -07:00
$this -> authorize ( 'update' , User :: class );
2017-08-03 19:50:18 -07:00
$user = User :: findOrFail ( $id );
$user -> fill ( $request -> all ());
2017-11-03 12:48:00 -07:00
if ( $user -> id == $request -> input ( 'manager_id' )) {
return response () -> json ( Helper :: formatStandardApiResponse ( 'error' , null , 'You cannot be your own manager' ));
}
2019-05-23 17:39:50 -07:00
if ( $request -> filled ( 'password' )) {
2017-08-08 14:41:58 -07:00
$user -> password = bcrypt ( $request -> input ( 'password' ));
}
2020-03-06 15:28:46 -08:00
// We need to use has() instead of filled()
// here because we need to overwrite permissions
// if someone needs to null them out
if ( $request -> has ( 'permissions' )) {
$permissions_array = $request -> input ( 'permissions' );
// Strip out the superuser permission if the API user isn't a superadmin
if ( ! Auth :: user () -> isSuperUser ()) {
unset ( $permissions_array [ 'superuser' ]);
}
$user -> permissions = $permissions_array ;
}
2017-10-30 19:33:52 -07:00
// Update the location of any assets checked out to this user
Asset :: where ( 'assigned_type' , User :: class )
-> where ( 'assigned_to' , $user -> id ) -> update ([ 'location_id' => $request -> input ( 'location_id' , null )]);
2017-08-08 14:41:58 -07:00
2017-08-03 19:50:18 -07:00
if ( $user -> save ()) {
2019-05-15 16:39:34 -07:00
2019-07-15 15:27:02 -07:00
// Sync group memberships:
// This was changed in Snipe-IT v4.6.x to 4.7, since we upgraded to Laravel 5.5
// which changes the behavior of has vs filled.
// The $request->has method will now return true even if the input value is an empty string or null.
// A new $request->filled method has was added that provides the previous behavior of the has method.
// Check if the request has groups passed and has a value
2019-05-23 17:39:50 -07:00
if ( $request -> filled ( 'groups' )) {
2019-05-15 16:39:34 -07:00
$user -> groups () -> sync ( $request -> input ( 'groups' ));
2019-07-15 15:31:09 -07:00
// The groups field has been passed but it is null, so we should blank it out
2019-07-15 15:27:02 -07:00
} elseif ( $request -> has ( 'groups' )) {
2019-05-15 16:39:34 -07:00
$user -> groups () -> sync ( array ());
}
2019-07-15 15:27:02 -07:00
2017-08-03 19:50:18 -07:00
return response () -> json ( Helper :: formatStandardApiResponse ( 'success' , ( new UsersTransformer ) -> transformUser ( $user ), trans ( 'admin/users/message.success.update' )));
}
return response () -> json ( Helper :: formatStandardApiResponse ( 'error' , null , $user -> getErrors ()));
2017-01-12 19:40:20 -08:00
}
/**
* Remove the specified resource from storage .
*
* @ author [ A . Gianotto ] [ < snipe @ snipe . net > ]
* @ since [ v4 . 0 ]
* @ param int $id
* @ return \Illuminate\Http\Response
*/
public function destroy ( $id )
{
2017-08-03 19:50:18 -07:00
$this -> authorize ( 'delete' , User :: class );
$user = User :: findOrFail ( $id );
$this -> authorize ( 'delete' , $user );
2019-07-17 17:51:13 -07:00
if (( $user -> assets ) && ( $user -> assets -> count () > 0 )) {
2017-08-03 19:50:18 -07:00
return response () -> json ( Helper :: formatStandardApiResponse ( 'error' , null , trans ( 'admin/users/message.error.delete_has_assets' )));
}
2019-07-17 17:51:13 -07:00
if (( $user -> licenses ) && ( $user -> licenses -> count () > 0 )) {
return response () -> json ( Helper :: formatStandardApiResponse ( 'error' , null , 'This user still has ' . $user -> licenses -> count () . ' license(s) associated with them and cannot be deleted.' ));
}
if (( $user -> accessories ) && ( $user -> accessories -> count () > 0 )) {
return response () -> json ( Helper :: formatStandardApiResponse ( 'error' , null , 'This user still has ' . $user -> accessories -> count () . ' accessories associated with them.' ));
}
if (( $user -> managedLocations ()) && ( $user -> managedLocations () -> count () > 0 )) {
return response () -> json ( Helper :: formatStandardApiResponse ( 'error' , null , 'This user still has ' . $user -> managedLocations () -> count () . ' locations that they manage.' ));
}
2017-08-03 19:50:18 -07:00
if ( $user -> delete ()) {
return response () -> json ( Helper :: formatStandardApiResponse ( 'success' , null , trans ( 'admin/users/message.success.delete' )));
}
return response () -> json ( Helper :: formatStandardApiResponse ( 'error' , null , trans ( 'admin/users/message.error.delete' )));
2017-01-12 19:40:20 -08:00
}
2017-08-26 15:21:38 -07:00
/**
* Return JSON containing a list of assets assigned to a user .
*
* @ author [ A . Gianotto ] [ < snipe @ snipe . net > ]
* @ since [ v3 . 0 ]
* @ param $userId
* @ return string JSON
*/
public function assets ( $id )
{
$this -> authorize ( 'view' , User :: class );
2018-07-12 18:28:02 -07:00
$this -> authorize ( 'view' , Asset :: class );
2018-07-25 21:38:14 -07:00
$assets = Asset :: where ( 'assigned_to' , '=' , $id ) -> where ( 'assigned_type' , '=' , User :: class ) -> with ( 'model' ) -> get ();
2017-10-24 19:18:20 -07:00
return ( new AssetsTransformer ) -> transformAssets ( $assets , $assets -> count ());
2017-08-26 15:21:38 -07:00
}
2018-02-26 15:43:49 -08:00
2019-03-01 17:21:03 -08:00
/**
* Return JSON containing a list of accessories assigned to a user .
*
* @ author [ A . Gianotto ] [ < snipe @ snipe . net > ]
* @ since [ v4 . 6.14 ]
* @ param $userId
* @ return string JSON
*/
public function accessories ( $id )
{
$this -> authorize ( 'view' , User :: class );
$user = User :: findOrFail ( $id );
$this -> authorize ( 'view' , Accessory :: class );
$accessories = $user -> accessories ;
return ( new AccessoriesTransformer ) -> transformAccessories ( $accessories , $accessories -> count ());
}
2019-12-19 18:00:36 -08:00
/**
* Return JSON containing a list of licenses assigned to a user .
*
* @ author [ N . Mathar ] [ < snipe @ snipe . net > ]
* @ since [ v5 . 0 ]
* @ param $userId
* @ return string JSON
*/
public function licenses ( $id )
{
$this -> authorize ( 'view' , User :: class );
$this -> authorize ( 'view' , License :: class );
$user = User :: where ( 'id' , $id ) -> withTrashed () -> first ();
$licenses = $user -> licenses () -> get ();
return ( new LicensesTransformer ()) -> transformLicenses ( $licenses , $licenses -> count ());
}
2018-02-26 15:43:49 -08:00
/**
* Reset the user ' s two - factor status
*
* @ author [ A . Gianotto ] [ < snipe @ snipe . net > ]
* @ since [ v3 . 0 ]
* @ param $userId
* @ return string JSON
*/
public function postTwoFactorReset ( Request $request )
{
2018-07-12 18:28:02 -07:00
$this -> authorize ( 'update' , User :: class );
2018-02-26 15:43:49 -08:00
2019-05-23 17:39:50 -07:00
if ( $request -> filled ( 'id' )) {
2018-02-26 15:43:49 -08:00
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 );
}
}
return response () -> json ([ 'message' => 'No ID provided' ], 500 );
}
2018-07-02 20:35:10 -07:00
/**
* Get info on the current user .
*
* @ author [ Juan Font ] [ < juanfontalonso @ gmail . com > ]
* @ since [ v4 . 4.2 ]
* @ param \Illuminate\Http\Request $request
* @ return \Illuminate\Http\Response
*/
public function getCurrentUserInfo ( Request $request )
{
2020-01-30 13:12:43 -08:00
return ( new UsersTransformer ) -> transformUser ( $request -> user ());
2018-07-02 20:35:10 -07:00
}
2017-01-12 19:40:20 -08:00
}