Refactored the activity service

- Renamed to "ActivityLogger" to be more focused in usage.
- Extracted out query elements to seperate "ActivityQueries" class.
- Removed old 'addForEntity' activity method to limit activity record
  points.
This commit is contained in:
Dan Brown
2021-12-11 17:29:33 +00:00
parent f2cb3b94f9
commit 9079700170
21 changed files with 166 additions and 153 deletions

View File

@ -0,0 +1,95 @@
<?php
namespace BookStack\Actions;
use BookStack\Auth\Permissions\PermissionService;
use BookStack\Entities\Models\Entity;
use BookStack\Interfaces\Loggable;
use Illuminate\Support\Facades\Log;
class ActivityLogger
{
protected $permissionService;
public function __construct(PermissionService $permissionService)
{
$this->permissionService = $permissionService;
}
/**
* Add a generic activity event to the database.
*
* @param string|Loggable $detail
*/
public function add(string $type, $detail = '')
{
$detailToStore = ($detail instanceof Loggable) ? $detail->logDescriptor() : $detail;
$activity = $this->newActivityForUser($type);
$activity->detail = $detailToStore;
if ($detail instanceof Entity) {
$activity->entity_id = $detail->id;
$activity->entity_type = $detail->getMorphClass();
}
$activity->save();
$this->setNotification($type);
}
/**
* Get a new activity instance for the current user.
*/
protected function newActivityForUser(string $type): Activity
{
$ip = request()->ip() ?? '';
return (new Activity())->forceFill([
'type' => strtolower($type),
'user_id' => user()->id,
'ip' => config('app.env') === 'demo' ? '127.0.0.1' : $ip,
]);
}
/**
* Removes the entity attachment from each of its activities
* and instead uses the 'extra' field with the entities name.
* Used when an entity is deleted.
*/
public function removeEntity(Entity $entity)
{
$entity->activity()->update([
'detail' => $entity->name,
'entity_id' => null,
'entity_type' => null,
]);
}
/**
* Flashes a notification message to the session if an appropriate message is available.
*/
protected function setNotification(string $type)
{
$notificationTextKey = 'activities.' . $type . '_notification';
if (trans()->has($notificationTextKey)) {
$message = trans($notificationTextKey);
session()->flash('success', $message);
}
}
/**
* Log out a failed login attempt, Providing the given username
* as part of the message if the '%u' string is used.
*/
public function logFailedLogin(string $username)
{
$message = config('logging.failed_login.message');
if (!$message) {
return;
}
$message = str_replace('%u', $username, $message);
$channel = config('logging.failed_login.channel');
Log::channel($channel)->warning($message);
}
}

View File

