22
33namespace Tests \User ;
44
5+ use BookStack \Access \Mfa \MfaValue ;
56use BookStack \Activity \Tools \UserEntityWatchOptions ;
67use BookStack \Activity \WatchLevels ;
8+ use BookStack \Api \ApiToken ;
9+ use BookStack \Uploads \Image ;
10+ use Illuminate \Support \Facades \Hash ;
11+ use Illuminate \Support \Str ;
712use Tests \TestCase ;
813
914class UserMyAccountTest extends TestCase
@@ -26,6 +31,166 @@ public function test_views_not_accessible_to_guest_user()
2631 $ resp ->assertRedirect ('/ ' );
2732 }
2833 }
34+
35+ public function test_profile_updating ()
36+ {
37+ $ editor = $ this ->users ->editor ();
38+
39+ $ resp = $ this ->actingAs ($ editor )->get ('/my-account/profile ' );
40+ $ resp ->assertSee ('Profile Details ' );
41+
42+ $ html = $ this ->withHtml ($ resp );
43+ $ html ->assertFieldHasValue ('name ' , $ editor ->name );
44+ $ html ->assertFieldHasValue ('email ' , $ editor ->email );
45+
46+ $ resp = $ this ->put ('/my-account/profile ' , [
47+ 'name ' => 'Barryius ' ,
48+ 'email ' => 'barryius@example.com ' ,
49+ 'language ' => 'fr ' ,
50+ ]);
51+
52+ $ resp ->assertRedirect ('/my-account/profile ' );
53+ $ this ->assertDatabaseHas ('users ' , [
54+ 'name ' => 'Barryius ' ,
55+ 'email ' => $ editor ->email , // No email change due to not having permissions
56+ ]);
57+ $ this ->assertEquals (setting ()->getUser ($ editor , 'language ' ), 'fr ' );
58+ }
59+
60+ public function test_profile_user_avatar_update_and_reset ()
61+ {
62+ $ user = $ this ->users ->viewer ();
63+ $ avatarFile = $ this ->files ->uploadedImage ('avatar-icon.png ' );
64+
65+ $ this ->assertEquals (0 , $ user ->image_id );
66+
67+ $ upload = $ this ->actingAs ($ user )->call ('PUT ' , "/my-account/profile " , [
68+ 'name ' => 'Barry Scott ' ,
69+ ], [], ['profile_image ' => $ avatarFile ], []);
70+ $ upload ->assertRedirect ('/my-account/profile ' );
71+
72+
73+ $ user ->refresh ();
74+ $ this ->assertNotEquals (0 , $ user ->image_id );
75+ /** @var Image $image */
76+ $ image = Image::query ()->findOrFail ($ user ->image_id );
77+ $ this ->assertFileExists (public_path ($ image ->path ));
78+
79+ $ reset = $ this ->put ("/my-account/profile " , [
80+ 'name ' => 'Barry Scott ' ,
81+ 'profile_image_reset ' => 'true ' ,
82+ ]);
83+ $ upload ->assertRedirect ('/my-account/profile ' );
84+
85+ $ user ->refresh ();
86+ $ this ->assertFileDoesNotExist (public_path ($ image ->path ));
87+ $ this ->assertEquals (0 , $ user ->image_id );
88+ }
89+
90+ public function test_profile_admin_options_link_shows_if_permissions_allow ()
91+ {
92+ $ editor = $ this ->users ->editor ();
93+
94+ $ resp = $ this ->actingAs ($ editor )->get ('/my-account/profile ' );
95+ $ resp ->assertDontSee ('Administrator Options ' );
96+ $ this ->withHtml ($ resp )->assertLinkNotExists (url ("/settings/users/ {$ editor ->id }" ));
97+
98+ $ this ->permissions ->grantUserRolePermissions ($ editor , ['users-manage ' ]);
99+
100+ $ resp = $ this ->actingAs ($ editor )->get ('/my-account/profile ' );
101+ $ resp ->assertSee ('Administrator Options ' );
102+ $ this ->withHtml ($ resp )->assertLinkExists (url ("/settings/users/ {$ editor ->id }" ));
103+ }
104+
105+ public function test_profile_self_delete ()
106+ {
107+ $ editor = $ this ->users ->editor ();
108+
109+ $ resp = $ this ->actingAs ($ editor )->get ('/my-account/profile ' );
110+ $ this ->withHtml ($ resp )->assertLinkExists (url ('/my-account/delete ' ), 'Delete Account ' );
111+
112+ $ resp = $ this ->get ('/my-account/delete ' );
113+ $ resp ->assertSee ('Delete My Account ' );
114+ $ this ->withHtml ($ resp )->assertElementContains ('form[action$="/my-account"] button ' , 'Confirm ' );
115+
116+ $ resp = $ this ->delete ('/my-account ' );
117+ $ resp ->assertRedirect ('/ ' );
118+
119+ $ this ->assertDatabaseMissing ('users ' , ['id ' => $ editor ->id ]);
120+ }
121+
122+ public function test_profile_self_delete_shows_ownership_migration_if_can_manage_users ()
123+ {
124+ $ editor = $ this ->users ->editor ();
125+
126+ $ resp = $ this ->actingAs ($ editor )->get ('/my-account/delete ' );
127+ $ resp ->assertDontSee ('Migrate Ownership ' );
128+
129+ $ this ->permissions ->grantUserRolePermissions ($ editor , ['users-manage ' ]);
130+
131+ $ resp = $ this ->actingAs ($ editor )->get ('/my-account/delete ' );
132+ $ resp ->assertSee ('Migrate Ownership ' );
133+ }
134+
135+ public function test_auth_password_change ()
136+ {
137+ $ editor = $ this ->users ->editor ();
138+
139+ $ resp = $ this ->actingAs ($ editor )->get ('/my-account/auth ' );
140+ $ resp ->assertSee ('Change Password ' );
141+ $ this ->withHtml ($ resp )->assertElementExists ('form[action$="/my-account/auth/password"] ' );
142+
143+ $ password = Str::random ();
144+ $ resp = $ this ->put ('/my-account/auth/password ' , [
145+ 'password ' => $ password ,
146+ 'password-confirm ' => $ password ,
147+ ]);
148+ $ resp ->assertRedirect ('/my-account/auth ' );
149+
150+ $ editor ->refresh ();
151+ $ this ->assertTrue (Hash::check ($ password , $ editor ->password ));
152+ }
153+
154+ public function test_auth_password_change_hides_if_not_using_email_auth ()
155+ {
156+ $ editor = $ this ->users ->editor ();
157+
158+ $ resp = $ this ->actingAs ($ editor )->get ('/my-account/auth ' );
159+ $ resp ->assertSee ('Change Password ' );
160+
161+ config ()->set ('auth.method ' , 'oidc ' );
162+
163+ $ resp = $ this ->actingAs ($ editor )->get ('/my-account/auth ' );
164+ $ resp ->assertDontSee ('Change Password ' );
165+ }
166+
167+ public function test_auth_page_has_mfa_links ()
168+ {
169+ $ editor = $ this ->users ->editor ();
170+ $ resp = $ this ->actingAs ($ editor )->get ('/my-account/auth ' );
171+ $ resp ->assertSee ('0 methods configured ' );
172+ $ this ->withHtml ($ resp )->assertLinkExists (url ('/mfa/setup ' ));
173+
174+ MfaValue::upsertWithValue ($ editor , 'totp ' , 'testval ' );
175+
176+ $ resp = $ this ->get ('/my-account/auth ' );
177+ $ resp ->assertSee ('1 method configured ' );
178+ }
179+
180+ public function test_auth_page_api_tokens ()
181+ {
182+ $ editor = $ this ->users ->editor ();
183+ $ resp = $ this ->actingAs ($ editor )->get ('/my-account/auth ' );
184+ $ resp ->assertSee ('API Tokens ' );
185+ $ this ->withHtml ($ resp )->assertLinkExists (url ("/api-tokens/ {$ editor ->id }/create?context=my-account " ));
186+
187+ ApiToken::factory ()->create (['user_id ' => $ editor ->id , 'name ' => 'My great token ' ]);
188+ $ editor ->unsetRelations ();
189+
190+ $ resp = $ this ->get ('/my-account/auth ' );
191+ $ resp ->assertSee ('My great token ' );
192+ }
193+
29194 public function test_interface_shortcuts_updating ()
30195 {
31196 $ this ->asEditor ();
0 commit comments