Implemented user, api_tokem & role activity logging

Also refactored some role content, primarily updating the permission
controller to be RoleController since it only dealt with roles.
This commit is contained in:
Dan Brown 2020-11-20 18:53:01 +00:00
parent 3f7180fa99
commit da37700ac2
No known key found for this signature in database
GPG Key ID: 46D9F943C24A2EF9
12 changed files with 118 additions and 59 deletions

View File

@ -32,7 +32,6 @@ class ActivityType
const RECYCLE_BIN_RESTORE = 'recycle_bin_restore'; const RECYCLE_BIN_RESTORE = 'recycle_bin_restore';
const RECYCLE_BIN_DESTROY = 'recycle_bin_destroy'; const RECYCLE_BIN_DESTROY = 'recycle_bin_destroy';
// TODO - Implement all below
const USER_CREATE = 'user_create'; const USER_CREATE = 'user_create';
const USER_UPDATE = 'user_update'; const USER_UPDATE = 'user_update';
const USER_DELETE = 'user_delete'; const USER_DELETE = 'user_delete';
@ -45,6 +44,7 @@ class ActivityType
const ROLE_UPDATE = 'role_update'; const ROLE_UPDATE = 'role_update';
const ROLE_DELETE = 'role_delete'; const ROLE_DELETE = 'role_delete';
// TODO - Implement all below
const ACCESS_PASSWORD_RESET = 'access_password_reset_request'; const ACCESS_PASSWORD_RESET = 'access_password_reset_request';
const ACCESS_PASSWORD_RESET_UPDATE = 'access_password_reset_update'; const ACCESS_PASSWORD_RESET_UPDATE = 'access_password_reset_update';
const ACCESS_LOGIN = 'access_login'; const ACCESS_LOGIN = 'access_login';

View File

@ -1,11 +1,22 @@
<?php namespace BookStack\Api; <?php namespace BookStack\Api;
use BookStack\Auth\User; use BookStack\Auth\User;
use BookStack\Interfaces\Loggable;
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo; use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Support\Carbon; use Illuminate\Support\Carbon;
class ApiToken extends Model /**
* Class ApiToken
* @property int $id
* @property string $token_id
* @property string $secret
* @property string $name
* @property Carbon $expires_at
* @property User $user
* @package BookStack\Api
*/
class ApiToken extends Model implements Loggable
{ {
protected $fillable = ['name', 'expires_at']; protected $fillable = ['name', 'expires_at'];
protected $casts = [ protected $casts = [
@ -28,4 +39,12 @@ class ApiToken extends Model
{ {
return Carbon::now()->addYears(100)->format('Y-m-d'); return Carbon::now()->addYears(100)->format('Y-m-d');
} }
/**
* @inheritdoc
*/
public function logDescriptor(): string
{
return "({$this->id}) {$this->name}; User: {$this->user->logDescriptor()}";
}
} }

View File

@ -1,10 +1,11 @@
<?php namespace BookStack\Auth\Permissions; <?php namespace BookStack\Auth\Permissions;
use BookStack\Actions\ActivityType;
use BookStack\Auth\Role; use BookStack\Auth\Role;
use BookStack\Exceptions\PermissionsException; use BookStack\Exceptions\PermissionsException;
use BookStack\Facades\Activity;
use Exception; use Exception;
use Illuminate\Database\Eloquent\Collection; use Illuminate\Database\Eloquent\Collection;
use Illuminate\Support\Str;
class PermissionsRepo class PermissionsRepo
{ {
@ -60,6 +61,7 @@ class PermissionsRepo
$permissions = isset($roleData['permissions']) ? array_keys($roleData['permissions']) : []; $permissions = isset($roleData['permissions']) ? array_keys($roleData['permissions']) : [];
$this->assignRolePermissions($role, $permissions); $this->assignRolePermissions($role, $permissions);
$this->permissionService->buildJointPermissionForRole($role); $this->permissionService->buildJointPermissionForRole($role);
Activity::add(ActivityType::ROLE_CREATE, $role);
return $role; return $role;
} }
@ -88,12 +90,13 @@ class PermissionsRepo
$role->fill($roleData); $role->fill($roleData);
$role->save(); $role->save();
$this->permissionService->buildJointPermissionForRole($role); $this->permissionService->buildJointPermissionForRole($role);
Activity::add(ActivityType::ROLE_UPDATE, $role);
} }
/** /**
* Assign an list of permission names to an 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 = []; $permissions = [];
$permissionNameArray = array_values($permissionNameArray); $permissionNameArray = array_values($permissionNameArray);
@ -137,6 +140,7 @@ class PermissionsRepo
} }
$this->permissionService->deleteJointPermissionsForRole($role); $this->permissionService->deleteJointPermissionsForRole($role);
Activity::add(ActivityType::ROLE_DELETE, $role);
$role->delete(); $role->delete();
} }
} }

View File

@ -2,6 +2,7 @@
use BookStack\Auth\Permissions\JointPermission; use BookStack\Auth\Permissions\JointPermission;
use BookStack\Auth\Permissions\RolePermission; use BookStack\Auth\Permissions\RolePermission;
use BookStack\Interfaces\Loggable;
use BookStack\Model; use BookStack\Model;
use Illuminate\Database\Eloquent\Collection; use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Eloquent\Relations\HasMany; use Illuminate\Database\Eloquent\Relations\HasMany;
@ -14,7 +15,7 @@ use Illuminate\Database\Eloquent\Relations\HasMany;
* @property string $external_auth_id * @property string $external_auth_id
* @property string $system_name * @property string $system_name
*/ */
class Role extends Model class Role extends Model implements Loggable
{ {
protected $fillable = ['display_name', 'description', 'external_auth_id']; protected $fillable = ['display_name', 'description', 'external_auth_id'];
@ -104,4 +105,12 @@ class Role extends Model
{ {
return static::query()->where('system_name', '!=', 'admin')->get(); return static::query()->where('system_name', '!=', 'admin')->get();
} }
/**
* @inheritdoc
*/
public function logDescriptor(): string
{
return "({$this->id}) {$this->display_name}";
}
} }