@ -8,84 +8,25 @@ use BookStack\Entities\Models\Book;
use BookStack\Entities\Models\Chapter; use BookStack\Entities\Models\Chapter;
use BookStack\Entities\Models\Entity; use BookStack\Entities\Models\Entity;
use BookStack\Entities\Models\Page; use BookStack\Entities\Models\Page;
use BookStack\Interfaces\Loggable;
use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Relations\Relation; use Illuminate\Database\Eloquent\Relations\Relation;
use Illuminate\Support\Facades\Log;
class ActivityService class ActivityQueries
{ {
protected $activity;
protected $permissionService; protected $permissionService;
public function __construct(Activity $activity, PermissionService $permissionService) public function __construct(PermissionService $permissionService)
{ {
$this->activity = $activity;
$this->permissionService = $permissionService; $this->permissionService = $permissionService;
} }
/**
* Add activity data to database for an entity.
*/
public function addForEntity(Entity $entity, string $type)
{
$activity = $this->newActivityForUser($type);
$entity->activity()->save($activity);
$this->setNotification($type);
}
/**
* Add a generic activity event to the database.
*
* @param string|Loggable $detail
*/
public function add(string $type, $detail = '')
{
if ($detail instanceof Loggable) {
$detail = $detail->logDescriptor();
}
$activity = $this->newActivityForUser($type);
$activity->detail = $detail;
$activity->save();
$this->setNotification($type);
}
/**
* Get a new activity instance for the current user.
*/
protected function newActivityForUser(string $type): Activity
{
$ip = request()->ip() ?? '';
return $this->activity->newInstance()->forceFill([
'type' => strtolower($type),
'user_id' => user()->id,
'ip' => config('app.env') === 'demo' ? '127.0.0.1' : $ip,
]);
}
/**
* Removes the entity attachment from each of its activities
* and instead uses the 'extra' field with the entities name.
* Used when an entity is deleted.
*/
public function removeEntity(Entity $entity)
{
$entity->activity()->update([
'detail' => $entity->name,
'entity_id' => null,
'entity_type' => null,
]);
}
/** /**
* Gets the latest activity. * Gets the latest activity.
*/ */
public function latest(int $count = 20, int $page = 0): array public function latest(int $count = 20, int $page = 0): array
{ {
$activityList = $this->permissionService $activityList = $this->permissionService
->filterRestrictedEntityRelations($this->activity->newQuery(), 'activities', 'entity_id', 'entity_type') ->filterRestrictedEntityRelations(Activity::query(), 'activities', 'entity_id', 'entity_type')
->orderBy('created_at', 'desc') ->orderBy('created_at', 'desc')
->with(['user', 'entity']) ->with(['user', 'entity'])
->skip($count * $page) ->skip($count * $page)
@ -111,7 +52,7 @@ class ActivityService
$queryIds[(new Page())->getMorphClass()] = $entity->pages()->scopes('visible')->pluck('id'); $queryIds[(new Page())->getMorphClass()] = $entity->pages()->scopes('visible')->pluck('id');
} }
$query = $this->activity->newQuery(); $query = Activity::query();
$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) {
@ -138,7 +79,7 @@ class ActivityService
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->permissionService $activityList = $this->permissionService
->filterRestrictedEntityRelations($this->activity->newQuery(), 'activities', 'entity_id', 'entity_type') ->filterRestrictedEntityRelations(Activity::query(), 'activities', 'entity_id', 'entity_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)
@ -152,8 +93,6 @@ class ActivityService
* Filters out similar activity. * Filters out similar activity.
* *
* @param Activity[] $activities * @param Activity[] $activities
*
* @return array
*/ */
protected function filterSimilar(iterable $activities): array protected function filterSimilar(iterable $activities): array
{ {
@ -171,31 +110,4 @@ class ActivityService
return $newActivity; return $newActivity;
} }
/** }
* Flashes a notification message to the session if an appropriate message is available.
*/
protected function setNotification(string $type)
{
$notificationTextKey = 'activities.' . $type . '_notification';
if (trans()->has($notificationTextKey)) {
$message = trans($notificationTextKey);
session()->flash('success', $message);
}
}
/**
* Log out a failed login attempt, Providing the given username
* as part of the message if the '%u' string is used.
*/
public function logFailedLogin(string $username)
{
$message = config('logging.failed_login.message');
if (!$message) {
return;
}
$message = str_replace('%u', $username, $message);
$channel = config('logging.failed_login.channel');
Log::channel($channel)->warning($message);
}
}

View File

@ -45,7 +45,7 @@ class CommentRepo
$comment->parent_id = $parent_id; $comment->parent_id = $parent_id;
$entity->comments()->save($comment); $entity->comments()->save($comment);
ActivityService::addForEntity($entity, ActivityType::COMMENTED_ON); ActivityService::add(ActivityType::COMMENTED_ON, $entity);
return $comment; return $comment;
} }

View File

@ -2,7 +2,6 @@
namespace BookStack\Auth; namespace BookStack\Auth;
use Activity;
use BookStack\Entities\EntityProvider; use BookStack\Entities\EntityProvider;
use BookStack\Entities\Models\Book; use BookStack\Entities\Models\Book;
use BookStack\Entities\Models\Bookshelf; use BookStack\Entities\Models\Bookshelf;
@ -215,14 +214,6 @@ class UserRepo
} }
} }
/**
* Get the latest activity for a user.
*/
public function getActivity(User $user, int $count = 20, int $page = 0): array
{
return Activity::userActivity($user, $count, $page);
}
/** /**
* Get the recently created content for this given user. * Get the recently created content for this given user.
*/ */

