1+ <?php namespace Test ;
2+
3+ use BookStack \Api \ApiToken ;
4+ use Carbon \Carbon ;
5+ use Tests \TestCase ;
6+
7+ class UserApiTokenTest extends TestCase
8+ {
9+
10+ protected $ testTokenData = [
11+ 'name ' => 'My test API token ' ,
12+ 'expires_at ' => '2099-04-01 ' ,
13+ ];
14+
15+ public function test_tokens_section_not_visible_without_access_api_permission ()
16+ {
17+ $ user = $ this ->getEditor ();
18+
19+ $ resp = $ this ->actingAs ($ user )->get ($ user ->getEditUrl ());
20+ $ resp ->assertDontSeeText ('API Tokens ' );
21+
22+ $ this ->giveUserPermissions ($ user , ['access-api ' ]);
23+
24+ $ resp = $ this ->actingAs ($ user )->get ($ user ->getEditUrl ());
25+ $ resp ->assertSeeText ('API Tokens ' );
26+ $ resp ->assertSeeText ('Create Token ' );
27+ }
28+
29+ public function test_those_with_manage_users_can_view_other_user_tokens_but_not_create ()
30+ {
31+ $ viewer = $ this ->getViewer ();
32+ $ editor = $ this ->getEditor ();
33+ $ this ->giveUserPermissions ($ editor , ['users-manage ' ]);
34+
35+ $ resp = $ this ->actingAs ($ editor )->get ($ viewer ->getEditUrl ());
36+ $ resp ->assertSeeText ('API Tokens ' );
37+ $ resp ->assertDontSeeText ('Create Token ' );
38+ }
39+
40+ public function test_create_api_token ()
41+ {
42+ $ editor = $ this ->getEditor ();
43+
44+ $ resp = $ this ->asAdmin ()->get ($ editor ->getEditUrl ('/create-api-token ' ));
45+ $ resp ->assertStatus (200 );
46+ $ resp ->assertSee ('Create API Token ' );
47+ $ resp ->assertSee ('client secret ' );
48+
49+ $ resp = $ this ->post ($ editor ->getEditUrl ('/create-api-token ' ), $ this ->testTokenData );
50+ $ token = ApiToken::query ()->latest ()->first ();
51+ $ resp ->assertRedirect ($ editor ->getEditUrl ('/api-tokens/ ' . $ token ->id ));
52+ $ this ->assertDatabaseHas ('api_tokens ' , [
53+ 'user_id ' => $ editor ->id ,
54+ 'name ' => $ this ->testTokenData ['name ' ],
55+ 'expires_at ' => $ this ->testTokenData ['expires_at ' ],
56+ ]);
57+
58+ // Check secret token
59+ $ this ->assertSessionHas ('api-token-secret: ' . $ token ->id );
60+ $ secret = session ('api-token-secret: ' . $ token ->id );
61+ $ this ->assertDatabaseMissing ('api_tokens ' , [
62+ 'client_secret ' => $ secret ,
63+ ]);
64+ $ this ->assertTrue (\Hash::check ($ secret , $ token ->client_secret ));
65+
66+ $ this ->assertTrue (strlen ($ token ->client_id ) === 32 );
67+ $ this ->assertTrue (strlen ($ secret ) === 32 );
68+
69+ $ this ->assertSessionHas ('success ' );
70+ }
71+
72+ public function test_create_with_no_expiry_sets_expiry_hundred_years_away ()
73+ {
74+ $ editor = $ this ->getEditor ();
75+ $ this ->asAdmin ()->post ($ editor ->getEditUrl ('/create-api-token ' ), ['name ' => 'No expiry token ' ]);
76+ $ token = ApiToken::query ()->latest ()->first ();
77+
78+ $ over = Carbon::now ()->addYears (101 );
79+ $ under = Carbon::now ()->addYears (99 );
80+ $ this ->assertTrue (
81+ ($ token ->expires_at < $ over && $ token ->expires_at > $ under ),
82+ "Token expiry set at 100 years in future "
83+ );
84+ }
85+
86+ public function test_created_token_displays_on_profile_page ()
87+ {
88+ $ editor = $ this ->getEditor ();
89+ $ this ->asAdmin ()->post ($ editor ->getEditUrl ('/create-api-token ' ), $ this ->testTokenData );
90+ $ token = ApiToken::query ()->latest ()->first ();
91+
92+ $ resp = $ this ->get ($ editor ->getEditUrl ());
93+ $ resp ->assertElementExists ('#api_tokens ' );
94+ $ resp ->assertElementContains ('#api_tokens ' , $ token ->name );
95+ $ resp ->assertElementContains ('#api_tokens ' , $ token ->client_id );
96+ $ resp ->assertElementContains ('#api_tokens ' , $ token ->expires_at ->format ('Y-m-d ' ));
97+ }
98+
99+ public function test_client_secret_shown_once_after_creation ()
100+ {
101+ $ editor = $ this ->getEditor ();
102+ $ resp = $ this ->asAdmin ()->followingRedirects ()->post ($ editor ->getEditUrl ('/create-api-token ' ), $ this ->testTokenData );
103+ $ resp ->assertSeeText ('Client Secret ' );
104+
105+ $ token = ApiToken::query ()->latest ()->first ();
106+ $ this ->assertNull (session ('api-token-secret: ' . $ token ->id ));
107+
108+ $ resp = $ this ->get ($ editor ->getEditUrl ('/api-tokens/ ' . $ token ->id ));
109+ $ resp ->assertDontSeeText ('Client Secret ' );
110+ }
111+
112+ public function test_token_update ()
113+ {
114+ $ editor = $ this ->getEditor ();
115+ $ this ->asAdmin ()->post ($ editor ->getEditUrl ('/create-api-token ' ), $ this ->testTokenData );
116+ $ token = ApiToken::query ()->latest ()->first ();
117+ $ updateData = [
118+ 'name ' => 'My updated token ' ,
119+ 'expires_at ' => '2011-01-01 ' ,
120+ ];
121+
122+ $ resp = $ this ->put ($ editor ->getEditUrl ('/api-tokens/ ' . $ token ->id ), $ updateData );
123+ $ resp ->assertRedirect ($ editor ->getEditUrl ('/api-tokens/ ' . $ token ->id ));
124+
125+ $ this ->assertDatabaseHas ('api_tokens ' , array_merge ($ updateData , ['id ' => $ token ->id ]));
126+ $ this ->assertSessionHas ('success ' );
127+ }
128+
129+ public function test_token_delete ()
130+ {
131+ $ editor = $ this ->getEditor ();
132+ $ this ->asAdmin ()->post ($ editor ->getEditUrl ('/create-api-token ' ), $ this ->testTokenData );
133+ $ token = ApiToken::query ()->latest ()->first ();
134+
135+ $ tokenUrl = $ editor ->getEditUrl ('/api-tokens/ ' . $ token ->id );
136+
137+ $ resp = $ this ->get ($ tokenUrl . '/delete ' );
138+ $ resp ->assertSeeText ('Delete Token ' );
139+ $ resp ->assertSeeText ($ token ->name );
140+ $ resp ->assertElementExists ('form[action=" ' .$ tokenUrl .'"] ' );
141+
142+ $ resp = $ this ->delete ($ tokenUrl );
143+ $ resp ->assertRedirect ($ editor ->getEditUrl ('#api_tokens ' ));
144+ $ this ->assertDatabaseMissing ('api_tokens ' , ['id ' => $ token ->id ]);
145+ }
146+
147+ public function test_user_manage_can_delete_token_without_api_permission_themselves ()
148+ {
149+ $ viewer = $ this ->getViewer ();
150+ $ editor = $ this ->getEditor ();
151+ $ this ->giveUserPermissions ($ editor , ['users-manage ' ]);
152+
153+ $ this ->asAdmin ()->post ($ viewer ->getEditUrl ('/create-api-token ' ), $ this ->testTokenData );
154+ $ token = ApiToken::query ()->latest ()->first ();
155+
156+ $ resp = $ this ->actingAs ($ editor )->get ($ viewer ->getEditUrl ('/api-tokens/ ' . $ token ->id ));
157+ $ resp ->assertStatus (200 );
158+ $ resp ->assertSeeText ('Delete Token ' );
159+
160+ $ resp = $ this ->actingAs ($ editor )->delete ($ viewer ->getEditUrl ('/api-tokens/ ' . $ token ->id ));
161+ $ resp ->assertRedirect ($ viewer ->getEditUrl ('#api_tokens ' ));
162+ $ this ->assertDatabaseMissing ('api_tokens ' , ['id ' => $ token ->id ]);
163+ }
164+
165+ }
0 commit comments