3 use BookStack\Api\ApiToken;
7 class UserApiTokenTest extends TestCase
10 protected $testTokenData = [
11 'name' => 'My test API token',
12 'expires_at' => '2050-04-01',
15 public function test_tokens_section_not_visible_without_access_api_permission()
17 $user = $this->getViewer();
19 $resp = $this->actingAs($user)->get($user->getEditUrl());
20 $resp->assertDontSeeText('API Tokens');
22 $this->giveUserPermissions($user, ['access-api']);
24 $resp = $this->actingAs($user)->get($user->getEditUrl());
25 $resp->assertSeeText('API Tokens');
26 $resp->assertSeeText('Create Token');
29 public function test_those_with_manage_users_can_view_other_user_tokens_but_not_create()
31 $viewer = $this->getViewer();
32 $editor = $this->getEditor();
33 $this->giveUserPermissions($viewer, ['users-manage']);
35 $resp = $this->actingAs($viewer)->get($editor->getEditUrl());
36 $resp->assertSeeText('API Tokens');
37 $resp->assertDontSeeText('Create Token');
40 public function test_create_api_token()
42 $editor = $this->getEditor();
44 $resp = $this->asAdmin()->get($editor->getEditUrl('/create-api-token'));
45 $resp->assertStatus(200);
46 $resp->assertSee('Create API Token');
47 $resp->assertSee('Token Secret');
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'],
59 $this->assertSessionHas('api-token-secret:' . $token->id);
60 $secret = session('api-token-secret:' . $token->id);
61 $this->assertDatabaseMissing('api_tokens', [
64 $this->assertTrue(\Hash::check($secret, $token->secret));
66 $this->assertTrue(strlen($token->token_id) === 32);
67 $this->assertTrue(strlen($secret) === 32);
69 $this->assertSessionHas('success');
72 public function test_create_with_no_expiry_sets_expiry_hundred_years_away()
74 $editor = $this->getEditor();
75 $this->asAdmin()->post($editor->getEditUrl('/create-api-token'), ['name' => 'No expiry token', 'expires_at' => '']);
76 $token = ApiToken::query()->latest()->first();
78 $over = Carbon::now()->addYears(101);
79 $under = Carbon::now()->addYears(99);
81 ($token->expires_at < $over && $token->expires_at > $under),
82 "Token expiry set at 100 years in future"
86 public function test_created_token_displays_on_profile_page()
88 $editor = $this->getEditor();
89 $this->asAdmin()->post($editor->getEditUrl('/create-api-token'), $this->testTokenData);
90 $token = ApiToken::query()->latest()->first();
92 $resp = $this->get($editor->getEditUrl());
93 $resp->assertElementExists('#api_tokens');
94 $resp->assertElementContains('#api_tokens', $token->name);
95 $resp->assertElementContains('#api_tokens', $token->token_id);
96 $resp->assertElementContains('#api_tokens', $token->expires_at->format('Y-m-d'));
99 public function test_secret_shown_once_after_creation()
101 $editor = $this->getEditor();
102 $resp = $this->asAdmin()->followingRedirects()->post($editor->getEditUrl('/create-api-token'), $this->testTokenData);
103 $resp->assertSeeText('Token Secret');
105 $token = ApiToken::query()->latest()->first();
106 $this->assertNull(session('api-token-secret:' . $token->id));
108 $resp = $this->get($editor->getEditUrl('/api-tokens/' . $token->id));
109 $resp->assertDontSeeText('Client Secret');
112 public function test_token_update()
114 $editor = $this->getEditor();
115 $this->asAdmin()->post($editor->getEditUrl('/create-api-token'), $this->testTokenData);
116 $token = ApiToken::query()->latest()->first();
118 'name' => 'My updated token',
119 'expires_at' => '2011-01-01',
122 $resp = $this->put($editor->getEditUrl('/api-tokens/' . $token->id), $updateData);
123 $resp->assertRedirect($editor->getEditUrl('/api-tokens/' . $token->id));
125 $this->assertDatabaseHas('api_tokens', array_merge($updateData, ['id' => $token->id]));
126 $this->assertSessionHas('success');
129 public function test_token_update_with_blank_expiry_sets_to_hundred_years_away()
131 $editor = $this->getEditor();
132 $this->asAdmin()->post($editor->getEditUrl('/create-api-token'), $this->testTokenData);
133 $token = ApiToken::query()->latest()->first();
135 $resp = $this->put($editor->getEditUrl('/api-tokens/' . $token->id), [
136 'name' => 'My updated token',
141 $over = Carbon::now()->addYears(101);
142 $under = Carbon::now()->addYears(99);
144 ($token->expires_at < $over && $token->expires_at > $under),
145 "Token expiry set at 100 years in future"
149 public function test_token_delete()
151 $editor = $this->getEditor();
152 $this->asAdmin()->post($editor->getEditUrl('/create-api-token'), $this->testTokenData);
153 $token = ApiToken::query()->latest()->first();
155 $tokenUrl = $editor->getEditUrl('/api-tokens/' . $token->id);
157 $resp = $this->get($tokenUrl . '/delete');
158 $resp->assertSeeText('Delete Token');
159 $resp->assertSeeText($token->name);
160 $resp->assertElementExists('form[action="'.$tokenUrl.'"]');
162 $resp = $this->delete($tokenUrl);
163 $resp->assertRedirect($editor->getEditUrl('#api_tokens'));
164 $this->assertDatabaseMissing('api_tokens', ['id' => $token->id]);
167 public function test_user_manage_can_delete_token_without_api_permission_themselves()
169 $viewer = $this->getViewer();
170 $editor = $this->getEditor();
171 $this->giveUserPermissions($editor, ['users-manage']);
173 $this->asAdmin()->post($viewer->getEditUrl('/create-api-token'), $this->testTokenData);
174 $token = ApiToken::query()->latest()->first();
176 $resp = $this->actingAs($editor)->get($viewer->getEditUrl('/api-tokens/' . $token->id));
177 $resp->assertStatus(200);
178 $resp->assertSeeText('Delete Token');
180 $resp = $this->actingAs($editor)->delete($viewer->getEditUrl('/api-tokens/' . $token->id));
181 $resp->assertRedirect($viewer->getEditUrl('#api_tokens'));
182 $this->assertDatabaseMissing('api_tokens', ['id' => $token->id]);