] * @since [v4.0] * * @return \Illuminate\Http\Response */ public function index(Request $request) { $this->authorize('view', User::class); $users = User::select([ 'users.activated', 'users.created_by', 'users.address', 'users.avatar', 'users.city', 'users.company_id', 'users.country', 'users.created_at', 'users.deleted_at', 'users.department_id', 'users.email', 'users.employee_num', 'users.first_name', 'users.id', 'users.jobtitle', 'users.last_login', 'users.last_name', 'users.locale', 'users.location_id', 'users.manager_id', 'users.notes', 'users.permissions', 'users.phone', 'users.state', 'users.two_factor_enrolled', 'users.two_factor_optin', 'users.updated_at', 'users.username', 'users.zip', 'users.remote', 'users.ldap_import', 'users.start_date', 'users.end_date', 'users.vip', 'users.autoassign_licenses', 'users.website', ])->with('manager', 'groups', 'userloc', 'company', 'department', 'assets', 'licenses', 'accessories', 'consumables', 'createdBy',) ->withCount('assets as assets_count', 'licenses as licenses_count', 'accessories as accessories_count', 'consumables as consumables_count'); if ($request->filled('activated')) { $users = $users->where('users.activated', '=', $request->input('activated')); } if ($request->filled('company_id')) { $users = $users->where('users.company_id', '=', $request->input('company_id')); } if ($request->filled('location_id')) { $users = $users->where('users.location_id', '=', $request->input('location_id')); } if ($request->filled('created_by')) { $users = $users->where('users.created_by', '=', $request->input('created_by')); } if ($request->filled('email')) { $users = $users->where('users.email', '=', $request->input('email')); } if ($request->filled('username')) { $users = $users->where('users.username', '=', $request->input('username')); } if ($request->filled('first_name')) { $users = $users->where('users.first_name', '=', $request->input('first_name')); } if ($request->filled('last_name')) { $users = $users->where('users.last_name', '=', $request->input('last_name')); } if ($request->filled('employee_num')) { $users = $users->where('users.employee_num', '=', $request->input('employee_num')); } if ($request->filled('state')) { $users = $users->where('users.state', '=', $request->input('state')); } if ($request->filled('country')) { $users = $users->where('users.country', '=', $request->input('country')); } if ($request->filled('website')) { $users = $users->where('users.website', '=', $request->input('website')); } if ($request->filled('zip')) { $users = $users->where('users.zip', '=', $request->input('zip')); } if ($request->filled('group_id')) { $users = $users->ByGroup($request->get('group_id')); } if ($request->filled('department_id')) { $users = $users->where('users.department_id', '=', $request->input('department_id')); } if ($request->filled('manager_id')) { $users = $users->where('users.manager_id','=',$request->input('manager_id')); } if ($request->filled('ldap_import')) { $users = $users->where('ldap_import', '=', $request->input('ldap_import')); } if ($request->filled('remote')) { $users = $users->where('remote', '=', $request->input('remote')); } if ($request->filled('vip')) { $users = $users->where('vip', '=', $request->input('vip')); } if ($request->filled('two_factor_enrolled')) { $users = $users->where('two_factor_enrolled', '=', $request->input('two_factor_enrolled')); } if ($request->filled('two_factor_optin')) { $users = $users->where('two_factor_optin', '=', $request->input('two_factor_optin')); } if ($request->filled('start_date')) { $users = $users->where('users.start_date', '=', $request->input('start_date')); } if ($request->filled('end_date')) { $users = $users->where('users.end_date', '=', $request->input('end_date')); } if ($request->filled('assets_count')) { $users->has('assets', '=', $request->input('assets_count')); } if ($request->filled('consumables_count')) { $users->has('consumables', '=', $request->input('consumables_count')); } if ($request->filled('licenses_count')) { $users->has('licenses', '=', $request->input('licenses_count')); } if ($request->filled('accessories_count')) { $users->has('accessories', '=', $request->input('accessories_count')); } if ($request->filled('autoassign_licenses')) { $users->where('autoassign_licenses', '=', $request->input('autoassign_licenses')); } if ($request->filled('search')) { $users = $users->TextSearch($request->input('search')); } $order = $request->input('order') === 'asc' ? 'asc' : 'desc'; switch ($request->input('sort')) { case 'manager': $users = $users->OrderManager($order); break; case 'location': $users = $users->OrderLocation($order); break; case 'department': $users = $users->OrderDepartment($order); break; case 'created_by': $users = $users->OrderByCreatedBy($order); break; case 'company': $users = $users->OrderCompany($order); break; case 'first_name': $users->orderBy('first_name', $order); $users->orderBy('last_name', $order); break; case 'last_name': $users->orderBy('last_name', $order); $users->orderBy('first_name', $order); break; default: $allowed_columns = [ 'last_name', 'first_name', 'email', 'jobtitle', 'username', 'employee_num', 'assets', 'accessories', 'consumables', 'licenses', 'groups', 'activated', 'created_at', 'two_factor_enrolled', 'two_factor_optin', 'last_login', 'assets_count', 'licenses_count', 'consumables_count', 'accessories_count', 'phone', 'address', 'city', 'state', 'country', 'zip', 'id', 'ldap_import', 'two_factor_optin', 'two_factor_enrolled', 'remote', 'vip', 'start_date', 'end_date', 'autoassign_licenses', 'website', ]; $sort = in_array($request->get('sort'), $allowed_columns) ? $request->get('sort') : 'first_name'; $users = $users->orderBy($sort, $order); break; } if (($request->filled('deleted')) && ($request->input('deleted') == 'true')) { $users = $users->onlyTrashed(); } elseif (($request->filled('all')) && ($request->input('all') == 'true')) { $users = $users->withTrashed(); } // Apply companyable scope $users = Company::scopeCompanyables($users); // Make sure the offset and limit are actually integers and do not exceed system limits $offset = ($request->input('offset') > $users->count()) ? $users->count() : app('api_offset_value'); $limit = app('api_limit_value'); $total = $users->count(); $users = $users->skip($offset)->take($limit)->get(); return (new UsersTransformer)->transformUsers($users, $total); } /** * Gets a paginated collection for the select2 menus * * @author [A. Gianotto] [] * @since [v4.0.16] * @see \App\Http\Transformers\SelectlistTransformer */ public function selectlist(Request $request) { $users = User::select( [ 'users.id', 'users.username', 'users.employee_num', 'users.first_name', 'users.last_name', 'users.gravatar', 'users.avatar', 'users.email', ] )->where('show_in_list', '=', '1'); $users = Company::scopeCompanyables($users); if ($request->filled('search')) { $users = $users->where(function ($query) use ($request) { $query->SimpleNameSearch($request->get('search')) ->orWhere('username', 'LIKE', '%'.$request->get('search').'%') ->orWhere('employee_num', 'LIKE', '%'.$request->get('search').'%'); }); } $users = $users->orderBy('last_name', 'asc')->orderBy('first_name', 'asc'); $users = $users->paginate(50); foreach ($users as $user) { $name_str = ''; if ($user->last_name != '') { $name_str .= $user->last_name.', '; } $name_str .= $user->first_name; if ($user->username != '') { $name_str .= ' ('.$user->username.')'; } if ($user->employee_num != '') { $name_str .= ' - #'.$user->employee_num; } $user->use_text = $name_str; $user->use_image = ($user->present()->gravatar) ? $user->present()->gravatar : null; } return (new SelectlistTransformer)->transformSelectlist($users); } /** * Store a newly created resource in storage. * * @author [A. Gianotto] [] * @since [v4.0] * @param \Illuminate\Http\Request $request * @return \Illuminate\Http\Response */ public function store(SaveUserRequest $request) { $this->authorize('create', User::class); $user = new User; $user->fill($request->all()); $user->created_by = Auth::user()->id; 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; } // if ($request->filled('password')) { $user->password = bcrypt($request->get('password')); } else { $user->password = $user->noPassword(); } app('App\Http\Requests\ImageUploadRequest')->handleImages($user, 600, 'image', 'avatars', 'avatar'); if ($user->save()) { if ($request->filled('groups')) { $user->groups()->sync($request->input('groups')); } else { $user->groups()->sync([]); } return response()->json(Helper::formatStandardApiResponse('success', (new UsersTransformer)->transformUser($user), trans('admin/users/message.success.create'))); } return response()->json(Helper::formatStandardApiResponse('error', null, $user->getErrors())); } /** * Display the specified resource. * * @author [A. Gianotto] [] * @param int $id * @return \Illuminate\Http\Response */ public function show($id) { $this->authorize('view', User::class); $user = User::withCount('assets as assets_count', 'licenses as licenses_count', 'accessories as accessories_count', 'consumables as consumables_count')->findOrFail($id); $user = Company::scopeCompanyables($user)->find($id); $this->authorize('update', $user); return (new UsersTransformer)->transformUser($user); } /** * Update the specified resource in storage. * * @author [A. Gianotto] [] * @since [v4.0] * @param \Illuminate\Http\Request $request * @param int $id * @return \Illuminate\Http\Response */ public function update(SaveUserRequest $request, $id) { $this->authorize('update', User::class); $user = User::findOrFail($id); $user = Company::scopeCompanyables($user)->find($id); $this->authorize('update', $user); /** * This is a janky hack to prevent people from changing admin demo user data on the public demo. * * The $ids 1 and 2 are special since they are seeded as superadmins in the demo seeder. * * Thanks, jerks. You are why we can't have nice things. - snipe * */ if ((($id == 1) || ($id == 2)) && (config('app.lock_passwords'))) { return response()->json(Helper::formatStandardApiResponse('error', null, 'Permission denied. You cannot update user information via API on the demo.')); } $user->fill($request->all()); if ($user->id == $request->input('manager_id')) { return response()->json(Helper::formatStandardApiResponse('error', null, 'You cannot be your own manager')); } if ($request->filled('password')) { $user->password = bcrypt($request->input('password')); } // 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; } // 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)]); app('App\Http\Requests\ImageUploadRequest')->handleImages($user, 600, 'image', 'avatars', 'avatar'); if ($user->save()) { // 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 if ($request->filled('groups')) { $validator = Validator::make($request->all(), [ 'groups.*' => 'integer|exists:permission_groups,id', ]); if ($validator->fails()){ return response()->json(Helper::formatStandardApiResponse('error', null, $user->getErrors())); } // Only save groups if the user is a superuser if (Auth::user()->isSuperUser()) { $user->groups()->sync($request->input('groups')); } // The groups field has been passed but it is null, so we should blank it out } elseif ($request->has('groups')) { // Only save groups if the user is a superuser if (Auth::user()->isSuperUser()) { $user->groups()->sync($request->input('groups')); } } 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())); } /** * Remove the specified resource from storage. * * @author [A. Gianotto] [] * @since [v4.0] * @param int $id * @return \Illuminate\Http\Response */ public function destroy($id) { $this->authorize('delete', User::class); $user = User::with('assets', 'assets.model', 'consumables', 'accessories', 'licenses', 'userloc')->withTrashed(); $user = Company::scopeCompanyables($user)->find($id); $this->authorize('delete', $user); if ($user) { $this->authorize('delete', $user); if (($user->assets) && ($user->assets->count() > 0)) { return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/users/message.error.delete_has_assets'))); } 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.')); } if ($user->delete()) { // Remove the user's avatar if they have one if (Storage::disk('public')->exists('avatars/' . $user->avatar)) { try { Storage::disk('public')->delete('avatars/' . $user->avatar); } catch (\Exception $e) { \Log::debug($e); } } 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'))); } /** * Return JSON containing a list of assets assigned to a user. * * @author [A. Gianotto] [] * @since [v3.0] * @param $userId * @return string JSON */ public function assets(Request $request, $id) { $this->authorize('view', User::class); $this->authorize('view', Asset::class); $user = User::with('assets', 'assets.model', 'consumables', 'accessories', 'licenses', 'userloc')->withTrashed(); $user = Company::scopeCompanyables($user)->find($id); $this->authorize('view', $user); $assets = Asset::where('assigned_to', '=', $id)->where('assigned_type', '=', User::class)->with('model'); // Filter on category ID if ($request->filled('category_id')) { $assets = $assets->InCategory($request->input('category_id')); } // Filter on model ID if ($request->filled('model_id')) { $model_ids = $request->input('model_id'); if (!is_array($model_ids)) { $model_ids = array($model_ids); } $assets = $assets->InModelList($model_ids); } $assets = $assets->get(); return (new AssetsTransformer)->transformAssets($assets, $assets->count(), $request); } /** * Notify a specific user via email with all of their assigned assets. * * @author [Lukas Fehling] [] * @since [v6.0.13] * @param Request $request * @param $id * @return string JSON */ public function emailAssetList(Request $request, $id) { $this->authorize('update', User::class); $user = User::findOrFail($id); $user = Company::scopeCompanyables($user)->find($id); $this->authorize('update', $user); if (empty($user->email)) { return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/users/message.inventorynotification.error'))); } $user->notify((new CurrentInventory($user))); return response()->json(Helper::formatStandardApiResponse('success', null, trans('admin/users/message.inventorynotification.success'))); } /** * Return JSON containing a list of consumables assigned to a user. * * @author [A. Gianotto] [] * @since [v3.0] * @param $userId * @return string JSON */ public function consumables(Request $request, $id) { $this->authorize('view', User::class); $this->authorize('view', Consumable::class); $user = User::findOrFail($id); $this->authorize('update', $user); $consumables = $user->consumables; return (new ConsumablesTransformer)->transformConsumables($consumables, $consumables->count(), $request); } /** * Return JSON containing a list of accessories assigned to a user. * * @author [A. Gianotto] [] * @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', $user); $this->authorize('view', Accessory::class); $accessories = $user->accessories; return (new AccessoriesTransformer)->transformAccessories($accessories, $accessories->count()); } /** * Return JSON containing a list of licenses assigned to a user. * * @author [N. Mathar] [] * @since [v5.0] * @param $userId * @return string JSON */ public function licenses($id) { $this->authorize('view', User::class); $this->authorize('view', License::class); if ($user = User::where('id', $id)->withTrashed()->first()) { $this->authorize('update', $user); $licenses = $user->licenses()->get(); return (new LicensesTransformer())->transformLicenses($licenses, $licenses->count()); } return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/users/message.user_not_found', compact('id')))); } /** * Reset the user's two-factor status * * @author [A. Gianotto] [] * @since [v3.0] * @param $userId * @return string JSON */ public function postTwoFactorReset(Request $request) { $this->authorize('update', User::class); if ($request->filled('id')) { try { $user = User::find($request->get('id')); $this->authorize('update', $user); $user->two_factor_secret = null; $user->two_factor_enrolled = 0; $user->saveQuietly(); // Log the reset $logaction = new Actionlog(); $logaction->target_type = User::class; $logaction->target_id = $user->id; $logaction->item_type = User::class; $logaction->item_id = $user->id; $logaction->created_at = date('Y-m-d H:i:s'); $logaction->user_id = Auth::user()->id; $logaction->logaction('2FA reset'); 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); } /** * Get info on the current user. * * @author [Juan Font] [] * @since [v4.4.2] * @param \Illuminate\Http\Request $request * @return \Illuminate\Http\Response */ public function getCurrentUserInfo(Request $request) { return (new UsersTransformer)->transformUser($request->user()); } /** * Restore a soft-deleted user. * * @author [E. Taylor] [] * @param int $userId * @since [v6.0.0] * @return JsonResponse */ public function restore($userId = null) { if ($user = User::withTrashed()->find($userId)) { $this->authorize('delete', $user); if ($user->deleted_at == '') { return response()->json(Helper::formatStandardApiResponse('error', trans('general.not_deleted', ['item_type' => trans('general.user')])), 200); } if ($user->restore()) { $logaction = new Actionlog(); $logaction->item_type = User::class; $logaction->item_id = $user->id; $logaction->created_at = date('Y-m-d H:i:s'); $logaction->user_id = Auth::user()->id; $logaction->logaction('restore'); return response()->json(Helper::formatStandardApiResponse('success', null, trans('admin/users/message.success.restored')), 200); } // Check validation to make sure we're not restoring a user with the same username as an existing user return response()->json(Helper::formatStandardApiResponse('error', null, $user->getErrors())); } return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/users/message.user_not_found')), 200); } }