middleware('auth'); } /** * Users list. */ public function users() { $this->authorize('create', 'App\User'); $users = User::nonDeleted()->get(); $users = User::sortUsers($users); return view('users/users', ['users' => $users]); } /** * New user. */ public function create() { $this->authorize('create', 'App\User'); $mailboxes = Mailbox::all(); return view('users/create', ['mailboxes' => $mailboxes]); } /** * Create new user. * * @param \Illuminate\Http\Request $request */ public function createSave(Request $request) { $invalid = false; $this->authorize('create', 'App\User'); $auth_user = auth()->user(); $rules = [ 'first_name' => 'required|string|max:20', 'last_name' => 'required|string|max:30', 'email' => 'required|string|email|max:100|unique:users', //'role' => ['required', Rule::in(array_keys(User::$roles))], ]; if ($auth_user->isAdmin()) { $rules['role'] = ['required', Rule::in(array_keys(User::$roles))]; } if (empty($request->send_invite)) { $rules['password'] = 'required|string|max:255'; } $validator = Validator::make($request->all(), $rules); if (User::mailboxEmailExists($request->email)) { $invalid = true; $validator->errors()->add('email', __('There is a mailbox with such email. Users and mailboxes can not have the same email addresses.')); } if ($invalid || $validator->fails()) { return redirect()->route('users.create') ->withErrors($validator) ->withInput(); } $user = new User(); $user->fill($request->all()); if (!$auth_user->can('changeRole', $user)) { $user->role = User::ROLE_USER; } if (empty($request->send_invite)) { // Set password from request $user->password = Hash::make($request->password); } else { // Set some random password before sending invite $user->password = Hash::make($user->generateRandomPassword()); } // Set system timezone. $user->timezone = config('app.timezone') ?: User::DEFAULT_TIMEZONE; $user = \Eventy::filter('user.create_save', $user, $request); $user->save(); $user->mailboxes()->sync($request->mailboxes ?: []); $user->syncPersonalFolders($request->mailboxes); // Send invite if (!empty($request->send_invite)) { try { $user->sendInvite(true); } catch (\Exception $e) { // Admin is allowed to see exceptions \Session::flash('flash_error_floating', $e->getMessage().' — '.__('Check mail settings in "Manage » Settings » Mail Settings"')); } } \Session::flash('flash_success_floating', __('User created successfully')); return redirect()->route('users.profile', ['id' => $user->id]); } /** * User profile. */ public function profile($id) { $user = User::findOrFail($id); if ($user->isDeleted()) { abort(404); } $this->authorize('update', $user); $users = $this->getUsersForSidebar($id); return view('users/profile', ['user' => $user, 'users' => $users]); } public function getUsersForSidebar($except_id) { if (auth()->user()->isAdmin()) { return User::sortUsers(User::nonDeleted()->get());/*->except($except_id)*/; } else { return []; } } /** * Handle a registration request for the application. * * @param \Illuminate\Http\Request $request * * @return \Illuminate\Http\Response */ public function profileSave($id, Request $request) { $invalid = false; $user = User::findOrFail($id); $this->authorize('update', $user); // This is also present in PublicController::userSetup $validator = Validator::make($request->all(), [ 'first_name' => 'required|string|max:20', 'last_name' => 'required|string|max:30', 'email' => 'required|string|email|max:100|unique:users,email,'.$id, //'emails' => 'max:100', 'job_title' => 'max:100', 'phone' => 'max:60', 'timezone' => 'required|string|max:255', 'time_format' => 'required', 'role' => ['nullable', Rule::in(array_keys(User::$roles))], 'photo_url' => 'nullable|image|mimes:jpeg,png,jpg,gif', ]); $validator->setAttributeNames([ 'photo_url' => __('Photo'), ]); // Photo $validator->after(function ($validator) use ($user, $request) { if ($request->hasFile('photo_url')) { $path_url = $user->savePhoto($request->file('photo_url')); if ($path_url) { $user->photo_url = $path_url; } else { $invalid = true; $validator->errors()->add('photo_url', __('Error occurred processing the image. Make sure that PHP GD extension is enabled.')); } } // Do not allow to remove last administrator if ($user->isAdmin() && isset($request->role) && $request->role != User::ROLE_ADMIN) { $admins_count = User::where('role', User::ROLE_ADMIN)->count(); if ($admins_count < 2) { $invalid = true; $validator->errors()->add('role', __('Role of the only one administrator can not be changed.')); } } }); if (User::mailboxEmailExists($request->email)) { $invalid = true; $validator->errors()->add('email', __('There is a mailbox with such email. Users and mailboxes can not have the same email addresses.')); } if ($invalid || $validator->fails()) { return redirect()->route('users.profile', ['id' => $id]) ->withErrors($validator) ->withInput(); } // Save language into session. if (auth()->user()->id == $id && $request->locale) { session()->put('user_locale', $request->locale); } $request_data = $request->all(); if (isset($request_data['photo_url'])) { unset($request_data['photo_url']); } if (!auth()->user()->can('changeRole', $user)) { unset($request_data['role']); } if ($user->status != User::STATUS_DELETED) { if (!empty($request_data['disabled'])) { $request_data['status'] = User::STATUS_DISABLED; } else { $request_data['status'] = User::STATUS_ACTIVE; } } $user->setData($request_data); if (empty($request->input('enable_kb_shortcuts'))) { $user->enable_kb_shortcuts = false; } $user = \Eventy::filter('user.save_profile', $user, $request); $user->save(); \Session::flash('flash_success_floating', __('Profile saved successfully')); return redirect()->route('users.profile', ['id' => $id]); } /** * User permissions. */ public function permissions($id) { $user = auth()->user(); if (!$user->isAdmin()) { abort(403); } $user = User::findOrFail($id); $mailboxes = Mailbox::all(); $users = $this->getUsersForSidebar($id); return view('users/permissions', [ 'user' => $user, 'mailboxes' => $mailboxes, 'user_mailboxes' => $user->mailboxes, 'users' => $users, ]); } /** * Save user permissions. * * @param int $id * @param \Illuminate\Http\Request $request */ public function permissionsSave($id, Request $request) { $user = auth()->user(); if (!$user->isAdmin()) { abort(403); } $user = User::findOrFail($id); $user->mailboxes()->sync($request->mailboxes ?: []); $user->syncPersonalFolders($request->mailboxes); // Save permissions. $user_permissions = $request->user_permissions ?? []; $permissions = []; foreach (User::getUserPermissionsList() as $permission_id) { $new_has_permission = in_array($permission_id, $user_permissions); if ($user->hasPermission($permission_id, false) != $new_has_permission) { $permissions[$permission_id] = (int)(bool)$new_has_permission; $save_user = true; } } $user->permissions = $permissions; $user->save(); \Session::flash('flash_success_floating', __('Permissions saved successfully')); return redirect()->route('users.permissions', ['id' => $id]); } /** * User notifications settings. */ public function notifications($id) { $user = User::findOrFail($id); $this->authorize('update', $user); $subscriptions = $user->subscriptions()->select('medium', 'event')->get(); $person = ''; if ($id != auth()->user()->id) { $person = $user->getFirstName(true); } $users = $this->getUsersForSidebar($id); return view('users/notifications', [ 'user' => $user, 'subscriptions' => $subscriptions, 'person' => $person, 'users' => $users, 'mobile_available' => \Eventy::filter('notifications.mobile_available', false), ]); } /** * Save user notifications settings. * * @param int $id * @param \Illuminate\Http\Request $request */ public function notificationsSave($id, Request $request) { $user = User::findOrFail($id); $this->authorize('update', $user); Subscription::saveFromArray($request->subscriptions, $user->id); \Session::flash('flash_success_floating', __('Notifications saved successfully')); return redirect()->route('users.notifications', ['id' => $id]); } /** * Users ajax controller. */ public function ajax(Request $request) { $response = [ 'status' => 'error', 'msg' => '', // this is error message ]; $auth_user = auth()->user(); switch ($request->action) { // Both send and resend case 'send_invite': if (!$auth_user->isAdmin()) { $response['msg'] = __('Not enough permissions'); } if (empty($request->user_id)) { $response['msg'] = __('Incorrect user'); } if (!$response['msg']) { $user = User::find($request->user_id); if (!$user) { $response['msg'] = __('User not found'); } elseif ($user->invite_state == User::INVITE_STATE_ACTIVATED) { $response['msg'] = __('User already accepted invitation'); } } if (!$response['msg']) { try { $user->sendInvite(true); $response['status'] = 'success'; } catch (\Exception $e) { // Admin is allowed to see exceptions. $response['msg'] = $e->getMessage().' — '.__('Check mail settings in "Manage » Settings » Mail Settings"'); } } break; // Reset password case 'reset_password': if (!auth()->user()->isAdmin()) { $response['msg'] = __('Not enough permissions'); } if (empty($request->user_id)) { $response['msg'] = __('Incorrect user'); } if (!$response['msg']) { $user = User::find($request->user_id); if (!$user) { $response['msg'] = __('User not found'); } } if (!$response['msg']) { $reset_result = Password::broker()->sendResetLink( //['id' => $request->user_id] ['id' => $request->user_id] ); if ($reset_result == Password::RESET_LINK_SENT) { $response['status'] = 'success'; $response['msg_success'] = __('Password reset email has been sent'); } } break; // Load website notifications case 'web_notifications': if (!$auth_user) { $response['msg'] = __('You are not logged in'); } if (!$response['msg']) { $web_notifications_info = $auth_user->getWebsiteNotificationsInfo(false); $response['html'] = view('users/partials/web_notifications', [ 'web_notifications_info_data' => $web_notifications_info['data'], ])->render(); $response['has_more_pages'] = (int) $web_notifications_info['notifications']->hasMorePages(); $response['status'] = 'success'; } break; // Mark all user website notifications as read case 'mark_notifications_as_read': if (!$auth_user) { $response['msg'] = __('You are not logged in'); } if (!$response['msg']) { $auth_user->unreadNotifications()->update(['read_at' => now()]); $auth_user->clearWebsiteNotificationsCache(); $response['status'] = 'success'; } break; // Delete user photo case 'delete_photo': $user = User::find($request->user_id); if (!$user) { $response['msg'] = __('User not found'); } elseif (!$auth_user->can('update', $user)) { $response['msg'] = __('Not enough permissions'); } if (!$response['msg']) { $user->removePhoto(); $user->save(); $response['status'] = 'success'; } break; // Delete user case 'delete_user': $user = User::find($request->user_id); if (!$user) { $response['msg'] = __('User not found'); } elseif (!$auth_user->can('delete', $user)) { $response['msg'] = __('Not enough permissions'); } // Check if the user is the only one admin if (!$response['msg'] && $user->isAdmin()) { $admins_count = User::where('role', User::ROLE_ADMIN)->count(); if ($admins_count < 2) { $response['msg'] = __('Administrator can not be deleted'); } } if (!$response['msg']) { // We have to process conversations one by one to move them to Unassigned folder, // as conversations may be in different mailboxes // $user->conversations()->update(['user_id' => null, 'folder_id' => ]); $mailbox_unassigned_folders = []; $user->conversations->each(function ($conversation) use ($auth_user, $request) { // We don't fire ConversationUserChanged event to avoid sending notifications to users if (!empty($request->assign_user) && !empty($request->assign_user[$conversation->mailbox_id]) && (int) $request->assign_user[$conversation->mailbox_id] != -1 ) { // Set assignee. // In this case conversation stays assigned, just assignee changes. $conversation->user_id = $request->assign_user[$conversation->mailbox_id]; } else { // Make convesation Unassigned. // Unset assignee. // Maybe use changeUser() here. $conversation->user_id = null; if ($conversation->isPublished() && ($conversation->isActive() || $conversation->isPending()) ) { // Change conversation folder to UNASSIGNED. $folder_id = null; if (!empty($mailbox_unassigned_folders[$conversation->mailbox_id])) { $folder_id = $mailbox_unassigned_folders[$conversation->mailbox_id]; } else { $folder = $conversation->mailbox->folders() ->where('type', Folder::TYPE_UNASSIGNED) ->first(); if ($folder) { $folder_id = $folder->id; $mailbox_unassigned_folders[$conversation->mailbox_id] = $folder_id; } } if ($folder_id) { $conversation->folder_id = $folder_id; } } } $conversation->save(); // Create lineitem thread $thread = new Thread(); $thread->conversation_id = $conversation->id; $thread->user_id = $conversation->user_id; $thread->type = Thread::TYPE_LINEITEM; $thread->state = Thread::STATE_PUBLISHED; $thread->status = Thread::STATUS_NOCHANGE; $thread->action_type = Thread::ACTION_TYPE_USER_CHANGED; $thread->source_via = Thread::PERSON_USER; $thread->source_type = Thread::SOURCE_TYPE_WEB; $thread->customer_id = $conversation->customer_id; $thread->created_by_user_id = $auth_user->id; $thread->save(); }); // Recalculate counters for folders //if ($user->isAdmin()) { // Admin has access to all mailboxes Mailbox::all()->each(function ($mailbox) { $mailbox->updateFoldersCounters(); }); // } else { // $user->mailboxes->each(function ($mailbox) { // $mailbox->updateFoldersCounters(); // }); // } // Disconnect user from mailboxes. $user->mailboxes()->sync([]); $user->folders()->delete(); $user->status = \App\User::STATUS_DELETED; // Update email. $email_suffix = User::EMAIL_DELETED_SUFFIX.date('YmdHis'); // We have to truncate email to avoid "Data too long" error. $user->email = mb_substr($user->email, 0, User::EMAIL_MAX_LENGTH - mb_strlen($email_suffix)).$email_suffix; $user->save(); event(new UserDeleted($user, $auth_user)); \Session::flash('flash_success_floating', __('User deleted').': '.$user->getFullName()); $response['status'] = 'success'; } break; default: $response['msg'] = 'Unknown action'; break; } if ($response['status'] == 'error' && empty($response['msg'])) { $response['msg'] = 'Unknown error occurred'; } return \Response::json($response); } /** * Change user password. */ public function password($id) { $user = User::findOrFail($id); $this->authorize('update', $user); $users = User::all()->except($id); return view('users/password', ['user' => $user, 'users' => $users]); } /** * Save changed user password. * * @param \Illuminate\Http\Request $request * * @return \Illuminate\Http\Response */ public function passwordSave($id, Request $request) { // It is allowed to edit only your own password $user = auth()->user(); if ($user->id != $id) { abort(403); } // This is also present in PublicController::userSetup $validator = Validator::make($request->all(), [ 'password_current' => 'required|string', 'password' => 'required|string|min:8|confirmed', ]); $validator->after(function ($validator) use ($user, $request) { // Check current password if (!Hash::check($request->password_current, $user->password)) { $validator->errors()->add('password_current', __('This password is incorrect.')); } elseif (Hash::check($request->password, $user->password)) { // Check new password $validator->errors()->add('password', __('The new password is the same as the old password.')); } }); if ($validator->fails()) { return redirect()->route('users.password', ['id' => $id]) ->withErrors($validator) ->withInput(); } $user->password = bcrypt($request->password); $user->save(); $user->sendPasswordChanged(); \Session::flash('flash_success_floating', __('Password saved successfully!')); return redirect()->route('users.profile', ['id' => $id]); } }