View File

@ -14,6 +14,7 @@ use BookStack\Entities\Tools\SlugGenerator;
use BookStack\Facades\Permissions; use BookStack\Facades\Permissions;
use BookStack\Interfaces\Deletable; use BookStack\Interfaces\Deletable;
use BookStack\Interfaces\Favouritable; use BookStack\Interfaces\Favouritable;
use BookStack\Interfaces\Loggable;
use BookStack\Interfaces\Sluggable; use BookStack\Interfaces\Sluggable;
use BookStack\Interfaces\Viewable; use BookStack\Interfaces\Viewable;
use BookStack\Model; use BookStack\Model;
@ -45,7 +46,7 @@ use Illuminate\Database\Eloquent\SoftDeletes;
* @method static Builder withLastView() * @method static Builder withLastView()
* @method static Builder withViewCount() * @method static Builder withViewCount()
*/ */
abstract class Entity extends Model implements Sluggable, Favouritable, Viewable, Deletable abstract class Entity extends Model implements Sluggable, Favouritable, Viewable, Deletable, Loggable
{ {
use SoftDeletes; use SoftDeletes;
use HasCreatorAndUpdater; use HasCreatorAndUpdater;
@ -321,4 +322,12 @@ abstract class Entity extends Model implements Sluggable, Favouritable, Viewable
->where('user_id', '=', user()->id) ->where('user_id', '=', user()->id)
->exists(); ->exists();
} }
/**
* {@inheritdoc}
*/
public function logDescriptor(): string
{
return "({$this->id}) {$this->name}";
}
} }

View File

@ -91,7 +91,7 @@ class BookRepo
{ {
$book = new Book(); $book = new Book();
$this->baseRepo->create($book, $input); $this->baseRepo->create($book, $input);
Activity::addForEntity($book, ActivityType::BOOK_CREATE); Activity::add(ActivityType::BOOK_CREATE, $book);
return $book; return $book;
} }
@ -102,7 +102,7 @@ class BookRepo
public function update(Book $book, array $input): Book public function update(Book $book, array $input): Book
{ {
$this->baseRepo->update($book, $input); $this->baseRepo->update($book, $input);
Activity::addForEntity($book, ActivityType::BOOK_UPDATE); Activity::add(ActivityType::BOOK_UPDATE, $book);
return $book; return $book;
} }
@ -127,7 +127,7 @@ class BookRepo
{ {
$trashCan = new TrashCan(); $trashCan = new TrashCan();
$trashCan->softDestroyBook($book); $trashCan->softDestroyBook($book);
Activity::addForEntity($book, ActivityType::BOOK_DELETE); Activity::add(ActivityType::BOOK_DELETE, $book);
$trashCan->autoClearOld(); $trashCan->autoClearOld();
} }

View File

@ -90,7 +90,7 @@ class BookshelfRepo
$shelf = new Bookshelf(); $shelf = new Bookshelf();
$this->baseRepo->create($shelf, $input); $this->baseRepo->create($shelf, $input);
$this->updateBooks($shelf, $bookIds); $this->updateBooks($shelf, $bookIds);
Activity::addForEntity($shelf, ActivityType::BOOKSHELF_CREATE); Activity::add(ActivityType::BOOKSHELF_CREATE, $shelf);
return $shelf; return $shelf;
} }
@ -106,7 +106,7 @@ class BookshelfRepo
$this->updateBooks($shelf, $bookIds); $this->updateBooks($shelf, $bookIds);
} }
Activity::addForEntity($shelf, ActivityType::BOOKSHELF_UPDATE); Activity::add(ActivityType::BOOKSHELF_UPDATE, $shelf);
return $shelf; return $shelf;
} }
@ -177,7 +177,7 @@ class BookshelfRepo
{ {
$trashCan = new TrashCan(); $trashCan = new TrashCan();
$trashCan->softDestroyShelf($shelf); $trashCan->softDestroyShelf($shelf);
Activity::addForEntity($shelf, ActivityType::BOOKSHELF_DELETE); Activity::add(ActivityType::BOOKSHELF_DELETE, $shelf);
$trashCan->autoClearOld(); $trashCan->autoClearOld();
} }
} }

