mirror of
https://github.com/BookStackApp/BookStack.git
synced 2025-06-07 03:14:33 +08:00
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:
95
app/Actions/ActivityLogger.php
Normal file
95
app/Actions/ActivityLogger.php
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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.
|
||||||
*/
|
*/
|
||||||
|
@ -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}";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -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();
|
||||||
}
|
}
|
||||||
|
@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -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;
|
||||||
|
@ -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),
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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());
|
||||||
|
@ -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,
|
||||||
]);
|
]);
|
||||||
|
@ -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()) {
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
@ -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 () {
|
||||||
|
@ -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;
|
||||||
|
@ -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);
|
||||||
|
@ -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');
|
||||||
|
|
||||||
|
@ -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('/')
|
||||||
|
Reference in New Issue
Block a user