3 namespace BookStack\Users\Controllers;
5 use BookStack\Access\SocialAuthService;
6 use BookStack\Http\Controller;
7 use BookStack\Permissions\PermissionApplicator;
8 use BookStack\Settings\UserNotificationPreferences;
9 use BookStack\Settings\UserShortcutMap;
10 use BookStack\Uploads\ImageRepo;
11 use BookStack\Users\UserRepo;
13 use Illuminate\Http\Request;
14 use Illuminate\Validation\Rules\Password;
16 class UserAccountController extends Controller
18 public function __construct(
19 protected UserRepo $userRepo,
21 $this->middleware(function (Request $request, Closure $next) {
22 $this->preventGuestAccess();
23 $this->preventAccessInDemoMode();
24 return $next($request);
29 * Show the overview for user preferences.
31 public function index()
33 $mfaMethods = user()->mfaValues->groupBy('method');
35 return view('users.account.index', [
36 'mfaMethods' => $mfaMethods,
41 * Show the profile form interface.
43 public function showProfile()
45 return view('users.account.profile', [
47 'category' => 'profile',
52 * Handle the submission of the user profile form.
54 public function updateProfile(Request $request, ImageRepo $imageRepo)
57 $validated = $this->validate($request, [
58 'name' => ['min:2', 'max:100'],
59 'email' => ['min:2', 'email', 'unique:users,email,' . $user->id],
60 'language' => ['string', 'max:15', 'alpha_dash'],
61 'profile_image' => array_merge(['nullable'], $this->getImageValidationRules()),
64 $this->userRepo->update($user, $validated, userCan('users-manage'));
66 // Save profile image if in request
67 if ($request->hasFile('profile_image')) {
68 $imageUpload = $request->file('profile_image');
69 $imageRepo->destroyImage($user->avatar);
70 $image = $imageRepo->saveNew($imageUpload, 'user', $user->id);
71 $user->image_id = $image->id;
75 // Delete the profile image if reset option is in request
76 if ($request->has('profile_image_reset')) {
77 $imageRepo->destroyImage($user->avatar);
82 return redirect('/my-account/profile');
86 * Show the user-specific interface shortcuts.
88 public function showShortcuts()
90 $shortcuts = UserShortcutMap::fromUserPreferences();
91 $enabled = setting()->getForCurrentUser('ui-shortcuts-enabled', false);
93 $this->setPageTitle(trans('preferences.shortcuts_interface'));
95 return view('users.account.shortcuts', [
96 'category' => 'shortcuts',
97 'shortcuts' => $shortcuts,
98 'enabled' => $enabled,
103 * Update the user-specific interface shortcuts.
105 public function updateShortcuts(Request $request)
107 $enabled = $request->get('enabled') === 'true';
108 $providedShortcuts = $request->get('shortcut', []);
109 $shortcuts = new UserShortcutMap($providedShortcuts);
111 setting()->putForCurrentUser('ui-shortcuts', $shortcuts->toJson());
112 setting()->putForCurrentUser('ui-shortcuts-enabled', $enabled);
114 $this->showSuccessNotification(trans('preferences.shortcuts_update_success'));
116 return redirect('/my-account/shortcuts');
120 * Show the notification preferences for the current user.
122 public function showNotifications(PermissionApplicator $permissions)
124 $this->checkPermission('receive-notifications');
126 $preferences = (new UserNotificationPreferences(user()));
128 $query = user()->watches()->getQuery();
129 $query = $permissions->restrictEntityRelationQuery($query, 'watches', 'watchable_id', 'watchable_type');
130 $query = $permissions->filterDeletedFromEntityRelationQuery($query, 'watches', 'watchable_id', 'watchable_type');
131 $watches = $query->with('watchable')->paginate(20);
133 $this->setPageTitle(trans('preferences.notifications'));
134 return view('users.account.notifications', [
135 'category' => 'notifications',
136 'preferences' => $preferences,
137 'watches' => $watches,
142 * Update the notification preferences for the current user.
144 public function updateNotifications(Request $request)
146 $this->checkPermission('receive-notifications');
147 $data = $this->validate($request, [
148 'preferences' => ['required', 'array'],
149 'preferences.*' => ['required', 'string'],
152 $preferences = (new UserNotificationPreferences(user()));
153 $preferences->updateFromSettingsArray($data['preferences']);
154 $this->showSuccessNotification(trans('preferences.notifications_update_success'));
156 return redirect('/my-account/notifications');
160 * Show the view for the "Access & Security" account options.
162 public function showAuth(SocialAuthService $socialAuthService)
164 $mfaMethods = user()->mfaValues->groupBy('method');
166 $this->setPageTitle(trans('preferences.auth'));
168 return view('users.account.auth', [
169 'category' => 'auth',
170 'mfaMethods' => $mfaMethods,
171 'authMethod' => config('auth.method'),
172 'activeSocialDrivers' => $socialAuthService->getActiveDrivers(),
177 * Handle the submission for the auth change password form.
179 public function updatePassword(Request $request)
181 if (config('auth.method') !== 'standard') {
182 $this->showPermissionError();
185 $validated = $this->validate($request, [
186 'password' => ['required_with:password_confirm', Password::default()],
187 'password-confirm' => ['same:password', 'required_with:password'],
190 $this->userRepo->update(user(), $validated, false);
192 $this->showSuccessNotification(trans('preferences.auth_change_password_success'));
194 return redirect('/my-account/auth');