View File

@ -49,7 +49,7 @@ class ChapterRepo
$chapter->book_id = $parentBook->id; $chapter->book_id = $parentBook->id;
$chapter->priority = (new BookContents($parentBook))->getLastPriority() + 1; $chapter->priority = (new BookContents($parentBook))->getLastPriority() + 1;
$this->baseRepo->create($chapter, $input); $this->baseRepo->create($chapter, $input);
Activity::addForEntity($chapter, ActivityType::CHAPTER_CREATE); Activity::add(ActivityType::CHAPTER_CREATE, $chapter);
return $chapter; return $chapter;
} }
@ -60,7 +60,7 @@ class ChapterRepo
public function update(Chapter $chapter, array $input): Chapter public function update(Chapter $chapter, array $input): Chapter
{ {
$this->baseRepo->update($chapter, $input); $this->baseRepo->update($chapter, $input);
Activity::addForEntity($chapter, ActivityType::CHAPTER_UPDATE); Activity::add(ActivityType::CHAPTER_UPDATE, $chapter);
return $chapter; return $chapter;
} }
@ -74,7 +74,7 @@ class ChapterRepo
{ {
$trashCan = new TrashCan(); $trashCan = new TrashCan();
$trashCan->softDestroyChapter($chapter); $trashCan->softDestroyChapter($chapter);
Activity::addForEntity($chapter, ActivityType::CHAPTER_DELETE); Activity::add(ActivityType::CHAPTER_DELETE, $chapter);
$trashCan->autoClearOld(); $trashCan->autoClearOld();
} }
@ -103,7 +103,7 @@ class ChapterRepo
$chapter->changeBook($parent->id); $chapter->changeBook($parent->id);
$chapter->rebuildPermissions(); $chapter->rebuildPermissions();
Activity::addForEntity($chapter, ActivityType::CHAPTER_MOVE); Activity::add(ActivityType::CHAPTER_MOVE, $chapter);
return $parent; return $parent;
} }

View File

@ -171,7 +171,7 @@ class PageRepo
$draft->indexForSearch(); $draft->indexForSearch();
$draft->refresh(); $draft->refresh();
Activity::addForEntity($draft, ActivityType::PAGE_CREATE); Activity::add(ActivityType::PAGE_CREATE, $draft);
return $draft; return $draft;
} }
@ -205,7 +205,7 @@ class PageRepo
$this->savePageRevision($page, $summary); $this->savePageRevision($page, $summary);
} }
Activity::addForEntity($page, ActivityType::PAGE_UPDATE); Activity::add(ActivityType::PAGE_UPDATE, $page);
return $page; return $page;
} }
@ -281,7 +281,7 @@ class PageRepo
{ {
$trashCan = new TrashCan(); $trashCan = new TrashCan();
$trashCan->softDestroyPage($page); $trashCan->softDestroyPage($page);
Activity::addForEntity($page, ActivityType::PAGE_DELETE); Activity::add(ActivityType::PAGE_DELETE, $page);
$trashCan->autoClearOld(); $trashCan->autoClearOld();
} }
@ -312,7 +312,7 @@ class PageRepo
$summary = trans('entities.pages_revision_restored_from', ['id' => strval($revisionId), 'summary' => $revision->summary]); $summary = trans('entities.pages_revision_restored_from', ['id' => strval($revisionId), 'summary' => $revision->summary]);
$this->savePageRevision($page, $summary); $this->savePageRevision($page, $summary);
Activity::addForEntity($page, ActivityType::PAGE_RESTORE); Activity::add(ActivityType::PAGE_RESTORE, $page);
return $page; return $page;
} }
@ -341,7 +341,7 @@ class PageRepo
$page->changeBook($newBookId); $page->changeBook($newBookId);
$page->rebuildPermissions(); $page->rebuildPermissions();
Activity::addForEntity($page, ActivityType::PAGE_MOVE); Activity::add(ActivityType::PAGE_MOVE, $page);
return $parent; return $parent;
} }

View File

