]> BookStack Code Mirror - bookstack/blob - app/Users/Controllers/UserAccountController.php
83e942b045543bfcf96393f8aca255087c38fb3c
[bookstack] / app / Users / Controllers / UserAccountController.php
1 <?php
2
3 namespace BookStack\Users\Controllers;
4
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;
12 use Closure;
13 use Illuminate\Http\Request;
14 use Illuminate\Validation\Rules\Password;
15
16 class UserAccountController extends Controller
17 {
18     public function __construct(
19         protected UserRepo $userRepo,
20     ) {
21         $this->middleware(function (Request $request, Closure $next) {
22             $this->preventGuestAccess();
23             $this->preventAccessInDemoMode();
24             return $next($request);
25         });
26     }
27
28     /**
29      * Show the overview for user preferences.
30      */
31     public function index()
32     {
33         $mfaMethods = user()->mfaValues->groupBy('method');
34
35         return view('users.account.index', [
36             'mfaMethods' => $mfaMethods,
37         ]);
38     }
39
40     /**
41      * Show the profile form interface.
42      */
43     public function showProfile()
44     {
45         return view('users.account.profile', [
46             'model' => user(),
47             'category' => 'profile',
48         ]);
49     }
50
51     /**
52      * Handle the submission of the user profile form.
53      */
54     public function updateProfile(Request $request, ImageRepo $imageRepo)
55     {
56         $user = user();
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()),
62         ]);
63
64         $this->userRepo->update($user, $validated, userCan('users-manage'));
65
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;
72             $user->save();
73         }
74
75         // Delete the profile image if reset option is in request
76         if ($request->has('profile_image_reset')) {
77             $imageRepo->destroyImage($user->avatar);
78             $user->image_id = 0;
79             $user->save();
80         }
81
82         return redirect('/my-account/profile');
83     }
84
85     /**
86      * Show the user-specific interface shortcuts.
87      */
88     public function showShortcuts()
89     {
90         $shortcuts = UserShortcutMap::fromUserPreferences();
91         $enabled = setting()->getForCurrentUser('ui-shortcuts-enabled', false);
92
93         $this->setPageTitle(trans('preferences.shortcuts_interface'));
94
95         return view('users.account.shortcuts', [
96             'category' => 'shortcuts',
97             'shortcuts' => $shortcuts,
98             'enabled' => $enabled,
99         ]);
100     }
101
102     /**
103      * Update the user-specific interface shortcuts.
104      */
105     public function updateShortcuts(Request $request)
106     {
107         $enabled = $request->get('enabled') === 'true';
108         $providedShortcuts = $request->get('shortcut', []);
109         $shortcuts = new UserShortcutMap($providedShortcuts);
110
111         setting()->putForCurrentUser('ui-shortcuts', $shortcuts->toJson());
112         setting()->putForCurrentUser('ui-shortcuts-enabled', $enabled);
113
114         $this->showSuccessNotification(trans('preferences.shortcuts_update_success'));
115
116         return redirect('/my-account/shortcuts');
117     }
118
119     /**
120      * Show the notification preferences for the current user.
121      */
122     public function showNotifications(PermissionApplicator $permissions)
123     {
124         $this->checkPermission('receive-notifications');
125
126         $preferences = (new UserNotificationPreferences(user()));
127
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);
132
133         $this->setPageTitle(trans('preferences.notifications'));
134         return view('users.account.notifications', [
135             'category' => 'notifications',
136             'preferences' => $preferences,
137             'watches' => $watches,
138         ]);
139     }
140
141     /**
142      * Update the notification preferences for the current user.
143      */
144     public function updateNotifications(Request $request)
145     {
146         $this->checkPermission('receive-notifications');
147         $data = $this->validate($request, [
148            'preferences' => ['required', 'array'],
149            'preferences.*' => ['required', 'string'],
150         ]);
151
152         $preferences = (new UserNotificationPreferences(user()));
153         $preferences->updateFromSettingsArray($data['preferences']);
154         $this->showSuccessNotification(trans('preferences.notifications_update_success'));
155
156         return redirect('/my-account/notifications');
157     }
158
159     /**
160      * Show the view for the "Access & Security" account options.
161      */
162     public function showAuth(SocialAuthService $socialAuthService)
163     {
164         $mfaMethods = user()->mfaValues->groupBy('method');
165
166         $this->setPageTitle(trans('preferences.auth'));
167
168         return view('users.account.auth', [
169             'category' => 'auth',
170             'mfaMethods' => $mfaMethods,
171             'authMethod' => config('auth.method'),
172             'activeSocialDrivers' => $socialAuthService->getActiveDrivers(),
173         ]);
174     }
175
176     /**
177      * Handle the submission for the auth change password form.
178      */
179     public function updatePassword(Request $request)
180     {
181         if (config('auth.method') !== 'standard') {
182             $this->showPermissionError();
183         }
184
185         $validated = $this->validate($request, [
186             'password'         => ['required_with:password_confirm', Password::default()],
187             'password-confirm' => ['same:password', 'required_with:password'],
188         ]);
189
190         $this->userRepo->update(user(), $validated, false);
191
192         $this->showSuccessNotification(trans('preferences.auth_change_password_success'));
193
194         return redirect('/my-account/auth');
195     }
196 }