]> BookStack Code Mirror - bookstack/blob - tests/Actions/AuditLogTest.php
Added ability to adjust stored IP address precision
[bookstack] / tests / Actions / AuditLogTest.php
1 <?php
2
3 namespace Tests\Actions;
4
5 use function app;
6 use BookStack\Actions\Activity;
7 use BookStack\Actions\ActivityLogger;
8 use BookStack\Actions\ActivityType;
9 use BookStack\Auth\UserRepo;
10 use BookStack\Entities\Models\Chapter;
11 use BookStack\Entities\Models\Page;
12 use BookStack\Entities\Repos\PageRepo;
13 use BookStack\Entities\Tools\TrashCan;
14 use Carbon\Carbon;
15 use function config;
16 use Tests\TestCase;
17
18 class AuditLogTest extends TestCase
19 {
20     /** @var ActivityLogger */
21     protected $activityService;
22
23     protected function setUp(): void
24     {
25         parent::setUp();
26         $this->activityService = app(ActivityLogger::class);
27     }
28
29     public function test_only_accessible_with_right_permissions()
30     {
31         $viewer = $this->getViewer();
32         $this->actingAs($viewer);
33
34         $resp = $this->get('/settings/audit');
35         $this->assertPermissionError($resp);
36
37         $this->giveUserPermissions($viewer, ['settings-manage']);
38         $resp = $this->get('/settings/audit');
39         $this->assertPermissionError($resp);
40
41         $this->giveUserPermissions($viewer, ['users-manage']);
42         $resp = $this->get('/settings/audit');
43         $resp->assertStatus(200);
44         $resp->assertSeeText('Audit Log');
45     }
46
47     public function test_shows_activity()
48     {
49         $admin = $this->getAdmin();
50         $this->actingAs($admin);
51         $page = Page::query()->first();
52         $this->activityService->add(ActivityType::PAGE_CREATE, $page);
53         $activity = Activity::query()->orderBy('id', 'desc')->first();
54
55         $resp = $this->get('settings/audit');
56         $resp->assertSeeText($page->name);
57         $resp->assertSeeText('page_create');
58         $resp->assertSeeText($activity->created_at->toDateTimeString());
59         $resp->assertElementContains('.table-user-item', $admin->name);
60     }
61
62     public function test_shows_name_for_deleted_items()
63     {
64         $this->actingAs($this->getAdmin());
65         $page = Page::query()->first();
66         $pageName = $page->name;
67         $this->activityService->add(ActivityType::PAGE_CREATE, $page);
68
69         app(PageRepo::class)->destroy($page);
70         app(TrashCan::class)->empty();
71
72         $resp = $this->get('settings/audit');
73         $resp->assertSeeText('Deleted Item');
74         $resp->assertSeeText('Name: ' . $pageName);
75     }
76
77     public function test_shows_activity_for_deleted_users()
78     {
79         $viewer = $this->getViewer();
80         $this->actingAs($viewer);
81         $page = Page::query()->first();
82         $this->activityService->add(ActivityType::PAGE_CREATE, $page);
83
84         $this->actingAs($this->getAdmin());
85         app(UserRepo::class)->destroy($viewer);
86
87         $resp = $this->get('settings/audit');
88         $resp->assertSeeText("[ID: {$viewer->id}] Deleted User");
89     }
90
91     public function test_filters_by_key()
92     {
93         $this->actingAs($this->getAdmin());
94         $page = Page::query()->first();
95         $this->activityService->add(ActivityType::PAGE_CREATE, $page);
96
97         $resp = $this->get('settings/audit');
98         $resp->assertSeeText($page->name);
99
100         $resp = $this->get('settings/audit?event=page_delete');
101         $resp->assertDontSeeText($page->name);
102     }
103
104     public function test_date_filters()
105     {
106         $this->actingAs($this->getAdmin());
107         $page = Page::query()->first();
108         $this->activityService->add(ActivityType::PAGE_CREATE, $page);
109
110         $yesterday = (Carbon::now()->subDay()->format('Y-m-d'));
111         $tomorrow = (Carbon::now()->addDay()->format('Y-m-d'));
112
113         $resp = $this->get('settings/audit?date_from=' . $yesterday);
114         $resp->assertSeeText($page->name);
115
116         $resp = $this->get('settings/audit?date_from=' . $tomorrow);
117         $resp->assertDontSeeText($page->name);
118
119         $resp = $this->get('settings/audit?date_to=' . $tomorrow);
120         $resp->assertSeeText($page->name);
121
122         $resp = $this->get('settings/audit?date_to=' . $yesterday);
123         $resp->assertDontSeeText($page->name);
124     }
125
126     public function test_user_filter()
127     {
128         $admin = $this->getAdmin();
129         $editor = $this->getEditor();
130         $this->actingAs($admin);
131         $page = Page::query()->first();
132         $this->activityService->add(ActivityType::PAGE_CREATE, $page);
133
134         $this->actingAs($editor);
135         $chapter = Chapter::query()->first();
136         $this->activityService->add(ActivityType::CHAPTER_UPDATE, $chapter);
137
138         $resp = $this->actingAs($admin)->get('settings/audit?user=' . $admin->id);
139         $resp->assertSeeText($page->name);
140         $resp->assertDontSeeText($chapter->name);
141
142         $resp = $this->actingAs($admin)->get('settings/audit?user=' . $editor->id);
143         $resp->assertSeeText($chapter->name);
144         $resp->assertDontSeeText($page->name);
145     }
146
147     public function test_ip_address_logged_and_visible()
148     {
149         config()->set('app.proxies', '*');
150         $editor = $this->getEditor();
151         /** @var Page $page */
152         $page = Page::query()->first();
153
154         $this->actingAs($editor)->put($page->getUrl(), [
155             'name' => 'Updated page',
156             'html' => '<p>Updated content</p>',
157         ], [
158             'X-Forwarded-For' => '192.123.45.1',
159         ])->assertRedirect($page->refresh()->getUrl());
160
161         $this->assertDatabaseHas('activities', [
162             'type'      => ActivityType::PAGE_UPDATE,
163             'ip'        => '192.123.45.1',
164             'user_id'   => $editor->id,
165             'entity_id' => $page->id,
166         ]);
167
168         $resp = $this->asAdmin()->get('/settings/audit');
169         $resp->assertSee('192.123.45.1');
170     }
171
172     public function test_ip_address_is_searchable()
173     {
174         config()->set('app.proxies', '*');
175         $editor = $this->getEditor();
176         /** @var Page $page */
177         $page = Page::query()->first();
178
179         $this->actingAs($editor)->put($page->getUrl(), [
180             'name' => 'Updated page',
181             'html' => '<p>Updated content</p>',
182         ], [
183             'X-Forwarded-For' => '192.123.45.1',
184         ])->assertRedirect($page->refresh()->getUrl());
185
186         $this->actingAs($editor)->put($page->getUrl(), [
187             'name' => 'Updated page',
188             'html' => '<p>Updated content</p>',
189         ], [
190             'X-Forwarded-For' => '192.122.45.1',
191         ])->assertRedirect($page->refresh()->getUrl());
192
193         $resp = $this->asAdmin()->get('/settings/audit?&ip=192.123');
194         $resp->assertSee('192.123.45.1');
195         $resp->assertDontSee('192.122.45.1');
196     }
197
198     public function test_ip_address_not_logged_in_demo_mode()
199     {
200         config()->set('app.proxies', '*');
201         config()->set('app.env', 'demo');
202         $editor = $this->getEditor();
203         /** @var Page $page */
204         $page = Page::query()->first();
205
206         $this->actingAs($editor)->put($page->getUrl(), [
207             'name' => 'Updated page',
208             'html' => '<p>Updated content</p>',
209         ], [
210             'X-Forwarded-For' => '192.123.45.1',
211             'REMOTE_ADDR'     => '192.123.45.2',
212         ])->assertRedirect($page->refresh()->getUrl());
213
214         $this->assertDatabaseHas('activities', [
215             'type'      => ActivityType::PAGE_UPDATE,
216             'ip'        => '127.0.0.1',
217             'user_id'   => $editor->id,
218             'entity_id' => $page->id,
219         ]);
220     }
221
222     public function test_ip_address_respects_precision_setting()
223     {
224         config()->set('app.proxies', '*');
225         config()->set('app.ip_address_precision', 2);
226         $editor = $this->getEditor();
227         /** @var Page $page */
228         $page = Page::query()->first();
229
230         $this->actingAs($editor)->put($page->getUrl(), [
231             'name' => 'Updated page',
232             'html' => '<p>Updated content</p>',
233         ], [
234             'X-Forwarded-For' => '192.123.45.1',
235         ])->assertRedirect($page->refresh()->getUrl());
236
237         $this->assertDatabaseHas('activities', [
238             'type'      => ActivityType::PAGE_UPDATE,
239             'ip'        => '192.123.x.x',
240             'user_id'   => $editor->id,
241             'entity_id' => $page->id,
242         ]);
243     }
244 }