@ -35,7 +35,7 @@ class PermissionsUpdater
$entity->save(); $entity->save();
$entity->rebuildPermissions(); $entity->rebuildPermissions();
Activity::addForEntity($entity, ActivityType::PERMISSIONS_UPDATE); Activity::add(ActivityType::PERMISSIONS_UPDATE, $entity);
} }
/** /**

View File

@ -2,11 +2,11 @@
namespace BookStack\Http\Controllers\Auth; namespace BookStack\Http\Controllers\Auth;
use Activity;
use BookStack\Auth\Access\LoginService; use BookStack\Auth\Access\LoginService;
use BookStack\Auth\Access\SocialAuthService; use BookStack\Auth\Access\SocialAuthService;
use BookStack\Exceptions\LoginAttemptEmailNeededException; use BookStack\Exceptions\LoginAttemptEmailNeededException;
use BookStack\Exceptions\LoginAttemptException; use BookStack\Exceptions\LoginAttemptException;
use BookStack\Facades\Activity;
use BookStack\Http\Controllers\Controller; use BookStack\Http\Controllers\Controller;
use Illuminate\Foundation\Auth\AuthenticatesUsers; use Illuminate\Foundation\Auth\AuthenticatesUsers;
use Illuminate\Http\Request; use Illuminate\Http\Request;

View File

@ -3,6 +3,7 @@
namespace BookStack\Http\Controllers; namespace BookStack\Http\Controllers;
use Activity; use Activity;
use BookStack\Actions\ActivityQueries;
use BookStack\Actions\ActivityType; use BookStack\Actions\ActivityType;
use BookStack\Actions\View; use BookStack\Actions\View;
use BookStack\Entities\Models\Bookshelf; use BookStack\Entities\Models\Bookshelf;
@ -101,7 +102,7 @@ class BookController extends Controller
if ($bookshelf) { if ($bookshelf) {
$bookshelf->appendBook($book); $bookshelf->appendBook($book);
Activity::addForEntity($bookshelf, ActivityType::BOOKSHELF_UPDATE); Activity::add(ActivityType::BOOKSHELF_UPDATE, $bookshelf);
} }
return redirect($book->getUrl()); return redirect($book->getUrl());
@ -110,7 +111,7 @@ class BookController extends Controller
/** /**
* Display the specified book. * Display the specified book.
*/ */
public function show(Request $request, string $slug) public function show(Request $request, ActivityQueries $activities, string $slug)
{ {
$book = $this->bookRepo->getBySlug($slug); $book = $this->bookRepo->getBySlug($slug);
$bookChildren = (new BookContents($book))->getTree(true); $bookChildren = (new BookContents($book))->getTree(true);
@ -128,7 +129,7 @@ class BookController extends Controller
'current' => $book, 'current' => $book,
'bookChildren' => $bookChildren, 'bookChildren' => $bookChildren,
'bookParentShelves' => $bookParentShelves, 'bookParentShelves' => $bookParentShelves,
'activity' => Activity::entityActivity($book, 20, 1), 'activity' => $activities->entityActivity($book, 20, 1),
]); ]);
} }

View File

@ -71,7 +71,7 @@ class BookSortController extends Controller
// Rebuild permissions and add activity for involved books. // Rebuild permissions and add activity for involved books.
$booksInvolved->each(function (Book $book) { $booksInvolved->each(function (Book $book) {
Activity::addForEntity($book, ActivityType::BOOK_SORT); Activity::add(ActivityType::BOOK_SORT, $book);
}); });
return redirect($book->getUrl()); return redirect($book->getUrl());

View File

