diff --git a/extensions/suspend/bootstrap.php b/extensions/suspend/bootstrap.php index 74d3f0c8a..9c15afe7f 100644 --- a/extensions/suspend/bootstrap.php +++ b/extensions/suspend/bootstrap.php @@ -18,6 +18,7 @@ return function (Dispatcher $events) { $events->subscribe(Listener\AddUserSuspendAttributes::class); $events->subscribe(Listener\RevokeAccessFromSuspendedUsers::class); $events->subscribe(Listener\SaveSuspensionToDatabase::class); + $events->subscribe(Listener\SendNotificationWhenUserIsSuspended::class); $events->subscribe(Access\UserPolicy::class); }; diff --git a/extensions/suspend/js/forum/dist/extension.js b/extensions/suspend/js/forum/dist/extension.js index 0bf8c06f4..2ba4fb221 100644 --- a/extensions/suspend/js/forum/dist/extension.js +++ b/extensions/suspend/js/forum/dist/extension.js @@ -152,10 +152,115 @@ System.register('flarum/suspend/components/SuspendUserModal', ['flarum/component });; 'use strict'; -System.register('flarum/suspend/main', ['flarum/extend', 'flarum/app', 'flarum/utils/UserControls', 'flarum/components/Button', 'flarum/components/Badge', 'flarum/Model', 'flarum/models/User', 'flarum/suspend/components/SuspendUserModal'], function (_export, _context) { +System.register('flarum/suspend/components/UserSuspendedNotification', ['flarum/components/Notification', 'flarum/helpers/username', 'flarum/helpers/humanTime'], function (_export, _context) { "use strict"; - var extend, app, UserControls, Button, Badge, Model, User, SuspendUserModal; + var Notification, username, humanTime, UserSuspendedNotification; + return { + setters: [function (_flarumComponentsNotification) { + Notification = _flarumComponentsNotification.default; + }, function (_flarumHelpersUsername) { + username = _flarumHelpersUsername.default; + }, function (_flarumHelpersHumanTime) { + humanTime = _flarumHelpersHumanTime.default; + }], + execute: function () { + UserSuspendedNotification = function (_Notification) { + babelHelpers.inherits(UserSuspendedNotification, _Notification); + + function UserSuspendedNotification() { + babelHelpers.classCallCheck(this, UserSuspendedNotification); + return babelHelpers.possibleConstructorReturn(this, (UserSuspendedNotification.__proto__ || Object.getPrototypeOf(UserSuspendedNotification)).apply(this, arguments)); + } + + babelHelpers.createClass(UserSuspendedNotification, [{ + key: 'icon', + value: function icon() { + return 'ban'; + } + }, { + key: 'href', + value: function href() { + return app.route.user(this.props.notification.subject()); + } + }, { + key: 'content', + value: function content() { + var notification = this.props.notification; + var actor = notification.sender(); + var suspendUntil = notification.content(); + var timeReadable = moment(suspendUntil.date).from(notification.time(), true); + + return app.translator.transChoice('flarum-suspend.forum.notifications.user_suspended_text', { + actor: actor, + timeReadable: timeReadable + }); + } + }]); + return UserSuspendedNotification; + }(Notification); + + _export('default', UserSuspendedNotification); + } + }; +});; +'use strict'; + +System.register('flarum/suspend/components/UserUnsuspendedNotification', ['flarum/components/Notification', 'flarum/helpers/username', 'flarum/helpers/humanTime'], function (_export, _context) { + "use strict"; + + var Notification, username, humanTime, UserUnsuspendedNotification; + return { + setters: [function (_flarumComponentsNotification) { + Notification = _flarumComponentsNotification.default; + }, function (_flarumHelpersUsername) { + username = _flarumHelpersUsername.default; + }, function (_flarumHelpersHumanTime) { + humanTime = _flarumHelpersHumanTime.default; + }], + execute: function () { + UserUnsuspendedNotification = function (_Notification) { + babelHelpers.inherits(UserUnsuspendedNotification, _Notification); + + function UserUnsuspendedNotification() { + babelHelpers.classCallCheck(this, UserUnsuspendedNotification); + return babelHelpers.possibleConstructorReturn(this, (UserUnsuspendedNotification.__proto__ || Object.getPrototypeOf(UserUnsuspendedNotification)).apply(this, arguments)); + } + + babelHelpers.createClass(UserUnsuspendedNotification, [{ + key: 'icon', + value: function icon() { + return 'ban'; + } + }, { + key: 'href', + value: function href() { + return app.route.user(this.props.notification.subject()); + } + }, { + key: 'content', + value: function content() { + var notification = this.props.notification; + var actor = notification.sender(); + + return app.translator.transChoice('flarum-suspend.forum.notifications.user_unsuspended_text', { + actor: actor + }); + } + }]); + return UserUnsuspendedNotification; + }(Notification); + + _export('default', UserUnsuspendedNotification); + } + }; +});; +'use strict'; + +System.register('flarum/suspend/main', ['flarum/extend', 'flarum/app', 'flarum/utils/UserControls', 'flarum/components/Button', 'flarum/components/Badge', 'flarum/Model', 'flarum/models/User', 'flarum/suspend/components/SuspendUserModal', 'flarum/suspend/components/UserSuspendedNotification', 'flarum/suspend/components/UserUnsuspendedNotification'], function (_export, _context) { + "use strict"; + + var extend, app, UserControls, Button, Badge, Model, User, SuspendUserModal, UserSuspendedNotification, UserUnsuspendedNotification; return { setters: [function (_flarumExtend) { extend = _flarumExtend.extend; @@ -173,10 +278,17 @@ System.register('flarum/suspend/main', ['flarum/extend', 'flarum/app', 'flarum/u User = _flarumModelsUser.default; }, function (_flarumSuspendComponentsSuspendUserModal) { SuspendUserModal = _flarumSuspendComponentsSuspendUserModal.default; + }, function (_flarumSuspendComponentsUserSuspendedNotification) { + UserSuspendedNotification = _flarumSuspendComponentsUserSuspendedNotification.default; + }, function (_flarumSuspendComponentsUserUnsuspendedNotification) { + UserUnsuspendedNotification = _flarumSuspendComponentsUserUnsuspendedNotification.default; }], execute: function () { app.initializers.add('flarum-suspend', function () { + app.notificationComponents.userSuspended = UserSuspendedNotification; + app.notificationComponents.userUnsuspended = UserUnsuspendedNotification; + User.prototype.canSuspend = Model.attribute('canSuspend'); User.prototype.suspendUntil = Model.attribute('suspendUntil', Model.transformDate); diff --git a/extensions/suspend/js/forum/src/components/UserSuspendedNotification.js b/extensions/suspend/js/forum/src/components/UserSuspendedNotification.js new file mode 100644 index 000000000..008c83b7d --- /dev/null +++ b/extensions/suspend/js/forum/src/components/UserSuspendedNotification.js @@ -0,0 +1,25 @@ +import Notification from 'flarum/components/Notification'; +import username from 'flarum/helpers/username'; +import humanTime from 'flarum/helpers/humanTime'; + +export default class UserSuspendedNotification extends Notification { + icon() { + return 'ban'; + } + + href() { + return app.route.user(this.props.notification.subject()); + } + + content() { + const notification = this.props.notification; + const actor = notification.sender(); + const suspendUntil = notification.content(); + const timeReadable = moment(suspendUntil.date).from(notification.time(), true); + + return app.translator.transChoice('flarum-suspend.forum.notifications.user_suspended_text', { + actor, + timeReadable, + }); + } +} diff --git a/extensions/suspend/js/forum/src/components/UserUnsuspendedNotification.js b/extensions/suspend/js/forum/src/components/UserUnsuspendedNotification.js new file mode 100644 index 000000000..3a92009c6 --- /dev/null +++ b/extensions/suspend/js/forum/src/components/UserUnsuspendedNotification.js @@ -0,0 +1,22 @@ +import Notification from 'flarum/components/Notification'; +import username from 'flarum/helpers/username'; +import humanTime from 'flarum/helpers/humanTime'; + +export default class UserUnsuspendedNotification extends Notification { + icon() { + return 'ban'; + } + + href() { + return app.route.user(this.props.notification.subject()); + } + + content() { + const notification = this.props.notification; + const actor = notification.sender(); + + return app.translator.transChoice('flarum-suspend.forum.notifications.user_unsuspended_text', { + actor, + }); + } +} diff --git a/extensions/suspend/js/forum/src/main.js b/extensions/suspend/js/forum/src/main.js index 6998fbcea..34715bf0e 100644 --- a/extensions/suspend/js/forum/src/main.js +++ b/extensions/suspend/js/forum/src/main.js @@ -7,8 +7,13 @@ import Model from 'flarum/Model'; import User from 'flarum/models/User'; import SuspendUserModal from 'flarum/suspend/components/SuspendUserModal'; +import UserSuspendedNotification from 'flarum/suspend/components/UserSuspendedNotification'; +import UserUnsuspendedNotification from 'flarum/suspend/components/UserUnsuspendedNotification'; app.initializers.add('flarum-suspend', () => { + app.notificationComponents.userSuspended = UserSuspendedNotification; + app.notificationComponents.userUnsuspended = UserUnsuspendedNotification; + User.prototype.canSuspend = Model.attribute('canSuspend'); User.prototype.suspendUntil = Model.attribute('suspendUntil', Model.transformDate); diff --git a/extensions/suspend/src/Event/UserWasSuspended.php b/extensions/suspend/src/Event/UserWasSuspended.php new file mode 100644 index 000000000..6b7ee7749 --- /dev/null +++ b/extensions/suspend/src/Event/UserWasSuspended.php @@ -0,0 +1,38 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Flarum\Suspend\Event; + +use Flarum\Core\Post; +use Flarum\Core\User; + +class UserWasSuspended +{ + /** + * @var User + */ + public $user; + + /** + * @var User + */ + public $actor; + + /** + * @param User $user + * @param User $actor + */ + public function __construct(User $user, User $actor) + { + $this->user = $user; + $this->actor = $actor; + } +} diff --git a/extensions/suspend/src/Event/UserWasUnsuspended.php b/extensions/suspend/src/Event/UserWasUnsuspended.php new file mode 100644 index 000000000..c54511d28 --- /dev/null +++ b/extensions/suspend/src/Event/UserWasUnsuspended.php @@ -0,0 +1,38 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Flarum\Suspend\Event; + +use Flarum\Core\Post; +use Flarum\Core\User; + +class UserWasUnsuspended +{ + /** + * @var User + */ + public $user; + + /** + * @var User + */ + public $actor; + + /** + * @param User $user + * @param User $actor + */ + public function __construct(User $user, User $actor) + { + $this->user = $user; + $this->actor = $actor; + } +} diff --git a/extensions/suspend/src/Listener/SaveSuspensionToDatabase.php b/extensions/suspend/src/Listener/SaveSuspensionToDatabase.php index 8c90fcdbe..70cee6e82 100755 --- a/extensions/suspend/src/Listener/SaveSuspensionToDatabase.php +++ b/extensions/suspend/src/Listener/SaveSuspensionToDatabase.php @@ -15,6 +15,8 @@ use DateTime; use Flarum\Core\Access\AssertPermissionTrait; use Flarum\Event\UserWillBeSaved; use Flarum\Suspend\SuspendValidator; +use Flarum\Suspend\Event\UserWasSuspended; +use Flarum\Suspend\Event\UserWasUnsuspended; use Illuminate\Contracts\Events\Dispatcher; class SaveSuspensionToDatabase @@ -60,6 +62,12 @@ class SaveSuspensionToDatabase $this->assertCan($actor, 'suspend', $user); $user->suspend_until = new DateTime($attributes['suspendUntil']); + + if (isset($attributes['suspendUntil'])) { + $user->raise(new UserWasSuspended($user, $actor)); + } else { + $user->raise(new UserWasUnsuspended($user, $actor)); + } } } } diff --git a/extensions/suspend/src/Listener/SendNotificationWhenUserIsSuspended.php b/extensions/suspend/src/Listener/SendNotificationWhenUserIsSuspended.php new file mode 100644 index 000000000..163dc3d76 --- /dev/null +++ b/extensions/suspend/src/Listener/SendNotificationWhenUserIsSuspended.php @@ -0,0 +1,95 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Flarum\Suspend\Listener; + +use DateTime; +use Flarum\Api\Serializer\UserBasicSerializer; +use Flarum\Core\Notification\NotificationSyncer; +use Flarum\Core\Post; +use Flarum\Core\User; +use Flarum\Event\ConfigureNotificationTypes; +use Flarum\Suspend\Event\UserWasSuspended; +use Flarum\Suspend\Event\UserWasUnsuspended; +use Flarum\Suspend\Notification\UserSuspendedBlueprint; +use Flarum\Suspend\Notification\UserUnsuspendedBlueprint; +use Illuminate\Contracts\Events\Dispatcher; + +class SendNotificationWhenUserIsSuspended +{ + /** + * @var NotificationSyncer + */ + protected $notifications; + + /** + * @param NotificationSyncer $notifications + */ + public function __construct(NotificationSyncer $notifications) + { + $this->notifications = $notifications; + } + + /** + * @param Dispatcher $events + */ + public function subscribe(Dispatcher $events) + { + $events->listen(ConfigureNotificationTypes::class, [$this, 'registerNotificationType']); + $events->listen(UserWasSuspended::class, [$this, 'whenUserWasSuspended']); + $events->listen(UserWasUnsuspended::class, [$this, 'whenUserWasUnsuspended']); + } + + /** + * @param ConfigureNotificationTypes $event + */ + public function registerNotificationType(ConfigureNotificationTypes $event) + { + $event->add(UserSuspendedBlueprint::class, UserBasicSerializer::class, ['alert', 'email']); + $event->add(UserUnsuspendedBlueprint::class, UserBasicSerializer::class, ['alert', 'email']); + } + + /** + * @param UserWasSuspended $event + */ + public function whenUserWasSuspended(UserWasSuspended $event) + { + $this->sync($event->user, $event->actor, [$event->user]); + } + + /** + * @param UserWasSuspended $event + */ + public function whenUserWasUnsuspended(UserWasUnsuspended $event) + { + $this->sync($event->user, $event->actor, [$event->user]); + } + + /** + * @param User $user + * @param User $actor + * @param array $recipients + */ + public function sync(User $user, User $actor, array $recipients) + { + if ($user->suspend_until > new DateTime()) { + $this->notifications->sync( + new UserSuspendedBlueprint($user, $actor), + $recipients + ); + } else { + $this->notifications->sync( + new UserUnsuspendedBlueprint($user, $actor), + $recipients + ); + } + } +} diff --git a/extensions/suspend/src/Notification/UserSuspendedBlueprint.php b/extensions/suspend/src/Notification/UserSuspendedBlueprint.php new file mode 100644 index 000000000..cd6269b84 --- /dev/null +++ b/extensions/suspend/src/Notification/UserSuspendedBlueprint.php @@ -0,0 +1,78 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Flarum\Suspend\Notification; + +use Flarum\Core\Notification\BlueprintInterface; +use Flarum\Core\User; + +class UserSuspendedBlueprint implements BlueprintInterface +{ + /** + * @var User + */ + public $user; + + /** + * @var User + */ + public $actor; + + /** + * @param User $user + * @param User $actor + */ + public function __construct(User $user, User $actor) + { + $this->user = $user; + $this->actor = $actor; + } + + /** + * {@inheritdoc} + */ + public function getSubject() + { + return $this->user; + } + + /** + * {@inheritdoc} + */ + public function getSender() + { + return $this->actor; + } + + /** + * {@inheritdoc} + */ + public function getData() + { + return $this->user['suspend_until']; + } + + /** + * {@inheritdoc} + */ + public static function getType() + { + return 'userSuspended'; + } + + /** + * {@inheritdoc} + */ + public static function getSubjectModel() + { + return User::class; + } +} diff --git a/extensions/suspend/src/Notification/UserUnsuspendedBlueprint.php b/extensions/suspend/src/Notification/UserUnsuspendedBlueprint.php new file mode 100644 index 000000000..adf79df32 --- /dev/null +++ b/extensions/suspend/src/Notification/UserUnsuspendedBlueprint.php @@ -0,0 +1,77 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Flarum\Suspend\Notification; + +use Flarum\Core\Notification\BlueprintInterface; +use Flarum\Core\User; + +class UserUnsuspendedBlueprint implements BlueprintInterface +{ + /** + * @var User + */ + public $user; + + /** + * @var User + */ + public $actor; + + /** + * @param User $user + * @param User $actor + */ + public function __construct(User $user, User $actor) + { + $this->user = $user; + $this->actor = $actor; + } + + /** + * {@inheritdoc} + */ + public function getSubject() + { + return $this->user; + } + + /** + * {@inheritdoc} + */ + public function getSender() + { + return $this->actor; + } + + /** + * {@inheritdoc} + */ + public function getData() + { + } + + /** + * {@inheritdoc} + */ + public static function getType() + { + return 'userUnsuspended'; + } + + /** + * {@inheritdoc} + */ + public static function getSubjectModel() + { + return User::class; + } +}