diff --git a/app/Actions/ActivityType.php b/app/Actions/ActivityType.php index 9b4e86a16..376312cbb 100644 --- a/app/Actions/ActivityType.php +++ b/app/Actions/ActivityType.php @@ -32,7 +32,6 @@ class ActivityType const RECYCLE_BIN_RESTORE = 'recycle_bin_restore'; const RECYCLE_BIN_DESTROY = 'recycle_bin_destroy'; - // TODO - Implement all below const USER_CREATE = 'user_create'; const USER_UPDATE = 'user_update'; const USER_DELETE = 'user_delete'; @@ -45,6 +44,7 @@ class ActivityType const ROLE_UPDATE = 'role_update'; const ROLE_DELETE = 'role_delete'; + // TODO - Implement all below const ACCESS_PASSWORD_RESET = 'access_password_reset_request'; const ACCESS_PASSWORD_RESET_UPDATE = 'access_password_reset_update'; const ACCESS_LOGIN = 'access_login'; diff --git a/app/Api/ApiToken.php b/app/Api/ApiToken.php index 523c3b8b8..91c407fd8 100644 --- a/app/Api/ApiToken.php +++ b/app/Api/ApiToken.php @@ -1,11 +1,22 @@ addYears(100)->format('Y-m-d'); } + + /** + * @inheritdoc + */ + public function logDescriptor(): string + { + return "({$this->id}) {$this->name}; User: {$this->user->logDescriptor()}"; + } } diff --git a/app/Auth/Permissions/PermissionsRepo.php b/app/Auth/Permissions/PermissionsRepo.php index ce61093cc..f54612a43 100644 --- a/app/Auth/Permissions/PermissionsRepo.php +++ b/app/Auth/Permissions/PermissionsRepo.php @@ -1,10 +1,11 @@ assignRolePermissions($role, $permissions); $this->permissionService->buildJointPermissionForRole($role); + Activity::add(ActivityType::ROLE_CREATE, $role); return $role; } @@ -88,12 +90,13 @@ class PermissionsRepo $role->fill($roleData); $role->save(); $this->permissionService->buildJointPermissionForRole($role); + Activity::add(ActivityType::ROLE_UPDATE, $role); } /** * Assign an list of permission names to an role. */ - public function assignRolePermissions(Role $role, array $permissionNameArray = []) + protected function assignRolePermissions(Role $role, array $permissionNameArray = []) { $permissions = []; $permissionNameArray = array_values($permissionNameArray); @@ -137,6 +140,7 @@ class PermissionsRepo } $this->permissionService->deleteJointPermissionsForRole($role); + Activity::add(ActivityType::ROLE_DELETE, $role); $role->delete(); } } diff --git a/app/Auth/Role.php b/app/Auth/Role.php index 13ec6df16..255158afb 100644 --- a/app/Auth/Role.php +++ b/app/Auth/Role.php @@ -2,6 +2,7 @@ use BookStack\Auth\Permissions\JointPermission; use BookStack\Auth\Permissions\RolePermission; +use BookStack\Interfaces\Loggable; use BookStack\Model; use Illuminate\Database\Eloquent\Collection; use Illuminate\Database\Eloquent\Relations\HasMany; @@ -14,7 +15,7 @@ use Illuminate\Database\Eloquent\Relations\HasMany; * @property string $external_auth_id * @property string $system_name */ -class Role extends Model +class Role extends Model implements Loggable { protected $fillable = ['display_name', 'description', 'external_auth_id']; @@ -104,4 +105,12 @@ class Role extends Model { return static::query()->where('system_name', '!=', 'admin')->get(); } + + /** + * @inheritdoc + */ + public function logDescriptor(): string + { + return "({$this->id}) {$this->display_name}"; + } } diff --git a/app/Auth/User.php b/app/Auth/User.php index f65ef5316..6bf656be3 100644 --- a/app/Auth/User.php +++ b/app/Auth/User.php @@ -1,6 +1,7 @@ notify(new ResetPassword($token)); } + + /** + * @inheritdoc + */ + public function logDescriptor(): string + { + return "({$this->id}) {$this->name}"; + } } diff --git a/app/Http/Controllers/RecycleBinController.php b/app/Http/Controllers/RecycleBinController.php index 57038046a..928310779 100644 --- a/app/Http/Controllers/RecycleBinController.php +++ b/app/Http/Controllers/RecycleBinController.php @@ -85,9 +85,9 @@ class RecycleBinController extends Controller { /** @var Deletion $deletion */ $deletion = Deletion::query()->findOrFail($id); + $this->logActivity(ActivityType::RECYCLE_BIN_DESTROY, $deletion); $deleteCount = (new TrashCan())->destroyFromDeletion($deletion); - $this->logActivity(ActivityType::RECYCLE_BIN_DESTROY, $deletion); $this->showSuccessNotification(trans('settings.recycle_bin_destroy_notification', ['count' => $deleteCount])); return redirect($this->recycleBinBaseUrl); } diff --git a/app/Http/Controllers/PermissionController.php b/app/Http/Controllers/RoleController.php similarity index 90% rename from app/Http/Controllers/PermissionController.php rename to app/Http/Controllers/RoleController.php index 1200d44ab..6e3d5afdc 100644 --- a/app/Http/Controllers/PermissionController.php +++ b/app/Http/Controllers/RoleController.php @@ -6,7 +6,7 @@ use Exception; use Illuminate\Http\Request; use Illuminate\Validation\ValidationException; -class PermissionController extends Controller +class RoleController extends Controller { protected $permissionsRepo; @@ -23,7 +23,7 @@ class PermissionController extends Controller /** * Show a listing of the roles in the system. */ - public function listRoles() + public function list() { $this->checkPermission('user-roles-manage'); $roles = $this->permissionsRepo->getAllRoles(); @@ -33,7 +33,7 @@ class PermissionController extends Controller /** * Show the form to create a new role */ - public function createRole() + public function create() { $this->checkPermission('user-roles-manage'); return view('settings.roles.create'); @@ -42,7 +42,7 @@ class PermissionController extends Controller /** * Store a new role in the system. */ - public function storeRole(Request $request) + public function store(Request $request) { $this->checkPermission('user-roles-manage'); $this->validate($request, [ @@ -59,7 +59,7 @@ class PermissionController extends Controller * Show the form for editing a user role. * @throws PermissionsException */ - public function editRole(string $id) + public function edit(string $id) { $this->checkPermission('user-roles-manage'); $role = $this->permissionsRepo->getRoleById($id); @@ -73,7 +73,7 @@ class PermissionController extends Controller * Updates a user role. * @throws ValidationException */ - public function updateRole(Request $request, string $id) + public function update(Request $request, string $id) { $this->checkPermission('user-roles-manage'); $this->validate($request, [ @@ -90,7 +90,7 @@ class PermissionController extends Controller * Show the view to delete a role. * Offers the chance to migrate users. */ - public function showDeleteRole(string $id) + public function showDelete(string $id) { $this->checkPermission('user-roles-manage'); $role = $this->permissionsRepo->getRoleById($id); @@ -105,7 +105,7 @@ class PermissionController extends Controller * Migrate from a previous role if set. * @throws Exception */ - public function deleteRole(Request $request, string $id) + public function delete(Request $request, string $id) { $this->checkPermission('user-roles-manage'); diff --git a/app/Http/Controllers/UserApiTokenController.php b/app/Http/Controllers/UserApiTokenController.php index 55675233c..ab0e9069e 100644 --- a/app/Http/Controllers/UserApiTokenController.php +++ b/app/Http/Controllers/UserApiTokenController.php @@ -1,9 +1,9 @@ flash('api-token-secret:' . $token->id, $secret); $this->showSuccessNotification(trans('settings.user_api_token_create_success')); + $this->logActivity(ActivityType::API_TOKEN_CREATE, $token); + return redirect($user->getEditUrl('/api-tokens/' . $token->id)); } @@ -93,6 +95,7 @@ class UserApiTokenController extends Controller ])->save(); $this->showSuccessNotification(trans('settings.user_api_token_update_success')); + $this->logActivity(ActivityType::API_TOKEN_UPDATE, $token); return redirect($user->getEditUrl('/api-tokens/' . $token->id)); } @@ -117,6 +120,8 @@ class UserApiTokenController extends Controller $token->delete(); $this->showSuccessNotification(trans('settings.user_api_token_delete_success')); + $this->logActivity(ActivityType::API_TOKEN_DELETE, $token); + return redirect($user->getEditUrl('#api_tokens')); } diff --git a/app/Http/Controllers/UserController.php b/app/Http/Controllers/UserController.php index 651dedc0d..b1b7e5c44 100644 --- a/app/Http/Controllers/UserController.php +++ b/app/Http/Controllers/UserController.php @@ -1,5 +1,6 @@ userRepo->downloadAndAssignUserAvatar($user); + $this->logActivity(ActivityType::USER_CREATE, $user); return redirect('/settings/users'); } @@ -194,6 +196,7 @@ class UserController extends Controller $user->save(); $this->showSuccessNotification(trans('settings.users_edit_success')); + $this->logActivity(ActivityType::USER_UPDATE, $user); $redirectUrl = userCan('users-manage') ? '/settings/users' : ('/settings/users/' . $user->id); return redirect($redirectUrl); @@ -234,6 +237,7 @@ class UserController extends Controller $this->userRepo->destroy($user); $this->showSuccessNotification(trans('settings.users_delete_success')); + $this->logActivity(ActivityType::USER_DELETE, $user); return redirect('/settings/users'); } diff --git a/routes/web.php b/routes/web.php index b87355105..afefcb99e 100644 --- a/routes/web.php +++ b/routes/web.php @@ -201,13 +201,13 @@ Route::group(['middleware' => 'auth'], function () { Route::delete('/users/{userId}/api-tokens/{tokenId}', 'UserApiTokenController@destroy'); // Roles - Route::get('/roles', 'PermissionController@listRoles'); - Route::get('/roles/new', 'PermissionController@createRole'); - Route::post('/roles/new', 'PermissionController@storeRole'); - Route::get('/roles/delete/{id}', 'PermissionController@showDeleteRole'); - Route::delete('/roles/delete/{id}', 'PermissionController@deleteRole'); - Route::get('/roles/{id}', 'PermissionController@editRole'); - Route::put('/roles/{id}', 'PermissionController@updateRole'); + Route::get('/roles', 'RoleController@list'); + Route::get('/roles/new', 'RoleController@create'); + Route::post('/roles/new', 'RoleController@store'); + Route::get('/roles/delete/{id}', 'RoleController@showDelete'); + Route::delete('/roles/delete/{id}', 'RoleController@delete'); + Route::get('/roles/{id}', 'RoleController@edit'); + Route::put('/roles/{id}', 'RoleController@update'); }); }); diff --git a/tests/Permissions/RolesTest.php b/tests/Permissions/RolesTest.php index 73060c834..6bfa8067f 100644 --- a/tests/Permissions/RolesTest.php +++ b/tests/Permissions/RolesTest.php @@ -1,8 +1,13 @@ id; $this->asAdmin()->visit($deletePageUrl) ->press('Confirm') @@ -195,7 +200,7 @@ class RolesTest extends BrowserKitTest public function test_restrictions_manage_all_permission() { - $page = \BookStack\Entities\Page::take(1)->get()->first(); + $page = Page::take(1)->get()->first(); $this->actingAs($this->user)->visit($page->getUrl()) ->dontSee('Permissions') ->visit($page->getUrl() . '/permissions') @@ -209,7 +214,7 @@ class RolesTest extends BrowserKitTest public function test_restrictions_manage_own_permission() { - $otherUsersPage = \BookStack\Entities\Page::first(); + $otherUsersPage = Page::first(); $content = $this->createEntityChainBelongingToUser($this->user); // Check can't restrict other's content $this->actingAs($this->user)->visit($otherUsersPage->getUrl()) @@ -301,7 +306,7 @@ class RolesTest extends BrowserKitTest public function test_bookshelves_edit_all_permission() { - $otherShelf = \BookStack\Entities\Bookshelf::first(); + $otherShelf = Bookshelf::first(); $this->checkAccessPermission('bookshelf-update-all', [ $otherShelf->getUrl('/edit') ], [ @@ -312,7 +317,7 @@ class RolesTest extends BrowserKitTest public function test_bookshelves_delete_own_permission() { $this->giveUserPermissions($this->user, ['bookshelf-update-all']); - $otherShelf = \BookStack\Entities\Bookshelf::first(); + $otherShelf = Bookshelf::first(); $ownShelf = $this->newShelf(['name' => 'test-shelf', 'slug' => 'test-shelf']); $ownShelf->forceFill(['created_by' => $this->user->id, 'updated_by' => $this->user->id])->save(); $this->regenEntityPermissions($ownShelf); @@ -336,7 +341,7 @@ class RolesTest extends BrowserKitTest public function test_bookshelves_delete_all_permission() { $this->giveUserPermissions($this->user, ['bookshelf-update-all']); - $otherShelf = \BookStack\Entities\Bookshelf::first(); + $otherShelf = Bookshelf::first(); $this->checkAccessPermission('bookshelf-delete-all', [ $otherShelf->getUrl('/delete') ], [ @@ -366,7 +371,7 @@ class RolesTest extends BrowserKitTest public function test_books_edit_own_permission() { - $otherBook = \BookStack\Entities\Book::take(1)->get()->first(); + $otherBook = Book::take(1)->get()->first(); $ownBook = $this->createEntityChainBelongingToUser($this->user)['book']; $this->checkAccessPermission('book-update-own', [ $ownBook->getUrl() . '/edit' @@ -382,7 +387,7 @@ class RolesTest extends BrowserKitTest public function test_books_edit_all_permission() { - $otherBook = \BookStack\Entities\Book::take(1)->get()->first(); + $otherBook = Book::take(1)->get()->first(); $this->checkAccessPermission('book-update-all', [ $otherBook->getUrl() . '/edit' ], [ @@ -393,7 +398,7 @@ class RolesTest extends BrowserKitTest public function test_books_delete_own_permission() { $this->giveUserPermissions($this->user, ['book-update-all']); - $otherBook = \BookStack\Entities\Book::take(1)->get()->first(); + $otherBook = Book::take(1)->get()->first(); $ownBook = $this->createEntityChainBelongingToUser($this->user)['book']; $this->checkAccessPermission('book-delete-own', [ $ownBook->getUrl() . '/delete' @@ -414,7 +419,7 @@ class RolesTest extends BrowserKitTest public function test_books_delete_all_permission() { $this->giveUserPermissions($this->user, ['book-update-all']); - $otherBook = \BookStack\Entities\Book::take(1)->get()->first(); + $otherBook = Book::take(1)->get()->first(); $this->checkAccessPermission('book-delete-all', [ $otherBook->getUrl() . '/delete' ], [ @@ -429,7 +434,7 @@ class RolesTest extends BrowserKitTest public function test_chapter_create_own_permissions() { - $book = \BookStack\Entities\Book::take(1)->get()->first(); + $book = Book::take(1)->get()->first(); $ownBook = $this->createEntityChainBelongingToUser($this->user)['book']; $this->checkAccessPermission('chapter-create-own', [ $ownBook->getUrl('/create-chapter') @@ -451,7 +456,7 @@ class RolesTest extends BrowserKitTest public function test_chapter_create_all_permissions() { - $book = \BookStack\Entities\Book::take(1)->get()->first(); + $book = Book::take(1)->get()->first(); $this->checkAccessPermission('chapter-create-all', [ $book->getUrl('/create-chapter') ], [ @@ -467,7 +472,7 @@ class RolesTest extends BrowserKitTest public function test_chapter_edit_own_permission() { - $otherChapter = \BookStack\Entities\Chapter::take(1)->get()->first(); + $otherChapter = Chapter::take(1)->get()->first(); $ownChapter = $this->createEntityChainBelongingToUser($this->user)['chapter']; $this->checkAccessPermission('chapter-update-own', [ $ownChapter->getUrl() . '/edit' @@ -483,7 +488,7 @@ class RolesTest extends BrowserKitTest public function test_chapter_edit_all_permission() { - $otherChapter = \BookStack\Entities\Chapter::take(1)->get()->first(); + $otherChapter = Chapter::take(1)->get()->first(); $this->checkAccessPermission('chapter-update-all', [ $otherChapter->getUrl() . '/edit' ], [ @@ -494,7 +499,7 @@ class RolesTest extends BrowserKitTest public function test_chapter_delete_own_permission() { $this->giveUserPermissions($this->user, ['chapter-update-all']); - $otherChapter = \BookStack\Entities\Chapter::take(1)->get()->first(); + $otherChapter = Chapter::take(1)->get()->first(); $ownChapter = $this->createEntityChainBelongingToUser($this->user)['chapter']; $this->checkAccessPermission('chapter-delete-own', [ $ownChapter->getUrl() . '/delete' @@ -516,7 +521,7 @@ class RolesTest extends BrowserKitTest public function test_chapter_delete_all_permission() { $this->giveUserPermissions($this->user, ['chapter-update-all']); - $otherChapter = \BookStack\Entities\Chapter::take(1)->get()->first(); + $otherChapter = Chapter::take(1)->get()->first(); $this->checkAccessPermission('chapter-delete-all', [ $otherChapter->getUrl() . '/delete' ], [ @@ -532,8 +537,8 @@ class RolesTest extends BrowserKitTest public function test_page_create_own_permissions() { - $book = \BookStack\Entities\Book::first(); - $chapter = \BookStack\Entities\Chapter::first(); + $book = Book::first(); + $chapter = Chapter::first(); $entities = $this->createEntityChainBelongingToUser($this->user); $ownBook = $entities['book']; @@ -557,7 +562,7 @@ class RolesTest extends BrowserKitTest foreach ($accessUrls as $index => $url) { $this->actingAs($this->user)->visit($url); - $expectedUrl = \BookStack\Entities\Page::where('draft', '=', true)->orderBy('id', 'desc')->first()->getUrl(); + $expectedUrl = Page::where('draft', '=', true)->orderBy('id', 'desc')->first()->getUrl(); $this->seePageIs($expectedUrl); } @@ -579,8 +584,8 @@ class RolesTest extends BrowserKitTest public function test_page_create_all_permissions() { - $book = \BookStack\Entities\Book::take(1)->get()->first(); - $chapter = \BookStack\Entities\Chapter::take(1)->get()->first(); + $book = Book::take(1)->get()->first(); + $chapter = Chapter::take(1)->get()->first(); $baseUrl = $book->getUrl() . '/page'; $createUrl = $book->getUrl('/create-page'); @@ -601,7 +606,7 @@ class RolesTest extends BrowserKitTest foreach ($accessUrls as $index => $url) { $this->actingAs($this->user)->visit($url); - $expectedUrl = \BookStack\Entities\Page::where('draft', '=', true)->orderBy('id', 'desc')->first()->getUrl(); + $expectedUrl = Page::where('draft', '=', true)->orderBy('id', 'desc')->first()->getUrl(); $this->seePageIs($expectedUrl); } @@ -620,7 +625,7 @@ class RolesTest extends BrowserKitTest public function test_page_edit_own_permission() { - $otherPage = \BookStack\Entities\Page::take(1)->get()->first(); + $otherPage = Page::take(1)->get()->first(); $ownPage = $this->createEntityChainBelongingToUser($this->user)['page']; $this->checkAccessPermission('page-update-own', [ $ownPage->getUrl() . '/edit' @@ -636,7 +641,7 @@ class RolesTest extends BrowserKitTest public function test_page_edit_all_permission() { - $otherPage = \BookStack\Entities\Page::take(1)->get()->first(); + $otherPage = Page::take(1)->get()->first(); $this->checkAccessPermission('page-update-all', [ $otherPage->getUrl() . '/edit' ], [ @@ -647,7 +652,7 @@ class RolesTest extends BrowserKitTest public function test_page_delete_own_permission() { $this->giveUserPermissions($this->user, ['page-update-all']); - $otherPage = \BookStack\Entities\Page::take(1)->get()->first(); + $otherPage = Page::take(1)->get()->first(); $ownPage = $this->createEntityChainBelongingToUser($this->user)['page']; $this->checkAccessPermission('page-delete-own', [ $ownPage->getUrl() . '/delete' @@ -669,7 +674,7 @@ class RolesTest extends BrowserKitTest public function test_page_delete_all_permission() { $this->giveUserPermissions($this->user, ['page-update-all']); - $otherPage = \BookStack\Entities\Page::take(1)->get()->first(); + $otherPage = Page::take(1)->get()->first(); $this->checkAccessPermission('page-delete-all', [ $otherPage->getUrl() . '/delete' ], [ @@ -685,7 +690,7 @@ class RolesTest extends BrowserKitTest public function test_public_role_visible_in_user_edit_screen() { - $user = \BookStack\Auth\User::first(); + $user = User::first(); $adminRole = Role::getSystemRole('admin'); $publicRole = Role::getSystemRole('public'); $this->asAdmin()->visit('/settings/users/' . $user->id) @@ -721,8 +726,8 @@ class RolesTest extends BrowserKitTest public function test_image_delete_own_permission() { $this->giveUserPermissions($this->user, ['image-update-all']); - $page = \BookStack\Entities\Page::first(); - $image = factory(\BookStack\Uploads\Image::class)->create(['uploaded_to' => $page->id, 'created_by' => $this->user->id, 'updated_by' => $this->user->id]); + $page = Page::first(); + $image = factory(Image::class)->create(['uploaded_to' => $page->id, 'created_by' => $this->user->id, 'updated_by' => $this->user->id]); $this->actingAs($this->user)->json('delete', '/images/' . $image->id) ->seeStatusCode(403); @@ -738,8 +743,8 @@ class RolesTest extends BrowserKitTest { $this->giveUserPermissions($this->user, ['image-update-all']); $admin = $this->getAdmin(); - $page = \BookStack\Entities\Page::first(); - $image = factory(\BookStack\Uploads\Image::class)->create(['uploaded_to' => $page->id, 'created_by' => $admin->id, 'updated_by' => $admin->id]); + $page = Page::first(); + $image = factory(Image::class)->create(['uploaded_to' => $page->id, 'created_by' => $admin->id, 'updated_by' => $admin->id]); $this->actingAs($this->user)->json('delete', '/images/' . $image->id) ->seeStatusCode(403); @@ -760,7 +765,7 @@ class RolesTest extends BrowserKitTest { // To cover issue fixed in f99c8ff99aee9beb8c692f36d4b84dc6e651e50a. $page = Page::first(); - $viewerRole = \BookStack\Auth\Role::getRole('viewer'); + $viewerRole = Role::getRole('viewer'); $viewer = $this->getViewer(); $this->actingAs($viewer)->visit($page->getUrl())->assertResponseStatus(200); @@ -778,14 +783,14 @@ class RolesTest extends BrowserKitTest { $admin = $this->getAdmin(); // Book links - $book = factory(\BookStack\Entities\Book::class)->create(['created_by' => $admin->id, 'updated_by' => $admin->id]); + $book = factory(Book::class)->create(['created_by' => $admin->id, 'updated_by' => $admin->id]); $this->updateEntityPermissions($book); $this->actingAs($this->getViewer())->visit($book->getUrl()) ->dontSee('Create a new page') ->dontSee('Add a chapter'); // Chapter links - $chapter = factory(\BookStack\Entities\Chapter::class)->create(['created_by' => $admin->id, 'updated_by' => $admin->id, 'book_id' => $book->id]); + $chapter = factory(Chapter::class)->create(['created_by' => $admin->id, 'updated_by' => $admin->id, 'book_id' => $book->id]); $this->updateEntityPermissions($chapter); $this->actingAs($this->getViewer())->visit($chapter->getUrl()) ->dontSee('Create a new page') @@ -869,7 +874,7 @@ class RolesTest extends BrowserKitTest } private function addComment($page) { - $comment = factory(\BookStack\Actions\Comment::class)->make(); + $comment = factory(Comment::class)->make(); $url = "/comment/$page->id"; $request = [ 'text' => $comment->text, @@ -882,7 +887,7 @@ class RolesTest extends BrowserKitTest } private function updateComment($commentId) { - $comment = factory(\BookStack\Actions\Comment::class)->make(); + $comment = factory(Comment::class)->make(); $url = "/comment/$commentId"; $request = [ 'text' => $comment->text, diff --git a/tests/User/UserApiTokenTest.php b/tests/User/UserApiTokenTest.php index c89a590f0..df686dd77 100644 --- a/tests/User/UserApiTokenTest.php +++ b/tests/User/UserApiTokenTest.php @@ -1,5 +1,6 @@ assertTrue(strlen($secret) === 32); $this->assertSessionHas('success'); + $this->assertActivityExists(ActivityType::API_TOKEN_CREATE); } public function test_create_with_no_expiry_sets_expiry_hundred_years_away() @@ -124,6 +126,7 @@ class UserApiTokenTest extends TestCase $this->assertDatabaseHas('api_tokens', array_merge($updateData, ['id' => $token->id])); $this->assertSessionHas('success'); + $this->assertActivityExists(ActivityType::API_TOKEN_UPDATE); } public function test_token_update_with_blank_expiry_sets_to_hundred_years_away() @@ -162,6 +165,7 @@ class UserApiTokenTest extends TestCase $resp = $this->delete($tokenUrl); $resp->assertRedirect($editor->getEditUrl('#api_tokens')); $this->assertDatabaseMissing('api_tokens', ['id' => $token->id]); + $this->assertActivityExists(ActivityType::API_TOKEN_DELETE); } public function test_user_manage_can_delete_token_without_api_permission_themselves()