View File

@ -1,6 +1,7 @@
<?php namespace BookStack\Auth; <?php namespace BookStack\Auth;
use BookStack\Api\ApiToken; use BookStack\Api\ApiToken;
use BookStack\Interfaces\Loggable;
use BookStack\Model; use BookStack\Model;
use BookStack\Notifications\ResetPassword; use BookStack\Notifications\ResetPassword;
use BookStack\Uploads\Image; use BookStack\Uploads\Image;
@ -27,7 +28,7 @@ use Illuminate\Notifications\Notifiable;
* @property string $external_auth_id * @property string $external_auth_id
* @property string $system_name * @property string $system_name
*/ */
class User extends Model implements AuthenticatableContract, CanResetPasswordContract class User extends Model implements AuthenticatableContract, CanResetPasswordContract, Loggable
{ {
use Authenticatable, CanResetPassword, Notifiable; use Authenticatable, CanResetPassword, Notifiable;
@ -274,4 +275,12 @@ class User extends Model implements AuthenticatableContract, CanResetPasswordCon
{ {
$this->notify(new ResetPassword($token)); $this->notify(new ResetPassword($token));
} }
/**
* @inheritdoc
*/
public function logDescriptor(): string
{
return "({$this->id}) {$this->name}";
}
} }

View File

@ -85,9 +85,9 @@ class RecycleBinController extends Controller
{ {
/** @var Deletion $deletion */ /** @var Deletion $deletion */
$deletion = Deletion::query()->findOrFail($id); $deletion = Deletion::query()->findOrFail($id);
$this->logActivity(ActivityType::RECYCLE_BIN_DESTROY, $deletion);
$deleteCount = (new TrashCan())->destroyFromDeletion($deletion); $deleteCount = (new TrashCan())->destroyFromDeletion($deletion);
$this->logActivity(ActivityType::RECYCLE_BIN_DESTROY, $deletion);
$this->showSuccessNotification(trans('settings.recycle_bin_destroy_notification', ['count' => $deleteCount])); $this->showSuccessNotification(trans('settings.recycle_bin_destroy_notification', ['count' => $deleteCount]));
return redirect($this->recycleBinBaseUrl); return redirect($this->recycleBinBaseUrl);
} }

