mirror of
https://github.com/flarum/core.git
synced 2025-10-12 07:24:27 +02:00
Massive refactor
- Use contextual namespaces within Flarum\Core - Clean up and docblock everything - Refactor Activity/Notification blueprint stuff - Refactor Formatter stuff - Refactor Search stuff - Upgrade to JSON-API 1.0 - Removed “addedPosts” and “removedPosts” relationships from discussion API. This was used for adding/removing event posts after renaming a discussion etc. Instead we should make an additional request to get all new posts Todo: - Fix Extenders and extensions - Get rid of repository interfaces - Fix other bugs I’ve inevitably introduced
This commit is contained in:
19
src/Core/Users/Commands/ConfirmEmail.php
Normal file
19
src/Core/Users/Commands/ConfirmEmail.php
Normal file
@@ -0,0 +1,19 @@
|
||||
<?php namespace Flarum\Core\Users\Commands;
|
||||
|
||||
class ConfirmEmail
|
||||
{
|
||||
/**
|
||||
* The email confirmation token.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $token;
|
||||
|
||||
/**
|
||||
* @param string $token The email confirmation token.
|
||||
*/
|
||||
public function __construct($token)
|
||||
{
|
||||
$this->token = $token;
|
||||
}
|
||||
}
|
55
src/Core/Users/Commands/ConfirmEmailHandler.php
Normal file
55
src/Core/Users/Commands/ConfirmEmailHandler.php
Normal file
@@ -0,0 +1,55 @@
|
||||
<?php namespace Flarum\Core\Users\Commands;
|
||||
|
||||
use Flarum\Core\Users\UserRepositoryInterface;
|
||||
use Flarum\Core\Users\Events\UserWillBeSaved;
|
||||
use Flarum\Core\Support\DispatchesEvents;
|
||||
use Flarum\Core\Exceptions\InvalidConfirmationTokenException;
|
||||
use Flarum\Core\Users\EmailToken;
|
||||
|
||||
class ConfirmEmailHandler
|
||||
{
|
||||
use DispatchesEvents;
|
||||
|
||||
/**
|
||||
* @var UserRepositoryInterface
|
||||
*/
|
||||
protected $users;
|
||||
|
||||
/**
|
||||
* @param UserRepositoryInterface $users
|
||||
*/
|
||||
public function __construct(UserRepositoryInterface $users)
|
||||
{
|
||||
$this->users = $users;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ConfirmEmail $command
|
||||
* @return \Flarum\Core\Users\User
|
||||
* @throws InvalidConfirmationTokenException
|
||||
*/
|
||||
public function handle(ConfirmEmail $command)
|
||||
{
|
||||
$token = EmailToken::find($command->token);
|
||||
|
||||
if (! $token) {
|
||||
throw new InvalidConfirmationTokenException;
|
||||
}
|
||||
|
||||
$user = $token->user;
|
||||
$user->changeEmail($token->email);
|
||||
|
||||
if (! $user->is_activated) {
|
||||
$user->activate();
|
||||
}
|
||||
|
||||
event(new UserWillBeSaved($user, $command));
|
||||
|
||||
$user->save();
|
||||
$this->dispatchEventsFor($user);
|
||||
|
||||
$token->delete();
|
||||
|
||||
return $user;
|
||||
}
|
||||
}
|
30
src/Core/Users/Commands/DeleteAvatar.php
Normal file
30
src/Core/Users/Commands/DeleteAvatar.php
Normal file
@@ -0,0 +1,30 @@
|
||||
<?php namespace Flarum\Core\Users\Commands;
|
||||
|
||||
use Flarum\Core\Users\User;
|
||||
|
||||
class DeleteAvatar
|
||||
{
|
||||
/**
|
||||
* The ID of the user to delete the avatar of.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
public $userId;
|
||||
|
||||
/**
|
||||
* The user performing the action.
|
||||
*
|
||||
* @var User
|
||||
*/
|
||||
public $actor;
|
||||
|
||||
/**
|
||||
* @param int $userId The ID of the user to delete the avatar of.
|
||||
* @param User $actor The user performing the action.
|
||||
*/
|
||||
public function __construct($userId, User $actor)
|
||||
{
|
||||
$this->userId = $userId;
|
||||
$this->actor = $actor;
|
||||
}
|
||||
}
|
59
src/Core/Users/Commands/DeleteAvatarHandler.php
Normal file
59
src/Core/Users/Commands/DeleteAvatarHandler.php
Normal file
@@ -0,0 +1,59 @@
|
||||
<?php namespace Flarum\Core\Users\Commands;
|
||||
|
||||
use Flarum\Core\Users\Events\AvatarWillBeDeleted;
|
||||
use Flarum\Core\Users\UserRepositoryInterface;
|
||||
use Flarum\Core\Support\DispatchesEvents;
|
||||
use League\Flysystem\FilesystemInterface;
|
||||
|
||||
class DeleteAvatarHandler
|
||||
{
|
||||
use DispatchesEvents;
|
||||
|
||||
/**
|
||||
* @var UserRepositoryInterface
|
||||
*/
|
||||
protected $users;
|
||||
|
||||
/**
|
||||
* @var FilesystemInterface
|
||||
*/
|
||||
protected $uploadDir;
|
||||
|
||||
/**
|
||||
* @param UserRepositoryInterface $users
|
||||
* @param FilesystemInterface $uploadDir
|
||||
*/
|
||||
public function __construct(UserRepositoryInterface $users, FilesystemInterface $uploadDir)
|
||||
{
|
||||
$this->users = $users;
|
||||
$this->uploadDir = $uploadDir;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param DeleteAvatar $command
|
||||
* @return \Flarum\Core\Users\User
|
||||
*/
|
||||
public function handle(DeleteAvatar $command)
|
||||
{
|
||||
$actor = $command->actor;
|
||||
|
||||
$user = $this->users->findOrFail($command->userId);
|
||||
|
||||
// Make sure the current user is allowed to edit the user profile.
|
||||
// This will let admins and the user themselves pass through, and
|
||||
// throw an exception otherwise.
|
||||
$user->assertCan($actor, 'edit');
|
||||
|
||||
$avatarPath = $user->avatar_path;
|
||||
$user->changeAvatarPath(null);
|
||||
|
||||
event(new AvatarWillBeDeleted($user, $actor));
|
||||
|
||||
$this->uploadDir->delete($avatarPath);
|
||||
|
||||
$user->save();
|
||||
$this->dispatchEventsFor($user);
|
||||
|
||||
return $user;
|
||||
}
|
||||
}
|
41
src/Core/Users/Commands/DeleteUser.php
Normal file
41
src/Core/Users/Commands/DeleteUser.php
Normal file
@@ -0,0 +1,41 @@
|
||||
<?php namespace Flarum\Core\Users\Commands;
|
||||
|
||||
use Flarum\Core\Users\User;
|
||||
|
||||
class DeleteUser
|
||||
{
|
||||
/**
|
||||
* The ID of the user to delete.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
public $userId;
|
||||
|
||||
/**
|
||||
* The user performing the action.
|
||||
*
|
||||
* @var User
|
||||
*/
|
||||
public $actor;
|
||||
|
||||
/**
|
||||
* Any other user input associated with the action. This is unused by
|
||||
* default, but may be used by extensions.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $data;
|
||||
|
||||
/**
|
||||
* @param int $userId The ID of the user to delete.
|
||||
* @param User $actor The user performing the action.
|
||||
* @param array $data Any other user input associated with the action. This
|
||||
* is unused by default, but may be used by extensions.
|
||||
*/
|
||||
public function __construct($userId, User $actor, array $data = [])
|
||||
{
|
||||
$this->userId = $userId;
|
||||
$this->actor = $actor;
|
||||
$this->data = $data;
|
||||
}
|
||||
}
|
44
src/Core/Users/Commands/DeleteUserHandler.php
Normal file
44
src/Core/Users/Commands/DeleteUserHandler.php
Normal file
@@ -0,0 +1,44 @@
|
||||
<?php namespace Flarum\Core\Users\Commands;
|
||||
|
||||
use Flarum\Core\Users\User;
|
||||
use Flarum\Core\Users\UserRepositoryInterface;
|
||||
use Flarum\Core\Users\Events\UserWillBeDeleted;
|
||||
use Flarum\Core\Support\DispatchesEvents;
|
||||
|
||||
class DeleteUserHandler
|
||||
{
|
||||
use DispatchesEvents;
|
||||
|
||||
/**
|
||||
* @var UserRepositoryInterface
|
||||
*/
|
||||
protected $users;
|
||||
|
||||
/**
|
||||
* @param UserRepositoryInterface $users
|
||||
*/
|
||||
public function __construct(UserRepositoryInterface $users)
|
||||
{
|
||||
$this->users = $users;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param DeleteUser $command
|
||||
* @return User
|
||||
* @throws \Flarum\Core\Exceptions\PermissionDeniedException
|
||||
*/
|
||||
public function handle(DeleteUser $command)
|
||||
{
|
||||
$actor = $command->actor;
|
||||
$user = $this->users->findOrFail($command->userId, $actor);
|
||||
|
||||
$user->assertCan($actor, 'delete');
|
||||
|
||||
event(new UserWillBeDeleted($user, $actor, $command->data));
|
||||
|
||||
$user->delete();
|
||||
$this->dispatchEventsFor($user);
|
||||
|
||||
return $user;
|
||||
}
|
||||
}
|
39
src/Core/Users/Commands/EditUser.php
Normal file
39
src/Core/Users/Commands/EditUser.php
Normal file
@@ -0,0 +1,39 @@
|
||||
<?php namespace Flarum\Core\Users\Commands;
|
||||
|
||||
use Flarum\Core\Users\User;
|
||||
|
||||
class EditUser
|
||||
{
|
||||
/**
|
||||
* The ID of the user to edit.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
public $userId;
|
||||
|
||||
/**
|
||||
* The user performing the action.
|
||||
*
|
||||
* @var User
|
||||
*/
|
||||
public $actor;
|
||||
|
||||
/**
|
||||
* The attributes to update on the post.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $data;
|
||||
|
||||
/**
|
||||
* @param int $userId The ID of the user to edit.
|
||||
* @param User $actor The user performing the action.
|
||||
* @param array $data The attributes to update on the post.
|
||||
*/
|
||||
public function __construct($userId, User $actor, array $data)
|
||||
{
|
||||
$this->userId = $userId;
|
||||
$this->actor = $actor;
|
||||
$this->data = $data;
|
||||
}
|
||||
}
|
75
src/Core/Users/Commands/EditUserHandler.php
Normal file
75
src/Core/Users/Commands/EditUserHandler.php
Normal file
@@ -0,0 +1,75 @@
|
||||
<?php namespace Flarum\Core\Users\Commands;
|
||||
|
||||
use Flarum\Core\Users\User;
|
||||
use Flarum\Core\Users\UserRepositoryInterface;
|
||||
use Flarum\Core\Users\Events\UserWillBeSaved;
|
||||
use Flarum\Core\Support\DispatchesEvents;
|
||||
|
||||
class EditUserHandler
|
||||
{
|
||||
use DispatchesEvents;
|
||||
|
||||
/**
|
||||
* @var UserRepositoryInterface
|
||||
*/
|
||||
protected $users;
|
||||
|
||||
/**
|
||||
* @param UserRepositoryInterface $users
|
||||
*/
|
||||
public function __construct(UserRepositoryInterface $users)
|
||||
{
|
||||
$this->users = $users;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param EditUser $command
|
||||
* @return User
|
||||
* @throws \Flarum\Core\Exceptions\PermissionDeniedException
|
||||
*/
|
||||
public function handle(EditUser $command)
|
||||
{
|
||||
$actor = $command->actor;
|
||||
$data = $command->data;
|
||||
|
||||
$user = $this->users->findOrFail($command->userId, $actor);
|
||||
|
||||
$user->assertCan($actor, 'edit');
|
||||
|
||||
$attributes = array_get($data, 'attributes', []);
|
||||
|
||||
if (isset($attributes['username'])) {
|
||||
$user->assertCan($actor, 'rename');
|
||||
$user->rename($attributes['username']);
|
||||
}
|
||||
|
||||
if (isset($attributes['email'])) {
|
||||
$user->requestEmailChange($attributes['email']);
|
||||
}
|
||||
|
||||
if (isset($attributes['password'])) {
|
||||
$user->changePassword($attributes['password']);
|
||||
}
|
||||
|
||||
if (isset($attributes['bio'])) {
|
||||
$user->changeBio($attributes['bio']);
|
||||
}
|
||||
|
||||
if (! empty($attributes['readTime'])) {
|
||||
$user->markAllAsRead();
|
||||
}
|
||||
|
||||
if (! empty($attributes['preferences'])) {
|
||||
foreach ($attributes['preferences'] as $k => $v) {
|
||||
$user->setPreference($k, $v);
|
||||
}
|
||||
}
|
||||
|
||||
event(new UserWillBeSaved($actor, $actor, $data));
|
||||
|
||||
$user->save();
|
||||
$this->dispatchEventsFor($user);
|
||||
|
||||
return $user;
|
||||
}
|
||||
}
|
30
src/Core/Users/Commands/RegisterUser.php
Normal file
30
src/Core/Users/Commands/RegisterUser.php
Normal file
@@ -0,0 +1,30 @@
|
||||
<?php namespace Flarum\Core\Users\Commands;
|
||||
|
||||
use Flarum\Core\Users\User;
|
||||
|
||||
class RegisterUser
|
||||
{
|
||||
/**
|
||||
* The user performing the action.
|
||||
*
|
||||
* @var User
|
||||
*/
|
||||
public $actor;
|
||||
|
||||
/**
|
||||
* The attributes of the new user.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $data;
|
||||
|
||||
/**
|
||||
* @param User $actor The user performing the action.
|
||||
* @param array $data The attributes of the new user.
|
||||
*/
|
||||
public function __construct(User $actor, array $data)
|
||||
{
|
||||
$this->actor = $actor;
|
||||
$this->data = $data;
|
||||
}
|
||||
}
|
35
src/Core/Users/Commands/RegisterUserHandler.php
Normal file
35
src/Core/Users/Commands/RegisterUserHandler.php
Normal file
@@ -0,0 +1,35 @@
|
||||
<?php namespace Flarum\Core\Users\Commands;
|
||||
|
||||
use Flarum\Core\Users\User;
|
||||
use Flarum\Core\Users\Events\UserWillBeSaved;
|
||||
use Flarum\Core\Support\DispatchesEvents;
|
||||
|
||||
class RegisterUserHandler
|
||||
{
|
||||
use DispatchesEvents;
|
||||
|
||||
/**
|
||||
* @param RegisterUser $command
|
||||
* @return User
|
||||
*/
|
||||
public function handle(RegisterUser $command)
|
||||
{
|
||||
$actor = $command->actor;
|
||||
$data = $command->data;
|
||||
|
||||
// TODO: check whether or not registration is open (config)
|
||||
|
||||
$user = User::register(
|
||||
array_get($data, 'attributes.username'),
|
||||
array_get($data, 'attributes.email'),
|
||||
array_get($data, 'attributes.password')
|
||||
);
|
||||
|
||||
event(new UserWillBeSaved($user, $actor, $data));
|
||||
|
||||
$user->save();
|
||||
$this->dispatchEventsFor($user);
|
||||
|
||||
return $user;
|
||||
}
|
||||
}
|
19
src/Core/Users/Commands/RequestPasswordReset.php
Normal file
19
src/Core/Users/Commands/RequestPasswordReset.php
Normal file
@@ -0,0 +1,19 @@
|
||||
<?php namespace Flarum\Core\Users\Commands;
|
||||
|
||||
class RequestPasswordReset
|
||||
{
|
||||
/**
|
||||
* The email of the user to request a password reset for.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $email;
|
||||
|
||||
/**
|
||||
* @param string $email The email of the user to request a password reset for.
|
||||
*/
|
||||
public function __construct($email)
|
||||
{
|
||||
$this->email = $email;
|
||||
}
|
||||
}
|
67
src/Core/Users/Commands/RequestPasswordResetHandler.php
Normal file
67
src/Core/Users/Commands/RequestPasswordResetHandler.php
Normal file
@@ -0,0 +1,67 @@
|
||||
<?php namespace Flarum\Core\Users\Commands;
|
||||
|
||||
use Flarum\Core\Users\PasswordToken;
|
||||
use Flarum\Core\Users\UserRepositoryInterface;
|
||||
use Illuminate\Contracts\Mail\Mailer;
|
||||
use Illuminate\Mail\Message;
|
||||
use Illuminate\Database\Eloquent\ModelNotFoundException;
|
||||
use Flarum\Core;
|
||||
use Flarum\Http\UrlGeneratorInterface;
|
||||
|
||||
class RequestPasswordResetHandler
|
||||
{
|
||||
/**
|
||||
* @var UserRepositoryInterface
|
||||
*/
|
||||
protected $users;
|
||||
|
||||
/**
|
||||
* @var Mailer
|
||||
*/
|
||||
protected $mailer;
|
||||
|
||||
/**
|
||||
* @param UserRepositoryInterface $users
|
||||
* @param Mailer $mailer
|
||||
* @param UrlGeneratorInterface $url
|
||||
*/
|
||||
public function __construct(UserRepositoryInterface $users, Mailer $mailer, UrlGeneratorInterface $url)
|
||||
{
|
||||
$this->users = $users;
|
||||
$this->mailer = $mailer;
|
||||
$this->url = $url;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param RequestPasswordReset $command
|
||||
* @return \Flarum\Core\Users\User
|
||||
* @throws ModelNotFoundException
|
||||
*/
|
||||
public function handle(RequestPasswordReset $command)
|
||||
{
|
||||
$user = $this->users->findByEmail($command->email);
|
||||
|
||||
if (! $user) {
|
||||
throw new ModelNotFoundException;
|
||||
}
|
||||
|
||||
$token = PasswordToken::generate($user->id);
|
||||
$token->save();
|
||||
|
||||
// TODO: Need to use UrlGenerator, but since this is part of core we
|
||||
// don't know that the forum routes will be loaded. Should the reset
|
||||
// password route be part of core??
|
||||
$data = [
|
||||
'username' => $user->username,
|
||||
'url' => Core::config('base_url').'/reset/'.$token->id,
|
||||
'forumTitle' => Core::config('forum_title')
|
||||
];
|
||||
|
||||
$this->mailer->send(['text' => 'flarum::emails.resetPassword'], $data, function (Message $message) use ($user) {
|
||||
$message->to($user->email);
|
||||
$message->subject('Reset Your Password');
|
||||
});
|
||||
|
||||
return $user;
|
||||
}
|
||||
}
|
40
src/Core/Users/Commands/UploadAvatar.php
Normal file
40
src/Core/Users/Commands/UploadAvatar.php
Normal file
@@ -0,0 +1,40 @@
|
||||
<?php namespace Flarum\Core\Users\Commands;
|
||||
|
||||
use Flarum\Core\Users\User;
|
||||
use Psr\Http\Message\UploadedFileInterface;
|
||||
|
||||
class UploadAvatar
|
||||
{
|
||||
/**
|
||||
* The ID of the user to upload the avatar for.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
public $userId;
|
||||
|
||||
/**
|
||||
* The avatar file to upload.
|
||||
*
|
||||
* @var UploadedFileInterface
|
||||
*/
|
||||
public $file;
|
||||
|
||||
/**
|
||||
* The user performing the action.
|
||||
*
|
||||
* @var User
|
||||
*/
|
||||
public $actor;
|
||||
|
||||
/**
|
||||
* @param int $userId The ID of the user to upload the avatar for.
|
||||
* @param UploadedFileInterface $file The avatar file to upload.
|
||||
* @param User $actor The user performing the action.
|
||||
*/
|
||||
public function __construct($userId, UploadedFileInterface $file, User $actor)
|
||||
{
|
||||
$this->userId = $userId;
|
||||
$this->file = $file;
|
||||
$this->actor = $actor;
|
||||
}
|
||||
}
|
81
src/Core/Users/Commands/UploadAvatarHandler.php
Normal file
81
src/Core/Users/Commands/UploadAvatarHandler.php
Normal file
@@ -0,0 +1,81 @@
|
||||
<?php namespace Flarum\Core\Users\Commands;
|
||||
|
||||
use Flarum\Core\Users\Events\AvatarWillBeSaved;
|
||||
use Flarum\Core\Users\UserRepositoryInterface;
|
||||
use Flarum\Core\Support\DispatchesEvents;
|
||||
use Illuminate\Support\Str;
|
||||
use League\Flysystem\Adapter\Local;
|
||||
use League\Flysystem\Filesystem;
|
||||
use League\Flysystem\FilesystemInterface;
|
||||
use League\Flysystem\MountManager;
|
||||
use Intervention\Image\ImageManager;
|
||||
|
||||
class UploadAvatarHandler
|
||||
{
|
||||
use DispatchesEvents;
|
||||
|
||||
/**
|
||||
* @var UserRepositoryInterface
|
||||
*/
|
||||
protected $users;
|
||||
|
||||
/**
|
||||
* @var FilesystemInterface
|
||||
*/
|
||||
protected $uploadDir;
|
||||
|
||||
/**
|
||||
* @param UserRepositoryInterface $users
|
||||
* @param FilesystemInterface $uploadDir
|
||||
*/
|
||||
public function __construct(UserRepositoryInterface $users, FilesystemInterface $uploadDir)
|
||||
{
|
||||
$this->users = $users;
|
||||
$this->uploadDir = $uploadDir;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param UploadAvatar $command
|
||||
* @return \Flarum\Core\Users\User
|
||||
* @throws \Flarum\Core\Exceptions\PermissionDeniedException
|
||||
*/
|
||||
public function handle(UploadAvatar $command)
|
||||
{
|
||||
$actor = $command->actor;
|
||||
|
||||
$user = $this->users->findOrFail($command->userId);
|
||||
|
||||
// Make sure the current user is allowed to edit the user profile.
|
||||
// This will let admins and the user themselves pass through, and
|
||||
// throw an exception otherwise.
|
||||
$user->assertCan($actor, 'edit');
|
||||
|
||||
$tmpFile = tempnam(sys_get_temp_dir(), 'avatar');
|
||||
$command->file->moveTo($tmpFile);
|
||||
|
||||
$manager = new ImageManager(['driver' => 'imagick']);
|
||||
$manager->make($tmpFile)->fit(100, 100)->save();
|
||||
|
||||
event(new AvatarWillBeSaved($user, $actor, $tmpFile));
|
||||
|
||||
$mount = new MountManager([
|
||||
'source' => new Filesystem(new Local(pathinfo($tmpFile, PATHINFO_DIRNAME))),
|
||||
'target' => $this->uploadDir,
|
||||
]);
|
||||
|
||||
if ($user->avatar_path && $mount->has($file = "target://$user->avatar_path")) {
|
||||
$mount->delete($file);
|
||||
}
|
||||
|
||||
$uploadName = Str::lower(Str::quickRandom()) . '.jpg';
|
||||
|
||||
$user->changeAvatarPath($uploadName);
|
||||
|
||||
$mount->move("source://".pathinfo($tmpFile, PATHINFO_BASENAME), "target://$uploadName");
|
||||
|
||||
$user->save();
|
||||
$this->dispatchEventsFor($user);
|
||||
|
||||
return $user;
|
||||
}
|
||||
}
|
80
src/Core/Users/EloquentUserRepository.php
Normal file
80
src/Core/Users/EloquentUserRepository.php
Normal file
@@ -0,0 +1,80 @@
|
||||
<?php namespace Flarum\Core\Users;
|
||||
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
|
||||
class EloquentUserRepository implements UserRepositoryInterface
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function query()
|
||||
{
|
||||
return User::query();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function findOrFail($id, User $actor = null)
|
||||
{
|
||||
$query = User::where('id', $id);
|
||||
|
||||
return $this->scopeVisibleTo($query, $actor)->firstOrFail();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function findByIdentification($identification)
|
||||
{
|
||||
$field = filter_var($identification, FILTER_VALIDATE_EMAIL) ? 'email' : 'username';
|
||||
|
||||
return User::where($field, $identification)->first();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function findByEmail($email)
|
||||
{
|
||||
return User::where('email', $email)->first();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getIdForUsername($username, User $actor = null)
|
||||
{
|
||||
$query = User::where('username', 'like', $username);
|
||||
|
||||
return $this->scopeVisibleTo($query, $actor)->pluck('id');
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getIdsForUsername($string, User $actor = null)
|
||||
{
|
||||
$query = User::where('username', 'like', '%'.$string.'%')
|
||||
->orderByRaw('username = ? desc', [$string])
|
||||
->orderByRaw('username like ? desc', [$string.'%']);
|
||||
|
||||
return $this->scopeVisibleTo($query, $actor)->lists('id');
|
||||
}
|
||||
|
||||
/**
|
||||
* Scope a query to only include records that are visible to a user.
|
||||
*
|
||||
* @param Builder $query
|
||||
* @param User $actor
|
||||
* @return Builder
|
||||
*/
|
||||
protected function scopeVisibleTo(Builder $query, User $actor = null)
|
||||
{
|
||||
if ($actor !== null) {
|
||||
$query->whereVisibleTo($actor);
|
||||
}
|
||||
|
||||
return $query;
|
||||
}
|
||||
}
|
47
src/Core/Users/EmailToken.php
Normal file
47
src/Core/Users/EmailToken.php
Normal file
@@ -0,0 +1,47 @@
|
||||
<?php namespace Flarum\Core\Users;
|
||||
|
||||
use Flarum\Core\Model;
|
||||
|
||||
class EmailToken extends Model
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected $table = 'email_tokens';
|
||||
|
||||
/**
|
||||
* Use a custom primary key for this model.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
public $incrementing = false;
|
||||
|
||||
/**
|
||||
* Generate an email token for the specified user.
|
||||
*
|
||||
* @param int $userId
|
||||
* @param string $email
|
||||
* @return static
|
||||
*/
|
||||
public static function generate($userId, $email)
|
||||
{
|
||||
$token = new static;
|
||||
|
||||
$token->id = str_random(40);
|
||||
$token->user_id = $userId;
|
||||
$token->email = $email;
|
||||
$token->created_at = time();
|
||||
|
||||
return $token;
|
||||
}
|
||||
|
||||
/**
|
||||
* Define the relationship with the owner of this email token.
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
|
||||
*/
|
||||
public function user()
|
||||
{
|
||||
return $this->belongsTo('Flarum\Core\Users\User');
|
||||
}
|
||||
}
|
30
src/Core/Users/Events/AvatarWillBeDeleted.php
Normal file
30
src/Core/Users/Events/AvatarWillBeDeleted.php
Normal file
@@ -0,0 +1,30 @@
|
||||
<?php namespace Flarum\Core\Users\Events;
|
||||
|
||||
use Flarum\Core\Users\User;
|
||||
|
||||
class AvatarWillBeDeleted
|
||||
{
|
||||
/**
|
||||
* The user whose avatar will be deleted.
|
||||
*
|
||||
* @var User
|
||||
*/
|
||||
public $user;
|
||||
|
||||
/**
|
||||
* The user performing the action.
|
||||
*
|
||||
* @var User
|
||||
*/
|
||||
public $actor;
|
||||
|
||||
/**
|
||||
* @param User $user The user whose avatar will be deleted.
|
||||
* @param User $actor The user performing the action.
|
||||
*/
|
||||
public function __construct(User $user, User $actor)
|
||||
{
|
||||
$this->user = $user;
|
||||
$this->actor = $actor;
|
||||
}
|
||||
}
|
39
src/Core/Users/Events/AvatarWillBeSaved.php
Normal file
39
src/Core/Users/Events/AvatarWillBeSaved.php
Normal file
@@ -0,0 +1,39 @@
|
||||
<?php namespace Flarum\Core\Users\Events;
|
||||
|
||||
use Flarum\Core\Users\User;
|
||||
|
||||
class AvatarWillBeSaved
|
||||
{
|
||||
/**
|
||||
* The user whose avatar will be saved.
|
||||
*
|
||||
* @var User
|
||||
*/
|
||||
public $user;
|
||||
|
||||
/**
|
||||
* The user performing the action.
|
||||
*
|
||||
* @var User
|
||||
*/
|
||||
public $actor;
|
||||
|
||||
/**
|
||||
* The path to the avatar that will be saved.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $path;
|
||||
|
||||
/**
|
||||
* @param User $user The user whose avatar will be saved.
|
||||
* @param User $actor The user performing the action.
|
||||
* @param string $path The path to the avatar that will be saved.
|
||||
*/
|
||||
public function __construct(User $user, User $actor, $path)
|
||||
{
|
||||
$this->user = $user;
|
||||
$this->actor = $actor;
|
||||
$this->path = $path;
|
||||
}
|
||||
}
|
21
src/Core/Users/Events/UserAvatarWasChanged.php
Normal file
21
src/Core/Users/Events/UserAvatarWasChanged.php
Normal file
@@ -0,0 +1,21 @@
|
||||
<?php namespace Flarum\Core\Users\Events;
|
||||
|
||||
use Flarum\Core\Users\User;
|
||||
|
||||
class UserAvatarWasChanged
|
||||
{
|
||||
/**
|
||||
* The user whose avatar was changed.
|
||||
*
|
||||
* @var User
|
||||
*/
|
||||
public $user;
|
||||
|
||||
/**
|
||||
* @param User $user The user whose avatar was changed.
|
||||
*/
|
||||
public function __construct(User $user)
|
||||
{
|
||||
$this->user = $user;
|
||||
}
|
||||
}
|
21
src/Core/Users/Events/UserBioWasChanged.php
Normal file
21
src/Core/Users/Events/UserBioWasChanged.php
Normal file
@@ -0,0 +1,21 @@
|
||||
<?php namespace Flarum\Core\Users\Events;
|
||||
|
||||
use Flarum\Core\Users\User;
|
||||
|
||||
class UserBioWasChanged
|
||||
{
|
||||
/**
|
||||
* The user whose bio was changed.
|
||||
*
|
||||
* @var User
|
||||
*/
|
||||
public $user;
|
||||
|
||||
/**
|
||||
* @param User $user The user whose bio was changed.
|
||||
*/
|
||||
public function __construct(User $user)
|
||||
{
|
||||
$this->user = $user;
|
||||
}
|
||||
}
|
30
src/Core/Users/Events/UserEmailChangeWasRequested.php
Normal file
30
src/Core/Users/Events/UserEmailChangeWasRequested.php
Normal file
@@ -0,0 +1,30 @@
|
||||
<?php namespace Flarum\Core\Users\Events;
|
||||
|
||||
use Flarum\Core\Users\User;
|
||||
|
||||
class UserEmailChangeWasRequested
|
||||
{
|
||||
/**
|
||||
* The user who requested the email change.
|
||||
*
|
||||
* @var User
|
||||
*/
|
||||
public $user;
|
||||
|
||||
/**
|
||||
* The email they requested to change to.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $email;
|
||||
|
||||
/**
|
||||
* @param User $user The user who requested the email change.
|
||||
* @param string $email The email they requested to change to.
|
||||
*/
|
||||
public function __construct(User $user, $email)
|
||||
{
|
||||
$this->user = $user;
|
||||
$this->email = $email;
|
||||
}
|
||||
}
|
21
src/Core/Users/Events/UserEmailWasChanged.php
Normal file
21
src/Core/Users/Events/UserEmailWasChanged.php
Normal file
@@ -0,0 +1,21 @@
|
||||
<?php namespace Flarum\Core\Users\Events;
|
||||
|
||||
use Flarum\Core\Users\User;
|
||||
|
||||
class UserEmailWasChanged
|
||||
{
|
||||
/**
|
||||
* The user whose email was changed.
|
||||
*
|
||||
* @var User
|
||||
*/
|
||||
public $user;
|
||||
|
||||
/**
|
||||
* @param User $user The user whose email was changed.
|
||||
*/
|
||||
public function __construct(User $user)
|
||||
{
|
||||
$this->user = $user;
|
||||
}
|
||||
}
|
21
src/Core/Users/Events/UserPasswordWasChanged.php
Normal file
21
src/Core/Users/Events/UserPasswordWasChanged.php
Normal file
@@ -0,0 +1,21 @@
|
||||
<?php namespace Flarum\Core\Users\Events;
|
||||
|
||||
use Flarum\Core\Users\User;
|
||||
|
||||
class UserPasswordWasChanged
|
||||
{
|
||||
/**
|
||||
* The user whose password was changed.
|
||||
*
|
||||
* @var User
|
||||
*/
|
||||
public $user;
|
||||
|
||||
/**
|
||||
* @param User $user The user whose password was changed.
|
||||
*/
|
||||
public function __construct(User $user)
|
||||
{
|
||||
$this->user = $user;
|
||||
}
|
||||
}
|
27
src/Core/Users/Events/UserSearchWillBePerformed.php
Normal file
27
src/Core/Users/Events/UserSearchWillBePerformed.php
Normal file
@@ -0,0 +1,27 @@
|
||||
<?php namespace Flarum\Core\Users\Events;
|
||||
|
||||
use Flarum\Core\Users\Search\UserSearch;
|
||||
use Flarum\Core\Search\SearchCriteria;
|
||||
|
||||
class UserSearchWillBePerformed
|
||||
{
|
||||
/**
|
||||
* @var UserSearch
|
||||
*/
|
||||
public $search;
|
||||
|
||||
/**
|
||||
* @var SearchCriteria
|
||||
*/
|
||||
public $criteria;
|
||||
|
||||
/**
|
||||
* @param UserSearch $search
|
||||
* @param SearchCriteria $criteria
|
||||
*/
|
||||
public function __construct(UserSearch $search, SearchCriteria $criteria)
|
||||
{
|
||||
$this->search = $search;
|
||||
$this->criteria = $criteria;
|
||||
}
|
||||
}
|
21
src/Core/Users/Events/UserWasActivated.php
Normal file
21
src/Core/Users/Events/UserWasActivated.php
Normal file
@@ -0,0 +1,21 @@
|
||||
<?php namespace Flarum\Core\Users\Events;
|
||||
|
||||
use Flarum\Core\Users\User;
|
||||
|
||||
class UserWasActivated
|
||||
{
|
||||
/**
|
||||
* The user whose account was activated.
|
||||
*
|
||||
* @var User
|
||||
*/
|
||||
public $user;
|
||||
|
||||
/**
|
||||
* @param User $user The user whose account was activated.
|
||||
*/
|
||||
public function __construct(User $user)
|
||||
{
|
||||
$this->user = $user;
|
||||
}
|
||||
}
|
21
src/Core/Users/Events/UserWasDeleted.php
Normal file
21
src/Core/Users/Events/UserWasDeleted.php
Normal file
@@ -0,0 +1,21 @@
|
||||
<?php namespace Flarum\Core\Users\Events;
|
||||
|
||||
use Flarum\Core\Users\User;
|
||||
|
||||
class UserWasDeleted
|
||||
{
|
||||
/**
|
||||
* The user who was deleted.
|
||||
*
|
||||
* @var User
|
||||
*/
|
||||
public $user;
|
||||
|
||||
/**
|
||||
* @param User $user The user who was deleted.
|
||||
*/
|
||||
public function __construct(User $user)
|
||||
{
|
||||
$this->user = $user;
|
||||
}
|
||||
}
|
21
src/Core/Users/Events/UserWasRegistered.php
Normal file
21
src/Core/Users/Events/UserWasRegistered.php
Normal file
@@ -0,0 +1,21 @@
|
||||
<?php namespace Flarum\Core\Users\Events;
|
||||
|
||||
use Flarum\Core\Users\User;
|
||||
|
||||
class UserWasRegistered
|
||||
{
|
||||
/**
|
||||
* The user who was registered.
|
||||
*
|
||||
* @var User
|
||||
*/
|
||||
public $user;
|
||||
|
||||
/**
|
||||
* @param User $user The user who was registered.
|
||||
*/
|
||||
public function __construct(User $user)
|
||||
{
|
||||
$this->user = $user;
|
||||
}
|
||||
}
|
21
src/Core/Users/Events/UserWasRenamed.php
Normal file
21
src/Core/Users/Events/UserWasRenamed.php
Normal file
@@ -0,0 +1,21 @@
|
||||
<?php namespace Flarum\Core\Users\Events;
|
||||
|
||||
use Flarum\Core\Users\User;
|
||||
|
||||
class UserWasRenamed
|
||||
{
|
||||
/**
|
||||
* The user who was renamed.
|
||||
*
|
||||
* @var User
|
||||
*/
|
||||
public $user;
|
||||
|
||||
/**
|
||||
* @param User $user The user who was renamed.
|
||||
*/
|
||||
public function __construct(User $user)
|
||||
{
|
||||
$this->user = $user;
|
||||
}
|
||||
}
|
39
src/Core/Users/Events/UserWillBeDeleted.php
Normal file
39
src/Core/Users/Events/UserWillBeDeleted.php
Normal file
@@ -0,0 +1,39 @@
|
||||
<?php namespace Flarum\Core\Users\Events;
|
||||
|
||||
use Flarum\Core\Users\User;
|
||||
|
||||
class UserWillBeDeleted
|
||||
{
|
||||
/**
|
||||
* The user who will be deleted.
|
||||
*
|
||||
* @var User
|
||||
*/
|
||||
public $user;
|
||||
|
||||
/**
|
||||
* The user who is performing the action.
|
||||
*
|
||||
* @var User
|
||||
*/
|
||||
public $actor;
|
||||
|
||||
/**
|
||||
* Any user input associated with the command.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $data;
|
||||
|
||||
/**
|
||||
* @param User $user The user who will be deleted.
|
||||
* @param User $actor The user performing the action.
|
||||
* @param array $data Any user input associated with the command.
|
||||
*/
|
||||
public function __construct(User $user, User $actor, array $data)
|
||||
{
|
||||
$this->user = $user;
|
||||
$this->actor = $actor;
|
||||
$this->data = $data;
|
||||
}
|
||||
}
|
39
src/Core/Users/Events/UserWillBeSaved.php
Normal file
39
src/Core/Users/Events/UserWillBeSaved.php
Normal file
@@ -0,0 +1,39 @@
|
||||
<?php namespace Flarum\Core\Users\Events;
|
||||
|
||||
use Flarum\Core\Users\User;
|
||||
|
||||
class UserWillBeSaved
|
||||
{
|
||||
/**
|
||||
* The user that will be saved.
|
||||
*
|
||||
* @var User
|
||||
*/
|
||||
public $user;
|
||||
|
||||
/**
|
||||
* The user who is performing the action.
|
||||
*
|
||||
* @var User
|
||||
*/
|
||||
public $actor;
|
||||
|
||||
/**
|
||||
* The attributes to update on the user.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $data;
|
||||
|
||||
/**
|
||||
* @param User $user The user that will be saved.
|
||||
* @param User $actor The user who is performing the action.
|
||||
* @param array $data The attributes to update on the user.
|
||||
*/
|
||||
public function __construct(User $user, User $actor, array $data)
|
||||
{
|
||||
$this->user = $user;
|
||||
$this->actor = $actor;
|
||||
$this->data = $data;
|
||||
}
|
||||
}
|
36
src/Core/Users/Group.php
Executable file
36
src/Core/Users/Group.php
Executable file
@@ -0,0 +1,36 @@
|
||||
<?php namespace Flarum\Core\Users;
|
||||
|
||||
use Flarum\Core\Model;
|
||||
|
||||
class Group extends Model
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected $table = 'groups';
|
||||
|
||||
/**
|
||||
* The ID of the administrator group.
|
||||
*/
|
||||
const ADMINISTRATOR_ID = 1;
|
||||
|
||||
/**
|
||||
* The ID of the guest group.
|
||||
*/
|
||||
const GUEST_ID = 2;
|
||||
|
||||
/**
|
||||
* The ID of the member group.
|
||||
*/
|
||||
const MEMBER_ID = 3;
|
||||
|
||||
/**
|
||||
* Define the relationship with the group's users.
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
|
||||
*/
|
||||
public function users()
|
||||
{
|
||||
return $this->belongsToMany('Flarum\Core\Users\User', 'users_groups');
|
||||
}
|
||||
}
|
33
src/Core/Users/Guest.php
Executable file
33
src/Core/Users/Guest.php
Executable file
@@ -0,0 +1,33 @@
|
||||
<?php namespace Flarum\Core\Users;
|
||||
|
||||
class Guest extends User
|
||||
{
|
||||
/**
|
||||
* Override the ID of this user, as a guest does not have an ID.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
public $id = 0;
|
||||
|
||||
/**
|
||||
* Get the guest's group, containing only the 'guests' group model.
|
||||
*
|
||||
* @return \Flarum\Core\Models\Group
|
||||
*/
|
||||
public function getGroupsAttribute()
|
||||
{
|
||||
if (! isset($this->attributes['groups'])) {
|
||||
$this->attributes['groups'] = $this->relations['groups'] = Group::where('id', Group::GUEST_ID)->get();
|
||||
}
|
||||
|
||||
return $this->attributes['groups'];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function isGuest()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
97
src/Core/Users/Listeners/EmailConfirmationMailer.php
Executable file
97
src/Core/Users/Listeners/EmailConfirmationMailer.php
Executable file
@@ -0,0 +1,97 @@
|
||||
<?php namespace Flarum\Core\Users\Listeners;
|
||||
|
||||
use Flarum\Core\Users\Events\UserWasRegistered;
|
||||
use Flarum\Core\Users\Events\UserEmailChangeWasRequested;
|
||||
use Flarum\Core;
|
||||
use Flarum\Core\Users\EmailToken;
|
||||
use Flarum\Core\Users\User;
|
||||
use Illuminate\Contracts\Events\Dispatcher;
|
||||
use Illuminate\Contracts\Mail\Mailer;
|
||||
use Illuminate\Mail\Message;
|
||||
|
||||
class EmailConfirmationMailer
|
||||
{
|
||||
/**
|
||||
* @var Mailer
|
||||
*/
|
||||
protected $mailer;
|
||||
|
||||
/**
|
||||
* @param Mailer $mailer
|
||||
*/
|
||||
public function __construct(Mailer $mailer)
|
||||
{
|
||||
$this->mailer = $mailer;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Dispatcher $events
|
||||
*/
|
||||
public function subscribe(Dispatcher $events)
|
||||
{
|
||||
$events->listen(UserWasRegistered::class, __CLASS__.'@whenUserWasRegistered');
|
||||
$events->listen(UserEmailChangeWasRequested::class, __CLASS__.'@whenUserEmailChangeWasRequested');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param UserWasRegistered $event
|
||||
*/
|
||||
public function whenUserWasRegistered(UserWasRegistered $event)
|
||||
{
|
||||
$user = $event->user;
|
||||
$data = $this->getEmailData($user, $user->email);
|
||||
|
||||
$this->mailer->send(['text' => 'flarum::emails.activateAccount'], $data, function (Message $message) use ($user) {
|
||||
$message->to($user->email);
|
||||
$message->subject('Activate Your New Account');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @param UserEmailChangeWasRequested $event
|
||||
*/
|
||||
public function whenUserEmailChangeWasRequested(UserEmailChangeWasRequested $event)
|
||||
{
|
||||
$email = $event->email;
|
||||
$data = $this->getEmailData($event->user, $email);
|
||||
|
||||
$this->mailer->send(['text' => 'flarum::emails.confirmEmail'], $data, function (Message $message) use ($email) {
|
||||
$message->to($email);
|
||||
$message->subject('Confirm Your New Email Address');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @param User $user
|
||||
* @param string $email
|
||||
* @return EmailToken
|
||||
*/
|
||||
protected function generateToken(User $user, $email)
|
||||
{
|
||||
$token = EmailToken::generate($user->id, $email);
|
||||
$token->save();
|
||||
|
||||
return $token;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the data that should be made available to email templates.
|
||||
*
|
||||
* @param User $user
|
||||
* @param string $email
|
||||
* @return array
|
||||
*/
|
||||
protected function getEmailData(User $user, $email)
|
||||
{
|
||||
$token = $this->generateToken($user, $email);
|
||||
|
||||
// TODO: Need to use UrlGenerator, but since this is part of core we
|
||||
// don't know that the forum routes will be loaded. Should the confirm
|
||||
// email route be part of core??
|
||||
return [
|
||||
'username' => $user->username,
|
||||
'url' => Core::config('base_url').'/confirm/'.$token->id,
|
||||
'forumTitle' => Core::config('forum_title')
|
||||
];
|
||||
}
|
||||
}
|
94
src/Core/Users/Listeners/UserMetadataUpdater.php
Executable file
94
src/Core/Users/Listeners/UserMetadataUpdater.php
Executable file
@@ -0,0 +1,94 @@
|
||||
<?php namespace Flarum\Core\Users\Listeners;
|
||||
|
||||
use Flarum\Core\Users\User;
|
||||
use Flarum\Core\Posts\Events\PostWasPosted;
|
||||
use Flarum\Core\Posts\Events\PostWasDeleted;
|
||||
use Flarum\Core\Posts\Events\PostWasHidden;
|
||||
use Flarum\Core\Posts\Events\PostWasRestored;
|
||||
use Flarum\Core\Discussions\Events\DiscussionWasStarted;
|
||||
use Flarum\Core\Discussions\Events\DiscussionWasDeleted;
|
||||
use Illuminate\Contracts\Events\Dispatcher;
|
||||
|
||||
class UserMetadataUpdater
|
||||
{
|
||||
/**
|
||||
* @param Dispatcher $events
|
||||
*/
|
||||
public function subscribe(Dispatcher $events)
|
||||
{
|
||||
$events->listen(PostWasPosted::class, __CLASS__.'@whenPostWasPosted');
|
||||
$events->listen(PostWasDeleted::class, __CLASS__.'@whenPostWasDeleted');
|
||||
$events->listen(PostWasHidden::class, __CLASS__.'@whenPostWasHidden');
|
||||
$events->listen(PostWasRestored::class, __CLASS__.'@whenPostWasRestored');
|
||||
$events->listen(DiscussionWasStarted::class, __CLASS__.'@whenDiscussionWasStarted');
|
||||
$events->listen(DiscussionWasDeleted::class, __CLASS__.'@whenDiscussionWasDeleted');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param PostWasPosted $event
|
||||
*/
|
||||
public function whenPostWasPosted(PostWasPosted $event)
|
||||
{
|
||||
$this->updateCommentsCount($event->post->user, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param PostWasDeleted $event
|
||||
*/
|
||||
public function whenPostWasDeleted(PostWasDeleted $event)
|
||||
{
|
||||
$this->updateCommentsCount($event->post->user, -1);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param PostWasHidden $event
|
||||
*/
|
||||
public function whenPostWasHidden(PostWasHidden $event)
|
||||
{
|
||||
$this->updateCommentsCount($event->post->user, -1);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param PostWasRestored $event
|
||||
*/
|
||||
public function whenPostWasRestored(PostWasRestored $event)
|
||||
{
|
||||
$this->updateCommentsCount($event->post->user, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param DiscussionWasStarted $event
|
||||
*/
|
||||
public function whenDiscussionWasStarted(DiscussionWasStarted $event)
|
||||
{
|
||||
$this->updateDiscussionsCount($event->discussion->startUser, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param DiscussionWasDeleted $event
|
||||
*/
|
||||
public function whenDiscussionWasDeleted(DiscussionWasDeleted $event)
|
||||
{
|
||||
$this->updateDiscussionsCount($event->discussion->startUser, -1);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param User $user
|
||||
* @param int $amount
|
||||
*/
|
||||
protected function updateCommentsCount(User $user, $amount)
|
||||
{
|
||||
$user->comments_count += $amount;
|
||||
$user->save();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param User $user
|
||||
* @param int $amount
|
||||
*/
|
||||
protected function updateDiscussionsCount(User $user, $amount)
|
||||
{
|
||||
$user->discussions_count += $amount;
|
||||
$user->save();
|
||||
}
|
||||
}
|
45
src/Core/Users/PasswordToken.php
Normal file
45
src/Core/Users/PasswordToken.php
Normal file
@@ -0,0 +1,45 @@
|
||||
<?php namespace Flarum\Core\Users;
|
||||
|
||||
use Flarum\Core\Model;
|
||||
|
||||
class PasswordToken extends Model
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected $table = 'password_tokens';
|
||||
|
||||
/**
|
||||
* Use a custom primary key for this model.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
public $incrementing = false;
|
||||
|
||||
/**
|
||||
* Generate a password token for the specified user.
|
||||
*
|
||||
* @param int $userId
|
||||
* @return static
|
||||
*/
|
||||
public static function generate($userId)
|
||||
{
|
||||
$token = new static;
|
||||
|
||||
$token->id = str_random(40);
|
||||
$token->user_id = $userId;
|
||||
$token->created_at = time();
|
||||
|
||||
return $token;
|
||||
}
|
||||
|
||||
/**
|
||||
* Define the relationship with the owner of this password token.
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
|
||||
*/
|
||||
public function user()
|
||||
{
|
||||
return $this->belongsTo('Flarum\Core\Users\User');
|
||||
}
|
||||
}
|
7
src/Core/Users/Permission.php
Normal file
7
src/Core/Users/Permission.php
Normal file
@@ -0,0 +1,7 @@
|
||||
<?php namespace Flarum\Core\Users;
|
||||
|
||||
use Flarum\Core\Model;
|
||||
|
||||
class Permission extends Model
|
||||
{
|
||||
}
|
33
src/Core/Users/Search/Gambits/FulltextGambit.php
Normal file
33
src/Core/Users/Search/Gambits/FulltextGambit.php
Normal file
@@ -0,0 +1,33 @@
|
||||
<?php namespace Flarum\Core\Users\Search\Gambits;
|
||||
|
||||
use Flarum\Core\Users\UserRepositoryInterface;
|
||||
use Flarum\Core\Search\Search;
|
||||
use Flarum\Core\Search\GambitInterface;
|
||||
|
||||
class FulltextGambit implements GambitInterface
|
||||
{
|
||||
/**
|
||||
* @var UserRepositoryInterface
|
||||
*/
|
||||
protected $users;
|
||||
|
||||
/**
|
||||
* @param UserRepositoryInterface $users
|
||||
*/
|
||||
public function __construct(UserRepositoryInterface $users)
|
||||
{
|
||||
$this->users = $users;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function apply(Search $search, $bit)
|
||||
{
|
||||
$users = $this->users->getIdsForUsername($bit, $search->getActor());
|
||||
|
||||
$search->getQuery()->whereIn('id', $users);
|
||||
|
||||
$search->setDefaultSort(['id' => $users]);
|
||||
}
|
||||
}
|
7
src/Core/Users/Search/UserSearch.php
Normal file
7
src/Core/Users/Search/UserSearch.php
Normal file
@@ -0,0 +1,7 @@
|
||||
<?php namespace Flarum\Core\Users\Search;
|
||||
|
||||
use Flarum\Core\Search\Search;
|
||||
|
||||
class UserSearch extends Search
|
||||
{
|
||||
}
|
76
src/Core/Users/Search/UserSearcher.php
Normal file
76
src/Core/Users/Search/UserSearcher.php
Normal file
@@ -0,0 +1,76 @@
|
||||
<?php namespace Flarum\Core\Users\Search;
|
||||
|
||||
use Flarum\Core\Search\AppliesParametersToSearch;
|
||||
use Flarum\Core\Search\GambitManager;
|
||||
use Flarum\Core\Search\SearchCriteria;
|
||||
use Flarum\Core\Search\SearchResults;
|
||||
use Flarum\Core\Users\UserRepositoryInterface;
|
||||
use Flarum\Core\Users\Events\UserSearchWillBePerformed;
|
||||
|
||||
/**
|
||||
* Takes a UserSearchCriteria object, performs a search using gambits,
|
||||
* and spits out a UserSearchResults object.
|
||||
*/
|
||||
class UserSearcher
|
||||
{
|
||||
use AppliesParametersToSearch;
|
||||
|
||||
/**
|
||||
* @var GambitManager
|
||||
*/
|
||||
protected $gambits;
|
||||
|
||||
/**
|
||||
* @var UserRepositoryInterface
|
||||
*/
|
||||
protected $users;
|
||||
|
||||
/**
|
||||
* @param GambitManager $gambits
|
||||
* @param UserRepositoryInterface $users
|
||||
*/
|
||||
public function __construct(GambitManager $gambits, UserRepositoryInterface $users)
|
||||
{
|
||||
$this->gambits = $gambits;
|
||||
$this->users = $users;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param SearchCriteria $criteria
|
||||
* @param int|null $limit
|
||||
* @param int $offset
|
||||
* @param array $load An array of relationships to load on the results.
|
||||
* @return SearchResults
|
||||
*/
|
||||
public function search(SearchCriteria $criteria, $limit = null, $offset = 0, array $load = [])
|
||||
{
|
||||
$actor = $criteria->actor;
|
||||
|
||||
$query = $this->users->query()->whereVisibleTo($actor);
|
||||
|
||||
// Construct an object which represents this search for users.
|
||||
// Apply gambits to it, sort, and paging criteria. Also give extensions
|
||||
// an opportunity to modify it.
|
||||
$search = new UserSearch($query->getQuery(), $actor);
|
||||
|
||||
$this->gambits->apply($search, $criteria->query);
|
||||
$this->applySort($search, $criteria->sort);
|
||||
$this->applyOffset($search, $offset);
|
||||
$this->applyLimit($search, $limit + 1);
|
||||
|
||||
event(new UserSearchWillBePerformed($search, $criteria));
|
||||
|
||||
// Execute the search query and retrieve the results. We get one more
|
||||
// results than the user asked for, so that we can say if there are more
|
||||
// results. If there are, we will get rid of that extra result.
|
||||
$users = $query->get();
|
||||
|
||||
if ($areMoreResults = ($limit > 0 && $users->count() > $limit)) {
|
||||
$users->pop();
|
||||
}
|
||||
|
||||
$users->load($load);
|
||||
|
||||
return new SearchResults($users, $areMoreResults);
|
||||
}
|
||||
}
|
589
src/Core/Users/User.php
Executable file
589
src/Core/Users/User.php
Executable file
@@ -0,0 +1,589 @@
|
||||
<?php namespace Flarum\Core\Users;
|
||||
|
||||
use Flarum\Core\Model;
|
||||
use Flarum\Core\Notifications\Notification;
|
||||
use Illuminate\Contracts\Hashing\Hasher;
|
||||
use Flarum\Core\Formatter\FormatterManager;
|
||||
use Flarum\Core\Users\Events\UserWasDeleted;
|
||||
use Flarum\Core\Users\Events\UserWasRegistered;
|
||||
use Flarum\Core\Users\Events\UserWasRenamed;
|
||||
use Flarum\Core\Users\Events\UserEmailWasChanged;
|
||||
use Flarum\Core\Users\Events\UserPasswordWasChanged;
|
||||
use Flarum\Core\Users\Events\UserBioWasChanged;
|
||||
use Flarum\Core\Users\Events\UserAvatarWasChanged;
|
||||
use Flarum\Core\Users\Events\UserWasActivated;
|
||||
use Flarum\Core\Users\Events\UserEmailChangeWasRequested;
|
||||
use Flarum\Core\Support\Locked;
|
||||
use Flarum\Core\Support\VisibleScope;
|
||||
use Flarum\Core\Support\EventGenerator;
|
||||
|
||||
class User extends Model
|
||||
{
|
||||
use EventGenerator;
|
||||
use Locked;
|
||||
use VisibleScope;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected $table = 'users';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $dateAttributes = [
|
||||
'join_time',
|
||||
'last_seen_time',
|
||||
'read_time',
|
||||
'notification_read_time'
|
||||
];
|
||||
|
||||
/**
|
||||
* The text formatter instance.
|
||||
*
|
||||
* @var FormatterManager
|
||||
*/
|
||||
protected static $formatter;
|
||||
|
||||
/**
|
||||
* The validation rules for this model.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $rules = [
|
||||
'username' => 'required|alpha_dash|unique',
|
||||
'email' => 'required|email|unique',
|
||||
'password' => 'required',
|
||||
'join_time' => 'date',
|
||||
'last_seen_time' => 'date',
|
||||
'discussions_count' => 'integer',
|
||||
'posts_count' => 'integer',
|
||||
];
|
||||
|
||||
/**
|
||||
* The hasher with which to hash passwords.
|
||||
*
|
||||
* @var \Illuminate\Contracts\Hashing\Hasher
|
||||
*/
|
||||
protected static $hasher;
|
||||
|
||||
/**
|
||||
* An array of registered user preferences. Each preference is defined with
|
||||
* a key, and its value is an array containing the following keys:
|
||||
*
|
||||
* - transformer: a callback that confines the value of the preference
|
||||
* - default: a default value if the preference isn't set
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected static $preferences = [];
|
||||
|
||||
/**
|
||||
* Boot the model.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function boot()
|
||||
{
|
||||
parent::boot();
|
||||
|
||||
static::deleted(function ($user) {
|
||||
$user->raise(new UserWasDeleted($user));
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a new user.
|
||||
*
|
||||
* @param string $username
|
||||
* @param string $email
|
||||
* @param string $password
|
||||
* @return static
|
||||
*/
|
||||
public static function register($username, $email, $password)
|
||||
{
|
||||
$user = new static;
|
||||
|
||||
$user->username = $username;
|
||||
$user->email = $email;
|
||||
$user->password = $password;
|
||||
$user->join_time = time();
|
||||
|
||||
$user->raise(new UserWasRegistered($user));
|
||||
|
||||
return $user;
|
||||
}
|
||||
|
||||
/**
|
||||
* Rename the user.
|
||||
*
|
||||
* @param string $username
|
||||
* @return $this
|
||||
*/
|
||||
public function rename($username)
|
||||
{
|
||||
if ($username !== $this->username) {
|
||||
$this->username = $username;
|
||||
|
||||
$this->raise(new UserWasRenamed($this));
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Change the user's email.
|
||||
*
|
||||
* @param string $email
|
||||
* @return $this
|
||||
*/
|
||||
public function changeEmail($email)
|
||||
{
|
||||
if ($email !== $this->email) {
|
||||
$this->email = $email;
|
||||
|
||||
$this->raise(new UserEmailWasChanged($this));
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Request that the user's email be changed.
|
||||
*
|
||||
* @param string $email
|
||||
* @return $this
|
||||
*/
|
||||
public function requestEmailChange($email)
|
||||
{
|
||||
if ($email !== $this->email) {
|
||||
$validator = static::$validator->make(
|
||||
compact('email'),
|
||||
$this->expandUniqueRules(array_only(static::$rules, 'email'))
|
||||
);
|
||||
|
||||
if ($validator->fails()) {
|
||||
$this->throwValidationFailureException($validator);
|
||||
}
|
||||
|
||||
$this->raise(new UserEmailChangeWasRequested($this, $email));
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Change the user's password.
|
||||
*
|
||||
* @param string $password
|
||||
* @return $this
|
||||
*/
|
||||
public function changePassword($password)
|
||||
{
|
||||
$this->password = $password;
|
||||
|
||||
$this->raise(new UserPasswordWasChanged($this));
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the password attribute, storing it as a hash.
|
||||
*
|
||||
* @param string $value
|
||||
*/
|
||||
public function setPasswordAttribute($value)
|
||||
{
|
||||
$this->attributes['password'] = $value ? static::$hasher->make($value) : '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Change the user's bio.
|
||||
*
|
||||
* @param string $bio
|
||||
* @return $this
|
||||
*/
|
||||
public function changeBio($bio)
|
||||
{
|
||||
$this->bio = $bio;
|
||||
$this->bio_html = null;
|
||||
|
||||
$this->raise(new UserBioWasChanged($this));
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the user's bio formatted as HTML.
|
||||
*
|
||||
* @param string $value
|
||||
* @return string
|
||||
*/
|
||||
public function getBioHtmlAttribute($value)
|
||||
{
|
||||
if ($value === null) {
|
||||
$this->bio_html = $value = static::formatBio($this);
|
||||
$this->save();
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Mark all discussions as read.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function markAllAsRead()
|
||||
{
|
||||
$this->read_time = time();
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Mark all notifications as read.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function markNotificationsAsRead()
|
||||
{
|
||||
$this->notification_read_time = time();
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Change the path of the user avatar.
|
||||
*
|
||||
* @param string $path
|
||||
* @return $this
|
||||
*/
|
||||
public function changeAvatarPath($path)
|
||||
{
|
||||
$this->avatar_path = $path;
|
||||
|
||||
$this->raise(new UserAvatarWasChanged($this));
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the URL of the user's avatar.
|
||||
*
|
||||
* @todo Allow different storage locations to be used
|
||||
* @return string
|
||||
*/
|
||||
public function getAvatarUrlAttribute()
|
||||
{
|
||||
return $this->avatar_path ? app('Flarum\Http\UrlGeneratorInterface')->toAsset('assets/avatars/'.$this->avatar_path) : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a given password matches the user's password.
|
||||
*
|
||||
* @param string $password
|
||||
* @return boolean
|
||||
*/
|
||||
public function checkPassword($password)
|
||||
{
|
||||
return static::$hasher->check($password, $this->password);
|
||||
}
|
||||
|
||||
/**
|
||||
* Activate the user's account.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function activate()
|
||||
{
|
||||
$this->is_activated = true;
|
||||
|
||||
$this->raise(new UserWasActivated($this));
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether the user has a certain permission based on their groups.
|
||||
*
|
||||
* @param string $permission
|
||||
* @return boolean
|
||||
*/
|
||||
public function hasPermission($permission)
|
||||
{
|
||||
if ($this->isAdmin()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (! array_key_exists('permissions', $this->relations)) {
|
||||
$this->setRelation('permissions', $this->permissions()->get());
|
||||
}
|
||||
|
||||
return (bool) $this->permissions->contains('permission', $permission);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the notification types that should be alerted to this user, according
|
||||
* to their preferences.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getAlertableNotificationTypes()
|
||||
{
|
||||
$types = array_keys(Notification::getSubjectModels());
|
||||
|
||||
return array_filter($types, [$this, 'shouldAlert']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the number of unread notifications for the user.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function getUnreadNotificationsCount()
|
||||
{
|
||||
return $this->notifications()
|
||||
->whereIn('type', $this->getAlertableNotificationTypes())
|
||||
->where('time', '>', $this->notification_read_time ?: 0)
|
||||
->where('is_read', 0)
|
||||
->count($this->getConnection()->raw('DISTINCT type, subject_id'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the values of all registered preferences for this user, by
|
||||
* transforming their stored preferences and merging them with the defaults.
|
||||
*
|
||||
* @param string $value
|
||||
* @return array
|
||||
*/
|
||||
public function getPreferencesAttribute($value)
|
||||
{
|
||||
$defaults = array_build(static::$preferences, function ($key, $value) {
|
||||
return [$key, $value['default']];
|
||||
});
|
||||
|
||||
$user = array_only((array) json_decode($value, true), array_keys(static::$preferences));
|
||||
|
||||
return array_merge($defaults, $user);
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode an array of preferences for storage in the database.
|
||||
*
|
||||
* @param mixed $value
|
||||
*/
|
||||
public function setPreferencesAttribute($value)
|
||||
{
|
||||
$this->attributes['preferences'] = json_encode($value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether or not the user should receive an alert for a notification
|
||||
* type.
|
||||
*
|
||||
* @param string $type
|
||||
* @return bool
|
||||
*/
|
||||
public function shouldAlert($type)
|
||||
{
|
||||
return (bool) $this->getPreference(static::getNotificationPreferenceKey($type, 'alert'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether or not the user should receive an email for a notification
|
||||
* type.
|
||||
*
|
||||
* @param string $type
|
||||
* @return bool
|
||||
*/
|
||||
public function shouldEmail($type)
|
||||
{
|
||||
return (bool) $this->getPreference(static::getNotificationPreferenceKey($type, 'email'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value of a preference for this user.
|
||||
*
|
||||
* @param string $key
|
||||
* @param mixed $default
|
||||
* @return mixed
|
||||
*/
|
||||
public function getPreference($key, $default = null)
|
||||
{
|
||||
return array_get($this->preferences, $key, $default);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the value of a preference for this user.
|
||||
*
|
||||
* @param string $key
|
||||
* @param mixed $value
|
||||
* @return $this
|
||||
*/
|
||||
public function setPreference($key, $value)
|
||||
{
|
||||
if (isset(static::$preferences[$key])) {
|
||||
$preferences = $this->preferences;
|
||||
|
||||
if (! is_null($transformer = static::$preferences[$key]['transformer'])) {
|
||||
$preferences[$key] = call_user_func($transformer, $value);
|
||||
} else {
|
||||
$preferences[$key] = $value;
|
||||
}
|
||||
|
||||
$this->preferences = $preferences;
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the user as being last seen just now.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function updateLastSeen()
|
||||
{
|
||||
$this->last_seen_time = time();
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether or not the user is an administrator.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isAdmin()
|
||||
{
|
||||
return $this->groups->contains(Group::ADMINISTRATOR_ID);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether or not the user is a guest.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isGuest()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Define the relationship with the user's activity.
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Relations\HasMany
|
||||
*/
|
||||
public function activity()
|
||||
{
|
||||
return $this->hasMany('Flarum\Core\Activity\Activity');
|
||||
}
|
||||
|
||||
/**
|
||||
* Define the relationship with the user's groups.
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
|
||||
*/
|
||||
public function groups()
|
||||
{
|
||||
return $this->belongsToMany('Flarum\Core\Users\Group', 'users_groups');
|
||||
}
|
||||
|
||||
/**
|
||||
* Define the relationship with the user's notifications.
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Relations\HasMany
|
||||
*/
|
||||
public function notifications()
|
||||
{
|
||||
return $this->hasMany('Flarum\Core\Notifications\Notification');
|
||||
}
|
||||
|
||||
/**
|
||||
* Define the relationship with the permissions of all of the groups that
|
||||
* the user is in.
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Builder
|
||||
*/
|
||||
public function permissions()
|
||||
{
|
||||
$groupIds = [Group::GUEST_ID];
|
||||
|
||||
// If a user's account hasn't been activated, they are essentially no
|
||||
// more than a guest. If they are activated, we can give them the
|
||||
// standard 'member' group, as well as any other groups they've been
|
||||
// assigned to.
|
||||
if ($this->is_activated) {
|
||||
$groupIds = array_merge($groupIds, [Group::MEMBER_ID], $this->groups->lists('id'));
|
||||
}
|
||||
|
||||
return Permission::whereIn('group_id', $groupIds);
|
||||
}
|
||||
|
||||
/**
|
||||
* Define the relationship with the user's access tokens.
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Relations\HasMany
|
||||
*/
|
||||
public function accessTokens()
|
||||
{
|
||||
return $this->hasMany('Flarum\Api\AccessToken');
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the hasher with which to hash passwords.
|
||||
*
|
||||
* @param \Illuminate\Contracts\Hashing\Hasher $hasher
|
||||
*/
|
||||
public static function setHasher(Hasher $hasher)
|
||||
{
|
||||
static::$hasher = $hasher;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the text formatter instance.
|
||||
*
|
||||
* @param FormatterManager $formatter
|
||||
*/
|
||||
public static function setFormatter(FormatterManager $formatter)
|
||||
{
|
||||
static::$formatter = $formatter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the formatted content of a user's bio.
|
||||
*
|
||||
* @param User $user
|
||||
* @return string
|
||||
*/
|
||||
protected static function formatBio(User $user)
|
||||
{
|
||||
return static::$formatter->format($user->bio, $user);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a preference with a transformer and a default value.
|
||||
*
|
||||
* @param string $key
|
||||
* @param callable $transformer
|
||||
* @param mixed $default
|
||||
*/
|
||||
public static function addPreference($key, callable $transformer = null, $default = null)
|
||||
{
|
||||
static::$preferences[$key] = compact('transformer', 'default');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the key for a preference which flags whether or not the user will
|
||||
* receive a notification for $type via $method.
|
||||
*
|
||||
* @param string $type
|
||||
* @param string $method
|
||||
* @return string
|
||||
*/
|
||||
public static function getNotificationPreferenceKey($type, $method)
|
||||
{
|
||||
return 'notify_'.$type.'_'.$method;
|
||||
}
|
||||
}
|
58
src/Core/Users/UserRepositoryInterface.php
Normal file
58
src/Core/Users/UserRepositoryInterface.php
Normal file
@@ -0,0 +1,58 @@
|
||||
<?php namespace Flarum\Core\Users;
|
||||
|
||||
interface UserRepositoryInterface
|
||||
{
|
||||
/**
|
||||
* Get a new query builder for the users table.
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Builder
|
||||
*/
|
||||
public function query();
|
||||
|
||||
/**
|
||||
* Find a user by ID, optionally making sure it is visible to a certain
|
||||
* user, or throw an exception.
|
||||
*
|
||||
* @param int $id
|
||||
* @param User $actor
|
||||
* @return User
|
||||
*
|
||||
* @throws \Illuminate\Database\Eloquent\ModelNotFoundException
|
||||
*/
|
||||
public function findOrFail($id, User $actor = null);
|
||||
|
||||
/**
|
||||
* Find a user by an identification (username or email).
|
||||
*
|
||||
* @param string $identification
|
||||
* @return User|null
|
||||
*/
|
||||
public function findByIdentification($identification);
|
||||
|
||||
/**
|
||||
* Find a user by email.
|
||||
*
|
||||
* @param string $email
|
||||
* @return User|null
|
||||
*/
|
||||
public function findByEmail($email);
|
||||
|
||||
/**
|
||||
* Get the ID of a user with the given username.
|
||||
*
|
||||
* @param string $username
|
||||
* @param User|null $actor
|
||||
* @return integer|null
|
||||
*/
|
||||
public function getIdForUsername($username, User $actor = null);
|
||||
|
||||
/**
|
||||
* Find users by matching a string of words against their username,
|
||||
* optionally making sure they are visible to a certain user.
|
||||
*
|
||||
* @param string $string
|
||||
* @param User|null $actor
|
||||
* @return array
|
||||
*/
|
||||
public function getIdsForUsername($string, User $actor = null);
|
||||
}
|
86
src/Core/Users/UsersServiceProvider.php
Normal file
86
src/Core/Users/UsersServiceProvider.php
Normal file
@@ -0,0 +1,86 @@
|
||||
<?php namespace Flarum\Core\Users;
|
||||
|
||||
use Flarum\Core\Search\GambitManager;
|
||||
use Flarum\Support\ServiceProvider;
|
||||
use Flarum\Extend;
|
||||
use Illuminate\Contracts\Container\Container;
|
||||
|
||||
class UsersServiceProvider extends ServiceProvider
|
||||
{
|
||||
/**
|
||||
* Bootstrap the application events.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function boot()
|
||||
{
|
||||
$this->extend([
|
||||
new Extend\EventSubscriber('Flarum\Core\Users\Listeners\UserMetadataUpdater'),
|
||||
new Extend\EventSubscriber('Flarum\Core\Users\Listeners\EmailConfirmationMailer')
|
||||
]);
|
||||
|
||||
User::setHasher($this->app->make('hash'));
|
||||
User::setFormatter($this->app->make('flarum.formatter'));
|
||||
|
||||
User::addPreference('discloseOnline', 'boolval', true);
|
||||
User::addPreference('indexProfile', 'boolval', true);
|
||||
|
||||
User::allow('*', function (User $user, User $actor, $action) {
|
||||
return $actor->hasPermission('user.'.$action) ?: null;
|
||||
});
|
||||
|
||||
User::allow(['edit', 'delete'], function (User $user, User $actor) {
|
||||
return $user->id == $actor->id ?: null;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the service provider.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function register()
|
||||
{
|
||||
$this->app->bind(
|
||||
'Flarum\Core\Users\UserRepositoryInterface',
|
||||
'Flarum\Core\Users\EloquentUserRepository'
|
||||
);
|
||||
|
||||
$this->registerAvatarsFilesystem();
|
||||
$this->registerGambits();
|
||||
}
|
||||
|
||||
public function registerAvatarsFilesystem()
|
||||
{
|
||||
$avatarsFilesystem = function (Container $app) {
|
||||
return $app->make('Illuminate\Contracts\Filesystem\Factory')->disk('flarum-avatars')->getDriver();
|
||||
};
|
||||
|
||||
$this->app->when('Flarum\Core\Users\Commands\UploadAvatarHandler')
|
||||
->needs('League\Flysystem\FilesystemInterface')
|
||||
->give($avatarsFilesystem);
|
||||
|
||||
$this->app->when('Flarum\Core\Users\Commands\DeleteAvatarHandler')
|
||||
->needs('League\Flysystem\FilesystemInterface')
|
||||
->give($avatarsFilesystem);
|
||||
}
|
||||
|
||||
public function registerGambits()
|
||||
{
|
||||
$this->app->instance('flarum.userGambits', []);
|
||||
|
||||
$this->app->when('Flarum\Core\Users\Search\UserSearcher')
|
||||
->needs('Flarum\Core\Search\GambitManager')
|
||||
->give(function (Container $app) {
|
||||
$gambits = new GambitManager($app);
|
||||
|
||||
foreach ($app->make('flarum.userGambits') as $gambit) {
|
||||
$gambits->add($gambit);
|
||||
}
|
||||
|
||||
$gambits->setFulltextGambit('Flarum\Core\Users\Search\Gambits\FulltextGambit');
|
||||
|
||||
return $gambits;
|
||||
});
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user