@ -3,6 +3,7 @@
namespace BookStack\Http\Controllers; namespace BookStack\Http\Controllers;
use Activity; use Activity;
use BookStack\Actions\ActivityQueries;
use BookStack\Actions\View; use BookStack\Actions\View;
use BookStack\Entities\Models\Book; use BookStack\Entities\Models\Book;
use BookStack\Entities\Repos\BookshelfRepo; use BookStack\Entities\Repos\BookshelfRepo;
@ -101,7 +102,7 @@ class BookshelfController extends Controller
* *
* @throws NotFoundException * @throws NotFoundException
*/ */
public function show(string $slug) public function show(ActivityQueries $activities, string $slug)
{ {
$shelf = $this->bookshelfRepo->getBySlug($slug); $shelf = $this->bookshelfRepo->getBySlug($slug);
$this->checkOwnablePermission('book-view', $shelf); $this->checkOwnablePermission('book-view', $shelf);
@ -124,7 +125,7 @@ class BookshelfController extends Controller
'shelf' => $shelf, 'shelf' => $shelf,
'sortedVisibleShelfBooks' => $sortedVisibleShelfBooks, 'sortedVisibleShelfBooks' => $sortedVisibleShelfBooks,
'view' => $view, 'view' => $view,
'activity' => Activity::entityActivity($shelf, 20, 1), 'activity' => $activities->entityActivity($shelf, 20, 1),
'order' => $order, 'order' => $order,
'sort' => $sort, 'sort' => $sort,
]); ]);

View File