View File

@ -6,7 +6,7 @@ use Exception;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Illuminate\Validation\ValidationException; use Illuminate\Validation\ValidationException;
class PermissionController extends Controller class RoleController extends Controller
{ {
protected $permissionsRepo; protected $permissionsRepo;
@ -23,7 +23,7 @@ class PermissionController extends Controller
/** /**
* Show a listing of the roles in the system. * Show a listing of the roles in the system.
*/ */
public function listRoles() public function list()
{ {
$this->checkPermission('user-roles-manage'); $this->checkPermission('user-roles-manage');
$roles = $this->permissionsRepo->getAllRoles(); $roles = $this->permissionsRepo->getAllRoles();
@ -33,7 +33,7 @@ class PermissionController extends Controller
/** /**
* Show the form to create a new role * Show the form to create a new role
*/ */
public function createRole() public function create()
{ {
$this->checkPermission('user-roles-manage'); $this->checkPermission('user-roles-manage');
return view('settings.roles.create'); return view('settings.roles.create');
@ -42,7 +42,7 @@ class PermissionController extends Controller
/** /**
* Store a new role in the system. * Store a new role in the system.
*/ */
public function storeRole(Request $request) public function store(Request $request)
{ {
$this->checkPermission('user-roles-manage'); $this->checkPermission('user-roles-manage');
$this->validate($request, [ $this->validate($request, [
@ -59,7 +59,7 @@ class PermissionController extends Controller
* Show the form for editing a user role. * Show the form for editing a user role.
* @throws PermissionsException * @throws PermissionsException
*/ */
public function editRole(string $id) public function edit(string $id)
{ {
$this->checkPermission('user-roles-manage'); $this->checkPermission('user-roles-manage');
$role = $this->permissionsRepo->getRoleById($id); $role = $this->permissionsRepo->getRoleById($id);
@ -73,7 +73,7 @@ class PermissionController extends Controller
* Updates a user role. * Updates a user role.
* @throws ValidationException * @throws ValidationException
*/ */
public function updateRole(Request $request, string $id) public function update(Request $request, string $id)
{ {
$this->checkPermission('user-roles-manage'); $this->checkPermission('user-roles-manage');
$this->validate($request, [ $this->validate($request, [
@ -90,7 +90,7 @@ class PermissionController extends Controller
* Show the view to delete a role. * Show the view to delete a role.
* Offers the chance to migrate users. * Offers the chance to migrate users.
*/ */
public function showDeleteRole(string $id) public function showDelete(string $id)
{ {
$this->checkPermission('user-roles-manage'); $this->checkPermission('user-roles-manage');
$role = $this->permissionsRepo->getRoleById($id); $role = $this->permissionsRepo->getRoleById($id);
@ -105,7 +105,7 @@ class PermissionController extends Controller
* Migrate from a previous role if set. * Migrate from a previous role if set.
* @throws Exception * @throws Exception
*/ */
public function deleteRole(Request $request, string $id) public function delete(Request $request, string $id)
{ {
$this->checkPermission('user-roles-manage'); $this->checkPermission('user-roles-manage');

View File

@ -1,9 +1,9 @@
<?php namespace BookStack\Http\Controllers; <?php namespace BookStack\Http\Controllers;
use BookStack\Actions\ActivityType;
use BookStack\Api\ApiToken; use BookStack\Api\ApiToken;
use BookStack\Auth\User; use BookStack\Auth\User;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\Hash; use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Str; use Illuminate\Support\Str;
@ -57,6 +57,8 @@ class UserApiTokenController extends Controller
session()->flash('api-token-secret:' . $token->id, $secret); session()->flash('api-token-secret:' . $token->id, $secret);
$this->showSuccessNotification(trans('settings.user_api_token_create_success')); $this->showSuccessNotification(trans('settings.user_api_token_create_success'));
$this->logActivity(ActivityType::API_TOKEN_CREATE, $token);
return redirect($user->getEditUrl('/api-tokens/' . $token->id)); return redirect($user->getEditUrl('/api-tokens/' . $token->id));
} }
@ -93,6 +95,7 @@ class UserApiTokenController extends Controller
])->save(); ])->save();
$this->showSuccessNotification(trans('settings.user_api_token_update_success')); $this->showSuccessNotification(trans('settings.user_api_token_update_success'));
$this->logActivity(ActivityType::API_TOKEN_UPDATE, $token);
return redirect($user->getEditUrl('/api-tokens/' . $token->id)); return redirect($user->getEditUrl('/api-tokens/' . $token->id));
} }
@ -117,6 +120,8 @@ class UserApiTokenController extends Controller
$token->delete(); $token->delete();
$this->showSuccessNotification(trans('settings.user_api_token_delete_success')); $this->showSuccessNotification(trans('settings.user_api_token_delete_success'));
$this->logActivity(ActivityType::API_TOKEN_DELETE, $token);
return redirect($user->getEditUrl('#api_tokens')); return redirect($user->getEditUrl('#api_tokens'));
} }

View File

@ -1,5 +1,6 @@
<?php namespace BookStack\Http\Controllers; <?php namespace BookStack\Http\Controllers;
use BookStack\Actions\ActivityType;
use BookStack\Auth\Access\SocialAuthService; use BookStack\Auth\Access\SocialAuthService;
use BookStack\Auth\Access\UserInviteService; use BookStack\Auth\Access\UserInviteService;
use BookStack\Auth\User; use BookStack\Auth\User;
@ -102,6 +103,7 @@ class UserController extends Controller
$this->userRepo->downloadAndAssignUserAvatar($user); $this->userRepo->downloadAndAssignUserAvatar($user);
$this->logActivity(ActivityType::USER_CREATE, $user);
return redirect('/settings/users'); return redirect('/settings/users');
} }
@ -194,6 +196,7 @@ class UserController extends Controller
$user->save(); $user->save();
$this->showSuccessNotification(trans('settings.users_edit_success')); $this->showSuccessNotification(trans('settings.users_edit_success'));
$this->logActivity(ActivityType::USER_UPDATE, $user);
$redirectUrl = userCan('users-manage') ? '/settings/users' : ('/settings/users/' . $user->id); $redirectUrl = userCan('users-manage') ? '/settings/users' : ('/settings/users/' . $user->id);
return redirect($redirectUrl); return redirect($redirectUrl);
@ -234,6 +237,7 @@ class UserController extends Controller
$this->userRepo->destroy($user); $this->userRepo->destroy($user);
$this->showSuccessNotification(trans('settings.users_delete_success')); $this->showSuccessNotification(trans('settings.users_delete_success'));
$this->logActivity(ActivityType::USER_DELETE, $user);
return redirect('/settings/users'); return redirect('/settings/users');
} }

View File

@ -201,13 +201,13 @@ Route::group(['middleware' => 'auth'], function () {
Route::delete('/users/{userId}/api-tokens/{tokenId}', 'UserApiTokenController@destroy'); Route::delete('/users/{userId}/api-tokens/{tokenId}', 'UserApiTokenController@destroy');
// Roles // Roles
Route::get('/roles', 'PermissionController@listRoles'); Route::get('/roles', 'RoleController@list');
Route::get('/roles/new', 'PermissionController@createRole'); Route::get('/roles/new', 'RoleController@create');
Route::post('/roles/new', 'PermissionController@storeRole'); Route::post('/roles/new', 'RoleController@store');
Route::get('/roles/delete/{id}', 'PermissionController@showDeleteRole'); Route::get('/roles/delete/{id}', 'RoleController@showDelete');
Route::delete('/roles/delete/{id}', 'PermissionController@deleteRole'); Route::delete('/roles/delete/{id}', 'RoleController@delete');
Route::get('/roles/{id}', 'PermissionController@editRole'); Route::get('/roles/{id}', 'RoleController@edit');
Route::put('/roles/{id}', 'PermissionController@updateRole'); Route::put('/roles/{id}', 'RoleController@update');
}); });
}); });

View File

@ -1,8 +1,13 @@
<?php namespace Tests\Permissions; <?php namespace Tests\Permissions;
use BookStack\Actions\Comment;
use BookStack\Auth\User;
use BookStack\Entities\Book;
use BookStack\Entities\Bookshelf; use BookStack\Entities\Bookshelf;
use BookStack\Entities\Chapter;
use BookStack\Entities\Page; use BookStack\Entities\Page;
use BookStack\Auth\Role; use BookStack\Auth\Role;
use BookStack\Uploads\Image;
use Laravel\BrowserKitTesting\HttpException; use Laravel\BrowserKitTesting\HttpException;
use Tests\BrowserKitTest; use Tests\BrowserKitTest;
@ -23,7 +28,7 @@ class RolesTest extends BrowserKitTest
public function test_cannot_delete_admin_role() public function test_cannot_delete_admin_role()
{ {
$adminRole = \BookStack\Auth\Role::getRole('admin'); $adminRole = Role::getRole('admin');
$deletePageUrl = '/settings/roles/delete/' . $adminRole->id; $deletePageUrl = '/settings/roles/delete/' . $adminRole->id;
$this->asAdmin()->visit($deletePageUrl) $this->asAdmin()->visit($deletePageUrl)
->press('Confirm') ->press('Confirm')
@ -195,7 +200,7 @@ class RolesTest extends BrowserKitTest
public function test_restrictions_manage_all_permission() 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()) $this->actingAs($this->user)->visit($page->getUrl())
->dontSee('Permissions') ->dontSee('Permissions')
->visit($page->getUrl() . '/permissions') ->visit($page->getUrl() . '/permissions')
@ -209,7 +214,7 @@ class RolesTest extends BrowserKitTest
public function test_restrictions_manage_own_permission() public function test_restrictions_manage_own_permission()
{ {
$otherUsersPage = \BookStack\Entities\Page::first(); $otherUsersPage = Page::first();
$content = $this->createEntityChainBelongingToUser($this->user); $content = $this->createEntityChainBelongingToUser($this->user);
// Check can't restrict other's content // Check can't restrict other's content
$this->actingAs($this->user)->visit($otherUsersPage->getUrl()) $this->actingAs($this->user)->visit($otherUsersPage->getUrl())
@ -301,7 +306,7 @@ class RolesTest extends BrowserKitTest
public function test_bookshelves_edit_all_permission() public function test_bookshelves_edit_all_permission()
{ {
$otherShelf = \BookStack\Entities\Bookshelf::first(); $otherShelf = Bookshelf::first();
$this->checkAccessPermission('bookshelf-update-all', [ $this->checkAccessPermission('bookshelf-update-all', [
$otherShelf->getUrl('/edit') $otherShelf->getUrl('/edit')
], [ ], [
@ -312,7 +317,7 @@ class RolesTest extends BrowserKitTest
public function test_bookshelves_delete_own_permission() public function test_bookshelves_delete_own_permission()
{ {
$this->giveUserPermissions($this->user, ['bookshelf-update-all']); $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 = $this->newShelf(['name' => 'test-shelf', 'slug' => 'test-shelf']);
$ownShelf->forceFill(['created_by' => $this->user->id, 'updated_by' => $this->user->id])->save(); $ownShelf->forceFill(['created_by' => $this->user->id, 'updated_by' => $this->user->id])->save();
$this->regenEntityPermissions($ownShelf); $this->regenEntityPermissions($ownShelf);
@ -336,7 +341,7 @@ class RolesTest extends BrowserKitTest
public function test_bookshelves_delete_all_permission() public function test_bookshelves_delete_all_permission()
{ {
$this->giveUserPermissions($this->user, ['bookshelf-update-all']); $this->giveUserPermissions($this->user, ['bookshelf-update-all']);
$otherShelf = \BookStack\Entities\Bookshelf::first(); $otherShelf = Bookshelf::first();
$this->checkAccessPermission('bookshelf-delete-all', [ $this->checkAccessPermission('bookshelf-delete-all', [
$otherShelf->getUrl('/delete') $otherShelf->getUrl('/delete')
], [ ], [
@ -366,7 +371,7 @@ class RolesTest extends BrowserKitTest
public function test_books_edit_own_permission() 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']; $ownBook = $this->createEntityChainBelongingToUser($this->user)['book'];
$this->checkAccessPermission('book-update-own', [ $this->checkAccessPermission('book-update-own', [
$ownBook->getUrl() . '/edit' $ownBook->getUrl() . '/edit'
@ -382,7 +387,7 @@ class RolesTest extends BrowserKitTest
public function test_books_edit_all_permission() 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', [ $this->checkAccessPermission('book-update-all', [
$otherBook->getUrl() . '/edit' $otherBook->getUrl() . '/edit'
], [ ], [
@ -393,7 +398,7 @@ class RolesTest extends BrowserKitTest
public function test_books_delete_own_permission() public function test_books_delete_own_permission()
{ {
$this->giveUserPermissions($this->user, ['book-update-all']); $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']; $ownBook = $this->createEntityChainBelongingToUser($this->user)['book'];
$this->checkAccessPermission('book-delete-own', [ $this->checkAccessPermission('book-delete-own', [
$ownBook->getUrl() . '/delete' $ownBook->getUrl() . '/delete'
@ -414,7 +419,7 @@ class RolesTest extends BrowserKitTest
public function test_books_delete_all_permission() public function test_books_delete_all_permission()
{ {
$this->giveUserPermissions($this->user, ['book-update-all']); $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', [ $this->checkAccessPermission('book-delete-all', [
$otherBook->getUrl() . '/delete' $otherBook->getUrl() . '/delete'
], [ ], [
@ -429,7 +434,7 @@ class RolesTest extends BrowserKitTest
public function test_chapter_create_own_permissions() 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']; $ownBook = $this->createEntityChainBelongingToUser($this->user)['book'];
$this->checkAccessPermission('chapter-create-own', [ $this->checkAccessPermission('chapter-create-own', [
$ownBook->getUrl('/create-chapter') $ownBook->getUrl('/create-chapter')
@ -451,7 +456,7 @@ class RolesTest extends BrowserKitTest
public function test_chapter_create_all_permissions() 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', [ $this->checkAccessPermission('chapter-create-all', [
$book->getUrl('/create-chapter') $book->getUrl('/create-chapter')
], [ ], [
@ -467,7 +472,7 @@ class RolesTest extends BrowserKitTest
public function test_chapter_edit_own_permission() 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']; $ownChapter = $this->createEntityChainBelongingToUser($this->user)['chapter'];
$this->checkAccessPermission('chapter-update-own', [ $this->checkAccessPermission('chapter-update-own', [
$ownChapter->getUrl() . '/edit' $ownChapter->getUrl() . '/edit'
@ -483,7 +488,7 @@ class RolesTest extends BrowserKitTest
public function test_chapter_edit_all_permission() 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', [ $this->checkAccessPermission('chapter-update-all', [
$otherChapter->getUrl() . '/edit' $otherChapter->getUrl() . '/edit'
], [ ], [
@ -494,7 +499,7 @@ class RolesTest extends BrowserKitTest
public function test_chapter_delete_own_permission() public function test_chapter_delete_own_permission()
{ {
$this->giveUserPermissions($this->user, ['chapter-update-all']); $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']; $ownChapter = $this->createEntityChainBelongingToUser($this->user)['chapter'];
$this->checkAccessPermission('chapter-delete-own', [ $this->checkAccessPermission('chapter-delete-own', [
$ownChapter->getUrl() . '/delete' $ownChapter->getUrl() . '/delete'
@ -516,7 +521,7 @@ class RolesTest extends BrowserKitTest
public function test_chapter_delete_all_permission() public function test_chapter_delete_all_permission()
{ {
$this->giveUserPermissions($this->user, ['chapter-update-all']); $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', [ $this->checkAccessPermission('chapter-delete-all', [
$otherChapter->getUrl() . '/delete' $otherChapter->getUrl() . '/delete'
], [ ], [
@ -532,8 +537,8 @@ class RolesTest extends BrowserKitTest
public function test_page_create_own_permissions() public function test_page_create_own_permissions()
{ {
$book = \BookStack\Entities\Book::first(); $book = Book::first();
$chapter = \BookStack\Entities\Chapter::first(); $chapter = Chapter::first();
$entities = $this->createEntityChainBelongingToUser($this->user); $entities = $this->createEntityChainBelongingToUser($this->user);
$ownBook = $entities['book']; $ownBook = $entities['book'];
@ -557,7 +562,7 @@ class RolesTest extends BrowserKitTest
foreach ($accessUrls as $index => $url) { foreach ($accessUrls as $index => $url) {
$this->actingAs($this->user)->visit($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); $this->seePageIs($expectedUrl);
} }
@ -579,8 +584,8 @@ class RolesTest extends BrowserKitTest
public function test_page_create_all_permissions() public function test_page_create_all_permissions()
{ {
$book = \BookStack\Entities\Book::take(1)->get()->first(); $book = Book::take(1)->get()->first();
$chapter = \BookStack\Entities\Chapter::take(1)->get()->first(); $chapter = Chapter::take(1)->get()->first();
$baseUrl = $book->getUrl() . '/page'; $baseUrl = $book->getUrl() . '/page';
$createUrl = $book->getUrl('/create-page'); $createUrl = $book->getUrl('/create-page');
@ -601,7 +606,7 @@ class RolesTest extends BrowserKitTest
foreach ($accessUrls as $index => $url) { foreach ($accessUrls as $index => $url) {
$this->actingAs($this->user)->visit($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); $this->seePageIs($expectedUrl);
} }
@ -620,7 +625,7 @@ class RolesTest extends BrowserKitTest
public function test_page_edit_own_permission() 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']; $ownPage = $this->createEntityChainBelongingToUser($this->user)['page'];
$this->checkAccessPermission('page-update-own', [ $this->checkAccessPermission('page-update-own', [
$ownPage->getUrl() . '/edit' $ownPage->getUrl() . '/edit'
@ -636,7 +641,7 @@ class RolesTest extends BrowserKitTest
public function test_page_edit_all_permission() 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', [ $this->checkAccessPermission('page-update-all', [
$otherPage->getUrl() . '/edit' $otherPage->getUrl() . '/edit'
], [ ], [
@ -647,7 +652,7 @@ class RolesTest extends BrowserKitTest
public function test_page_delete_own_permission() public function test_page_delete_own_permission()
{ {
$this->giveUserPermissions($this->user, ['page-update-all']); $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']; $ownPage = $this->createEntityChainBelongingToUser($this->user)['page'];
$this->checkAccessPermission('page-delete-own', [ $this->checkAccessPermission('page-delete-own', [
$ownPage->getUrl() . '/delete' $ownPage->getUrl() . '/delete'
@ -669,7 +674,7 @@ class RolesTest extends BrowserKitTest
public function test_page_delete_all_permission() public function test_page_delete_all_permission()
{ {
$this->giveUserPermissions($this->user, ['page-update-all']); $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', [ $this->checkAccessPermission('page-delete-all', [
$otherPage->getUrl() . '/delete' $otherPage->getUrl() . '/delete'
], [ ], [
@ -685,7 +690,7 @@ class RolesTest extends BrowserKitTest
public function test_public_role_visible_in_user_edit_screen() public function test_public_role_visible_in_user_edit_screen()
{ {
$user = \BookStack\Auth\User::first(); $user = User::first();
$adminRole = Role::getSystemRole('admin'); $adminRole = Role::getSystemRole('admin');
$publicRole = Role::getSystemRole('public'); $publicRole = Role::getSystemRole('public');
$this->asAdmin()->visit('/settings/users/' . $user->id) $this->asAdmin()->visit('/settings/users/' . $user->id)
@ -721,8 +726,8 @@ class RolesTest extends BrowserKitTest
public function test_image_delete_own_permission() public function test_image_delete_own_permission()
{ {
$this->giveUserPermissions($this->user, ['image-update-all']); $this->giveUserPermissions($this->user, ['image-update-all']);
$page = \BookStack\Entities\Page::first(); $page = Page::first();
$image = factory(\BookStack\Uploads\Image::class)->create(['uploaded_to' => $page->id, 'created_by' => $this->user->id, 'updated_by' => $this->user->id]); $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) $this->actingAs($this->user)->json('delete', '/images/' . $image->id)
->seeStatusCode(403); ->seeStatusCode(403);
@ -738,8 +743,8 @@ class RolesTest extends BrowserKitTest
{ {
$this->giveUserPermissions($this->user, ['image-update-all']); $this->giveUserPermissions($this->user, ['image-update-all']);
$admin = $this->getAdmin(); $admin = $this->getAdmin();
$page = \BookStack\Entities\Page::first(); $page = Page::first();
$image = factory(\BookStack\Uploads\Image::class)->create(['uploaded_to' => $page->id, 'created_by' => $admin->id, 'updated_by' => $admin->id]); $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) $this->actingAs($this->user)->json('delete', '/images/' . $image->id)
->seeStatusCode(403); ->seeStatusCode(403);
@ -760,7 +765,7 @@ class RolesTest extends BrowserKitTest
{ {
// To cover issue fixed in f99c8ff99aee9beb8c692f36d4b84dc6e651e50a. // To cover issue fixed in f99c8ff99aee9beb8c692f36d4b84dc6e651e50a.
$page = Page::first(); $page = Page::first();
$viewerRole = \BookStack\Auth\Role::getRole('viewer'); $viewerRole = Role::getRole('viewer');
$viewer = $this->getViewer(); $viewer = $this->getViewer();
$this->actingAs($viewer)->visit($page->getUrl())->assertResponseStatus(200); $this->actingAs($viewer)->visit($page->getUrl())->assertResponseStatus(200);
@ -778,14 +783,14 @@ class RolesTest extends BrowserKitTest
{ {
$admin = $this->getAdmin(); $admin = $this->getAdmin();
// Book links // 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->updateEntityPermissions($book);
$this->actingAs($this->getViewer())->visit($book->getUrl()) $this->actingAs($this->getViewer())->visit($book->getUrl())
->dontSee('Create a new page') ->dontSee('Create a new page')
->dontSee('Add a chapter'); ->dontSee('Add a chapter');
// Chapter links // 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->updateEntityPermissions($chapter);
$this->actingAs($this->getViewer())->visit($chapter->getUrl()) $this->actingAs($this->getViewer())->visit($chapter->getUrl())
->dontSee('Create a new page') ->dontSee('Create a new page')
@ -869,7 +874,7 @@ class RolesTest extends BrowserKitTest
} }
private function addComment($page) { private function addComment($page) {
$comment = factory(\BookStack\Actions\Comment::class)->make(); $comment = factory(Comment::class)->make();
$url = "/comment/$page->id"; $url = "/comment/$page->id";
$request = [ $request = [
'text' => $comment->text, 'text' => $comment->text,
@ -882,7 +887,7 @@ class RolesTest extends BrowserKitTest
} }
private function updateComment($commentId) { private function updateComment($commentId) {
$comment = factory(\BookStack\Actions\Comment::class)->make(); $comment = factory(Comment::class)->make();
$url = "/comment/$commentId"; $url = "/comment/$commentId";
$request = [ $request = [
'text' => $comment->text, 'text' => $comment->text,

View File

@ -1,5 +1,6 @@
<?php namespace Tests\User; <?php namespace Tests\User;
use BookStack\Actions\ActivityType;
use BookStack\Api\ApiToken; use BookStack\Api\ApiToken;
use Carbon\Carbon; use Carbon\Carbon;
use Tests\TestCase; use Tests\TestCase;
@ -67,6 +68,7 @@ class UserApiTokenTest extends TestCase
$this->assertTrue(strlen($secret) === 32); $this->assertTrue(strlen($secret) === 32);
$this->assertSessionHas('success'); $this->assertSessionHas('success');
$this->assertActivityExists(ActivityType::API_TOKEN_CREATE);
} }
public function test_create_with_no_expiry_sets_expiry_hundred_years_away() 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->assertDatabaseHas('api_tokens', array_merge($updateData, ['id' => $token->id]));
$this->assertSessionHas('success'); $this->assertSessionHas('success');
$this->assertActivityExists(ActivityType::API_TOKEN_UPDATE);
} }
public function test_token_update_with_blank_expiry_sets_to_hundred_years_away() 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 = $this->delete($tokenUrl);
$resp->assertRedirect($editor->getEditUrl('#api_tokens')); $resp->assertRedirect($editor->getEditUrl('#api_tokens'));
$this->assertDatabaseMissing('api_tokens', ['id' => $token->id]); $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() public function test_user_manage_can_delete_token_without_api_permission_themselves()