mirror of
https://github.com/BookStackApp/BookStack.git
synced 2024-10-01 01:36:00 -04:00
Merge pull request #4987 from BookStackApp/audit_api
Addition of Audit Log API Endpoint
This commit is contained in:
commit
baad7fa9cb
@ -27,14 +27,14 @@ class ActivityQueries
|
|||||||
public function latest(int $count = 20, int $page = 0): array
|
public function latest(int $count = 20, int $page = 0): array
|
||||||
{
|
{
|
||||||
$activityList = $this->permissions
|
$activityList = $this->permissions
|
||||||
->restrictEntityRelationQuery(Activity::query(), 'activities', 'entity_id', 'entity_type')
|
->restrictEntityRelationQuery(Activity::query(), 'activities', 'loggable_id', 'loggable_type')
|
||||||
->orderBy('created_at', 'desc')
|
->orderBy('created_at', 'desc')
|
||||||
->with(['user'])
|
->with(['user'])
|
||||||
->skip($count * $page)
|
->skip($count * $page)
|
||||||
->take($count)
|
->take($count)
|
||||||
->get();
|
->get();
|
||||||
|
|
||||||
$this->listLoader->loadIntoRelations($activityList->all(), 'entity', false);
|
$this->listLoader->loadIntoRelations($activityList->all(), 'loggable', false);
|
||||||
|
|
||||||
return $this->filterSimilar($activityList);
|
return $this->filterSimilar($activityList);
|
||||||
}
|
}
|
||||||
@ -59,14 +59,14 @@ class ActivityQueries
|
|||||||
$query->where(function (Builder $query) use ($queryIds) {
|
$query->where(function (Builder $query) use ($queryIds) {
|
||||||
foreach ($queryIds as $morphClass => $idArr) {
|
foreach ($queryIds as $morphClass => $idArr) {
|
||||||
$query->orWhere(function (Builder $innerQuery) use ($morphClass, $idArr) {
|
$query->orWhere(function (Builder $innerQuery) use ($morphClass, $idArr) {
|
||||||
$innerQuery->where('entity_type', '=', $morphClass)
|
$innerQuery->where('loggable_type', '=', $morphClass)
|
||||||
->whereIn('entity_id', $idArr);
|
->whereIn('loggable_id', $idArr);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
$activity = $query->orderBy('created_at', 'desc')
|
$activity = $query->orderBy('created_at', 'desc')
|
||||||
->with(['entity' => function (Relation $query) {
|
->with(['loggable' => function (Relation $query) {
|
||||||
$query->withTrashed();
|
$query->withTrashed();
|
||||||
}, 'user.avatar'])
|
}, 'user.avatar'])
|
||||||
->skip($count * ($page - 1))
|
->skip($count * ($page - 1))
|
||||||
@ -82,7 +82,7 @@ class ActivityQueries
|
|||||||
public function userActivity(User $user, int $count = 20, int $page = 0): array
|
public function userActivity(User $user, int $count = 20, int $page = 0): array
|
||||||
{
|
{
|
||||||
$activityList = $this->permissions
|
$activityList = $this->permissions
|
||||||
->restrictEntityRelationQuery(Activity::query(), 'activities', 'entity_id', 'entity_type')
|
->restrictEntityRelationQuery(Activity::query(), 'activities', 'loggable_id', 'loggable_type')
|
||||||
->orderBy('created_at', 'desc')
|
->orderBy('created_at', 'desc')
|
||||||
->where('user_id', '=', $user->id)
|
->where('user_id', '=', $user->id)
|
||||||
->skip($count * $page)
|
->skip($count * $page)
|
||||||
|
28
app/Activity/Controllers/AuditLogApiController.php
Normal file
28
app/Activity/Controllers/AuditLogApiController.php
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace BookStack\Activity\Controllers;
|
||||||
|
|
||||||
|
use BookStack\Activity\Models\Activity;
|
||||||
|
use BookStack\Http\ApiController;
|
||||||
|
|
||||||
|
class AuditLogApiController extends ApiController
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Get a listing of audit log events in the system.
|
||||||
|
* The loggable relation fields currently only relates to core
|
||||||
|
* content types (page, book, bookshelf, chapter) but this may be
|
||||||
|
* used more in the future across other types.
|
||||||
|
* Requires permission to manage both users and system settings.
|
||||||
|
*/
|
||||||
|
public function list()
|
||||||
|
{
|
||||||
|
$this->checkPermission('settings-manage');
|
||||||
|
$this->checkPermission('users-manage');
|
||||||
|
|
||||||
|
$query = Activity::query()->with(['user']);
|
||||||
|
|
||||||
|
return $this->apiListingResponse($query, [
|
||||||
|
'id', 'type', 'detail', 'user_id', 'loggable_id', 'loggable_type', 'ip', 'created_at',
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
@ -32,7 +32,7 @@ class AuditLogController extends Controller
|
|||||||
|
|
||||||
$query = Activity::query()
|
$query = Activity::query()
|
||||||
->with([
|
->with([
|
||||||
'entity' => fn ($query) => $query->withTrashed(),
|
'loggable' => fn ($query) => $query->withTrashed(),
|
||||||
'user',
|
'user',
|
||||||
])
|
])
|
||||||
->orderBy($listOptions->getSort(), $listOptions->getOrder());
|
->orderBy($listOptions->getSort(), $listOptions->getOrder());
|
||||||
|
@ -15,26 +15,24 @@ use Illuminate\Support\Str;
|
|||||||
/**
|
/**
|
||||||
* @property string $type
|
* @property string $type
|
||||||
* @property User $user
|
* @property User $user
|
||||||
* @property Entity $entity
|
* @property Entity $loggable
|
||||||
* @property string $detail
|
* @property string $detail
|
||||||
* @property string $entity_type
|
* @property string $loggable_type
|
||||||
* @property int $entity_id
|
* @property int $loggable_id
|
||||||
* @property int $user_id
|
* @property int $user_id
|
||||||
* @property Carbon $created_at
|
* @property Carbon $created_at
|
||||||
* @property Carbon $updated_at
|
|
||||||
*/
|
*/
|
||||||
class Activity extends Model
|
class Activity extends Model
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Get the entity for this activity.
|
* Get the loggable model related to this activity.
|
||||||
|
* Currently only used for entities (previously entity_[id/type] columns).
|
||||||
|
* Could be used for others but will need an audit of uses where assumed
|
||||||
|
* to be entities.
|
||||||
*/
|
*/
|
||||||
public function entity(): MorphTo
|
public function loggable(): MorphTo
|
||||||
{
|
{
|
||||||
if ($this->entity_type === '') {
|
return $this->morphTo('loggable');
|
||||||
$this->entity_type = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $this->morphTo('entity');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -47,8 +45,8 @@ class Activity extends Model
|
|||||||
|
|
||||||
public function jointPermissions(): HasMany
|
public function jointPermissions(): HasMany
|
||||||
{
|
{
|
||||||
return $this->hasMany(JointPermission::class, 'entity_id', 'entity_id')
|
return $this->hasMany(JointPermission::class, 'entity_id', 'loggable_id')
|
||||||
->whereColumn('activities.entity_type', '=', 'joint_permissions.entity_type');
|
->whereColumn('activities.loggable_type', '=', 'joint_permissions.entity_type');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -74,6 +72,6 @@ class Activity extends Model
|
|||||||
*/
|
*/
|
||||||
public function isSimilarTo(self $activityB): bool
|
public function isSimilarTo(self $activityB): bool
|
||||||
{
|
{
|
||||||
return [$this->type, $this->entity_type, $this->entity_id] === [$activityB->type, $activityB->entity_type, $activityB->entity_id];
|
return [$this->type, $this->loggable_type, $this->loggable_id] === [$activityB->type, $activityB->loggable_type, $activityB->loggable_id];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -32,8 +32,8 @@ class ActivityLogger
|
|||||||
$activity->detail = $detailToStore;
|
$activity->detail = $detailToStore;
|
||||||
|
|
||||||
if ($detail instanceof Entity) {
|
if ($detail instanceof Entity) {
|
||||||
$activity->entity_id = $detail->id;
|
$activity->loggable_id = $detail->id;
|
||||||
$activity->entity_type = $detail->getMorphClass();
|
$activity->loggable_type = $detail->getMorphClass();
|
||||||
}
|
}
|
||||||
|
|
||||||
$activity->save();
|
$activity->save();
|
||||||
@ -64,9 +64,9 @@ class ActivityLogger
|
|||||||
public function removeEntity(Entity $entity): void
|
public function removeEntity(Entity $entity): void
|
||||||
{
|
{
|
||||||
$entity->activity()->update([
|
$entity->activity()->update([
|
||||||
'detail' => $entity->name,
|
'detail' => $entity->name,
|
||||||
'entity_id' => null,
|
'loggable_id' => null,
|
||||||
'entity_type' => null,
|
'loggable_type' => null,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,7 +19,7 @@ class ClearActivityCommand extends Command
|
|||||||
*
|
*
|
||||||
* @var string
|
* @var string
|
||||||
*/
|
*/
|
||||||
protected $description = 'Clear user activity from the system';
|
protected $description = 'Clear user (audit-log) activity from the system';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Execute the console command.
|
* Execute the console command.
|
||||||
|
@ -137,7 +137,7 @@ abstract class Entity extends Model implements Sluggable, Favouritable, Viewable
|
|||||||
*/
|
*/
|
||||||
public function activity(): MorphMany
|
public function activity(): MorphMany
|
||||||
{
|
{
|
||||||
return $this->morphMany(Activity::class, 'entity')
|
return $this->morphMany(Activity::class, 'loggable')
|
||||||
->orderBy('created_at', 'desc');
|
->orderBy('created_at', 'desc');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,30 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
return new class extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*/
|
||||||
|
public function up(): void
|
||||||
|
{
|
||||||
|
Schema::table('activities', function (Blueprint $table) {
|
||||||
|
$table->renameColumn('entity_id', 'loggable_id');
|
||||||
|
$table->renameColumn('entity_type', 'loggable_type');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*/
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
Schema::table('activities', function (Blueprint $table) {
|
||||||
|
$table->renameColumn('loggable_id', 'entity_id');
|
||||||
|
$table->renameColumn('loggable_type', 'entity_type');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
80
dev/api/responses/audit-log-list.json
Normal file
80
dev/api/responses/audit-log-list.json
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
{
|
||||||
|
"data": [
|
||||||
|
{
|
||||||
|
"id": 1,
|
||||||
|
"type": "bookshelf_create",
|
||||||
|
"detail": "",
|
||||||
|
"user_id": 1,
|
||||||
|
"loggable_id": 1,
|
||||||
|
"loggable_type": "bookshelf",
|
||||||
|
"ip": "124.4.x.x",
|
||||||
|
"created_at": "2021-09-29T12:32:02.000000Z",
|
||||||
|
"user": {
|
||||||
|
"id": 1,
|
||||||
|
"name": "Admins",
|
||||||
|
"slug": "admins"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 2,
|
||||||
|
"type": "auth_login",
|
||||||
|
"detail": "standard; (1) Admin",
|
||||||
|
"user_id": 1,
|
||||||
|
"loggable_id": null,
|
||||||
|
"loggable_type": null,
|
||||||
|
"ip": "127.0.x.x",
|
||||||
|
"created_at": "2021-09-29T12:32:04.000000Z",
|
||||||
|
"user": {
|
||||||
|
"id": 1,
|
||||||
|
"name": "Admins",
|
||||||
|
"slug": "admins"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 3,
|
||||||
|
"type": "bookshelf_update",
|
||||||
|
"detail": "",
|
||||||
|
"user_id": 1,
|
||||||
|
"loggable_id": 1,
|
||||||
|
"loggable_type": "bookshelf",
|
||||||
|
"ip": "127.0.x.x",
|
||||||
|
"created_at": "2021-09-29T12:32:07.000000Z",
|
||||||
|
"user": {
|
||||||
|
"id": 1,
|
||||||
|
"name": "Admins",
|
||||||
|
"slug": "admins"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 4,
|
||||||
|
"type": "page_create",
|
||||||
|
"detail": "",
|
||||||
|
"user_id": 1,
|
||||||
|
"loggable_id": 1,
|
||||||
|
"loggable_type": "page",
|
||||||
|
"ip": "127.0.x.x",
|
||||||
|
"created_at": "2021-09-29T12:32:13.000000Z",
|
||||||
|
"user": {
|
||||||
|
"id": 1,
|
||||||
|
"name": "Admins",
|
||||||
|
"slug": "admins"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 5,
|
||||||
|
"type": "page_update",
|
||||||
|
"detail": "",
|
||||||
|
"user_id": 1,
|
||||||
|
"loggable_id": 1,
|
||||||
|
"loggable_type": "page",
|
||||||
|
"ip": "127.0.x.x",
|
||||||
|
"created_at": "2021-09-29T12:37:27.000000Z",
|
||||||
|
"user": {
|
||||||
|
"id": 1,
|
||||||
|
"name": "Admins",
|
||||||
|
"slug": "admins"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"total": 6088
|
||||||
|
}
|
@ -16,12 +16,12 @@
|
|||||||
|
|
||||||
{{ $activity->getText() }}
|
{{ $activity->getText() }}
|
||||||
|
|
||||||
@if($activity->entity && is_null($activity->entity->deleted_at))
|
@if($activity->loggable && is_null($activity->loggable->deleted_at))
|
||||||
<a href="{{ $activity->entity->getUrl() }}">{{ $activity->entity->name }}</a>
|
<a href="{{ $activity->loggable->getUrl() }}">{{ $activity->loggable->name }}</a>
|
||||||
@endif
|
@endif
|
||||||
|
|
||||||
@if($activity->entity && !is_null($activity->entity->deleted_at))
|
@if($activity->loggable && !is_null($activity->loggable->deleted_at))
|
||||||
"{{ $activity->entity->name }}"
|
"{{ $activity->loggable->name }}"
|
||||||
@endif
|
@endif
|
||||||
|
|
||||||
<br>
|
<br>
|
||||||
|
@ -94,8 +94,8 @@
|
|||||||
class="mr-xs hide-over-m">{{ trans('settings.audit_table_event') }}
|
class="mr-xs hide-over-m">{{ trans('settings.audit_table_event') }}
|
||||||
:</strong> {{ $activity->type }}</div>
|
:</strong> {{ $activity->type }}</div>
|
||||||
<div class="flex-3 px-m py-xxs min-width-l">
|
<div class="flex-3 px-m py-xxs min-width-l">
|
||||||
@if($activity->entity)
|
@if($activity->loggable instanceof \BookStack\Entities\Models\Entity)
|
||||||
@include('entities.icon-link', ['entity' => $activity->entity])
|
@include('entities.icon-link', ['entity' => $activity->loggable])
|
||||||
@elseif($activity->detail && $activity->isForEntity())
|
@elseif($activity->detail && $activity->isForEntity())
|
||||||
<div>
|
<div>
|
||||||
{{ trans('settings.audit_deleted_item') }} <br>
|
{{ trans('settings.audit_deleted_item') }} <br>
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
* Controllers all end with "ApiController"
|
* Controllers all end with "ApiController"
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
use BookStack\Activity\Controllers\AuditLogApiController;
|
||||||
use BookStack\Api\ApiDocsController;
|
use BookStack\Api\ApiDocsController;
|
||||||
use BookStack\Entities\Controllers as EntityControllers;
|
use BookStack\Entities\Controllers as EntityControllers;
|
||||||
use BookStack\Permissions\ContentPermissionApiController;
|
use BookStack\Permissions\ContentPermissionApiController;
|
||||||
@ -89,3 +90,5 @@ Route::delete('recycle-bin/{deletionId}', [EntityControllers\RecycleBinApiContro
|
|||||||
|
|
||||||
Route::get('content-permissions/{contentType}/{contentId}', [ContentPermissionApiController::class, 'read']);
|
Route::get('content-permissions/{contentType}/{contentId}', [ContentPermissionApiController::class, 'read']);
|
||||||
Route::put('content-permissions/{contentType}/{contentId}', [ContentPermissionApiController::class, 'update']);
|
Route::put('content-permissions/{contentType}/{contentId}', [ContentPermissionApiController::class, 'update']);
|
||||||
|
|
||||||
|
Route::get('audit-log', [AuditLogApiController::class, 'list']);
|
||||||
|
60
tests/Activity/AuditLogApiTest.php
Normal file
60
tests/Activity/AuditLogApiTest.php
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Activity;
|
||||||
|
|
||||||
|
use BookStack\Activity\ActivityType;
|
||||||
|
use BookStack\Facades\Activity;
|
||||||
|
use Tests\Api\TestsApi;
|
||||||
|
use Tests\TestCase;
|
||||||
|
|
||||||
|
class AuditLogApiTest extends TestCase
|
||||||
|
{
|
||||||
|
use TestsApi;
|
||||||
|
|
||||||
|
public function test_user_and_settings_manage_permissions_needed()
|
||||||
|
{
|
||||||
|
$editor = $this->users->editor();
|
||||||
|
|
||||||
|
$assertPermissionErrorOnCall = function () use ($editor) {
|
||||||
|
$resp = $this->actingAsForApi($editor)->getJson('/api/audit-log');
|
||||||
|
$resp->assertStatus(403);
|
||||||
|
$resp->assertJson($this->permissionErrorResponse());
|
||||||
|
};
|
||||||
|
|
||||||
|
$assertPermissionErrorOnCall();
|
||||||
|
$this->permissions->grantUserRolePermissions($editor, ['users-manage']);
|
||||||
|
$assertPermissionErrorOnCall();
|
||||||
|
$this->permissions->removeUserRolePermissions($editor, ['users-manage']);
|
||||||
|
$this->permissions->grantUserRolePermissions($editor, ['settings-manage']);
|
||||||
|
$assertPermissionErrorOnCall();
|
||||||
|
|
||||||
|
$this->permissions->grantUserRolePermissions($editor, ['settings-manage', 'users-manage']);
|
||||||
|
$resp = $this->actingAsForApi($editor)->getJson('/api/audit-log');
|
||||||
|
$resp->assertOk();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function test_index_endpoint_returns_expected_data()
|
||||||
|
{
|
||||||
|
$page = $this->entities->page();
|
||||||
|
$admin = $this->users->admin();
|
||||||
|
$this->actingAsForApi($admin);
|
||||||
|
Activity::add(ActivityType::PAGE_UPDATE, $page);
|
||||||
|
|
||||||
|
$resp = $this->get("/api/audit-log?filter[loggable_id]={$page->id}");
|
||||||
|
$resp->assertJson(['data' => [
|
||||||
|
[
|
||||||
|
'type' => 'page_update',
|
||||||
|
'detail' => "({$page->id}) {$page->name}",
|
||||||
|
'user_id' => $admin->id,
|
||||||
|
'loggable_id' => $page->id,
|
||||||
|
'loggable_type' => 'page',
|
||||||
|
'ip' => '127.0.0.1',
|
||||||
|
'user' => [
|
||||||
|
'id' => $admin->id,
|
||||||
|
'name' => $admin->name,
|
||||||
|
'slug' => $admin->slug,
|
||||||
|
],
|
||||||
|
]
|
||||||
|
]]);
|
||||||
|
}
|
||||||
|
}
|
@ -1,6 +1,6 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace Tests\Actions;
|
namespace Activity;
|
||||||
|
|
||||||
use BookStack\Activity\ActivityType;
|
use BookStack\Activity\ActivityType;
|
||||||
use BookStack\Activity\Models\Activity;
|
use BookStack\Activity\Models\Activity;
|
||||||
@ -156,7 +156,7 @@ class AuditLogTest extends TestCase
|
|||||||
'type' => ActivityType::PAGE_UPDATE,
|
'type' => ActivityType::PAGE_UPDATE,
|
||||||
'ip' => '192.123.45.1',
|
'ip' => '192.123.45.1',
|
||||||
'user_id' => $editor->id,
|
'user_id' => $editor->id,
|
||||||
'entity_id' => $page->id,
|
'loggable_id' => $page->id,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$resp = $this->asAdmin()->get('/settings/audit');
|
$resp = $this->asAdmin()->get('/settings/audit');
|
||||||
@ -207,7 +207,7 @@ class AuditLogTest extends TestCase
|
|||||||
'type' => ActivityType::PAGE_UPDATE,
|
'type' => ActivityType::PAGE_UPDATE,
|
||||||
'ip' => '127.0.0.1',
|
'ip' => '127.0.0.1',
|
||||||
'user_id' => $editor->id,
|
'user_id' => $editor->id,
|
||||||
'entity_id' => $page->id,
|
'loggable_id' => $page->id,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -229,7 +229,7 @@ class AuditLogTest extends TestCase
|
|||||||
'type' => ActivityType::PAGE_UPDATE,
|
'type' => ActivityType::PAGE_UPDATE,
|
||||||
'ip' => '192.123.x.x',
|
'ip' => '192.123.x.x',
|
||||||
'user_id' => $editor->id,
|
'user_id' => $editor->id,
|
||||||
'entity_id' => $page->id,
|
'loggable_id' => $page->id,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,6 +1,6 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace Tests\Actions;
|
namespace Activity;
|
||||||
|
|
||||||
use BookStack\Activity\ActivityType;
|
use BookStack\Activity\ActivityType;
|
||||||
use BookStack\Activity\DispatchWebhookJob;
|
use BookStack\Activity\DispatchWebhookJob;
|
@ -1,6 +1,6 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace Tests\Actions;
|
namespace Activity;
|
||||||
|
|
||||||
use BookStack\Activity\ActivityType;
|
use BookStack\Activity\ActivityType;
|
||||||
use BookStack\Activity\Models\Webhook;
|
use BookStack\Activity\Models\Webhook;
|
@ -1,6 +1,6 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace Tests\Actions;
|
namespace Activity;
|
||||||
|
|
||||||
use BookStack\Activity\ActivityType;
|
use BookStack\Activity\ActivityType;
|
||||||
use BookStack\Activity\Models\Webhook;
|
use BookStack\Activity\Models\Webhook;
|
@ -18,7 +18,7 @@ class ClearActivityCommandTest extends TestCase
|
|||||||
|
|
||||||
$this->assertDatabaseHas('activities', [
|
$this->assertDatabaseHas('activities', [
|
||||||
'type' => 'page_update',
|
'type' => 'page_update',
|
||||||
'entity_id' => $page->id,
|
'loggable_id' => $page->id,
|
||||||
'user_id' => $this->users->editor()->id,
|
'user_id' => $this->users->editor()->id,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
@ -153,22 +153,22 @@ class RecycleBinTest extends TestCase
|
|||||||
|
|
||||||
$this->assertDatabaseHas('activities', [
|
$this->assertDatabaseHas('activities', [
|
||||||
'type' => 'page_delete',
|
'type' => 'page_delete',
|
||||||
'entity_id' => $page->id,
|
'loggable_id' => $page->id,
|
||||||
'entity_type' => $page->getMorphClass(),
|
'loggable_type' => $page->getMorphClass(),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$this->asAdmin()->delete("/settings/recycle-bin/{$deletion->id}");
|
$this->asAdmin()->delete("/settings/recycle-bin/{$deletion->id}");
|
||||||
|
|
||||||
$this->assertDatabaseMissing('activities', [
|
$this->assertDatabaseMissing('activities', [
|
||||||
'type' => 'page_delete',
|
'type' => 'page_delete',
|
||||||
'entity_id' => $page->id,
|
'loggable_id' => $page->id,
|
||||||
'entity_type' => $page->getMorphClass(),
|
'loggable_type' => $page->getMorphClass(),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$this->assertDatabaseHas('activities', [
|
$this->assertDatabaseHas('activities', [
|
||||||
'type' => 'page_delete',
|
'type' => 'page_delete',
|
||||||
'entity_id' => null,
|
'loggable_id' => null,
|
||||||
'entity_type' => null,
|
'loggable_type' => null,
|
||||||
'detail' => $page->name,
|
'detail' => $page->name,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
@ -248,8 +248,8 @@ abstract class TestCase extends BaseTestCase
|
|||||||
$detailsToCheck = ['type' => $type];
|
$detailsToCheck = ['type' => $type];
|
||||||
|
|
||||||
if ($entity) {
|
if ($entity) {
|
||||||
$detailsToCheck['entity_type'] = $entity->getMorphClass();
|
$detailsToCheck['loggable_type'] = $entity->getMorphClass();
|
||||||
$detailsToCheck['entity_id'] = $entity->id;
|
$detailsToCheck['loggable_id'] = $entity->id;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($detail) {
|
if ($detail) {
|
||||||
|
@ -2,8 +2,8 @@
|
|||||||
|
|
||||||
namespace Tests\User;
|
namespace Tests\User;
|
||||||
|
|
||||||
use Activity;
|
|
||||||
use BookStack\Activity\ActivityType;
|
use BookStack\Activity\ActivityType;
|
||||||
|
use BookStack\Facades\Activity;
|
||||||
use BookStack\Users\Models\User;
|
use BookStack\Users\Models\User;
|
||||||
use Tests\TestCase;
|
use Tests\TestCase;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user