forked from BookStackApp/BookStack
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
435 changed files
with
6,701 additions
and
1,020 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
<?php | ||
|
||
namespace BookStack\Activity\Controllers; | ||
|
||
use BookStack\Activity\Tools\UserEntityWatchOptions; | ||
use BookStack\App\Model; | ||
use BookStack\Entities\Models\Entity; | ||
use BookStack\Http\Controller; | ||
use Exception; | ||
use Illuminate\Http\Request; | ||
use Illuminate\Validation\ValidationException; | ||
|
||
class WatchController extends Controller | ||
{ | ||
public function update(Request $request) | ||
{ | ||
$this->checkPermission('receive-notifications'); | ||
$this->preventGuestAccess(); | ||
|
||
$requestData = $this->validate($request, [ | ||
'level' => ['required', 'string'], | ||
]); | ||
|
||
$watchable = $this->getValidatedModelFromRequest($request); | ||
$watchOptions = new UserEntityWatchOptions(user(), $watchable); | ||
$watchOptions->updateLevelByName($requestData['level']); | ||
|
||
$this->showSuccessNotification(trans('activities.watch_update_level_notification')); | ||
|
||
return redirect()->back(); | ||
} | ||
|
||
/** | ||
* @throws ValidationException | ||
* @throws Exception | ||
*/ | ||
protected function getValidatedModelFromRequest(Request $request): Entity | ||
{ | ||
$modelInfo = $this->validate($request, [ | ||
'type' => ['required', 'string'], | ||
'id' => ['required', 'integer'], | ||
]); | ||
|
||
if (!class_exists($modelInfo['type'])) { | ||
throw new Exception('Model not found'); | ||
} | ||
|
||
/** @var Model $model */ | ||
$model = new $modelInfo['type'](); | ||
if (!$model instanceof Entity) { | ||
throw new Exception('Model not an entity'); | ||
} | ||
|
||
$modelInstance = $model->newQuery() | ||
->where('id', '=', $modelInfo['id']) | ||
->first(['id', 'name', 'owned_by']); | ||
|
||
$inaccessibleEntity = ($modelInstance instanceof Entity && !userCan('view', $modelInstance)); | ||
if (is_null($modelInstance) || $inaccessibleEntity) { | ||
throw new Exception('Model instance not found'); | ||
} | ||
|
||
return $modelInstance; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
<?php | ||
|
||
namespace BookStack\Activity\Models; | ||
|
||
use BookStack\Activity\WatchLevels; | ||
use BookStack\Permissions\Models\JointPermission; | ||
use Carbon\Carbon; | ||
use Illuminate\Database\Eloquent\Model; | ||
use Illuminate\Database\Eloquent\Relations\HasMany; | ||
use Illuminate\Database\Eloquent\Relations\MorphTo; | ||
|
||
/** | ||
* @property int $id | ||
* @property int $user_id | ||
* @property int $watchable_id | ||
* @property string $watchable_type | ||
* @property int $level | ||
* @property Carbon $created_at | ||
* @property Carbon $updated_at | ||
*/ | ||
class Watch extends Model | ||
{ | ||
protected $guarded = []; | ||
|
||
public function watchable(): MorphTo | ||
{ | ||
return $this->morphTo(); | ||
} | ||
|
||
public function jointPermissions(): HasMany | ||
{ | ||
return $this->hasMany(JointPermission::class, 'entity_id', 'watchable_id') | ||
->whereColumn('watches.watchable_type', '=', 'joint_permissions.entity_type'); | ||
} | ||
|
||
public function getLevelName(): string | ||
{ | ||
return WatchLevels::levelValueToName($this->level); | ||
} | ||
|
||
public function ignoring(): bool | ||
{ | ||
return $this->level === WatchLevels::IGNORE; | ||
} | ||
} |
42 changes: 42 additions & 0 deletions
42
app/Activity/Notifications/Handlers/BaseNotificationHandler.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
<?php | ||
|
||
namespace BookStack\Activity\Notifications\Handlers; | ||
|
||
use BookStack\Activity\Models\Loggable; | ||
use BookStack\Activity\Notifications\Messages\BaseActivityNotification; | ||
use BookStack\Entities\Models\Entity; | ||
use BookStack\Permissions\PermissionApplicator; | ||
use BookStack\Users\Models\User; | ||
|
||
abstract class BaseNotificationHandler implements NotificationHandler | ||
{ | ||
/** | ||
* @param class-string<BaseActivityNotification> $notification | ||
* @param int[] $userIds | ||
*/ | ||
protected function sendNotificationToUserIds(string $notification, array $userIds, User $initiator, string|Loggable $detail, Entity $relatedModel): void | ||
{ | ||
$users = User::query()->whereIn('id', array_unique($userIds))->get(); | ||
|
||
foreach ($users as $user) { | ||
// Prevent sending to the user that initiated the activity | ||
if ($user->id === $initiator->id) { | ||
continue; | ||
} | ||
|
||
// Prevent sending of the user does not have notification permissions | ||
if (!$user->can('receive-notifications')) { | ||
continue; | ||
} | ||
|
||
// Prevent sending if the user does not have access to the related content | ||
$permissions = new PermissionApplicator($user); | ||
if (!$permissions->checkOwnableUserAccess($relatedModel, 'view')) { | ||
continue; | ||
} | ||
|
||
// Send the notification | ||
$user->notify(new $notification($detail, $initiator)); | ||
} | ||
} | ||
} |
48 changes: 48 additions & 0 deletions
48
app/Activity/Notifications/Handlers/CommentCreationNotificationHandler.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
<?php | ||
|
||
namespace BookStack\Activity\Notifications\Handlers; | ||
|
||
use BookStack\Activity\Models\Activity; | ||
use BookStack\Activity\Models\Comment; | ||
use BookStack\Activity\Models\Loggable; | ||
use BookStack\Activity\Notifications\Messages\CommentCreationNotification; | ||
use BookStack\Activity\Tools\EntityWatchers; | ||
use BookStack\Activity\WatchLevels; | ||
use BookStack\Entities\Models\Page; | ||
use BookStack\Settings\UserNotificationPreferences; | ||
use BookStack\Users\Models\User; | ||
|
||
class CommentCreationNotificationHandler extends BaseNotificationHandler | ||
{ | ||
public function handle(Activity $activity, Loggable|string $detail, User $user): void | ||
{ | ||
if (!($detail instanceof Comment)) { | ||
throw new \InvalidArgumentException("Detail for comment creation notifications must be a comment"); | ||
} | ||
|
||
// Main watchers | ||
/** @var Page $page */ | ||
$page = $detail->entity; | ||
$watchers = new EntityWatchers($page, WatchLevels::COMMENTS); | ||
$watcherIds = $watchers->getWatcherUserIds(); | ||
|
||
// Page owner if user preferences allow | ||
if (!$watchers->isUserIgnoring($page->owned_by) && $page->ownedBy) { | ||
$userNotificationPrefs = new UserNotificationPreferences($page->ownedBy); | ||
if ($userNotificationPrefs->notifyOnOwnPageComments()) { | ||
$watcherIds[] = $page->owned_by; | ||
} | ||
} | ||
|
||
// Parent comment creator if preferences allow | ||
$parentComment = $detail->parent()->first(); | ||
if ($parentComment && !$watchers->isUserIgnoring($parentComment->created_by) && $parentComment->createdBy) { | ||
$parentCommenterNotificationsPrefs = new UserNotificationPreferences($parentComment->createdBy); | ||
if ($parentCommenterNotificationsPrefs->notifyOnCommentReplies()) { | ||
$watcherIds[] = $parentComment->created_by; | ||
} | ||
} | ||
|
||
$this->sendNotificationToUserIds(CommentCreationNotification::class, $watcherIds, $user, $detail, $page); | ||
} | ||
} |
17 changes: 17 additions & 0 deletions
17
app/Activity/Notifications/Handlers/NotificationHandler.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
<?php | ||
|
||
namespace BookStack\Activity\Notifications\Handlers; | ||
|
||
use BookStack\Activity\Models\Activity; | ||
use BookStack\Activity\Models\Loggable; | ||
use BookStack\Users\Models\User; | ||
|
||
interface NotificationHandler | ||
{ | ||
/** | ||
* Run this handler. | ||
* Provides the activity, related activity detail/model | ||
* along with the user that triggered the activity. | ||
*/ | ||
public function handle(Activity $activity, string|Loggable $detail, User $user): void; | ||
} |
24 changes: 24 additions & 0 deletions
24
app/Activity/Notifications/Handlers/PageCreationNotificationHandler.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
<?php | ||
|
||
namespace BookStack\Activity\Notifications\Handlers; | ||
|
||
use BookStack\Activity\Models\Activity; | ||
use BookStack\Activity\Models\Loggable; | ||
use BookStack\Activity\Notifications\Messages\PageCreationNotification; | ||
use BookStack\Activity\Tools\EntityWatchers; | ||
use BookStack\Activity\WatchLevels; | ||
use BookStack\Entities\Models\Page; | ||
use BookStack\Users\Models\User; | ||
|
||
class PageCreationNotificationHandler extends BaseNotificationHandler | ||
{ | ||
public function handle(Activity $activity, Loggable|string $detail, User $user): void | ||
{ | ||
if (!($detail instanceof Page)) { | ||
throw new \InvalidArgumentException("Detail for page create notifications must be a page"); | ||
} | ||
|
||
$watchers = new EntityWatchers($detail, WatchLevels::NEW); | ||
$this->sendNotificationToUserIds(PageCreationNotification::class, $watchers->getWatcherUserIds(), $user, $detail, $detail); | ||
} | ||
} |
Oops, something went wrong.