@ -2,7 +2,7 @@
namespace BookStack\Http\Controllers; namespace BookStack\Http\Controllers;
use Activity; use BookStack\Actions\ActivityQueries;
use BookStack\Entities\Models\Book; use BookStack\Entities\Models\Book;
use BookStack\Entities\Models\Page; use BookStack\Entities\Models\Page;
use BookStack\Entities\Queries\RecentlyViewed; use BookStack\Entities\Queries\RecentlyViewed;
@ -16,9 +16,9 @@ class HomeController extends Controller
/** /**
* Display the homepage. * Display the homepage.
*/ */
public function index() public function index(ActivityQueries $activities)
{ {
$activity = Activity::latest(10); $activity = $activities->latest(10);
$draftPages = []; $draftPages = [];
if ($this->isSignedIn()) { if ($this->isSignedIn()) {

View File

@ -2,6 +2,7 @@
namespace BookStack\Http\Controllers; namespace BookStack\Http\Controllers;
use BookStack\Actions\ActivityQueries;
use BookStack\Auth\UserRepo; use BookStack\Auth\UserRepo;
class UserProfileController extends Controller class UserProfileController extends Controller
@ -9,11 +10,11 @@ class UserProfileController extends Controller
/** /**
* Show the user profile page. * Show the user profile page.
*/ */
public function show(UserRepo $repo, string $slug) public function show(UserRepo $repo, ActivityQueries $activities, string $slug)
{ {
$user = $repo->getBySlug($slug); $user = $repo->getBySlug($slug);
$userActivity = $repo->getActivity($user); $userActivity = $activities->userActivity($user);
$recentlyCreated = $repo->getRecentlyCreated($user, 5); $recentlyCreated = $repo->getRecentlyCreated($user, 5);
$assetCounts = $repo->getAssetCounts($user); $assetCounts = $repo->getAssetCounts($user);

View File

@ -2,7 +2,7 @@
namespace BookStack\Providers; namespace BookStack\Providers;
use BookStack\Actions\ActivityService; use BookStack\Actions\ActivityLogger;
use BookStack\Auth\Permissions\PermissionService; use BookStack\Auth\Permissions\PermissionService;
use BookStack\Theming\ThemeService; use BookStack\Theming\ThemeService;
use BookStack\Uploads\ImageService; use BookStack\Uploads\ImageService;
@ -28,7 +28,7 @@ class CustomFacadeProvider extends ServiceProvider
public function register() public function register()
{ {
$this->app->singleton('activity', function () { $this->app->singleton('activity', function () {
return $this->app->make(ActivityService::class); return $this->app->make(ActivityLogger::class);
}); });
$this->app->singleton('images', function () { $this->app->singleton('images', function () {

View File

@ -1,6 +1,6 @@
<?php <?php
namespace Database\Factories; namespace Database\Factories\Actions;
use BookStack\Actions\ActivityType; use BookStack\Actions\ActivityType;
use BookStack\Actions\Webhook; use BookStack\Actions\Webhook;

View File

@ -3,7 +3,7 @@
namespace Tests\Actions; namespace Tests\Actions;
use BookStack\Actions\Activity; use BookStack\Actions\Activity;
use BookStack\Actions\ActivityService; use BookStack\Actions\ActivityLogger;
use BookStack\Actions\ActivityType; use BookStack\Actions\ActivityType;
use BookStack\Auth\UserRepo; use BookStack\Auth\UserRepo;
use BookStack\Entities\Models\Chapter; use BookStack\Entities\Models\Chapter;
@ -17,13 +17,13 @@ use function config;
class AuditLogTest extends TestCase class AuditLogTest extends TestCase
{ {
/** @var ActivityService */ /** @var ActivityLogger */
protected $activityService; protected $activityService;
protected function setUp(): void protected function setUp(): void
{ {
parent::setUp(); parent::setUp();
$this->activityService = app(ActivityService::class); $this->activityService = app(ActivityLogger::class);
} }
public function test_only_accessible_with_right_permissions() public function test_only_accessible_with_right_permissions()
@ -49,7 +49,7 @@ class AuditLogTest extends TestCase
$admin = $this->getAdmin(); $admin = $this->getAdmin();
$this->actingAs($admin); $this->actingAs($admin);
$page = Page::query()->first(); $page = Page::query()->first();
$this->activityService->addForEntity($page, ActivityType::PAGE_CREATE); $this->activityService->add(ActivityType::PAGE_CREATE, $page);
$activity = Activity::query()->orderBy('id', 'desc')->first(); $activity = Activity::query()->orderBy('id', 'desc')->first();
$resp = $this->get('settings/audit'); $resp = $this->get('settings/audit');
@ -64,7 +64,7 @@ class AuditLogTest extends TestCase
$this->actingAs($this->getAdmin()); $this->actingAs($this->getAdmin());
$page = Page::query()->first(); $page = Page::query()->first();
$pageName = $page->name; $pageName = $page->name;
$this->activityService->addForEntity($page, ActivityType::PAGE_CREATE); $this->activityService->add(ActivityType::PAGE_CREATE, $page);
app(PageRepo::class)->destroy($page); app(PageRepo::class)->destroy($page);
app(TrashCan::class)->empty(); app(TrashCan::class)->empty();
@ -79,7 +79,7 @@ class AuditLogTest extends TestCase
$viewer = $this->getViewer(); $viewer = $this->getViewer();
$this->actingAs($viewer); $this->actingAs($viewer);
$page = Page::query()->first(); $page = Page::query()->first();
$this->activityService->addForEntity($page, ActivityType::PAGE_CREATE); $this->activityService->add(ActivityType::PAGE_CREATE, $page);
$this->actingAs($this->getAdmin()); $this->actingAs($this->getAdmin());
app(UserRepo::class)->destroy($viewer); app(UserRepo::class)->destroy($viewer);
@ -92,7 +92,7 @@ class AuditLogTest extends TestCase
{ {
$this->actingAs($this->getAdmin()); $this->actingAs($this->getAdmin());
$page = Page::query()->first(); $page = Page::query()->first();
$this->activityService->addForEntity($page, ActivityType::PAGE_CREATE); $this->activityService->add(ActivityType::PAGE_CREATE, $page);
$resp = $this->get('settings/audit'); $resp = $this->get('settings/audit');
$resp->assertSeeText($page->name); $resp->assertSeeText($page->name);
@ -105,7 +105,7 @@ class AuditLogTest extends TestCase
{ {
$this->actingAs($this->getAdmin()); $this->actingAs($this->getAdmin());
$page = Page::query()->first(); $page = Page::query()->first();
$this->activityService->addForEntity($page, ActivityType::PAGE_CREATE); $this->activityService->add(ActivityType::PAGE_CREATE, $page);
$yesterday = (Carbon::now()->subDay()->format('Y-m-d')); $yesterday = (Carbon::now()->subDay()->format('Y-m-d'));
$tomorrow = (Carbon::now()->addDay()->format('Y-m-d')); $tomorrow = (Carbon::now()->addDay()->format('Y-m-d'));
@ -129,11 +129,11 @@ class AuditLogTest extends TestCase
$editor = $this->getEditor(); $editor = $this->getEditor();
$this->actingAs($admin); $this->actingAs($admin);
$page = Page::query()->first(); $page = Page::query()->first();
$this->activityService->addForEntity($page, ActivityType::PAGE_CREATE); $this->activityService->add(ActivityType::PAGE_CREATE, $page);
$this->actingAs($editor); $this->actingAs($editor);
$chapter = Chapter::query()->first(); $chapter = Chapter::query()->first();
$this->activityService->addForEntity($chapter, ActivityType::CHAPTER_UPDATE); $this->activityService->add(ActivityType::CHAPTER_UPDATE, $chapter);
$resp = $this->actingAs($admin)->get('settings/audit?user=' . $admin->id); $resp = $this->actingAs($admin)->get('settings/audit?user=' . $admin->id);
$resp->assertSeeText($page->name); $resp->assertSeeText($page->name);

View File

@ -4,6 +4,8 @@ namespace Tests\Commands;
use BookStack\Actions\ActivityType; use BookStack\Actions\ActivityType;
use BookStack\Entities\Models\Page; use BookStack\Entities\Models\Page;
use BookStack\Facades\Activity;
use Illuminate\Support\Facades\Artisan;
use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\DB;
use Tests\TestCase; use Tests\TestCase;
@ -12,8 +14,9 @@ class ClearActivityCommandTest extends TestCase
public function test_clear_activity_command() public function test_clear_activity_command()
{ {
$this->asEditor(); $this->asEditor();
$page = Page::first(); /** @var Page $page */
\Activity::addForEntity($page, ActivityType::PAGE_UPDATE); $page = Page::query()->first();
Activity::add(ActivityType::PAGE_UPDATE, $page);
$this->assertDatabaseHas('activities', [ $this->assertDatabaseHas('activities', [
'type' => 'page_update', 'type' => 'page_update',
@ -22,7 +25,7 @@ class ClearActivityCommandTest extends TestCase
]); ]);
DB::rollBack(); DB::rollBack();
$exitCode = \Artisan::call('bookstack:clear-activity'); $exitCode = Artisan::call('bookstack:clear-activity');
DB::beginTransaction(); DB::beginTransaction();
$this->assertTrue($exitCode === 0, 'Command executed successfully'); $this->assertTrue($exitCode === 0, 'Command executed successfully');

View File

@ -64,8 +64,8 @@ class UserProfileTest extends TestCase
$newUser = User::factory()->create(); $newUser = User::factory()->create();
$this->actingAs($newUser); $this->actingAs($newUser);
$entities = $this->createEntityChainBelongingToUser($newUser, $newUser); $entities = $this->createEntityChainBelongingToUser($newUser, $newUser);
Activity::addForEntity($entities['book'], ActivityType::BOOK_UPDATE); Activity::add(ActivityType::BOOK_UPDATE, $entities['book']);
Activity::addForEntity($entities['page'], ActivityType::PAGE_CREATE); Activity::add(ActivityType::PAGE_CREATE, $entities['page']);
$this->asAdmin()->get('/user/' . $newUser->slug) $this->asAdmin()->get('/user/' . $newUser->slug)
->assertElementContains('#recent-user-activity', 'updated book') ->assertElementContains('#recent-user-activity', 'updated book')
@ -78,8 +78,8 @@ class UserProfileTest extends TestCase
$newUser = User::factory()->create(); $newUser = User::factory()->create();
$this->actingAs($newUser); $this->actingAs($newUser);
$entities = $this->createEntityChainBelongingToUser($newUser, $newUser); $entities = $this->createEntityChainBelongingToUser($newUser, $newUser);
Activity::addForEntity($entities['book'], ActivityType::BOOK_UPDATE); Activity::add(ActivityType::BOOK_UPDATE, $entities['book']);
Activity::addForEntity($entities['page'], ActivityType::PAGE_CREATE); Activity::add(ActivityType::PAGE_CREATE, $entities['page']);
$linkSelector = '#recent-activity a[href$="/user/' . $newUser->slug . '"]'; $linkSelector = '#recent-activity a[href$="/user/' . $newUser->slug . '"]';
$this->asAdmin()->get('/') $this->asAdmin()->get('/')