diff options
author | Marvin Borner | 2018-06-28 21:15:57 +0200 |
---|---|---|
committer | Marvin Borner | 2018-06-28 21:15:57 +0200 |
commit | 15793496e8d56769c792cf39673c6e6dea3ec4d9 (patch) | |
tree | 1038f86603cdb52d7d9be5f125e5a88a25086995 /main/app/sprinkles/account/src | |
parent | 8781338896a0cfb47c871a0ecb13cd3fdee09d8e (diff) |
Preparing for complete rewrite..
Diffstat (limited to 'main/app/sprinkles/account/src')
47 files changed, 0 insertions, 5706 deletions
diff --git a/main/app/sprinkles/account/src/Account.php b/main/app/sprinkles/account/src/Account.php deleted file mode 100644 index 1faccf4..0000000 --- a/main/app/sprinkles/account/src/Account.php +++ /dev/null @@ -1,21 +0,0 @@ -<?php
-/**
- * UserFrosting (http://www.userfrosting.com)
- *
- * @link https://github.com/userfrosting/UserFrosting
- * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)
- */
-
-namespace UserFrosting\Sprinkle\Account;
-
-use UserFrosting\System\Sprinkle\Sprinkle;
-
-/**
- * Bootstrapper class for the 'account' sprinkle.
- *
- * @author Alex Weissman (https://alexanderweissman.com)
- */
-class Account extends Sprinkle
-{
-
-}
diff --git a/main/app/sprinkles/account/src/Authenticate/AuthGuard.php b/main/app/sprinkles/account/src/Authenticate/AuthGuard.php deleted file mode 100644 index 9603a87..0000000 --- a/main/app/sprinkles/account/src/Authenticate/AuthGuard.php +++ /dev/null @@ -1,55 +0,0 @@ -<?php
-/**
- * UserFrosting (http://www.userfrosting.com)
- *
- * @link https://github.com/userfrosting/UserFrosting
- * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)
- */
-
-namespace UserFrosting\Sprinkle\Account\Authenticate;
-
-use Psr\Http\Message\ResponseInterface;
-use Psr\Http\Message\ServerRequestInterface;
-use Slim\Http\Body;
-use UserFrosting\Sprinkle\Account\Authenticate\Exception\AuthExpiredException;
-
-/**
- * Middleware to catch requests that fail because they require user authentication.
- *
- * @author Alex Weissman (https://alexanderweissman.com)
- */
-class AuthGuard
-{
- /**
- * @var Authenticator
- */
- protected $authenticator;
-
- /**
- * Constructor.
- *
- * @param $authenticator Authenticator The current authentication object.
- */
- public function __construct($authenticator) {
- $this->authenticator = $authenticator;
- }
-
- /**
- * Invoke the AuthGuard middleware, throwing an exception if there is no authenticated user in the session.
- *
- * @param \Psr\Http\Message\ServerRequestInterface $request PSR7 request
- * @param \Psr\Http\Message\ResponseInterface $response PSR7 response
- * @param callable $next Next middleware
- *
- * @return \Psr\Http\Message\ResponseInterface
- */
- public function __invoke($request, $response, $next) {
- if (!$this->authenticator->check()) {
- throw new AuthExpiredException();
- } else {
- return $next($request, $response);
- }
-
- return $response;
- }
-}
diff --git a/main/app/sprinkles/account/src/Authenticate/Authenticator.php b/main/app/sprinkles/account/src/Authenticate/Authenticator.php deleted file mode 100644 index a4586e4..0000000 --- a/main/app/sprinkles/account/src/Authenticate/Authenticator.php +++ /dev/null @@ -1,407 +0,0 @@ -<?php
-/**
- * UserFrosting (http://www.userfrosting.com)
- *
- * @link https://github.com/userfrosting/UserFrosting
- * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)
- */
-
-namespace UserFrosting\Sprinkle\Account\Authenticate;
-
-use Birke\Rememberme\Authenticator as RememberMe;
-use Birke\Rememberme\Storage\PDOStorage as RememberMePDO;
-use Birke\Rememberme\Triplet as RememberMeTriplet;
-use Illuminate\Database\Capsule\Manager as Capsule;
-use UserFrosting\Session\Session;
-use UserFrosting\Sprinkle\Account\Authenticate\Exception\AccountDisabledException;
-use UserFrosting\Sprinkle\Account\Authenticate\Exception\AccountInvalidException;
-use UserFrosting\Sprinkle\Account\Authenticate\Exception\AccountNotVerifiedException;
-use UserFrosting\Sprinkle\Account\Authenticate\Exception\AuthCompromisedException;
-use UserFrosting\Sprinkle\Account\Authenticate\Exception\AuthExpiredException;
-use UserFrosting\Sprinkle\Account\Authenticate\Exception\InvalidCredentialsException;
-use UserFrosting\Sprinkle\Account\Database\Models\User;
-use UserFrosting\Sprinkle\Account\Facades\Password;
-use UserFrosting\Sprinkle\Core\Util\ClassMapper;
-
-/**
- * Handles authentication tasks.
- *
- * @author Alex Weissman (https://alexanderweissman.com)
- * Partially inspired by Laravel's Authentication component: https://github.com/laravel/framework/blob/5.3/src/Illuminate/Auth/SessionGuard.php
- */
-class Authenticator
-{
- /**
- * @var ClassMapper
- */
- protected $classMapper;
-
- /**
- * @var Session
- */
- protected $session;
-
- /**
- * @var Config
- */
- protected $config;
-
- /**
- * @var Cache
- */
- protected $cache;
-
- /**
- * @var bool
- */
- protected $loggedOut = FALSE;
-
- /**
- * @var RememberMePDO
- */
- protected $rememberMeStorage;
-
- /**
- * @var RememberMe
- */
- protected $rememberMe;
-
- /**
- * @var User
- */
- protected $user;
-
- /**
- * Indicates if the user was authenticated via a rememberMe cookie.
- *
- * @var bool
- */
- protected $viaRemember = FALSE;
-
- /**
- * Create a new Authenticator object.
- *
- * @param ClassMapper $classMapper Maps generic class identifiers to specific class names.
- * @param Session $session The session wrapper object that will store the user's id.
- * @param Config $config Config object that contains authentication settings.
- * @param mixed $cache Cache service instance
- */
- public function __construct(ClassMapper $classMapper, Session $session, $config, $cache) {
- $this->classMapper = $classMapper;
- $this->session = $session;
- $this->config = $config;
- $this->cache = $cache;
-
- // Initialize RememberMe storage
- $this->rememberMeStorage = new RememberMePDO($this->config['remember_me.table']);
-
- // Get the actual PDO instance from Eloquent
- $pdo = Capsule::connection()->getPdo();
-
- $this->rememberMeStorage->setConnection($pdo);
-
- // Set up RememberMe
- $this->rememberMe = new RememberMe($this->rememberMeStorage);
- // Set cookie name
- $cookieName = $this->config['session.name'] . '-' . $this->config['remember_me.cookie.name'];
- $this->rememberMe->getCookie()->setName($cookieName);
-
- // Change cookie path
- $this->rememberMe->getCookie()->setPath($this->config['remember_me.session.path']);
-
- // Set expire time, if specified
- if ($this->config->has('remember_me.expire_time') && ($this->config->has('remember_me.expire_time') != NULL)) {
- $this->rememberMe->getCookie()->setExpireTime($this->config['remember_me.expire_time']);
- }
-
- $this->user = NULL;
-
- $this->viaRemember = FALSE;
- }
-
- /**
- * Attempts to authenticate a user based on a supplied identity and password.
- *
- * If successful, the user's id is stored in session.
- */
- public function attempt($identityColumn, $identityValue, $password, $rememberMe = FALSE) {
- // Try to load the user, using the specified conditions
- $user = $this->classMapper->staticMethod('user', 'where', $identityColumn, $identityValue)->first();
-
- if (!$user) {
- throw new InvalidCredentialsException();
- }
-
- // Check that the user has a password set (so, rule out newly created accounts without a password)
- if (!$user->password) {
- throw new InvalidCredentialsException();
- }
-
- // Check that the user's account is enabled
- if ($user->flag_enabled == 0) {
- throw new AccountDisabledException();
- }
-
- // Check that the user's account is verified (if verification is required)
- if ($this->config['site.registration.require_email_verification'] && $user->flag_verified == 0) {
- throw new AccountNotVerifiedException();
- }
-
- // Here is my password. May I please assume the identify of this user now?
- if (Password::verify($password, $user->password)) {
- $this->login($user, $rememberMe);
- return $user;
- } else {
- // We know the password is at fault here (as opposed to the identity), but lets not give away the combination in case of someone bruteforcing
- throw new InvalidCredentialsException();
- }
- }
-
- /**
- * Determine if the current user is authenticated.
- *
- * @return bool
- */
- public function check() {
- return !is_null($this->user());
- }
-
- /**
- * Determine if the current user is a guest (unauthenticated).
- *
- * @return bool
- */
- public function guest() {
- return !$this->check();
- }
-
- /**
- * Process an account login request.
- *
- * This method logs in the specified user, allowing the client to assume the user's identity for the duration of the session.
- * @param User $user The user to log in.
- * @param bool $rememberMe Set to true to make this a "persistent session", i.e. one that will re-login even after the session expires.
- * @odo Figure out a way to update the currentUser service to reflect the logged-in user *immediately* in the service provider.
- * As it stands, the currentUser service will still reflect a "guest user" for the remainder of the request.
- */
- public function login($user, $rememberMe = FALSE) {
- $oldId = session_id();
- $this->session->regenerateId(TRUE);
-
- // Since regenerateId deletes the old session, we'll do the same in cache
- $this->flushSessionCache($oldId);
-
- // If the user wants to be remembered, create Rememberme cookie
- if ($rememberMe) {
- $this->rememberMe->createCookie($user->id);
- } else {
- $this->rememberMe->clearCookie();
- }
-
- // Assume identity
- $key = $this->config['session.keys.current_user_id'];
- $this->session[$key] = $user->id;
-
- // Set auth mode
- $this->viaRemember = FALSE;
-
- // User login actions
- $user->onLogin();
- }
-
- /**
- * Processes an account logout request.
- *
- * Logs the currently authenticated user out, destroying the PHP session and clearing the persistent session.
- * This can optionally remove persistent sessions across all browsers/devices, since there can be a "RememberMe" cookie
- * and corresponding database entries in multiple browsers/devices. See http://jaspan.com/improved_persistent_login_cookie_best_practice.
- *
- * @param bool $complete If set to true, will ensure that the user is logged out from *all* browsers on all devices.
- */
- public function logout($complete = FALSE) {
- $currentUserId = $this->session->get($this->config['session.keys.current_user_id']);
-
- // This removes all of the user's persistent logins from the database
- if ($complete) {
- $this->storage->cleanAllTriplets($currentUserId);
- }
-
- // Clear the rememberMe cookie
- $this->rememberMe->clearCookie();
-
- // User logout actions
- if ($currentUserId) {
- $currentUser = $this->classMapper->staticMethod('user', 'find', $currentUserId);
- if ($currentUser) {
- $currentUser->onLogout();
- }
- }
-
- $this->user = NULL;
- $this->loggedOut = TRUE;
-
- $oldId = session_id();
-
- // Completely destroy the session
- $this->session->destroy();
-
- // Since regenerateId deletes the old session, we'll do the same in cache
- $this->flushSessionCache($oldId);
-
- // Restart the session service
- $this->session->start();
- }
-
- /**
- * Try to get the currently authenticated user, returning a guest user if none was found.
- *
- * Tries to re-establish a session for "remember-me" users who have been logged out due to an expired session.
- * @return User|null
- * @throws AuthExpiredException
- * @throws AuthCompromisedException
- * @throws AccountInvalidException
- * @throws AccountDisabledException
- */
- public function user() {
- $user = NULL;
-
- if (!$this->loggedOut) {
-
- // Return any cached user
- if (!is_null($this->user)) {
- return $this->user;
- }
-
- // If this throws a PDOException we catch it and return null than allowing the exception to propagate.
- // This is because the error handler relies on Twig, which relies on a Twig Extension, which relies on the global current_user variable.
- // So, we really don't want this method to throw any database exceptions.
- try {
- // Now, check to see if we have a user in session
- $user = $this->loginSessionUser();
-
- // If no user was found in the session, try to login via RememberMe cookie
- if (!$user) {
- $user = $this->loginRememberedUser();
- }
- } catch (\PDOException $e) {
- $user = NULL;
- }
- }
-
- return $this->user = $user;
- }
-
- /**
- * Determine whether the current user was authenticated using a remember me cookie.
- *
- * This function is useful when users are performing sensitive operations, and you may want to force them to re-authenticate.
- * @return bool
- */
- public function viaRemember() {
- return $this->viaRemember;
- }
-
- /**
- * Attempt to log in the client from their rememberMe token (in their cookie).
- *
- * @return User|bool If successful, the User object of the remembered user. Otherwise, return false.
- * @throws AuthCompromisedException The client attempted to log in with an invalid rememberMe token.
- */
- protected function loginRememberedUser() {
- /** @var \Birke\Rememberme\LoginResult $loginResult */
- $loginResult = $this->rememberMe->login();
-
- if ($loginResult->isSuccess()) {
- // Update in session
- $this->session[$this->config['session.keys.current_user_id']] = $loginResult->getCredential();
- // There is a chance that an attacker has stolen the login token,
- // so we store the fact that the user was logged in via RememberMe (instead of login form)
- $this->viaRemember = TRUE;
- } else {
- // If $rememberMe->login() was not successful, check if the token was invalid as well. This means the cookie was stolen.
- if ($loginResult->hasPossibleManipulation()) {
- throw new AuthCompromisedException();
- }
- }
-
- return $this->validateUserAccount($loginResult->getCredential());
- }
-
- /**
- * Attempt to log in the client from the session.
- *
- * @return User|null If successful, the User object of the user in session. Otherwise, return null.
- * @throws AuthExpiredException The client attempted to use an expired rememberMe token.
- */
- protected function loginSessionUser() {
- $userId = $this->session->get($this->config['session.keys.current_user_id']);
-
- // If a user_id was found in the session, check any rememberMe cookie that was submitted.
- // If they submitted an expired rememberMe cookie, then we need to log them out.
- if ($userId) {
- if (!$this->validateRememberMeCookie()) {
- $this->logout();
- throw new AuthExpiredException();
- }
- }
-
- return $this->validateUserAccount($userId);
- }
-
- /**
- * Determine if the cookie contains a valid rememberMe token.
- *
- * @return bool
- */
- protected function validateRememberMeCookie() {
- $cookieValue = $this->rememberMe->getCookie()->getValue();
- if (!$cookieValue) {
- return TRUE;
- }
- $triplet = RememberMeTriplet::fromString($cookieValue);
- if (!$triplet->isValid()) {
- return FALSE;
- }
-
- return TRUE;
- }
-
- /**
- * Tries to load the specified user by id from the database.
- *
- * Checks that the account is valid and enabled, throwing an exception if not.
- * @param int $userId
- * @return User|null
- * @throws AccountInvalidException
- * @throws AccountDisabledException
- */
- protected function validateUserAccount($userId) {
- if ($userId) {
- $user = $this->classMapper->staticMethod('user', 'find', $userId);
-
- // If the user doesn't exist any more, throw an exception.
- if (!$user) {
- throw new AccountInvalidException();
- }
-
- // If the user has been disabled since their last request, throw an exception.
- if (!$user->flag_enabled) {
- throw new AccountDisabledException();
- }
-
- return $user;
- } else {
- return NULL;
- }
- }
-
- /**
- * Flush the cache associated with a session id
- *
- * @param string $id The session id
- * @return bool
- */
- public function flushSessionCache($id) {
- return $this->cache->tags('_s' . $id)->flush();
- }
-}
diff --git a/main/app/sprinkles/account/src/Authenticate/Exception/AccountDisabledException.php b/main/app/sprinkles/account/src/Authenticate/Exception/AccountDisabledException.php deleted file mode 100644 index 314fcc3..0000000 --- a/main/app/sprinkles/account/src/Authenticate/Exception/AccountDisabledException.php +++ /dev/null @@ -1,22 +0,0 @@ -<?php
-/**
- * UserFrosting (http://www.userfrosting.com)
- *
- * @link https://github.com/userfrosting/UserFrosting
- * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)
- */
-
-namespace UserFrosting\Sprinkle\Account\Authenticate\Exception;
-
-use UserFrosting\Support\Exception\HttpException;
-
-/**
- * Disabled account exception. Used when an account has been disabled.
- *
- * @author Alex Weissman (https://alexanderweissman.com)
- */
-class AccountDisabledException extends HttpException
-{
- protected $defaultMessage = 'ACCOUNT.DISABLED';
- protected $httpErrorCode = 403;
-}
diff --git a/main/app/sprinkles/account/src/Authenticate/Exception/AccountInvalidException.php b/main/app/sprinkles/account/src/Authenticate/Exception/AccountInvalidException.php deleted file mode 100644 index bc42b62..0000000 --- a/main/app/sprinkles/account/src/Authenticate/Exception/AccountInvalidException.php +++ /dev/null @@ -1,22 +0,0 @@ -<?php
-/**
- * UserFrosting (http://www.userfrosting.com)
- *
- * @link https://github.com/userfrosting/UserFrosting
- * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)
- */
-
-namespace UserFrosting\Sprinkle\Account\Authenticate\Exception;
-
-use UserFrosting\Support\Exception\HttpException;
-
-/**
- * Invalid account exception. Used when an account has been removed during an active session.
- *
- * @author Alex Weissman (https://alexanderweissman.com)
- */
-class AccountInvalidException extends HttpException
-{
- protected $defaultMessage = 'ACCOUNT.INVALID';
- protected $httpErrorCode = 403;
-}
diff --git a/main/app/sprinkles/account/src/Authenticate/Exception/AccountNotVerifiedException.php b/main/app/sprinkles/account/src/Authenticate/Exception/AccountNotVerifiedException.php deleted file mode 100644 index 1548201..0000000 --- a/main/app/sprinkles/account/src/Authenticate/Exception/AccountNotVerifiedException.php +++ /dev/null @@ -1,22 +0,0 @@ -<?php
-/**
- * UserFrosting (http://www.userfrosting.com)
- *
- * @link https://github.com/userfrosting/UserFrosting
- * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)
- */
-
-namespace UserFrosting\Sprinkle\Account\Authenticate\Exception;
-
-use UserFrosting\Support\Exception\HttpException;
-
-/**
- * Unverified account exception. Used when an account is required to complete email verification, but hasn't done so yet.
- *
- * @author Alex Weissman (https://alexanderweissman.com)
- */
-class AccountNotVerifiedException extends HttpException
-{
- protected $defaultMessage = 'ACCOUNT.UNVERIFIED';
- protected $httpErrorCode = 403;
-}
diff --git a/main/app/sprinkles/account/src/Authenticate/Exception/AuthCompromisedException.php b/main/app/sprinkles/account/src/Authenticate/Exception/AuthCompromisedException.php deleted file mode 100644 index dd169bd..0000000 --- a/main/app/sprinkles/account/src/Authenticate/Exception/AuthCompromisedException.php +++ /dev/null @@ -1,21 +0,0 @@ -<?php
-/**
- * UserFrosting (http://www.userfrosting.com)
- *
- * @link https://github.com/userfrosting/UserFrosting
- * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)
- */
-
-namespace UserFrosting\Sprinkle\Account\Authenticate\Exception;
-
-use UserFrosting\Support\Exception\ForbiddenException;
-
-/**
- * Compromised authentication exception. Used when we suspect theft of the rememberMe cookie.
- *
- * @author Alex Weissman (https://alexanderweissman.com)
- */
-class AuthCompromisedException extends ForbiddenException
-{
- protected $defaultMessage = 'ACCOUNT.SESSION_COMPROMISED';
-}
diff --git a/main/app/sprinkles/account/src/Authenticate/Exception/AuthExpiredException.php b/main/app/sprinkles/account/src/Authenticate/Exception/AuthExpiredException.php deleted file mode 100644 index 2345118..0000000 --- a/main/app/sprinkles/account/src/Authenticate/Exception/AuthExpiredException.php +++ /dev/null @@ -1,22 +0,0 @@ -<?php
-/**
- * UserFrosting (http://www.userfrosting.com)
- *
- * @link https://github.com/userfrosting/UserFrosting
- * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)
- */
-
-namespace UserFrosting\Sprinkle\Account\Authenticate\Exception;
-
-use UserFrosting\Support\Exception\HttpException;
-
-/**
- * Expired authentication exception. Used when the user needs to authenticate/reauthenticate.
- *
- * @author Alex Weissman (https://alexanderweissman.com)
- */
-class AuthExpiredException extends HttpException
-{
- protected $defaultMessage = 'ACCOUNT.SESSION_EXPIRED';
- protected $httpErrorCode = 401;
-}
diff --git a/main/app/sprinkles/account/src/Authenticate/Exception/InvalidCredentialsException.php b/main/app/sprinkles/account/src/Authenticate/Exception/InvalidCredentialsException.php deleted file mode 100644 index 8f73403..0000000 --- a/main/app/sprinkles/account/src/Authenticate/Exception/InvalidCredentialsException.php +++ /dev/null @@ -1,22 +0,0 @@ -<?php
-/**
- * UserFrosting (http://www.userfrosting.com)
- *
- * @link https://github.com/userfrosting/UserFrosting
- * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)
- */
-
-namespace UserFrosting\Sprinkle\Account\Authenticate\Exception;
-
-use UserFrosting\Support\Exception\HttpException;
-
-/**
- * Invalid credentials exception. Used when an account fails authentication for some reason.
- *
- * @author Alex Weissman (https://alexanderweissman.com)
- */
-class InvalidCredentialsException extends HttpException
-{
- protected $defaultMessage = 'USER_OR_PASS_INVALID';
- protected $httpErrorCode = 403;
-}
diff --git a/main/app/sprinkles/account/src/Authenticate/Hasher.php b/main/app/sprinkles/account/src/Authenticate/Hasher.php deleted file mode 100644 index 7ec832e..0000000 --- a/main/app/sprinkles/account/src/Authenticate/Hasher.php +++ /dev/null @@ -1,105 +0,0 @@ -<?php
-/**
- * UserFrosting (http://www.userfrosting.com)
- *
- * @link https://github.com/userfrosting/UserFrosting
- * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)
- */
-
-namespace UserFrosting\Sprinkle\Account\Authenticate;
-
-/**
- * Password hashing and validation class
- *
- * @author Alex Weissman (https://alexanderweissman.com)
- */
-class Hasher
-{
- /**
- * Default crypt cost factor.
- *
- * @var int
- */
- protected $defaultRounds = 10;
-
- /**
- * Returns the hashing type for a specified password hash.
- *
- * Automatically detects the hash type: "sha1" (for UserCake legacy accounts), "legacy" (for 0.1.x accounts), and "modern" (used for new accounts).
- * @param string $password the hashed password.
- * @return string "sha1"|"legacy"|"modern".
- */
- public function getHashType($password) {
- // If the password in the db is 65 characters long, we have an sha1-hashed password.
- if (strlen($password) == 65) {
- return 'sha1';
- } else if (strlen($password) == 82) {
- return 'legacy';
- }
-
- return 'modern';
- }
-
- /**
- * Hashes a plaintext password using bcrypt.
- *
- * @param string $password the plaintext password.
- * @param array $options
- * @return string the hashed password.
- * @throws HashFailedException
- */
- public function hash($password, array $options = []) {
- $hash = password_hash($password, PASSWORD_BCRYPT, [
- 'cost' => $this->cost($options),
- ]);
-
- if (!$hash) {
- throw new HashFailedException();
- }
-
- return $hash;
- }
-
- /**
- * Verify a plaintext password against the user's hashed password.
- *
- * @param string $password The plaintext password to verify.
- * @param string $hash The hash to compare against.
- * @param array $options
- * @return boolean True if the password matches, false otherwise.
- */
- public function verify($password, $hash, array $options = []) {
- $hashType = $this->getHashType($hash);
-
- if ($hashType == 'sha1') {
- // Legacy UserCake passwords
- $salt = substr($hash, 0, 25); // Extract the salt from the hash
- $inputHash = $salt . sha1($salt . $password);
-
- return (hash_equals($inputHash, $hash) === TRUE);
-
- } else if ($hashType == 'legacy') {
- // Homegrown implementation (assuming that current install has been using a cost parameter of 12)
- // Used for manual implementation of bcrypt.
- // Note that this legacy hashing put the salt at the _end_ for some reason.
- $salt = substr($hash, 60);
- $inputHash = crypt($password, '$2y$12$' . $salt);
- $correctHash = substr($hash, 0, 60);
-
- return (hash_equals($inputHash, $correctHash) === TRUE);
- }
-
- // Modern implementation
- return password_verify($password, $hash);
- }
-
- /**
- * Extract the cost value from the options array.
- *
- * @param array $options
- * @return int
- */
- protected function cost(array $options = []) {
- return isset($options['rounds']) ? $options['rounds'] : $this->defaultRounds;
- }
-}
diff --git a/main/app/sprinkles/account/src/Authorize/AccessConditionExpression.php b/main/app/sprinkles/account/src/Authorize/AccessConditionExpression.php deleted file mode 100644 index 8a8225e..0000000 --- a/main/app/sprinkles/account/src/Authorize/AccessConditionExpression.php +++ /dev/null @@ -1,138 +0,0 @@ -<?php
-/**
- * UserFrosting (http://www.userfrosting.com)
- *
- * @link https://github.com/userfrosting/UserFrosting
- * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)
- */
-
-namespace UserFrosting\Sprinkle\Account\Authorize;
-
-use Monolog\Logger;
-use PhpParser\Lexer\Emulative as EmulativeLexer;
-use PhpParser\Node;
-use PhpParser\NodeTraverser;
-use PhpParser\Parser as Parser;
-use PhpParser\PrettyPrinter\Standard as StandardPrettyPrinter;
-use PhpParser\Error as PhpParserException;
-use Psr\Http\Message\ServerRequestInterface as Request;
-use UserFrosting\Sprinkle\Account\Database\Models\User;
-
-/**
- * AccessConditionExpression class
- *
- * This class models the evaluation of an authorization condition expression, as associated with permissions.
- * A condition is built as a boolean expression composed of AccessCondition method calls.
- *
- * @author Alex Weissman (https://alexanderweissman.com)
- */
-class AccessConditionExpression
-{
- /**
- * @var User A user object, which for convenience can be referenced as 'self' in access conditions.
- */
- protected $user;
-
- /**
- * @var ParserNodeFunctionEvaluator The node visitor, which evaluates access condition callbacks used in a permission condition.
- */
- protected $nodeVisitor;
-
- /**
- * @var \PhpParser\Parser The PhpParser object to use (initialized in the ctor)
- */
- protected $parser;
-
- /**
- * @var NodeTraverser The NodeTraverser object to use (initialized in the ctor)
- */
- protected $traverser;
-
- /**
- * @var StandardPrettyPrinter The PrettyPrinter object to use (initialized in the ctor)
- */
- protected $prettyPrinter;
-
- /**
- * @var Logger
- */
- protected $logger;
-
- /**
- * @var bool Set to true if you want debugging information printed to the auth log.
- */
- protected $debug;
-
- /**
- * Create a new AccessConditionExpression object.
- *
- * @param User $user A user object, which for convenience can be referenced as 'self' in access conditions.
- * @param Logger $logger A Monolog logger, used to dump debugging info for authorization evaluations.
- * @param bool $debug Set to true if you want debugging information printed to the auth log.
- */
- public function __construct(ParserNodeFunctionEvaluator $nodeVisitor, User $user, Logger $logger, $debug = FALSE) {
- $this->nodeVisitor = $nodeVisitor;
- $this->user = $user;
- $this->parser = new Parser(new EmulativeLexer);
- $this->traverser = new NodeTraverser;
- $this->traverser->addVisitor($nodeVisitor);
- $this->prettyPrinter = new StandardPrettyPrinter;
- $this->logger = $logger;
- $this->debug = $debug;
- }
-
- /**
- * Evaluates a condition expression, based on the given parameters.
- *
- * The special parameter `self` is an array of the current user's data.
- * This get included automatically, and so does not need to be passed in.
- * @param string $condition a boolean expression composed of calls to AccessCondition functions.
- * @param array[mixed] $params the parameters to be used when evaluating the expression.
- * @return bool true if the condition is passed for the given parameters, otherwise returns false.
- */
- public function evaluateCondition($condition, $params) {
- // Set the reserved `self` parameters.
- // This replaces any values of `self` specified in the arguments, thus preventing them from being overridden in malicious user input.
- // (For example, from an unfiltered request body).
- $params['self'] = $this->user->export();
-
- $this->nodeVisitor->setParams($params);
-
- $code = "<?php $condition;";
-
- if ($this->debug) {
- $this->logger->debug("Evaluating access condition '$condition' with parameters:", $params);
- }
-
- // Traverse the parse tree, and execute any callbacks found using the supplied parameters.
- // Replace the function node with the return value of the callback.
- try {
- // parse
- $stmts = $this->parser->parse($code);
-
- // traverse
- $stmts = $this->traverser->traverse($stmts);
-
- // Evaluate boolean statement. It is safe to use eval() here, because our expression has been reduced entirely to a boolean expression.
- $expr = $this->prettyPrinter->prettyPrintExpr($stmts[0]);
- $expr_eval = "return " . $expr . ";\n";
- $result = eval($expr_eval);
-
- if ($this->debug) {
- $this->logger->debug("Expression '$expr' evaluates to " . ($result == TRUE ? "true" : "false"));
- }
-
- return $result;
- } catch (PhpParserException $e) {
- if ($this->debug) {
- $this->logger->debug("Error parsing access condition '$condition':" . $e->getMessage());
- }
- return FALSE; // Access fails if the access condition can't be parsed.
- } catch (AuthorizationException $e) {
- if ($this->debug) {
- $this->logger->debug("Error parsing access condition '$condition':" . $e->getMessage());
- }
- return FALSE;
- }
- }
-}
diff --git a/main/app/sprinkles/account/src/Authorize/AuthorizationException.php b/main/app/sprinkles/account/src/Authorize/AuthorizationException.php deleted file mode 100644 index f93e847..0000000 --- a/main/app/sprinkles/account/src/Authorize/AuthorizationException.php +++ /dev/null @@ -1,24 +0,0 @@ -<?php
-/**
- * UserFrosting (http://www.userfrosting.com)
- *
- * @link https://github.com/userfrosting/UserFrosting
- * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)
- */
-
-namespace UserFrosting\Sprinkle\Account\Authorize;
-
-use UserFrosting\Support\Exception\ForbiddenException;
-
-/**
- * AuthorizationException class
- *
- * Exception for AccessConditionExpression.
- *
- * @author Alex Weissman (https://alexanderweissman.com)
- * @see http://www.userfrosting.com/components/#authorization
- */
-class AuthorizationException extends ForbiddenException
-{
-
-}
diff --git a/main/app/sprinkles/account/src/Authorize/AuthorizationManager.php b/main/app/sprinkles/account/src/Authorize/AuthorizationManager.php deleted file mode 100644 index 487881f..0000000 --- a/main/app/sprinkles/account/src/Authorize/AuthorizationManager.php +++ /dev/null @@ -1,153 +0,0 @@ -<?php
-/**
- * UserFrosting (http://www.userfrosting.com)
- *
- * @link https://github.com/userfrosting/UserFrosting
- * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)
- */
-
-namespace UserFrosting\Sprinkle\Account\Authorize;
-
-use Interop\Container\ContainerInterface;
-use UserFrosting\Sprinkle\Account\Database\Models\User;
-
-/**
- * AuthorizationManager class.
- *
- * Manages a collection of access condition callbacks, and uses them to perform access control checks on user objects.
- * @author Alex Weissman (https://alexanderweissman.com)
- */
-class AuthorizationManager
-{
- /**
- * @var ContainerInterface The global container object, which holds all your services.
- */
- protected $ci;
-
- /**
- * @var array[callable] An array of callbacks that accept some parameters and evaluate to true or false.
- */
- protected $callbacks = [];
-
- /**
- * Create a new AuthorizationManager object.
- *
- * @param ContainerInterface $ci The global container object, which holds all your services.
- */
- public function __construct(ContainerInterface $ci, array $callbacks = []) {
- $this->ci = $ci;
- $this->callbacks = $callbacks;
- }
-
- /**
- * Register an authorization callback, which can then be used in permission conditions.
- *
- * To add additional callbacks, simply extend the `authorizer` service in your Sprinkle's service provider.
- * @param string $name
- * @param callable $callback
- */
- public function addCallback($name, $callback) {
- $this->callbacks[$name] = $callback;
- return $this;
- }
-
- /**
- * Get all authorization callbacks.
- *
- * @return callable[]
- */
- public function getCallbacks() {
- return $this->callbacks;
- }
-
- /**
- * Checks whether or not a user has access on a particular permission slug.
- *
- * Determine if this user has access to the given $slug under the given $params.
- *
- * @param UserFrosting\Sprinkle\Account\Database\Models\User $user
- * @param string $slug The permission slug to check for access.
- * @param array $params [optional] An array of field names => values, specifying any additional data to provide the authorization module
- * when determining whether or not this user has access.
- * @return boolean True if the user has access, false otherwise.
- */
- public function checkAccess(User $user, $slug, array $params = []) {
- $debug = $this->ci->config['debug.auth'];
-
- if ($debug) {
- $trace = array_slice(debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 3), 1);
- $this->ci->authLogger->debug("Authorization check requested at: ", $trace);
- $this->ci->authLogger->debug("Checking authorization for user {$user->id} ('{$user->user_name}') on permission '$slug'...");
- }
-
- if ($this->ci->authenticator->guest()) {
- if ($debug) {
- $this->ci->authLogger->debug("User is not logged in. Access denied.");
- }
- return FALSE;
- }
-
- // The master (root) account has access to everything.
- // Need to use loose comparison for now, because some DBs return `id` as a string.
-
- if ($user->id == $this->ci->config['reserved_user_ids.master']) {
- if ($debug) {
- $this->ci->authLogger->debug("User is the master (root) user. Access granted.");
- }
- return TRUE;
- }
-
- // Find all permissions that apply to this user (via roles), and check if any evaluate to true.
- $permissions = $user->getCachedPermissions();
-
- if (empty($permissions) || !isset($permissions[$slug])) {
- if ($debug) {
- $this->ci->authLogger->debug("No matching permissions found. Access denied.");
- }
- return FALSE;
- }
-
- $permissions = $permissions[$slug];
-
- if ($debug) {
- $this->ci->authLogger->debug("Found matching permissions: \n" . print_r($this->getPermissionsArrayDebugInfo($permissions), TRUE));
- }
-
- $nodeVisitor = new ParserNodeFunctionEvaluator($this->callbacks, $this->ci->authLogger, $debug);
- $ace = new AccessConditionExpression($nodeVisitor, $user, $this->ci->authLogger, $debug);
-
- foreach ($permissions as $permission) {
- $pass = $ace->evaluateCondition($permission->conditions, $params);
- if ($pass) {
- if ($debug) {
- $this->ci->authLogger->debug("User passed conditions '{$permission->conditions}' . Access granted.");
- }
- return TRUE;
- }
- }
-
- if ($debug) {
- $this->ci->authLogger->debug("User failed to pass any of the matched permissions. Access denied.");
- }
-
- return FALSE;
- }
-
- /**
- * Remove extraneous information from the permission to reduce verbosity.
- *
- * @param array
- * @return array
- */
- protected function getPermissionsArrayDebugInfo($permissions) {
- $permissionsInfo = [];
- foreach ($permissions as $permission) {
- $permissionData = array_only($permission->toArray(), ['id', 'slug', 'name', 'conditions', 'description']);
- // Remove this until we can find an efficient way to only load these once during debugging
- //$permissionData['roles_via'] = $permission->roles_via->pluck('id')->all();
- $permissionsInfo[] = $permissionData;
- }
-
- return $permissionsInfo;
- }
-}
diff --git a/main/app/sprinkles/account/src/Authorize/ParserNodeFunctionEvaluator.php b/main/app/sprinkles/account/src/Authorize/ParserNodeFunctionEvaluator.php deleted file mode 100644 index af26d9a..0000000 --- a/main/app/sprinkles/account/src/Authorize/ParserNodeFunctionEvaluator.php +++ /dev/null @@ -1,189 +0,0 @@ -<?php
-/**
- * UserFrosting (http://www.userfrosting.com)
- *
- * @link https://github.com/userfrosting/UserFrosting
- * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)
- */
-
-namespace UserFrosting\Sprinkle\Account\Authorize;
-
-use Monolog\Logger;
-use PhpParser\Node;
-use PhpParser\NodeVisitorAbstract;
-use PhpParser\PrettyPrinter\Standard as StandardPrettyPrinter;
-
-/**
- * ParserNodeFunctionEvaluator class
- *
- * This class parses access control condition expressions.
- *
- * @author Alex Weissman (https://alexanderweissman.com)
- * @see http://www.userfrosting.com/components/#authorization
- */
-class ParserNodeFunctionEvaluator extends NodeVisitorAbstract
-{
-
- /**
- * @var array[callable] An array of callback functions to be used when evaluating a condition expression.
- */
- protected $callbacks;
- /**
- * @var \PhpParser\PrettyPrinter\Standard The PrettyPrinter object to use (initialized in the ctor)
- */
- protected $prettyPrinter;
- /**
- * @var array The parameters to be used when evaluating the methods in the condition expression, as an array.
- */
- protected $params = [];
-
- /**
- * @var Logger
- */
- protected $logger;
-
- /**
- * @var bool Set to true if you want debugging information printed to the auth log.
- */
- protected $debug;
-
- /**
- * Create a new ParserNodeFunctionEvaluator object.
- *
- * @param array $params The parameters to be used when evaluating the methods in the condition expression, as an array.
- * @param Logger $logger A Monolog logger, used to dump debugging info for authorization evaluations.
- * @param bool $debug Set to true if you want debugging information printed to the auth log.
- */
- public function __construct($callbacks, $logger, $debug = FALSE) {
- $this->callbacks = $callbacks;
- $this->prettyPrinter = new StandardPrettyPrinter;
- $this->logger = $logger;
- $this->debug = $debug;
- $this->params = [];
- }
-
- public function leaveNode(Node $node) {
- // Look for function calls
- if ($node instanceof \PhpParser\Node\Expr\FuncCall) {
- $eval = new \PhpParser\Node\Scalar\LNumber;
-
- // Get the method name
- $callbackName = $node->name->toString();
- // Get the method arguments
- $argNodes = $node->args;
-
- $args = [];
- $argsInfo = [];
- foreach ($argNodes as $arg) {
- $argString = $this->prettyPrinter->prettyPrintExpr($arg->value);
-
- // Debugger info
- $currentArgInfo = [
- 'expression' => $argString
- ];
- // Resolve parameter placeholders ('variable' names (either single-word or array-dot identifiers))
- if (($arg->value instanceof \PhpParser\Node\Expr\BinaryOp\Concat) || ($arg->value instanceof \PhpParser\Node\Expr\ConstFetch)) {
- $value = $this->resolveParamPath($argString);
- $currentArgInfo['type'] = "parameter";
- $currentArgInfo['resolved_value'] = $value;
- // Resolve arrays
- } else if ($arg->value instanceof \PhpParser\Node\Expr\Array_) {
- $value = $this->resolveArray($arg);
- $currentArgInfo['type'] = "array";
- $currentArgInfo['resolved_value'] = print_r($value, TRUE);
- // Resolve strings
- } else if ($arg->value instanceof \PhpParser\Node\Scalar\String_) {
- $value = $arg->value->value;
- $currentArgInfo['type'] = "string";
- $currentArgInfo['resolved_value'] = $value;
- // Resolve numbers
- } else if ($arg->value instanceof \PhpParser\Node\Scalar\DNumber) {
- $value = $arg->value->value;
- $currentArgInfo['type'] = "float";
- $currentArgInfo['resolved_value'] = $value;
- } else if ($arg->value instanceof \PhpParser\Node\Scalar\LNumber) {
- $value = $arg->value->value;
- $currentArgInfo['type'] = "integer";
- $currentArgInfo['resolved_value'] = $value;
- // Anything else is simply interpreted as its literal string value
- } else {
- $value = $argString;
- $currentArgInfo['type'] = "unknown";
- $currentArgInfo['resolved_value'] = $value;
- }
-
- $args[] = $value;
- $argsInfo[] = $currentArgInfo;
- }
-
- if ($this->debug) {
- if (count($args)) {
- $this->logger->debug("Evaluating callback '$callbackName' on: ", $argsInfo);
- } else {
- $this->logger->debug("Evaluating callback '$callbackName'...");
- }
- }
-
- // Call the specified access condition callback with the specified arguments.
- if (isset($this->callbacks[$callbackName]) && is_callable($this->callbacks[$callbackName])) {
- $result = call_user_func_array($this->callbacks[$callbackName], $args);
- } else {
- throw new AuthorizationException("Authorization failed: Access condition method '$callbackName' does not exist.");
- }
-
- if ($this->debug) {
- $this->logger->debug("Result: " . ($result ? "1" : "0"));
- }
-
- return new \PhpParser\Node\Scalar\LNumber($result ? "1" : "0");
- }
- }
-
- public function setParams($params) {
- $this->params = $params;
- }
-
- /**
- * Resolve an array expression in a condition expression into an actual array.
- *
- * @param string $arg the array, represented as a string.
- * @return array[mixed] the array, as a plain ol' PHP array.
- */
- private function resolveArray($arg) {
- $arr = [];
- $items = (array)$arg->value->items;
- foreach ($items as $item) {
- if ($item->key) {
- $arr[$item->key] = $item->value->value;
- } else {
- $arr[] = $item->value->value;
- }
- }
- return $arr;
- }
-
- /**
- * Resolve a parameter path (e.g. "user.id", "post", etc) into its value.
- *
- * @param string $path the name of the parameter to resolve, based on the parameters set in this object.
- * @throws Exception the path could not be resolved. Path is malformed or key does not exist.
- * @return mixed the value of the specified parameter.
- */
- private function resolveParamPath($path) {
- $pathTokens = explode(".", $path);
- $value = $this->params;
- foreach ($pathTokens as $token) {
- $token = trim($token);
- if (is_array($value) && isset($value[$token])) {
- $value = $value[$token];
- continue;
- } else if (is_object($value) && isset($value->$token)) {
- $value = $value->$token;
- continue;
- } else {
- throw new AuthorizationException("Cannot resolve the path \"$path\". Error at token \"$token\".");
- }
- }
- return $value;
- }
-}
diff --git a/main/app/sprinkles/account/src/Bakery/CreateAdminUser.php b/main/app/sprinkles/account/src/Bakery/CreateAdminUser.php deleted file mode 100644 index 178c2b3..0000000 --- a/main/app/sprinkles/account/src/Bakery/CreateAdminUser.php +++ /dev/null @@ -1,321 +0,0 @@ -<?php
-/**
- * UserFrosting (http://www.userfrosting.com)
- *
- * @link https://github.com/userfrosting/UserFrosting
- * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)
- */
-
-namespace UserFrosting\Sprinkle\Account\Bakery;
-
-use Illuminate\Database\Capsule\Manager as Capsule;
-use Symfony\Component\Console\Input\InputInterface;
-use Symfony\Component\Console\Output\OutputInterface;
-use Symfony\Component\Console\Input\InputArgument;
-use Symfony\Component\Console\Input\InputOption;
-use UserFrosting\System\Bakery\BaseCommand;
-use UserFrosting\System\Bakery\DatabaseTest;
-use UserFrosting\System\Database\Model\Migrations;
-use UserFrosting\Sprinkle\Account\Database\Models\User;
-use UserFrosting\Sprinkle\Account\Database\Models\Role;
-use UserFrosting\Sprinkle\Account\Facades\Password;
-
-/**
- * Create root user CLI command.
- *
- * @author Alex Weissman (https://alexanderweissman.com)
- */
-class CreateAdminUser extends BaseCommand
-{
- use DatabaseTest;
-
- /**
- * @var string[] Migration dependencies for this command to work
- */
- protected $dependencies = [
- '\UserFrosting\Sprinkle\Account\Database\Migrations\v400\UsersTable',
- '\UserFrosting\Sprinkle\Account\Database\Migrations\v400\RolesTable',
- '\UserFrosting\Sprinkle\Account\Database\Migrations\v400\RoleUsersTable'
- ];
-
- /**
- * {@inheritDoc}
- */
- protected function configure() {
- $this->setName("create-admin")
- ->setDescription("Create the initial admin (root) user account");
- }
-
- /**
- * {@inheritDoc}
- */
- protected function execute(InputInterface $input, OutputInterface $output) {
- $this->io->title("Root account setup");
-
- // Need the database
- try {
- $this->io->writeln("<info>Testing database connection</info>", OutputInterface::VERBOSITY_VERBOSE);
- $this->testDB();
- $this->io->writeln("Ok", OutputInterface::VERBOSITY_VERBOSE);
- } catch (\Exception $e) {
- $this->io->error($e->getMessage());
- exit(1);
- }
-
- // Need migration table
- if (!Capsule::schema()->hasColumn('migrations', 'id')) {
- $this->io->error("Migrations doesn't appear to have been run! Make sure the database is properly migrated by using the `php bakery migrate` command.");
- exit(1);
- }
-
- // Make sure the required mirgations have been run
- foreach ($this->dependencies as $migration) {
- if (!Migrations::where('migration', $migration)->exists()) {
- $this->io->error("Migration `$migration` doesn't appear to have been run! Make sure all migrations are up to date by using the `php bakery migrate` command.");
- exit(1);
- }
- }
-
- // Make sure that there are no users currently in the user table
- // We setup the root account here so it can be done independent of the version check
- if (User::count() > 0) {
-
- $this->io->note("Table 'users' is not empty. Skipping root account setup. To set up the root account again, please truncate or drop the table and try again.");
-
- } else {
-
- $this->io->writeln("Please answer the following questions to create the root account:\n");
-
- // Get the account details
- $userName = $this->askUsername();
- $email = $this->askEmail();
- $firstName = $this->askFirstName();
- $lastName = $this->askLastName();
- $password = $this->askPassword();
-
- // Ok, now we've got the info and we can create the new user.
- $this->io->write("\n<info>Saving the root user details...</info>");
- $rootUser = new User([
- "user_name" => $userName,
- "email" => $email,
- "first_name" => $firstName,
- "last_name" => $lastName,
- "password" => Password::hash($password)
- ]);
-
- $rootUser->save();
-
- $defaultRoles = [
- 'user' => Role::where('slug', 'user')->first(),
- 'group-admin' => Role::where('slug', 'group-admin')->first(),
- 'site-admin' => Role::where('slug', 'site-admin')->first()
- ];
-
- foreach ($defaultRoles as $slug => $role) {
- if ($role) {
- $rootUser->roles()->attach($role->id);
- }
- }
-
- $this->io->success("Root user creation successful!");
- }
- }
-
- /**
- * Ask for the username
- *
- * @access protected
- * @return void
- */
- protected function askUsername() {
- while (!isset($userName) || !$this->validateUsername($userName)) {
- $userName = $this->io->ask("Choose a root username (1-50 characters, no leading or trailing whitespace)");
- }
- return $userName;
- }
-
- /**
- * Validate the username.
- *
- * @access protected
- * @param mixed $userName
- * @return void
- */
- protected function validateUsername($userName) {
- // Validate length
- if (strlen($userName) < 1 || strlen($userName) > 50) {
- $this->io->error("Username must be between 1-50 characters");
- return FALSE;
- }
-
- // Validate format
- $options = [
- 'options' => [
- 'regexp' => "/^\S((.*\S)|)$/"
- ]
- ];
- $validate = filter_var($userName, FILTER_VALIDATE_REGEXP, $options);
- if (!$validate) {
- $this->io->error("Username can't have any leading or trailing whitespace");
- return FALSE;
- }
-
- return TRUE;
- }
-
- /**
- * Ask for the email
- *
- * @access protected
- * @return void
- */
- protected function askEmail() {
- while (!isset($email) || !$this->validateEmail($email)) {
- $email = $this->io->ask("Enter a valid email address (1-254 characters, must be compatible with FILTER_VALIDATE_EMAIL)");
- }
- return $email;
- }
-
- /**
- * Validate the email.
- *
- * @access protected
- * @param mixed $email
- * @return void
- */
- protected function validateEmail($email) {
- // Validate length
- if (strlen($email) < 1 || strlen($email) > 254) {
- $this->io->error("Email must be between 1-254 characters");
- return FALSE;
- }
-
- // Validate format
- if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
- $this->io->error("Email must be compatible with FILTER_VALIDATE_EMAIL");
- return FALSE;
- }
-
- return TRUE;
- }
-
- /**
- * Ask for the first name
- *
- * @access protected
- * @return void
- */
- protected function askFirstName() {
- while (!isset($firstName) || !$this->validateFirstName($firstName)) {
- $firstName = $this->io->ask("Enter the user first name (1-20 characters)");
- }
- return $firstName;
- }
-
- /**
- * validateFirstName function.
- *
- * @access protected
- * @param mixed $name
- * @return void
- */
- protected function validateFirstName($firstName) {
- // Validate length
- if (strlen($firstName) < 1 || strlen($firstName) > 20) {
- $this->io->error("First name must be between 1-20 characters");
- return FALSE;
- }
-
- return TRUE;
- }
-
- /**
- * Ask for the last name
- *
- * @access protected
- * @return void
- */
- protected function askLastName() {
- while (!isset($lastName) || !$this->validateLastName($lastName)) {
- $lastName = $this->io->ask("Enter the user last name (1-30 characters)");
- }
- return $lastName;
- }
-
- /**
- * validateLastName function.
- *
- * @access protected
- * @param mixed $lastName
- * @return void
- */
- protected function validateLastName($lastName) {
- // Validate length
- if (strlen($lastName) < 1 || strlen($lastName) > 30) {
- $this->io->error("Last name must be between 1-30 characters");
- return FALSE;
- }
-
- return TRUE;
- }
-
- /**
- * Ask for the password
- *
- * @access protected
- * @return void
- */
- protected function askPassword() {
- while (!isset($password) || !$this->validatePassword($password) || !$this->confirmPassword($password)) {
- $password = $this->io->askHidden("Enter password (12-255 characters)");
- }
- return $password;
- }
-
- /**
- * validatePassword function.
- *
- * @access protected
- * @param mixed $password
- * @return void
- */
- protected function validatePassword($password) {
- if (strlen($password) < 12 || strlen($password) > 255) {
- $this->io->error("Password must be between 12-255 characters");
- return FALSE;
- }
-
- return TRUE;
- }
-
- /**
- * confirmPassword function.
- *
- * @access protected
- * @param mixed $passwordToConfirm
- * @return void
- */
- protected function confirmPassword($passwordToConfirm) {
- while (!isset($password)) {
- $password = $this->io->askHidden("Please re-enter the chosen password");
- }
- return $this->validatePasswordConfirmation($password, $passwordToConfirm);
- }
-
- /**
- * validatePasswordConfirmation function.
- *
- * @access protected
- * @param mixed $password
- * @param mixed $passwordToConfirm
- * @return void
- */
- protected function validatePasswordConfirmation($password, $passwordToConfirm) {
- if ($password != $passwordToConfirm) {
- $this->io->error("Passwords do not match, please try again.");
- return FALSE;
- }
-
- return TRUE;
- }
-}
\ No newline at end of file diff --git a/main/app/sprinkles/account/src/Controller/AccountController.php b/main/app/sprinkles/account/src/Controller/AccountController.php deleted file mode 100644 index c4201a7..0000000 --- a/main/app/sprinkles/account/src/Controller/AccountController.php +++ /dev/null @@ -1,1271 +0,0 @@ -<?php
-/**
- * UserFrosting (http://www.userfrosting.com)
- *
- * @link https://github.com/userfrosting/UserFrosting
- * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)
- */
-
-namespace UserFrosting\Sprinkle\Account\Controller;
-
-use Carbon\Carbon;
-use Illuminate\Database\Capsule\Manager as Capsule;
-use Psr\Http\Message\ResponseInterface as Response;
-use Psr\Http\Message\ServerRequestInterface as Request;
-use Slim\Exception\NotFoundException as NotFoundException;
-use UserFrosting\Fortress\RequestDataTransformer;
-use UserFrosting\Fortress\RequestSchema;
-use UserFrosting\Fortress\ServerSideValidator;
-use UserFrosting\Fortress\Adapter\JqueryValidationAdapter;
-use UserFrosting\Sprinkle\Account\Controller\Exception\SpammyRequestException;
-use UserFrosting\Sprinkle\Account\Facades\Password;
-use UserFrosting\Sprinkle\Account\Util\Util as AccountUtil;
-use UserFrosting\Sprinkle\Core\Controller\SimpleController;
-use UserFrosting\Sprinkle\Core\Mail\EmailRecipient;
-use UserFrosting\Sprinkle\Core\Mail\TwigMailMessage;
-use UserFrosting\Sprinkle\Core\Util\Captcha;
-use UserFrosting\Support\Exception\BadRequestException;
-use UserFrosting\Support\Exception\ForbiddenException;
-use UserFrosting\Support\Exception\HttpException;
-
-/**
- * Controller class for /account/* URLs. Handles account-related activities, including login, registration, password recovery, and account settings.
- *
- * @author Alex Weissman (https://alexanderweissman.com)
- * @see http://www.userfrosting.com/navigating/#structure
- */
-class AccountController extends SimpleController
-{
- /**
- * Check a username for availability.
- *
- * This route is throttled by default, to discourage abusing it for account enumeration.
- * This route is "public access".
- * Request type: GET
- *
- * @param Request $request
- * @param Response $response
- * @param array $args
- * @return void
- */
- public function checkUsername(Request $request, Response $response, $args) {
- /** @var \UserFrosting\Sprinkle\Core\Alert\AlertStream $ms */
- $ms = $this->ci->alerts;
-
- // GET parameters
- $params = $request->getQueryParams();
-
- // Load request schema
- $schema = new RequestSchema('schema://requests/check-username.yaml');
-
- // Whitelist and set parameter defaults
- $transformer = new RequestDataTransformer($schema);
- $data = $transformer->transform($params);
-
- // Validate, and halt on validation errors.
- $validator = new ServerSideValidator($schema, $this->ci->translator);
- if (!$validator->validate($data)) {
- // O: encapsulate the communication of error messages from ServerSideValidator to the BadRequestException
- $e = new BadRequestException('Missing or malformed request data!');
- foreach ($validator->errors() as $idx => $field) {
- foreach ($field as $eidx => $error) {
- $e->addUserMessage($error);
- }
- }
- throw $e;
- }
-
- /** @var \UserFrosting\Sprinkle\Core\Throttle\Throttler $throttler */
- $throttler = $this->ci->throttler;
- $delay = $throttler->getDelay('check_username_request');
-
- // Throttle requests
- if ($delay > 0) {
- return $response->withStatus(429);
- }
-
- /** @var \UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */
- $classMapper = $this->ci->classMapper;
-
- /** @var \UserFrosting\I18n\MessageTranslator $translator */
- $translator = $this->ci->translator;
-
- // Log throttleable event
- $throttler->logEvent('check_username_request');
-
- if ($classMapper->staticMethod('user', 'findUnique', $data['user_name'], 'user_name')) {
- $message = $translator->translate('USERNAME.NOT_AVAILABLE', $data);
- return $response->write($message)->withStatus(200);
- } else {
- return $response->write('true')->withStatus(200);
- }
- }
-
- /**
- * Processes a request to cancel a password reset request.
- *
- * This is provided so that users can cancel a password reset request, if they made it in error or if it was not initiated by themselves.
- * Processes the request from the password reset link, checking that:
- * 1. The provided token is associated with an existing user account, who has a pending password reset request.
- * Request type: GET
- *
- * @param Request $request
- * @param Response $response
- * @param array $args
- * @return void
- */
- public function denyResetPassword(Request $request, Response $response, $args) {
- // GET parameters
- $params = $request->getQueryParams();
-
- /** @var \UserFrosting\Sprinkle\Core\Alert\AlertStream $ms */
- $ms = $this->ci->alerts;
-
- /** @var \UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */
- $classMapper = $this->ci->classMapper;
-
- $loginPage = $this->ci->router->pathFor('login');
-
- // Load validation rules
- $schema = new RequestSchema('schema://requests/deny-password.yaml');
-
- // Whitelist and set parameter defaults
- $transformer = new RequestDataTransformer($schema);
- $data = $transformer->transform($params);
-
- // Validate, and halt on validation errors. Since this is a GET request, we need to redirect on failure
- $validator = new ServerSideValidator($schema, $this->ci->translator);
- if (!$validator->validate($data)) {
- $ms->addValidationErrors($validator);
- // 400 code + redirect is perfectly fine, according to user Dilaz in #laravel
- return $response->withRedirect($loginPage, 400);
- }
-
- $passwordReset = $this->ci->repoPasswordReset->cancel($data['token']);
-
- if (!$passwordReset) {
- $ms->addMessageTranslated('danger', 'PASSWORD.FORGET.INVALID');
- return $response->withRedirect($loginPage, 400);
- }
-
- $ms->addMessageTranslated('success', 'PASSWORD.FORGET.REQUEST_CANNED');
- return $response->withRedirect($loginPage);
- }
-
- /**
- * Processes a request to email a forgotten password reset link to the user.
- *
- * Processes the request from the form on the "forgot password" page, checking that:
- * 1. The rate limit for this type of request is being observed.
- * 2. The provided email address belongs to a registered account;
- * 3. The submitted data is valid.
- * Note that we have removed the requirement that a password reset request not already be in progress.
- * This is because we need to allow users to re-request a reset, even if they lose the first reset email.
- * This route is "public access".
- * Request type: POST
- * @odo require additional user information
- * @odo prevent password reset requests for root account?
- *
- * @param Request $request
- * @param Response $response
- * @param array $args
- * @return void
- */
- public function forgotPassword(Request $request, Response $response, $args) {
- /** @var \UserFrosting\Sprinkle\Core\Alert\AlertStream $ms */
- $ms = $this->ci->alerts;
-
- /** @var \UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */
- $classMapper = $this->ci->classMapper;
-
- /** @var \UserFrosting\Support\Repository\Repository $config */
- $config = $this->ci->config;
-
- // Get POST parameters
- $params = $request->getParsedBody();
-
- // Load the request schema
- $schema = new RequestSchema('schema://requests/forgot-password.yaml');
-
- // Whitelist and set parameter defaults
- $transformer = new RequestDataTransformer($schema);
- $data = $transformer->transform($params);
-
- // Validate, and halt on validation errors. Failed validation attempts do not count towards throttling limit.
- $validator = new ServerSideValidator($schema, $this->ci->translator);
- if (!$validator->validate($data)) {
- $ms->addValidationErrors($validator);
- return $response->withStatus(400);
- }
-
- // Throttle requests
-
- /** @var \UserFrosting\Sprinkle\Core\Throttle\Throttler $throttler */
- $throttler = $this->ci->throttler;
-
- $throttleData = [
- 'email' => $data['email']
- ];
- $delay = $throttler->getDelay('password_reset_request', $throttleData);
-
- if ($delay > 0) {
- $ms->addMessageTranslated('danger', 'RATE_LIMIT_EXCEEDED', ['delay' => $delay]);
- return $response->withStatus(429);
- }
-
- // All checks passed! log events/activities, update user, and send email
- // Begin transaction - DB will be rolled back if an exception occurs
- Capsule::transaction(function () use ($classMapper, $data, $throttler, $throttleData, $config) {
-
- // Log throttleable event
- $throttler->logEvent('password_reset_request', $throttleData);
-
- // Load the user, by email address
- $user = $classMapper->staticMethod('user', 'where', 'email', $data['email'])->first();
-
- // Check that the email exists.
- // If there is no user with that email address, we should still pretend like we succeeded, to prevent account enumeration
- if ($user) {
- // Try to generate a new password reset request.
- // Use timeout for "reset password"
- $passwordReset = $this->ci->repoPasswordReset->create($user, $config['password_reset.timeouts.reset']);
-
- // Create and send email
- $message = new TwigMailMessage($this->ci->view, 'mail/password-reset.html.twig');
- $message->from($config['address_book.admin'])
- ->addEmailRecipient(new EmailRecipient($user->email, $user->full_name))
- ->addParams([
- 'user' => $user,
- 'token' => $passwordReset->getToken(),
- 'request_date' => Carbon::now()->format('Y-m-d H:i:s')
- ]);
-
- $this->ci->mailer->send($message);
- }
- });
-
- $ms->addMessageTranslated('success', 'PASSWORD.FORGET.REQUEST_SENT', ['email' => $data['email']]);
- return $response->withStatus(200);
- }
-
- /**
- * Returns a modal containing account terms of service.
- *
- * This does NOT render a complete page. Instead, it renders the HTML for the form, which can be embedded in other pages.
- * Request type: GET
- *
- * @param Request $request
- * @param Response $response
- * @param array $args
- * @return void
- */
- public function getModalAccountTos(Request $request, Response $response, $args) {
- return $this->ci->view->render($response, 'modals/tos.html.twig');
- }
-
- /**
- * Generate a random captcha, store it to the session, and return the captcha image.
- *
- * Request type: GET
- *
- * @param Request $request
- * @param Response $response
- * @param array $args
- * @return void
- */
- public function imageCaptcha(Request $request, Response $response, $args) {
- $captcha = new Captcha($this->ci->session, $this->ci->config['session.keys.captcha']);
- $captcha->generateRandomCode();
-
- return $response->withStatus(200)
- ->withHeader('Content-Type', 'image/png;base64')
- ->write($captcha->getImage());
- }
-
- /**
- * Processes an account login request.
- *
- * Processes the request from the form on the login page, checking that:
- * 1. The user is not already logged in.
- * 2. The rate limit for this type of request is being observed.
- * 3. Email login is enabled, if an email address was used.
- * 4. The user account exists.
- * 5. The user account is enabled and verified.
- * 6. The user entered a valid username/email and password.
- * This route, by definition, is "public access".
- * Request type: POST
- *
- * @param Request $request
- * @param Response $response
- * @param array $args
- * @return void
- */
- public function login(Request $request, Response $response, $args) {
- /** @var \UserFrosting\Sprinkle\Core\Alert\AlertStream $ms */
- $ms = $this->ci->alerts;
-
- /** @var \UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */
- $currentUser = $this->ci->currentUser;
-
- /** @var \UserFrosting\Sprinkle\Account\Authenticate\Authenticator $authenticator */
- $authenticator = $this->ci->authenticator;
-
- // Return 200 success if user is already logged in
- if ($authenticator->check()) {
- $ms->addMessageTranslated('warning', 'LOGIN.ALREADY_COMPLETE');
- return $response->withStatus(200);
- }
-
- /** @var \UserFrosting\Support\Repository\Repository $config */
- $config = $this->ci->config;
-
- // Get POST parameters
- $params = $request->getParsedBody();
-
- // Load the request schema
- $schema = new RequestSchema('schema://requests/login.yaml');
-
- // Whitelist and set parameter defaults
- $transformer = new RequestDataTransformer($schema);
- $data = $transformer->transform($params);
-
- // Validate, and halt on validation errors. Failed validation attempts do not count towards throttling limit.
- $validator = new ServerSideValidator($schema, $this->ci->translator);
- if (!$validator->validate($data)) {
- $ms->addValidationErrors($validator);
- return $response->withStatus(400);
- }
-
- // Determine whether we are trying to log in with an email address or a username
- $isEmail = filter_var($data['user_name'], FILTER_VALIDATE_EMAIL);
-
- // Throttle requests
-
- /** @var \UserFrosting\Sprinkle\Core\Throttle\Throttler $throttler */
- $throttler = $this->ci->throttler;
-
- $userIdentifier = $data['user_name'];
-
- $throttleData = [
- 'user_identifier' => $userIdentifier
- ];
-
- $delay = $throttler->getDelay('sign_in_attempt', $throttleData);
- if ($delay > 0) {
- $ms->addMessageTranslated('danger', 'RATE_LIMIT_EXCEEDED', [
- 'delay' => $delay
- ]);
- return $response->withStatus(429);
- }
-
- // Log throttleable event
- $throttler->logEvent('sign_in_attempt', $throttleData);
-
- // If credential is an email address, but email login is not enabled, raise an error.
- // Note that we do this after logging throttle event, so this error counts towards throttling limit.
- if ($isEmail && !$config['site.login.enable_email']) {
- $ms->addMessageTranslated('danger', 'USER_OR_PASS_INVALID');
- return $response->withStatus(403);
- }
-
- // Try to authenticate the user. Authenticator will throw an exception on failure.
- /** @var \UserFrosting\Sprinkle\Account\Authenticate\Authenticator $authenticator */
- $authenticator = $this->ci->authenticator;
-
- $currentUser = $authenticator->attempt(($isEmail ? 'email' : 'user_name'), $userIdentifier, $data['password'], $data['rememberme']);
-
- $ms->addMessageTranslated('success', 'WELCOME', $currentUser->export());
-
- // Set redirect, if relevant
- $redirectOnLogin = $this->ci->get('redirect.onLogin');
-
- return $redirectOnLogin($request, $response, $args);
- }
-
- /**
- * Log the user out completely, including destroying any "remember me" token.
- *
- * Request type: GET
- *
- * @param Request $request
- * @param Response $response
- * @param array $args
- * @return void
- */
- public function logout(Request $request, Response $response, $args) {
- // Destroy the session
- $this->ci->authenticator->logout();
-
- // Return to home page
- $config = $this->ci->config;
- return $response->withStatus(302)->withHeader('Location', $config['site.uri.public']);
- }
-
- /**
- * Render the "forgot password" page.
- *
- * This creates a simple form to allow users who forgot their password to have a time-limited password reset link emailed to them.
- * By default, this is a "public page" (does not require authentication).
- * Request type: GET
- *
- * @param Request $request
- * @param Response $response
- * @param array $args
- * @return void
- */
- public function pageForgotPassword(Request $request, Response $response, $args) {
- // Load validation rules
- $schema = new RequestSchema('schema://requests/forgot-password.yaml');
- $validator = new JqueryValidationAdapter($schema, $this->ci->translator);
-
- return $this->ci->view->render($response, 'pages/forgot-password.html.twig', [
- 'page' => [
- 'validators' => [
- 'forgot_password' => $validator->rules('json', FALSE)
- ]
- ]
- ]);
- }
-
-
- /**
- * Render the account registration page for UserFrosting.
- *
- * This allows new (non-authenticated) users to create a new account for themselves on your website (if enabled).
- * By definition, this is a "public page" (does not require authentication).
- * Request type: GET
- *
- * @param Request $request
- * @param Response $response
- * @param array $args
- * @return void
- */
- public function pageRegister(Request $request, Response $response, $args) {
- /** @var \UserFrosting\Support\Repository\Repository $config */
- $config = $this->ci->config;
-
- if (!$config['site.registration.enabled']) {
- throw new NotFoundException($request, $response);
- }
-
- /** @var \UserFrosting\Sprinkle\Account\Authenticate\Authenticator $authenticator */
- $authenticator = $this->ci->authenticator;
-
- // Redirect if user is already logged in
- if ($authenticator->check()) {
- $redirect = $this->ci->get('redirect.onAlreadyLoggedIn');
-
- return $redirect($request, $response, $args);
- }
-
- // Load validation rules
- $schema = new RequestSchema('schema://requests/register.yaml');
- $validatorRegister = new JqueryValidationAdapter($schema, $this->ci->translator);
-
- return $this->ci->view->render($response, 'pages/register.html.twig', [
- 'page' => [
- 'validators' => [
- 'register' => $validatorRegister->rules('json', FALSE)
- ]
- ]
- ]);
- }
-
- /**
- * Render the "resend verification email" page.
- *
- * This is a form that allows users who lost their account verification link to have the link resent to their email address.
- * By default, this is a "public page" (does not require authentication).
- * Request type: GET
- *
- * @param Request $request
- * @param Response $response
- * @param array $args
- * @return void
- */
- public function pageResendVerification(Request $request, Response $response, $args) {
- // Load validation rules
- $schema = new RequestSchema('schema://requests/resend-verification.yaml');
- $validator = new JqueryValidationAdapter($schema, $this->ci->translator);
-
- return $this->ci->view->render($response, 'pages/resend-verification.html.twig', [
- 'page' => [
- 'validators' => [
- 'resend_verification' => $validator->rules('json', FALSE)
- ]
- ]
- ]);
- }
-
- /**
- * Reset password page.
- *
- * Renders the new password page for password reset requests.
- * Request type: GET
- *
- * @param Request $request
- * @param Response $response
- * @param array $args
- * @return void
- */
- public function pageResetPassword(Request $request, Response $response, $args) {
- // Insert the user's secret token from the link into the password reset form
- $params = $request->getQueryParams();
-
- // Load validation rules - note this uses the same schema as "set password"
- $schema = new RequestSchema('schema://requests/set-password.yaml');
- $validator = new JqueryValidationAdapter($schema, $this->ci->translator);
-
- return $this->ci->view->render($response, 'pages/reset-password.html.twig', [
- 'page' => [
- 'validators' => [
- 'set_password' => $validator->rules('json', FALSE)
- ]
- ],
- 'token' => isset($params['token']) ? $params['token'] : '',
- ]);
- }
-
- /**
- * Render the "set password" page.
- *
- * Renders the page where new users who have had accounts created for them by another user, can set their password.
- * By default, this is a "public page" (does not require authentication).
- * Request type: GET
- *
- * @param Request $request
- * @param Response $response
- * @param array $args
- * @return void
- */
- public function pageSetPassword(Request $request, Response $response, $args) {
- // Insert the user's secret token from the link into the password set form
- $params = $request->getQueryParams();
-
- // Load validation rules
- $schema = new RequestSchema('schema://requests/set-password.yaml');
- $validator = new JqueryValidationAdapter($schema, $this->ci->translator);
-
- return $this->ci->view->render($response, 'pages/set-password.html.twig', [
- 'page' => [
- 'validators' => [
- 'set_password' => $validator->rules('json', FALSE)
- ]
- ],
- 'token' => isset($params['token']) ? $params['token'] : '',
- ]);
- }
-
- /**
- * Account settings page.
- *
- * Provides a form for users to modify various properties of their account, such as name, email, locale, etc.
- * Any fields that the user does not have permission to modify will be automatically disabled.
- * This page requires authentication.
- * Request type: GET
- *
- * @param Request $request
- * @param Response $response
- * @param array $args
- * @return void
- */
- public function pageSettings(Request $request, Response $response, $args) {
- /** @var \UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager */
- $authorizer = $this->ci->authorizer;
-
- /** @var \UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */
- $currentUser = $this->ci->currentUser;
-
- // Access-controlled page
- if (!$authorizer->checkAccess($currentUser, 'uri_account_settings')) {
- throw new ForbiddenException();
- }
-
- // Load validation rules
- $schema = new RequestSchema('schema://requests/account-settings.yaml');
- $validatorAccountSettings = new JqueryValidationAdapter($schema, $this->ci->translator);
-
- $schema = new RequestSchema('schema://requests/profile-settings.yaml');
- $validatorProfileSettings = new JqueryValidationAdapter($schema, $this->ci->translator);
-
- /** @var \UserFrosting\Support\Repository\Repository $config */
- $config = $this->ci->config;
-
- // Get a list of all locales
- $locales = $config->getDefined('site.locales.available');
-
- return $this->ci->view->render($response, 'pages/account-settings.html.twig', [
- 'locales' => $locales,
- 'page' => [
- 'validators' => [
- 'account_settings' => $validatorAccountSettings->rules('json', FALSE),
- 'profile_settings' => $validatorProfileSettings->rules('json', FALSE)
- ],
- 'visibility' => ($authorizer->checkAccess($currentUser, 'update_account_settings') ? '' : 'disabled')
- ]
- ]);
- }
-
- /**
- * Render the account sign-in page for UserFrosting.
- *
- * This allows existing users to sign in.
- * By definition, this is a "public page" (does not require authentication).
- * Request type: GET
- *
- * @param Request $request
- * @param Response $response
- * @param array $args
- * @return void
- */
- public function pageSignIn(Request $request, Response $response, $args) {
- /** @var \UserFrosting\Support\Repository\Repository $config */
- $config = $this->ci->config;
-
- /** @var \UserFrosting\Sprinkle\Account\Authenticate\Authenticator $authenticator */
- $authenticator = $this->ci->authenticator;
-
- // Redirect if user is already logged in
- if ($authenticator->check()) {
- $redirect = $this->ci->get('redirect.onAlreadyLoggedIn');
-
- return $redirect($request, $response, $args);
- }
-
- // Load validation rules
- $schema = new RequestSchema('schema://requests/login.yaml');
- $validatorLogin = new JqueryValidationAdapter($schema, $this->ci->translator);
-
- return $this->ci->view->render($response, 'pages/sign-in.html.twig', [
- 'page' => [
- 'validators' => [
- 'login' => $validatorLogin->rules('json', FALSE)
- ]
- ]
- ]);
- }
-
- /**
- * Processes a request to update a user's profile information.
- *
- * Processes the request from the user profile settings form, checking that:
- * 1. They have the necessary permissions to update the posted field(s);
- * 2. The submitted data is valid.
- * This route requires authentication.
- * Request type: POST
- *
- * @param Request $request
- * @param Response $response
- * @param array $args
- * @return void
- */
- public function profile(Request $request, Response $response, $args) {
- /** @var \UserFrosting\Sprinkle\Core\Alert\AlertStream $ms */
- $ms = $this->ci->alerts;
-
- /** @var \UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager */
- $authorizer = $this->ci->authorizer;
-
- /** @var \UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */
- $currentUser = $this->ci->currentUser;
-
- // Access control for entire resource - check that the current user has permission to modify themselves
- // See recipe "per-field access control" for dynamic fine-grained control over which properties a user can modify.
- if (!$authorizer->checkAccess($currentUser, 'update_account_settings')) {
- $ms->addMessageTranslated('danger', 'ACCOUNT.ACCESS_DENIED');
- return $response->withStatus(403);
- }
-
- /** @var \UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */
- $classMapper = $this->ci->classMapper;
-
- /** @var \UserFrosting\Support\Repository\Repository $config */
- $config = $this->ci->config;
-
- // POST parameters
- $params = $request->getParsedBody();
-
- // Load the request schema
- $schema = new RequestSchema('schema://requests/profile-settings.yaml');
-
- // Whitelist and set parameter defaults
- $transformer = new RequestDataTransformer($schema);
- $data = $transformer->transform($params);
-
- $error = FALSE;
-
- // Validate, and halt on validation errors.
- $validator = new ServerSideValidator($schema, $this->ci->translator);
- if (!$validator->validate($data)) {
- $ms->addValidationErrors($validator);
- $error = TRUE;
- }
-
- // Check that locale is valid
- $locales = $config->getDefined('site.locales.available');
- if (!array_key_exists($data['locale'], $locales)) {
- $ms->addMessageTranslated('danger', 'LOCALE.INVALID', $data);
- $error = TRUE;
- }
-
- if ($error) {
- return $response->withStatus(400);
- }
-
- // Looks good, let's update with new values!
- // Note that only fields listed in `profile-settings.yaml` will be permitted in $data, so this prevents the user from updating all columns in the DB
- $currentUser->fill($data);
-
- $currentUser->save();
-
- // Create activity record
- $this->ci->userActivityLogger->info("User {$currentUser->user_name} updated their profile settings.", [
- 'type' => 'update_profile_settings'
- ]);
-
- $ms->addMessageTranslated('success', 'PROFILE.UPDATED');
- return $response->withStatus(200);
- }
-
- /**
- * Processes an new account registration request.
- *
- * This is throttled to prevent account enumeration, since it needs to divulge when a username/email has been used.
- * Processes the request from the form on the registration page, checking that:
- * 1. The honeypot was not modified;
- * 2. The master account has already been created (during installation);
- * 3. Account registration is enabled;
- * 4. The user is not already logged in;
- * 5. Valid information was entered;
- * 6. The captcha, if enabled, is correct;
- * 7. The username and email are not already taken.
- * Automatically sends an activation link upon success, if account activation is enabled.
- * This route is "public access".
- * Request type: POST
- * Returns the User Object for the user record that was created.
- *
- * @param Request $request
- * @param Response $response
- * @param array $args
- * @return void
- */
- public function register(Request $request, Response $response, $args) {
- /** @var \UserFrosting\Sprinkle\Core\Alert\AlertStream $ms */
- $ms = $this->ci->alerts;
-
- /** @var \UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */
- $classMapper = $this->ci->classMapper;
-
- /** @var \UserFrosting\Support\Repository\Repository $config */
- $config = $this->ci->config;
-
- // Get POST parameters: user_name, first_name, last_name, email, password, passwordc, captcha, spiderbro, csrf_token
- $params = $request->getParsedBody();
-
- // Check the honeypot. 'spiderbro' is not a real field, it is hidden on the main page and must be submitted with its default value for this to be processed.
- if (!isset($params['spiderbro']) || $params['spiderbro'] != 'http://') {
- throw new SpammyRequestException('Possible spam received:' . print_r($params, TRUE));
- }
-
- // Security measure: do not allow registering new users until the master account has been created.
- if (!$classMapper->staticMethod('user', 'find', $config['reserved_user_ids.master'])) {
- $ms->addMessageTranslated('danger', 'ACCOUNT.MASTER_NOT_EXISTS');
- return $response->withStatus(403);
- }
-
- // Check if registration is currently enabled
- if (!$config['site.registration.enabled']) {
- $ms->addMessageTranslated('danger', 'REGISTRATION.DISABLED');
- return $response->withStatus(403);
- }
-
- /** @var \UserFrosting\Sprinkle\Account\Authenticate\Authenticator $authenticator */
- $authenticator = $this->ci->authenticator;
-
- // Prevent the user from registering if he/she is already logged in
- if ($authenticator->check()) {
- $ms->addMessageTranslated('danger', 'REGISTRATION.LOGOUT');
- return $response->withStatus(403);
- }
-
- // Load the request schema
- $schema = new RequestSchema('schema://requests/register.yaml');
-
- // Whitelist and set parameter defaults
- $transformer = new RequestDataTransformer($schema);
- $data = $transformer->transform($params);
-
- $error = FALSE;
-
- // Validate request data
- $validator = new ServerSideValidator($schema, $this->ci->translator);
- if (!$validator->validate($data)) {
- $ms->addValidationErrors($validator);
- $error = TRUE;
- }
-
- /** @var \UserFrosting\Sprinkle\Core\Throttle\Throttler $throttler */
- $throttler = $this->ci->throttler;
- $delay = $throttler->getDelay('registration_attempt');
-
- // Throttle requests
- if ($delay > 0) {
- return $response->withStatus(429);
- }
-
- // Check if username or email already exists
- if ($classMapper->staticMethod('user', 'findUnique', $data['user_name'], 'user_name')) {
- $ms->addMessageTranslated('danger', 'USERNAME.IN_USE', $data);
- $error = TRUE;
- }
-
- if ($classMapper->staticMethod('user', 'findUnique', $data['email'], 'email')) {
- $ms->addMessageTranslated('danger', 'EMAIL.IN_USE', $data);
- $error = TRUE;
- }
-
- // Check captcha, if required
- if ($config['site.registration.captcha']) {
- $captcha = new Captcha($this->ci->session, $this->ci->config['session.keys.captcha']);
- if (!$data['captcha'] || !$captcha->verifyCode($data['captcha'])) {
- $ms->addMessageTranslated('danger', 'CAPTCHA.FAIL');
- $error = TRUE;
- }
- }
-
- if ($error) {
- return $response->withStatus(400);
- }
-
- // Remove captcha, password confirmation from object data after validation
- unset($data['captcha']);
- unset($data['passwordc']);
-
- if ($config['site.registration.require_email_verification']) {
- $data['flag_verified'] = FALSE;
- } else {
- $data['flag_verified'] = TRUE;
- }
-
- // Load default group
- $groupSlug = $config['site.registration.user_defaults.group'];
- $defaultGroup = $classMapper->staticMethod('group', 'where', 'slug', $groupSlug)->first();
-
- if (!$defaultGroup) {
- $e = new HttpException("Account registration is not working because the default group '$groupSlug' does not exist.");
- $e->addUserMessage('REGISTRATION.BROKEN');
- throw $e;
- }
-
- // Set default group
- $data['group_id'] = $defaultGroup->id;
-
- // Set default locale
- $data['locale'] = $config['site.registration.user_defaults.locale'];
-
- // Hash password
- $data['password'] = Password::hash($data['password']);
-
- // All checks passed! log events/activities, create user, and send verification email (if required)
- // Begin transaction - DB will be rolled back if an exception occurs
- Capsule::transaction(function () use ($classMapper, $data, $ms, $config, $throttler) {
- // Log throttleable event
- $throttler->logEvent('registration_attempt');
-
- // Create the user
- $user = $classMapper->createInstance('user', $data);
-
- // Store new user to database
- $user->save();
-
- // Create activity record
- $this->ci->userActivityLogger->info("User {$user->user_name} registered for a new account.", [
- 'type' => 'sign_up',
- 'user_id' => $user->id
- ]);
-
- // Load default roles
- $defaultRoleSlugs = $classMapper->staticMethod('role', 'getDefaultSlugs');
- $defaultRoles = $classMapper->staticMethod('role', 'whereIn', 'slug', $defaultRoleSlugs)->get();
- $defaultRoleIds = $defaultRoles->pluck('id')->all();
-
- // Attach default roles
- $user->roles()->attach($defaultRoleIds);
-
- // Verification email
- if ($config['site.registration.require_email_verification']) {
- // Try to generate a new verification request
- $verification = $this->ci->repoVerification->create($user, $config['verification.timeout']);
-
- // Create and send verification email
- $message = new TwigMailMessage($this->ci->view, 'mail/verify-account.html.twig');
-
- $message->from($config['address_book.admin'])
- ->addEmailRecipient(new EmailRecipient($user->email, $user->full_name))
- ->addParams([
- 'user' => $user,
- 'token' => $verification->getToken()
- ]);
-
- $this->ci->mailer->send($message);
-
- $ms->addMessageTranslated('success', 'REGISTRATION.COMPLETE_TYPE2', $user->toArray());
- } else {
- // No verification required
- $ms->addMessageTranslated('success', 'REGISTRATION.COMPLETE_TYPE1');
- }
- });
-
- return $response->withStatus(200);
- }
-
- /**
- * Processes a request to resend the verification email for a new user account.
- *
- * Processes the request from the resend verification email form, checking that:
- * 1. The rate limit on this type of request is observed;
- * 2. The provided email is associated with an existing user account;
- * 3. The user account is not already verified;
- * 4. The submitted data is valid.
- * This route is "public access".
- * Request type: POST
- *
- * @param Request $request
- * @param Response $response
- * @param array $args
- * @return void
- */
- public function resendVerification(Request $request, Response $response, $args) {
- /** @var \UserFrosting\Sprinkle\Core\Alert\AlertStream $ms */
- $ms = $this->ci->alerts;
-
- /** @var \UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */
- $classMapper = $this->ci->classMapper;
-
- /** @var \UserFrosting\Support\Repository\Repository $config */
- $config = $this->ci->config;
-
- // Get POST parameters
- $params = $request->getParsedBody();
-
- // Load the request schema
- $schema = new RequestSchema('schema://requests/resend-verification.yaml');
-
- // Whitelist and set parameter defaults
- $transformer = new RequestDataTransformer($schema);
- $data = $transformer->transform($params);
-
- // Validate, and halt on validation errors. Failed validation attempts do not count towards throttling limit.
- $validator = new ServerSideValidator($schema, $this->ci->translator);
- if (!$validator->validate($data)) {
- $ms->addValidationErrors($validator);
- return $response->withStatus(400);
- }
-
- // Throttle requests
-
- /** @var \UserFrosting\Sprinkle\Core\Throttle\Throttler $throttler */
- $throttler = $this->ci->throttler;
-
- $throttleData = [
- 'email' => $data['email']
- ];
- $delay = $throttler->getDelay('verification_request', $throttleData);
-
- if ($delay > 0) {
- $ms->addMessageTranslated('danger', 'RATE_LIMIT_EXCEEDED', ['delay' => $delay]);
- return $response->withStatus(429);
- }
-
- // All checks passed! log events/activities, create user, and send verification email (if required)
- // Begin transaction - DB will be rolled back if an exception occurs
- Capsule::transaction(function () use ($classMapper, $data, $throttler, $throttleData, $config) {
- // Log throttleable event
- $throttler->logEvent('verification_request', $throttleData);
-
- // Load the user, by email address
- $user = $classMapper->staticMethod('user', 'where', 'email', $data['email'])->first();
-
- // Check that the user exists and is not already verified.
- // If there is no user with that email address, or the user exists and is already verified,
- // we pretend like we succeeded to prevent account enumeration
- if ($user && $user->flag_verified != '1') {
- // We're good to go - record user activity and send the email
- $verification = $this->ci->repoVerification->create($user, $config['verification.timeout']);
-
- // Create and send verification email
- $message = new TwigMailMessage($this->ci->view, 'mail/resend-verification.html.twig');
-
- $message->from($config['address_book.admin'])
- ->addEmailRecipient(new EmailRecipient($user->email, $user->full_name))
- ->addParams([
- 'user' => $user,
- 'token' => $verification->getToken()
- ]);
-
- $this->ci->mailer->send($message);
- }
- });
-
- $ms->addMessageTranslated('success', 'ACCOUNT.VERIFICATION.NEW_LINK_SENT', ['email' => $data['email']]);
- return $response->withStatus(200);
- }
-
- /**
- * Processes a request to set the password for a new or current user.
- *
- * Processes the request from the password create/reset form, which should have the secret token embedded in it, checking that:
- * 1. The provided secret token is associated with an existing user account;
- * 2. The user has a password set/reset request in progress;
- * 3. The token has not expired;
- * 4. The submitted data (new password) is valid.
- * This route is "public access".
- * Request type: POST
- *
- * @param Request $request
- * @param Response $response
- * @param array $args
- * @return void
- */
- public function setPassword(Request $request, Response $response, $args) {
- /** @var \UserFrosting\Sprinkle\Core\Alert\AlertStream $ms */
- $ms = $this->ci->alerts;
-
- /** @var \UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */
- $classMapper = $this->ci->classMapper;
-
- /** @var \UserFrosting\Support\Repository\Repository $config */
- $config = $this->ci->config;
-
- // Get POST parameters
- $params = $request->getParsedBody();
-
- // Load the request schema
- $schema = new RequestSchema('schema://requests/set-password.yaml');
-
- // Whitelist and set parameter defaults
- $transformer = new RequestDataTransformer($schema);
- $data = $transformer->transform($params);
-
- // Validate, and halt on validation errors. Failed validation attempts do not count towards throttling limit.
- $validator = new ServerSideValidator($schema, $this->ci->translator);
- if (!$validator->validate($data)) {
- $ms->addValidationErrors($validator);
- return $response->withStatus(400);
- }
-
- $forgotPasswordPage = $this->ci->router->pathFor('forgot-password');
-
- // Ok, try to complete the request with the specified token and new password
- $passwordReset = $this->ci->repoPasswordReset->complete($data['token'], [
- 'password' => $data['password']
- ]);
-
- if (!$passwordReset) {
- $ms->addMessageTranslated('danger', 'PASSWORD.FORGET.INVALID', ['url' => $forgotPasswordPage]);
- return $response->withStatus(400);
- }
-
- $ms->addMessageTranslated('success', 'PASSWORD.UPDATED');
-
- /** @var \UserFrosting\Sprinkle\Account\Authenticate\Authenticator $authenticator */
- $authenticator = $this->ci->authenticator;
-
- // Log out any existing user, and create a new session
- if ($authenticator->check()) {
- $authenticator->logout();
- }
-
- // Auto-login the user (without "remember me")
- $user = $passwordReset->user;
- $authenticator->login($user);
-
- $ms->addMessageTranslated('success', 'WELCOME', $user->export());
- return $response->withStatus(200);
- }
-
- /**
- * Processes a request to update a user's account information.
- *
- * Processes the request from the user account settings form, checking that:
- * 1. The user correctly input their current password;
- * 2. They have the necessary permissions to update the posted field(s);
- * 3. The submitted data is valid.
- * This route requires authentication.
- * Request type: POST
- *
- * @param Request $request
- * @param Response $response
- * @param array $args
- * @return void
- */
- public function settings(Request $request, Response $response, $args) {
- /** @var \UserFrosting\Sprinkle\Core\Alert\AlertStream $ms */
- $ms = $this->ci->alerts;
-
- /** @var \UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager */
- $authorizer = $this->ci->authorizer;
-
- /** @var \UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */
- $currentUser = $this->ci->currentUser;
-
- // Access control for entire resource - check that the current user has permission to modify themselves
- // See recipe "per-field access control" for dynamic fine-grained control over which properties a user can modify.
- if (!$authorizer->checkAccess($currentUser, 'update_account_settings')) {
- $ms->addMessageTranslated('danger', 'ACCOUNT.ACCESS_DENIED');
- return $response->withStatus(403);
- }
-
- /** @var \UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */
- $classMapper = $this->ci->classMapper;
-
- /** @var \UserFrosting\Support\Repository\Repository $config */
- $config = $this->ci->config;
-
- // POST parameters
- $params = $request->getParsedBody();
-
- // Load the request schema
- $schema = new RequestSchema('schema://requests/account-settings.yaml');
-
- // Whitelist and set parameter defaults
- $transformer = new RequestDataTransformer($schema);
- $data = $transformer->transform($params);
-
- $error = FALSE;
-
- // Validate, and halt on validation errors.
- $validator = new ServerSideValidator($schema, $this->ci->translator);
- if (!$validator->validate($data)) {
- $ms->addValidationErrors($validator);
- $error = TRUE;
- }
-
- // Confirm current password
- if (!isset($data['passwordcheck']) || !Password::verify($data['passwordcheck'], $currentUser->password)) {
- $ms->addMessageTranslated('danger', 'PASSWORD.INVALID');
- $error = TRUE;
- }
-
- // Remove password check, password confirmation from object data after validation
- unset($data['passwordcheck']);
- unset($data['passwordc']);
-
- // If new email was submitted, check that the email address is not in use
- if (isset($data['email']) && $data['email'] != $currentUser->email && $classMapper->staticMethod('user', 'findUnique', $data['email'], 'email')) {
- $ms->addMessageTranslated('danger', 'EMAIL.IN_USE', $data);
- $error = TRUE;
- }
-
- if ($error) {
- return $response->withStatus(400);
- }
-
- // Hash new password, if specified
- if (isset($data['password']) && !empty($data['password'])) {
- $data['password'] = Password::hash($data['password']);
- } else {
- // Do not pass to model if no password is specified
- unset($data['password']);
- }
-
- // Looks good, let's update with new values!
- // Note that only fields listed in `account-settings.yaml` will be permitted in $data, so this prevents the user from updating all columns in the DB
- $currentUser->fill($data);
-
- $currentUser->save();
-
- // Create activity record
- $this->ci->userActivityLogger->info("User {$currentUser->user_name} updated their account settings.", [
- 'type' => 'update_account_settings'
- ]);
-
- $ms->addMessageTranslated('success', 'ACCOUNT.SETTINGS.UPDATED');
- return $response->withStatus(200);
- }
-
- /**
- * Suggest an available username for a specified first/last name.
- *
- * This route is "public access".
- * Request type: GET
- * @odo Can this route be abused for account enumeration? If so we should throttle it as well.
- *
- * @param Request $request
- * @param Response $response
- * @param array $args
- * @return void
- */
- public function suggestUsername(Request $request, Response $response, $args) {
- /** @var \UserFrosting\Sprinkle\Core\Alert\AlertStream $ms */
- $ms = $this->ci->alerts;
-
- /** @var \UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */
- $classMapper = $this->ci->classMapper;
-
- $suggestion = AccountUtil::randomUniqueUsername($classMapper, 50, 10);
-
- // Be careful how you consume this data - it has not been escaped and contains untrusted user-supplied content.
- // For example, if you plan to insert it into an HTML DOM, you must escape it on the client side (or use client-side templating).
- return $response->withJson([
- 'user_name' => $suggestion
- ], 200, JSON_PRETTY_PRINT);
- }
-
- /**
- * Processes an new email verification request.
- *
- * Processes the request from the email verification link that was emailed to the user, checking that:
- * 1. The token provided matches a user in the database;
- * 2. The user account is not already verified;
- * This route is "public access".
- * Request type: GET
- *
- * @param Request $request
- * @param Response $response
- * @param array $args
- * @return void
- */
- public function verify(Request $request, Response $response, $args) {
- /** @var \UserFrosting\Sprinkle\Core\Alert\AlertStream $ms */
- $ms = $this->ci->alerts;
-
- /** @var \UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */
- $classMapper = $this->ci->classMapper;
-
- /** @var \UserFrosting\Support\Repository\Repository $config */
- $config = $this->ci->config;
-
- $loginPage = $this->ci->router->pathFor('login');
-
- // GET parameters
- $params = $request->getQueryParams();
-
- // Load request schema
- $schema = new RequestSchema('schema://requests/account-verify.yaml');
-
- // Whitelist and set parameter defaults
- $transformer = new RequestDataTransformer($schema);
- $data = $transformer->transform($params);
-
- // Validate, and halt on validation errors. This is a GET request, so we redirect on validation error.
- $validator = new ServerSideValidator($schema, $this->ci->translator);
- if (!$validator->validate($data)) {
- $ms->addValidationErrors($validator);
- // 400 code + redirect is perfectly fine, according to user Dilaz in #laravel
- return $response->withRedirect($loginPage, 400);
- }
-
- $verification = $this->ci->repoVerification->complete($data['token']);
-
- if (!$verification) {
- $ms->addMessageTranslated('danger', 'ACCOUNT.VERIFICATION.TOKEN_NOT_FOUND');
- return $response->withRedirect($loginPage, 400);
- }
-
- $ms->addMessageTranslated('success', 'ACCOUNT.VERIFICATION.COMPLETE');
-
- // Forward to login page
- return $response->withRedirect($loginPage);
- }
-}
diff --git a/main/app/sprinkles/account/src/Controller/Exception/SpammyRequestException.php b/main/app/sprinkles/account/src/Controller/Exception/SpammyRequestException.php deleted file mode 100644 index 1f0cf4a..0000000 --- a/main/app/sprinkles/account/src/Controller/Exception/SpammyRequestException.php +++ /dev/null @@ -1,21 +0,0 @@ -<?php
-/**
- * UserFrosting (http://www.userfrosting.com)
- *
- * @link https://github.com/userfrosting/UserFrosting
- * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)
- */
-
-namespace UserFrosting\Sprinkle\Account\Controller\Exception;
-
-use UserFrosting\Support\Exception\HttpException;
-
-/**
- * Spammy request exception. Used when a bot has attempted to spam a public form, and fallen into our honeypot.
- *
- * @author Alex Weissman (https://alexanderweissman.com)
- */
-class SpammyRequestException extends HttpException
-{
-
-}
diff --git a/main/app/sprinkles/account/src/Database/Migrations/v400/ActivitiesTable.php b/main/app/sprinkles/account/src/Database/Migrations/v400/ActivitiesTable.php deleted file mode 100644 index 6fcb8aa..0000000 --- a/main/app/sprinkles/account/src/Database/Migrations/v400/ActivitiesTable.php +++ /dev/null @@ -1,53 +0,0 @@ -<?php
-/**
- * UserFrosting (http://www.userfrosting.com)
- *
- * @link https://github.com/userfrosting/UserFrosting
- * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)
- */
-
-namespace UserFrosting\Sprinkle\Account\Database\Migrations\v400;
-
-use UserFrosting\System\Bakery\Migration;
-use Illuminate\Database\Schema\Blueprint;
-use Illuminate\Database\Schema\Builder;
-
-/**
- * Sessions table migration
- * Version 4.0.0
- *
- * See https://laravel.com/docs/5.4/migrations#tables
- * @extends Migration
- * @author Alex Weissman (https://alexanderweissman.com)
- */
-class ActivitiesTable extends Migration
-{
- /**
- * {@inheritDoc}
- */
- public function up() {
- if (!$this->schema->hasTable('activities')) {
- $this->schema->create('activities', function (Blueprint $table) {
- $table->increments('id');
- $table->string('ip_address', 45)->nullable();
- $table->integer('user_id')->unsigned();
- $table->string('type', 255)->comment('An identifier used to track the type of activity.');
- $table->timestamp('occurred_at')->nullable();
- $table->text('description')->nullable();
-
- $table->engine = 'InnoDB';
- $table->collation = 'utf8_unicode_ci';
- $table->charset = 'utf8';
- //$table->foreign('user_id')->references('id')->on('users');
- $table->index('user_id');
- });
- }
- }
-
- /**
- * {@inheritDoc}
- */
- public function down() {
- $this->schema->drop('activities');
- }
-}
\ No newline at end of file diff --git a/main/app/sprinkles/account/src/Database/Migrations/v400/GroupsTable.php b/main/app/sprinkles/account/src/Database/Migrations/v400/GroupsTable.php deleted file mode 100644 index d8498f4..0000000 --- a/main/app/sprinkles/account/src/Database/Migrations/v400/GroupsTable.php +++ /dev/null @@ -1,81 +0,0 @@ -<?php
-/**
- * UserFrosting (http://www.userfrosting.com)
- *
- * @link https://github.com/userfrosting/UserFrosting
- * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)
- */
-
-namespace UserFrosting\Sprinkle\Account\Database\Migrations\v400;
-
-use Illuminate\Database\Schema\Blueprint;
-use Illuminate\Database\Schema\Builder;
-use UserFrosting\Sprinkle\Account\Database\Models\Group;
-use UserFrosting\System\Bakery\Migration;
-
-/**
- * Groups table migration
- * "Group" now replaces the notion of "primary group" in earlier versions of UF. A user can belong to exactly one group.
- * Version 4.0.0
- *
- * See https://laravel.com/docs/5.4/migrations#tables
- * @extends Migration
- * @author Alex Weissman (https://alexanderweissman.com)
- */
-class GroupsTable extends Migration
-{
- /**
- * {@inheritDoc}
- */
- public function up() {
- if (!$this->schema->hasTable('groups')) {
- $this->schema->create('groups', function (Blueprint $table) {
- $table->increments('id');
- $table->string('slug');
- $table->string('name');
- $table->text('description')->nullable();
- $table->string('icon', 100)->nullable(FALSE)->default('fa fa-user')->comment('The icon representing users in this group.');
- $table->timestamps();
-
- $table->engine = 'InnoDB';
- $table->collation = 'utf8_unicode_ci';
- $table->charset = 'utf8';
- $table->unique('slug');
- $table->index('slug');
- });
-
- // Add default groups
- $groups = [
- 'terran' => new Group([
- 'slug' => 'terran',
- 'name' => 'Terran',
- 'description' => 'The terrans are a young species with psionic potential. The terrans of the Koprulu sector descend from the survivors of a disastrous 23rd century colonization mission from Earth.',
- 'icon' => 'sc sc-terran'
- ]),
- 'zerg' => new Group([
- 'slug' => 'zerg',
- 'name' => 'Zerg',
- 'description' => 'Dedicated to the pursuit of genetic perfection, the zerg relentlessly hunt down and assimilate advanced species across the galaxy, incorporating useful genetic code into their own.',
- 'icon' => 'sc sc-zerg'
- ]),
- 'protoss' => new Group([
- 'slug' => 'protoss',
- 'name' => 'Protoss',
- 'description' => 'The protoss, a.k.a. the Firstborn, are a sapient humanoid race native to Aiur. Their advanced technology complements and enhances their psionic mastery.',
- 'icon' => 'sc sc-protoss'
- ])
- ];
-
- foreach ($groups as $slug => $group) {
- $group->save();
- }
- }
- }
-
- /**
- * {@inheritDoc}
- */
- public function down() {
- $this->schema->drop('groups');
- }
-}
diff --git a/main/app/sprinkles/account/src/Database/Migrations/v400/PasswordResetsTable.php b/main/app/sprinkles/account/src/Database/Migrations/v400/PasswordResetsTable.php deleted file mode 100644 index 932ab47..0000000 --- a/main/app/sprinkles/account/src/Database/Migrations/v400/PasswordResetsTable.php +++ /dev/null @@ -1,56 +0,0 @@ -<?php
-/**
- * UserFrosting (http://www.userfrosting.com)
- *
- * @link https://github.com/userfrosting/UserFrosting
- * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)
- */
-
-namespace UserFrosting\Sprinkle\Account\Database\Migrations\v400;
-
-use Illuminate\Database\Schema\Blueprint;
-use Illuminate\Database\Schema\Builder;
-use UserFrosting\System\Bakery\Migration;
-
-/**
- * password_resets table migration
- * Manages requests for password resets.
- * Version 4.0.0
- *
- * See https://laravel.com/docs/5.4/migrations#tables
- * @extends Migration
- * @author Alex Weissman (https://alexanderweissman.com)
- */
-class passwordResetsTable extends Migration
-{
- /**
- * {@inheritDoc}
- */
- public function up() {
- if (!$this->schema->hasTable('password_resets')) {
- $this->schema->create('password_resets', function (Blueprint $table) {
- $table->increments('id');
- $table->integer('user_id')->unsigned();
- $table->string('hash');
- $table->boolean('completed')->default(0);
- $table->timestamp('expires_at')->nullable();
- $table->timestamp('completed_at')->nullable();
- $table->timestamps();
-
- $table->engine = 'InnoDB';
- $table->collation = 'utf8_unicode_ci';
- $table->charset = 'utf8';
- //$table->foreign('user_id')->references('id')->on('users');
- $table->index('user_id');
- $table->index('hash');
- });
- }
- }
-
- /**
- * {@inheritDoc}
- */
- public function down() {
- $this->schema->drop('password_resets');
- }
-}
diff --git a/main/app/sprinkles/account/src/Database/Migrations/v400/PermissionRolesTable.php b/main/app/sprinkles/account/src/Database/Migrations/v400/PermissionRolesTable.php deleted file mode 100644 index dca6639..0000000 --- a/main/app/sprinkles/account/src/Database/Migrations/v400/PermissionRolesTable.php +++ /dev/null @@ -1,54 +0,0 @@ -<?php
-/**
- * UserFrosting (http://www.userfrosting.com)
- *
- * @link https://github.com/userfrosting/UserFrosting
- * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)
- */
-
-namespace UserFrosting\Sprinkle\Account\Database\Migrations\v400;
-
-use Illuminate\Database\Schema\Blueprint;
-use Illuminate\Database\Schema\Builder;
-use UserFrosting\System\Bakery\Migration;
-
-/**
- * Permission_roles table migration
- * Many-to-many mapping between permissions and roles.
- * Version 4.0.0
- *
- * See https://laravel.com/docs/5.4/migrations#tables
- * @extends Migration
- * @author Alex Weissman (https://alexanderweissman.com)
- */
-class PermissionRolesTable extends Migration
-{
- /**
- * {@inheritDoc}
- */
- public function up() {
- if (!$this->schema->hasTable('permission_roles')) {
- $this->schema->create('permission_roles', function (Blueprint $table) {
- $table->integer('permission_id')->unsigned();
- $table->integer('role_id')->unsigned();
- $table->timestamps();
-
- $table->engine = 'InnoDB';
- $table->collation = 'utf8_unicode_ci';
- $table->charset = 'utf8';
- $table->primary(['permission_id', 'role_id']);
- //$table->foreign('permission_id')->references('id')->on('permissions');
- //$table->foreign('role_id')->references('id')->on('roles');
- $table->index('permission_id');
- $table->index('role_id');
- });
- }
- }
-
- /**
- * {@inheritDoc}
- */
- public function down() {
- $this->schema->drop('permission_roles');
- }
-}
diff --git a/main/app/sprinkles/account/src/Database/Migrations/v400/PermissionsTable.php b/main/app/sprinkles/account/src/Database/Migrations/v400/PermissionsTable.php deleted file mode 100644 index efc014b..0000000 --- a/main/app/sprinkles/account/src/Database/Migrations/v400/PermissionsTable.php +++ /dev/null @@ -1,260 +0,0 @@ -<?php
-/**
- * UserFrosting (http://www.userfrosting.com)
- *
- * @link https://github.com/userfrosting/UserFrosting
- * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)
- */
-
-namespace UserFrosting\Sprinkle\Account\Database\Migrations\v400;
-
-use Illuminate\Database\Schema\Blueprint;
-use Illuminate\Database\Schema\Builder;
-use UserFrosting\Sprinkle\Account\Database\Models\Permission;
-use UserFrosting\Sprinkle\Account\Database\Models\Role;
-use UserFrosting\System\Bakery\Migration;
-
-/**
- * Permissions table migration
- * Permissions now replace the 'authorize_group' and 'authorize_user' tables.
- * Also, they now map many-to-many to roles.
- * Version 4.0.0
- *
- * See https://laravel.com/docs/5.4/migrations#tables
- * @extends Migration
- * @author Alex Weissman (https://alexanderweissman.com)
- */
-class PermissionsTable extends Migration
-{
- /**
- * {@inheritDoc}
- */
- public $dependencies = [
- '\UserFrosting\Sprinkle\Account\Database\Migrations\v400\RolesTable',
- '\UserFrosting\Sprinkle\Account\Database\Migrations\v400\PermissionRolesTable'
- ];
-
- /**
- * {@inheritDoc}
- */
- public function up() {
- if (!$this->schema->hasTable('permissions')) {
- $this->schema->create('permissions', function (Blueprint $table) {
- $table->increments('id');
- $table->string('slug')->comment('A code that references a specific action or URI that an assignee of this permission has access to.');
- $table->string('name');
- $table->text('conditions')->comment('The conditions under which members of this group have access to this hook.');
- $table->text('description')->nullable();
- $table->timestamps();
-
- $table->engine = 'InnoDB';
- $table->collation = 'utf8_unicode_ci';
- $table->charset = 'utf8';
- });
- }
- }
-
- /**
- * {@inheritDoc}
- */
- public function down() {
- $this->schema->drop('permissions');
- }
-
- /**
- * {@inheritDoc}
- */
- public function seed() {
- // Skip this if table is not empty
- if (Permission::count() == 0) {
-
- $defaultRoleIds = [
- 'user' => Role::where('slug', 'user')->first()->id,
- 'group-admin' => Role::where('slug', 'group-admin')->first()->id,
- 'site-admin' => Role::where('slug', 'site-admin')->first()->id
- ];
-
- // Add default permissions
- $permissions = [
- 'create_group' => new Permission([
- 'slug' => 'create_group',
- 'name' => 'Create group',
- 'conditions' => 'always()',
- 'description' => 'Create a new group.'
- ]),
- 'create_user' => new Permission([
- 'slug' => 'create_user',
- 'name' => 'Create user',
- 'conditions' => 'always()',
- 'description' => 'Create a new user in your own group and assign default roles.'
- ]),
- 'create_user_field' => new Permission([
- 'slug' => 'create_user_field',
- 'name' => 'Set new user group',
- 'conditions' => "subset(fields,['group'])",
- 'description' => 'Set the group when creating a new user.'
- ]),
- 'delete_group' => new Permission([
- 'slug' => 'delete_group',
- 'name' => 'Delete group',
- 'conditions' => "always()",
- 'description' => 'Delete a group.'
- ]),
- 'delete_user' => new Permission([
- 'slug' => 'delete_user',
- 'name' => 'Delete user',
- 'conditions' => "!has_role(user.id,{$defaultRoleIds['site-admin']}) && !is_master(user.id)",
- 'description' => 'Delete users who are not Site Administrators.'
- ]),
- 'update_account_settings' => new Permission([
- 'slug' => 'update_account_settings',
- 'name' => 'Edit user',
- 'conditions' => 'always()',
- 'description' => 'Edit your own account settings.'
- ]),
- 'update_group_field' => new Permission([
- 'slug' => 'update_group_field',
- 'name' => 'Edit group',
- 'conditions' => 'always()',
- 'description' => 'Edit basic properties of any group.'
- ]),
- 'update_user_field' => new Permission([
- 'slug' => 'update_user_field',
- 'name' => 'Edit user',
- 'conditions' => "!has_role(user.id,{$defaultRoleIds['site-admin']}) && subset(fields,['name','email','locale','group','flag_enabled','flag_verified','password'])",
- 'description' => 'Edit users who are not Site Administrators.'
- ]),
- 'update_user_field_group' => new Permission([
- 'slug' => 'update_user_field',
- 'name' => 'Edit group user',
- 'conditions' => "equals_num(self.group_id,user.group_id) && !is_master(user.id) && !has_role(user.id,{$defaultRoleIds['site-admin']}) && (!has_role(user.id,{$defaultRoleIds['group-admin']}) || equals_num(self.id,user.id)) && subset(fields,['name','email','locale','flag_enabled','flag_verified','password'])",
- 'description' => 'Edit users in your own group who are not Site or Group Administrators, except yourself.'
- ]),
- 'uri_account_settings' => new Permission([
- 'slug' => 'uri_account_settings',
- 'name' => 'Account settings page',
- 'conditions' => 'always()',
- 'description' => 'View the account settings page.'
- ]),
- 'uri_activities' => new Permission([
- 'slug' => 'uri_activities',
- 'name' => 'Activity monitor',
- 'conditions' => 'always()',
- 'description' => 'View a list of all activities for all users.'
- ]),
- 'uri_dashboard' => new Permission([
- 'slug' => 'uri_dashboard',
- 'name' => 'Admin dashboard',
- 'conditions' => 'always()',
- 'description' => 'View the administrative dashboard.'
- ]),
- 'uri_group' => new Permission([
- 'slug' => 'uri_group',
- 'name' => 'View group',
- 'conditions' => 'always()',
- 'description' => 'View the group page of any group.'
- ]),
- 'uri_group_own' => new Permission([
- 'slug' => 'uri_group',
- 'name' => 'View own group',
- 'conditions' => 'equals_num(self.group_id,group.id)',
- 'description' => 'View the group page of your own group.'
- ]),
- 'uri_groups' => new Permission([
- 'slug' => 'uri_groups',
- 'name' => 'Group management page',
- 'conditions' => 'always()',
- 'description' => 'View a page containing a list of groups.'
- ]),
- 'uri_user' => new Permission([
- 'slug' => 'uri_user',
- 'name' => 'View user',
- 'conditions' => 'always()',
- 'description' => 'View the user page of any user.'
- ]),
- 'uri_user_in_group' => new Permission([
- 'slug' => 'uri_user',
- 'name' => 'View user',
- 'conditions' => "equals_num(self.group_id,user.group_id) && !is_master(user.id) && !has_role(user.id,{$defaultRoleIds['site-admin']}) && (!has_role(user.id,{$defaultRoleIds['group-admin']}) || equals_num(self.id,user.id))",
- 'description' => 'View the user page of any user in your group, except the master user and Site and Group Administrators (except yourself).'
- ]),
- 'uri_users' => new Permission([
- 'slug' => 'uri_users',
- 'name' => 'User management page',
- 'conditions' => 'always()',
- 'description' => 'View a page containing a table of users.'
- ]),
- 'view_group_field' => new Permission([
- 'slug' => 'view_group_field',
- 'name' => 'View group',
- 'conditions' => "in(property,['name','icon','slug','description','users'])",
- 'description' => 'View certain properties of any group.'
- ]),
- 'view_group_field_own' => new Permission([
- 'slug' => 'view_group_field',
- 'name' => 'View group',
- 'conditions' => "equals_num(self.group_id,group.id) && in(property,['name','icon','slug','description','users'])",
- 'description' => 'View certain properties of your own group.'
- ]),
- 'view_user_field' => new Permission([
- 'slug' => 'view_user_field',
- 'name' => 'View user',
- 'conditions' => "in(property,['user_name','name','email','locale','theme','roles','group','activities'])",
- 'description' => 'View certain properties of any user.'
- ]),
- 'view_user_field_group' => new Permission([
- 'slug' => 'view_user_field',
- 'name' => 'View user',
- 'conditions' => "equals_num(self.group_id,user.group_id) && !is_master(user.id) && !has_role(user.id,{$defaultRoleIds['site-admin']}) && (!has_role(user.id,{$defaultRoleIds['group-admin']}) || equals_num(self.id,user.id)) && in(property,['user_name','name','email','locale','roles','group','activities'])",
- 'description' => 'View certain properties of any user in your own group, except the master user and Site and Group Administrators (except yourself).'
- ])
- ];
-
- foreach ($permissions as $slug => $permission) {
- $permission->save();
- }
-
- // Add default mappings to permissions
- $roleUser = Role::where('slug', 'user')->first();
- if ($roleUser) {
- $roleUser->permissions()->sync([
- $permissions['update_account_settings']->id,
- $permissions['uri_account_settings']->id,
- $permissions['uri_dashboard']->id
- ]);
- }
-
- $roleSiteAdmin = Role::where('slug', 'site-admin')->first();
- if ($roleSiteAdmin) {
- $roleSiteAdmin->permissions()->sync([
- $permissions['create_group']->id,
- $permissions['create_user']->id,
- $permissions['create_user_field']->id,
- $permissions['delete_group']->id,
- $permissions['delete_user']->id,
- $permissions['update_user_field']->id,
- $permissions['update_group_field']->id,
- $permissions['uri_activities']->id,
- $permissions['uri_group']->id,
- $permissions['uri_groups']->id,
- $permissions['uri_user']->id,
- $permissions['uri_users']->id,
- $permissions['view_group_field']->id,
- $permissions['view_user_field']->id
- ]);
- }
-
- $roleGroupAdmin = Role::where('slug', 'group-admin')->first();
- if ($roleGroupAdmin) {
- $roleGroupAdmin->permissions()->sync([
- $permissions['create_user']->id,
- $permissions['update_user_field_group']->id,
- $permissions['uri_group_own']->id,
- $permissions['uri_user_in_group']->id,
- $permissions['view_group_field_own']->id,
- $permissions['view_user_field_group']->id
- ]);
- }
- }
- }
-}
diff --git a/main/app/sprinkles/account/src/Database/Migrations/v400/PersistencesTable.php b/main/app/sprinkles/account/src/Database/Migrations/v400/PersistencesTable.php deleted file mode 100644 index c51461a..0000000 --- a/main/app/sprinkles/account/src/Database/Migrations/v400/PersistencesTable.php +++ /dev/null @@ -1,56 +0,0 @@ -<?php
-/**
- * UserFrosting (http://www.userfrosting.com)
- *
- * @link https://github.com/userfrosting/UserFrosting
- * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)
- */
-
-namespace UserFrosting\Sprinkle\Account\Database\Migrations\v400;
-
-use Illuminate\Database\Schema\Blueprint;
-use Illuminate\Database\Schema\Builder;
-use UserFrosting\System\Bakery\Migration;
-
-/**
- * Persistences table migration
- * Many-to-many mapping between roles and users.
- * Version 4.0.0
- *
- * See https://laravel.com/docs/5.4/migrations#tables
- * @extends Migration
- * @author Alex Weissman (https://alexanderweissman.com)
- */
-class PersistencesTable extends Migration
-{
- /**
- * {@inheritDoc}
- */
- public function up() {
- if (!$this->schema->hasTable('persistences')) {
- $this->schema->create('persistences', function (Blueprint $table) {
- $table->increments('id');
- $table->integer('user_id')->unsigned();
- $table->string('token', 40);
- $table->string('persistent_token', 40);
- $table->timestamp('expires_at')->nullable();
- $table->timestamps();
-
- $table->engine = 'InnoDB';
- $table->collation = 'utf8_unicode_ci';
- $table->charset = 'utf8';
- //$table->foreign('user_id')->references('id')->on('users');
- $table->index('user_id');
- $table->index('token');
- $table->index('persistent_token');
- });
- }
- }
-
- /**
- * {@inheritDoc}
- */
- public function down() {
- $this->schema->drop('persistences');
- }
-}
diff --git a/main/app/sprinkles/account/src/Database/Migrations/v400/RoleUsersTable.php b/main/app/sprinkles/account/src/Database/Migrations/v400/RoleUsersTable.php deleted file mode 100644 index 0820a02..0000000 --- a/main/app/sprinkles/account/src/Database/Migrations/v400/RoleUsersTable.php +++ /dev/null @@ -1,54 +0,0 @@ -<?php
-/**
- * UserFrosting (http://www.userfrosting.com)
- *
- * @link https://github.com/userfrosting/UserFrosting
- * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)
- */
-
-namespace UserFrosting\Sprinkle\Account\Database\Migrations\v400;
-
-use Illuminate\Database\Schema\Blueprint;
-use Illuminate\Database\Schema\Builder;
-use UserFrosting\System\Bakery\Migration;
-
-/**
- * Role_users table migration
- * Many-to-many mapping between roles and users.
- * Version 4.0.0
- *
- * See https://laravel.com/docs/5.4/migrations#tables
- * @extends Migration
- * @author Alex Weissman (https://alexanderweissman.com)
- */
-class RoleUsersTable extends Migration
-{
- /**
- * {@inheritDoc}
- */
- public function up() {
- if (!$this->schema->hasTable('role_users')) {
- $this->schema->create('role_users', function (Blueprint $table) {
- $table->integer('user_id')->unsigned();
- $table->integer('role_id')->unsigned();
- $table->timestamps();
-
- $table->engine = 'InnoDB';
- $table->collation = 'utf8_unicode_ci';
- $table->charset = 'utf8';
- $table->primary(['user_id', 'role_id']);
- //$table->foreign('user_id')->references('id')->on('users');
- //$table->foreign('role_id')->references('id')->on('roles');
- $table->index('user_id');
- $table->index('role_id');
- });
- }
- }
-
- /**
- * {@inheritDoc}
- */
- public function down() {
- $this->schema->drop('role_users');
- }
-}
diff --git a/main/app/sprinkles/account/src/Database/Migrations/v400/RolesTable.php b/main/app/sprinkles/account/src/Database/Migrations/v400/RolesTable.php deleted file mode 100644 index 3a524e2..0000000 --- a/main/app/sprinkles/account/src/Database/Migrations/v400/RolesTable.php +++ /dev/null @@ -1,77 +0,0 @@ -<?php
-/**
- * UserFrosting (http://www.userfrosting.com)
- *
- * @link https://github.com/userfrosting/UserFrosting
- * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)
- */
-
-namespace UserFrosting\Sprinkle\Account\Database\Migrations\v400;
-
-use Illuminate\Database\Schema\Blueprint;
-use Illuminate\Database\Schema\Builder;
-use UserFrosting\Sprinkle\Account\Database\Models\Role;
-use UserFrosting\System\Bakery\Migration;
-
-/**
- * Roles table migration
- * Roles replace "groups" in UF 0.3.x. Users acquire permissions through roles.
- * Version 4.0.0
- *
- * See https://laravel.com/docs/5.4/migrations#tables
- * @extends Migration
- * @author Alex Weissman (https://alexanderweissman.com)
- */
-class RolesTable extends Migration
-{
- /**
- * {@inheritDoc}
- */
- public function up() {
- if (!$this->schema->hasTable('roles')) {
- $this->schema->create('roles', function (Blueprint $table) {
- $table->increments('id');
- $table->string('slug');
- $table->string('name');
- $table->text('description')->nullable();
- $table->timestamps();
-
- $table->engine = 'InnoDB';
- $table->collation = 'utf8_unicode_ci';
- $table->charset = 'utf8';
- $table->unique('slug');
- $table->index('slug');
- });
-
- // Add default roles
- $roles = [
- 'user' => new Role([
- 'slug' => 'user',
- 'name' => 'User',
- 'description' => 'This role provides basic user functionality.'
- ]),
- 'site-admin' => new Role([
- 'slug' => 'site-admin',
- 'name' => 'Site Administrator',
- 'description' => 'This role is meant for "site administrators", who can basically do anything except create, edit, or delete other administrators.'
- ]),
- 'group-admin' => new Role([
- 'slug' => 'group-admin',
- 'name' => 'Group Administrator',
- 'description' => 'This role is meant for "group administrators", who can basically do anything with users in their own group, except other administrators of that group.'
- ])
- ];
-
- foreach ($roles as $slug => $role) {
- $role->save();
- }
- }
- }
-
- /**
- * {@inheritDoc}
- */
- public function down() {
- $this->schema->drop('roles');
- }
-}
diff --git a/main/app/sprinkles/account/src/Database/Migrations/v400/UsersTable.php b/main/app/sprinkles/account/src/Database/Migrations/v400/UsersTable.php deleted file mode 100644 index 694da5b..0000000 --- a/main/app/sprinkles/account/src/Database/Migrations/v400/UsersTable.php +++ /dev/null @@ -1,68 +0,0 @@ -<?php
-/**
- * UserFrosting (http://www.userfrosting.com)
- *
- * @link https://github.com/userfrosting/UserFrosting
- * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)
- */
-
-namespace UserFrosting\Sprinkle\Account\Database\Migrations\v400;
-
-use Illuminate\Database\Schema\Blueprint;
-use Illuminate\Database\Schema\Builder;
-use UserFrosting\System\Bakery\Migration;
-
-/**
- * Users table migration
- * Removed the 'display_name', 'title', 'secret_token', and 'flag_password_reset' fields, and added first and last name and 'last_activity_id'.
- * Version 4.0.0
- *
- * See https://laravel.com/docs/5.4/migrations#tables
- * @extends Migration
- * @author Alex Weissman (https://alexanderweissman.com)
- */
-class UsersTable extends Migration
-{
- /**
- * {@inheritDoc}
- */
- public function up() {
- if (!$this->schema->hasTable('users')) {
- $this->schema->create('users', function (Blueprint $table) {
- $table->increments('id');
- $table->string('user_name', 50);
- $table->string('email', 254);
- $table->string('first_name', 20);
- $table->string('last_name', 30);
- $table->string('locale', 10)->default('en_US')->comment('The language and locale to use for this user.');
- $table->string('theme', 100)->nullable()->comment("The user theme.");
- $table->integer('group_id')->unsigned()->default(1)->comment("The id of the user group.");
- $table->boolean('flag_verified')->default(1)->comment("Set to 1 if the user has verified their account via email, 0 otherwise.");
- $table->boolean('flag_enabled')->default(1)->comment("Set to 1 if the user account is currently enabled, 0 otherwise. Disabled accounts cannot be logged in to, but they retain all of their data and settings.");
- $table->integer('last_activity_id')->unsigned()->nullable()->comment("The id of the last activity performed by this user.");
- $table->string('password', 255);
- $table->softDeletes();
- $table->timestamps();
-
- $table->engine = 'InnoDB';
- $table->collation = 'utf8_unicode_ci';
- $table->charset = 'utf8';
- //$table->foreign('group_id')->references('id')->on('groups');
- //$table->foreign('last_activity_id')->references('id')->on('activities');
- $table->unique('user_name');
- $table->index('user_name');
- $table->unique('email');
- $table->index('email');
- $table->index('group_id');
- $table->index('last_activity_id');
- });
- }
- }
-
- /**
- * {@inheritDoc}
- */
- public function down() {
- $this->schema->drop('users');
- }
-}
diff --git a/main/app/sprinkles/account/src/Database/Migrations/v400/VerificationsTable.php b/main/app/sprinkles/account/src/Database/Migrations/v400/VerificationsTable.php deleted file mode 100644 index 2c4d28f..0000000 --- a/main/app/sprinkles/account/src/Database/Migrations/v400/VerificationsTable.php +++ /dev/null @@ -1,56 +0,0 @@ -<?php
-/**
- * UserFrosting (http://www.userfrosting.com)
- *
- * @link https://github.com/userfrosting/UserFrosting
- * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)
- */
-
-namespace UserFrosting\Sprinkle\Account\Database\Migrations\v400;
-
-use Illuminate\Database\Schema\Blueprint;
-use Illuminate\Database\Schema\Builder;
-use UserFrosting\System\Bakery\Migration;
-
-/**
- * Verifications table migration
- * Manages requests for email account verification.
- * Version 4.0.0
- *
- * See https://laravel.com/docs/5.4/migrations#tables
- * @extends Migration
- * @author Alex Weissman (https://alexanderweissman.com)
- */
-class VerificationsTable extends Migration
-{
- /**
- * {@inheritDoc}
- */
- public function up() {
- if (!$this->schema->hasTable('verifications')) {
- $this->schema->create('verifications', function (Blueprint $table) {
- $table->increments('id');
- $table->integer('user_id')->unsigned();
- $table->string('hash');
- $table->boolean('completed')->default(0);
- $table->timestamp('expires_at')->nullable();
- $table->timestamp('completed_at')->nullable();
- $table->timestamps();
-
- $table->engine = 'InnoDB';
- $table->collation = 'utf8_unicode_ci';
- $table->charset = 'utf8';
- //$table->foreign('user_id')->references('id')->on('users');
- $table->index('user_id');
- $table->index('hash');
- });
- }
- }
-
- /**
- * {@inheritDoc}
- */
- public function down() {
- $this->schema->drop('verifications');
- }
-}
diff --git a/main/app/sprinkles/account/src/Database/Models/Activity.php b/main/app/sprinkles/account/src/Database/Models/Activity.php deleted file mode 100644 index 8f6cd18..0000000 --- a/main/app/sprinkles/account/src/Database/Models/Activity.php +++ /dev/null @@ -1,83 +0,0 @@ -<?php
-/**
- * UserFrosting (http://www.userfrosting.com)
- *
- * @link https://github.com/userfrosting/UserFrosting
- * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)
- */
-
-namespace UserFrosting\Sprinkle\Account\Database\Models;
-
-use Illuminate\Database\Capsule\Manager as Capsule;
-use UserFrosting\Sprinkle\Core\Database\Models\Model;
-
-/**
- * Activity Class
- *
- * Represents a single user activity at a specified point in time.
- * @author Alex Weissman (https://alexanderweissman.com)
- * @property string ip_address
- * @property int user_id
- * @property string type
- * @property datetime occurred_at
- * @property string description
- */
-class Activity extends Model
-{
- /**
- * @var string The name of the table for the current model.
- */
- protected $table = "activities";
-
- protected $fillable = [
- "ip_address",
- "user_id",
- "type",
- "occurred_at",
- "description"
- ];
-
- /**
- * Joins the activity's user, so we can do things like sort, search, paginate, etc.
- */
- public function scopeJoinUser($query) {
- $query = $query->select('activities.*');
-
- $query = $query->leftJoin('users', 'activities.user_id', '=', 'users.id');
-
- return $query;
- }
-
- /**
- * Add clauses to select the most recent event of each type for each user, to the query.
- *
- * @return \Illuminate\Database\Query\Builder
- */
- public function scopeMostRecentEvents($query) {
- return $query->select('user_id', 'event_type', Capsule::raw('MAX(occurred_at) as occurred_at'))
- ->groupBy('user_id')
- ->groupBy('type');
- }
-
- /**
- * Add clauses to select the most recent event of a given type for each user, to the query.
- *
- * @param string $type The type of event, matching the `event_type` field in the user_event table.
- * @return \Illuminate\Database\Query\Builder
- */
- public function scopeMostRecentEventsByType($query, $type) {
- return $query->select('user_id', Capsule::raw('MAX(occurred_at) as occurred_at'))
- ->where('type', $type)
- ->groupBy('user_id');
- }
-
- /**
- * Get the user associated with this activity.
- */
- public function user() {
- /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */
- $classMapper = static::$ci->classMapper;
-
- return $this->belongsTo($classMapper->getClassMapping('user'), 'user_id');
- }
-}
diff --git a/main/app/sprinkles/account/src/Database/Models/Group.php b/main/app/sprinkles/account/src/Database/Models/Group.php deleted file mode 100644 index abb0e36..0000000 --- a/main/app/sprinkles/account/src/Database/Models/Group.php +++ /dev/null @@ -1,68 +0,0 @@ -<?php
-/**
- * UserFrosting (http://www.userfrosting.com)
- *
- * @link https://github.com/userfrosting/UserFrosting
- * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)
- */
-
-namespace UserFrosting\Sprinkle\Account\Database\Models;
-
-use Illuminate\Database\Capsule\Manager as Capsule;
-use UserFrosting\Sprinkle\Core\Database\Models\Model;
-
-/**
- * Group Class
- *
- * Represents a group object as stored in the database.
- *
- * @package UserFrosting
- * @author Alex Weissman
- * @see http://www.userfrosting.com/tutorials/lesson-3-data-model/
- *
- * @property string slug
- * @property string name
- * @property string description
- * @property string icon
- */
-class Group extends Model
-{
- /**
- * @var string The name of the table for the current model.
- */
- protected $table = "groups";
-
- protected $fillable = [
- "slug",
- "name",
- "description",
- "icon"
- ];
-
- /**
- * @var bool Enable timestamps for this class.
- */
- public $timestamps = TRUE;
-
- /**
- * Delete this group from the database, along with any user associations
- *
- * @odo What do we do with users when their group is deleted? Reassign them? Or, can a user be "groupless"?
- */
- public function delete() {
- // Delete the group
- $result = parent::delete();
-
- return $result;
- }
-
- /**
- * Lazily load a collection of Users which belong to this group.
- */
- public function users() {
- /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */
- $classMapper = static::$ci->classMapper;
-
- return $this->hasMany($classMapper->getClassMapping('user'), 'group_id');
- }
-}
diff --git a/main/app/sprinkles/account/src/Database/Models/PasswordReset.php b/main/app/sprinkles/account/src/Database/Models/PasswordReset.php deleted file mode 100644 index 99b1920..0000000 --- a/main/app/sprinkles/account/src/Database/Models/PasswordReset.php +++ /dev/null @@ -1,74 +0,0 @@ -<?php
-/**
- * UserFrosting (http://www.userfrosting.com)
- *
- * @link https://github.com/userfrosting/UserFrosting
- * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)
- */
-
-namespace UserFrosting\Sprinkle\Account\Database\Models;
-
-use Illuminate\Database\Capsule\Manager as Capsule;
-use UserFrosting\Sprinkle\Core\Database\Models\Model;
-
-/**
- * Password Reset Class
- *
- * Represents a password reset request for a specific user.
- * @author Alex Weissman (https://alexanderweissman.com)
- * @property int user_id
- * @property hash token
- * @property bool completed
- * @property datetime expires_at
- * @property datetime completed_at
- */
-class PasswordReset extends Model
-{
- /**
- * @var string The name of the table for the current model.
- */
- protected $table = "password_resets";
-
- protected $fillable = [
- "user_id",
- "hash",
- "completed",
- "expires_at",
- "completed_at"
- ];
-
- /**
- * @var bool Enable timestamps for PasswordResets.
- */
- public $timestamps = TRUE;
-
- /**
- * Stores the raw (unhashed) token when created, so that it can be emailed out to the user. NOT persisted.
- */
- protected $token;
-
- /**
- * @return string
- */
- public function getToken() {
- return $this->token;
- }
-
- /**
- * @param string $value
- */
- public function setToken($value) {
- $this->token = $value;
- return $this;
- }
-
- /**
- * Get the user associated with this reset request.
- */
- public function user() {
- /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */
- $classMapper = static::$ci->classMapper;
-
- return $this->belongsTo($classMapper->getClassMapping('user'), 'user_id');
- }
-}
diff --git a/main/app/sprinkles/account/src/Database/Models/Permission.php b/main/app/sprinkles/account/src/Database/Models/Permission.php deleted file mode 100644 index da4391f..0000000 --- a/main/app/sprinkles/account/src/Database/Models/Permission.php +++ /dev/null @@ -1,117 +0,0 @@ -<?php
-/**
- * UserFrosting (http://www.userfrosting.com)
- *
- * @link https://github.com/userfrosting/UserFrosting
- * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)
- */
-
-namespace UserFrosting\Sprinkle\Account\Database\Models;
-
-use Illuminate\Database\Capsule\Manager as Capsule;
-use UserFrosting\Sprinkle\Core\Database\Models\Model;
-
-/**
- * Permission Class.
- *
- * Represents a permission for a role or user.
- * @author Alex Weissman (https://alexanderweissman.com)
- * @property string slug
- * @property string name
- * @property string conditions
- * @property string description
- */
-class Permission extends Model
-{
- /**
- * @var string The name of the table for the current model.
- */
- protected $table = "permissions";
-
- protected $fillable = [
- "slug",
- "name",
- "conditions",
- "description"
- ];
-
- /**
- * @var bool Enable timestamps for this class.
- */
- public $timestamps = TRUE;
-
- /**
- * Delete this permission from the database, removing associations with roles.
- *
- */
- public function delete() {
- // Remove all role associations
- $this->roles()->detach();
-
- // Delete the permission
- $result = parent::delete();
-
- return $result;
- }
-
- /**
- * Get a list of roles to which this permission is assigned.
- *
- * @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
- */
- public function roles() {
- /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */
- $classMapper = static::$ci->classMapper;
-
- return $this->belongsToMany($classMapper->getClassMapping('role'), 'permission_roles', 'permission_id', 'role_id')->withTimestamps();
- }
-
- /**
- * Query scope to get all permissions assigned to a specific role.
- *
- * @param \Illuminate\Database\Eloquent\Builder $query
- * @param int $roleId
- * @return \Illuminate\Database\Eloquent\Builder
- */
- public function scopeForRole($query, $roleId) {
- return $query->join('permission_roles', function ($join) use ($roleId) {
- $join->on('permission_roles.permission_id', 'permissions.id')
- ->where('role_id', $roleId);
- });
- }
-
- /**
- * Query scope to get all permissions NOT associated with a specific role.
- *
- * @param \Illuminate\Database\Eloquent\Builder $query
- * @param int $roleId
- * @return \Illuminate\Database\Eloquent\Builder
- */
- public function scopeNotForRole($query, $roleId) {
- return $query->join('permission_roles', function ($join) use ($roleId) {
- $join->on('permission_roles.permission_id', 'permissions.id')
- ->where('role_id', '!=', $roleId);
- });
- }
-
- /**
- * Get a list of users who have this permission, along with a list of roles through which each user has the permission.
- *
- * @return \UserFrosting\Sprinkle\Core\Database\Relations\BelongsToManyThrough
- */
- public function users() {
- /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */
- $classMapper = static::$ci->classMapper;
-
- return $this->belongsToManyThrough(
- $classMapper->getClassMapping('user'),
- $classMapper->getClassMapping('role'),
- 'permission_roles',
- 'permission_id',
- 'role_id',
- 'role_users',
- 'role_id',
- 'user_id'
- );
- }
-}
diff --git a/main/app/sprinkles/account/src/Database/Models/Role.php b/main/app/sprinkles/account/src/Database/Models/Role.php deleted file mode 100644 index f8e40b3..0000000 --- a/main/app/sprinkles/account/src/Database/Models/Role.php +++ /dev/null @@ -1,101 +0,0 @@ -<?php
-/**
- * UserFrosting (http://www.userfrosting.com)
- *
- * @link https://github.com/userfrosting/UserFrosting
- * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)
- */
-
-namespace UserFrosting\Sprinkle\Account\Database\Models;
-
-use Illuminate\Database\Capsule\Manager as Capsule;
-use UserFrosting\Sprinkle\Core\Database\Models\Model;
-
-/**
- * Role Class
- *
- * Represents a role, which aggregates permissions and to which a user can be assigned.
- * @author Alex Weissman (https://alexanderweissman.com)
- * @property string slug
- * @property string name
- * @property string description
- */
-class Role extends Model
-{
- /**
- * @var string The name of the table for the current model.
- */
- protected $table = "roles";
-
- protected $fillable = [
- "slug",
- "name",
- "description"
- ];
-
- /**
- * @var bool Enable timestamps for this class.
- */
- public $timestamps = TRUE;
-
- /**
- * Delete this role from the database, removing associations with permissions and users.
- *
- */
- public function delete() {
- // Remove all permission associations
- $this->permissions()->detach();
-
- // Remove all user associations
- $this->users()->detach();
-
- // Delete the role
- $result = parent::delete();
-
- return $result;
- }
-
- /**
- * Get a list of default roles.
- */
- public static function getDefaultSlugs() {
- /** @var UserFrosting\Config $config */
- $config = static::$ci->config;
-
- return array_map('trim', array_keys($config['site.registration.user_defaults.roles'], TRUE));
- }
-
- /**
- * Get a list of permissions assigned to this role.
- */
- public function permissions() {
- /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */
- $classMapper = static::$ci->classMapper;
-
- return $this->belongsToMany($classMapper->getClassMapping('permission'), 'permission_roles', 'role_id', 'permission_id')->withTimestamps();
- }
-
- /**
- * Query scope to get all roles assigned to a specific user.
- *
- * @param \Illuminate\Database\Eloquent\Builder $query
- * @param int $userId
- * @return \Illuminate\Database\Eloquent\Builder
- */
- public function scopeForUser($query, $userId) {
- return $query->join('role_users', function ($join) use ($userId) {
- $join->on('role_users.role_id', 'roles.id')
- ->where('user_id', $userId);
- });
- }
-
- /**
- * Get a list of users who have this role.
- */
- public function users() {
- /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */
- $classMapper = static::$ci->classMapper;
-
- return $this->belongsToMany($classMapper->getClassMapping('user'), 'role_users', 'role_id', 'user_id');
- }
-}
diff --git a/main/app/sprinkles/account/src/Database/Models/User.php b/main/app/sprinkles/account/src/Database/Models/User.php deleted file mode 100644 index cccd307..0000000 --- a/main/app/sprinkles/account/src/Database/Models/User.php +++ /dev/null @@ -1,469 +0,0 @@ -<?php
-/**
- * UserFrosting (http://www.userfrosting.com)
- *
- * @link https://github.com/userfrosting/UserFrosting
- * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)
- */
-
-namespace UserFrosting\Sprinkle\Account\Database\Models;
-
-use Carbon\Carbon;
-use Illuminate\Database\Capsule\Manager as Capsule;
-use Illuminate\Database\Eloquent\SoftDeletes;
-use UserFrosting\Sprinkle\Account\Facades\Password;
-use UserFrosting\Sprinkle\Core\Database\Models\Model;
-use UserFrosting\Sprinkle\Core\Facades\Debug;
-
-/**
- * User Class
- *
- * Represents a User object as stored in the database.
- *
- * @author Alex Weissman (https://alexanderweissman.com)
- * @property int id
- * @property string user_name
- * @property string first_name
- * @property string last_name
- * @property string email
- * @property string locale
- * @property string theme
- * @property int group_id
- * @property bool flag_verified
- * @property bool flag_enabled
- * @property int last_activity_id
- * @property timestamp created_at
- * @property timestamp updated_at
- * @property string password
- * @property timestamp deleted_at
- */
-class User extends Model
-{
- use SoftDeletes;
-
- /**
- * The name of the table for the current model.
- *
- * @var string
- */
- protected $table = 'users';
-
- /**
- * Fields that should be mass-assignable when creating a new User.
- *
- * @var string[]
- */
- protected $fillable = [
- 'user_name',
- 'first_name',
- 'last_name',
- 'email',
- 'locale',
- 'theme',
- 'group_id',
- 'flag_verified',
- 'flag_enabled',
- 'last_activity_id',
- 'password',
- 'deleted_at'
- ];
-
- /**
- * A list of attributes to hide by default when using toArray() and toJson().
- *
- * @link https://laravel.com/docs/5.4/eloquent-serialization#hiding-attributes-from-json
- * @var string[]
- */
- protected $hidden = [
- 'password'
- ];
-
- /**
- * The attributes that should be mutated to dates.
- *
- * @var string[]
- */
- protected $dates = [
- 'deleted_at'
- ];
-
- protected $appends = [
- 'full_name'
- ];
-
- /**
- * Cached dictionary of permissions for the user.
- *
- * @var array
- */
- protected $cachedPermissions;
-
- /**
- * Enable timestamps for Users.
- *
- * @var bool
- */
- public $timestamps = TRUE;
-
- /**
- * Determine if the property for this object exists.
- *
- * We add relations here so that Twig will be able to find them.
- * See http://stackoverflow.com/questions/29514081/cannot-access-eloquent-attributes-on-twig/35908957#35908957
- * Every property in __get must also be implemented here for Twig to recognize it.
- * @param string $name the name of the property to check.
- * @return bool true if the property is defined, false otherwise.
- */
- public function __isset($name) {
- if (in_array($name, [
- 'group',
- 'last_sign_in_time',
- 'avatar'
- ])) {
- return TRUE;
- } else {
- return parent::__isset($name);
- }
- }
-
- /**
- * Get a property for this object.
- *
- * @param string $name the name of the property to retrieve.
- * @throws Exception the property does not exist for this object.
- * @return string the associated property.
- */
- public function __get($name) {
- if ($name == 'last_sign_in_time') {
- return $this->lastActivityTime('sign_in');
- } else if ($name == 'avatar') {
- // Use Gravatar as the user avatar
- $hash = md5(strtolower(trim($this->email)));
- return 'https://www.gravatar.com/avatar/' . $hash . '?d=mm';
- } else {
- return parent::__get($name);
- }
- }
-
- /**
- * Get all activities for this user.
- *
- * @return \Illuminate\Database\Eloquent\Relations\HasMany
- */
- public function activities() {
- /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */
- $classMapper = static::$ci->classMapper;
-
- return $this->hasMany($classMapper->getClassMapping('activity'), 'user_id');
- }
-
- /**
- * Delete this user from the database, along with any linked roles and activities.
- *
- * @param bool $hardDelete Set to true to completely remove the user and all associated objects.
- * @return bool true if the deletion was successful, false otherwise.
- */
- public function delete($hardDelete = FALSE) {
- /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */
- $classMapper = static::$ci->classMapper;
-
- if ($hardDelete) {
- // Remove all role associations
- $this->roles()->detach();
-
- // Remove all user activities
- $classMapper->staticMethod('activity', 'where', 'user_id', $this->id)->delete();
-
- // Remove all user tokens
- $classMapper->staticMethod('password_reset', 'where', 'user_id', $this->id)->delete();
- $classMapper->staticMethod('verification', 'where', 'user_id', $this->id)->delete();
-
- // Delete the user
- $result = parent::forceDelete();
- } else {
- // Soft delete the user, leaving all associated records alone
- $result = parent::delete();
- }
-
- return $result;
- }
-
- /**
- * Determines whether a user exists, including checking soft-deleted records
- *
- * @deprecated since 4.1.7 This method conflicts with and overrides the Builder::exists() method. Use Model::findUnique instead.
- * @param mixed $value
- * @param string $identifier
- * @param bool $checkDeleted set to true to include soft-deleted records
- * @return User|null
- */
- public static function exists($value, $identifier = 'user_name', $checkDeleted = TRUE) {
- return static::findUnique($value, $identifier, $checkDeleted);
- }
-
- /**
- * Return a cache instance specific to that user
- *
- * @return \Illuminate\Contracts\Cache\Store
- */
- public function getCache() {
- return static::$ci->cache->tags('_u' . $this->id);
- }
-
- /**
- * Allows you to get the full name of the user using `$user->full_name`
- *
- * @return string
- */
- public function getFullNameAttribute() {
- return $this->first_name . ' ' . $this->last_name;
- }
-
- /**
- * Retrieve the cached permissions dictionary for this user.
- *
- * @return array
- */
- public function getCachedPermissions() {
- if (!isset($this->cachedPermissions)) {
- $this->reloadCachedPermissions();
- }
-
- return $this->cachedPermissions;
- }
-
- /**
- * Retrieve the cached permissions dictionary for this user.
- *
- * @return User
- */
- public function reloadCachedPermissions() {
- $this->cachedPermissions = $this->buildPermissionsDictionary();
-
- return $this;
- }
-
- /**
- * Get the amount of time, in seconds, that has elapsed since the last activity of a certain time for this user.
- *
- * @param string $type The type of activity to search for.
- * @return int
- */
- public function getSecondsSinceLastActivity($type) {
- $time = $this->lastActivityTime($type);
- $time = $time ? $time : '0000-00-00 00:00:00';
- $time = new Carbon($time);
-
- return $time->diffInSeconds();
- }
-
- /**
- * Return this user's group.
- *
- * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
- */
- public function group() {
- /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */
- $classMapper = static::$ci->classMapper;
-
- return $this->belongsTo($classMapper->getClassMapping('group'), 'group_id');
- }
-
- /**
- * Returns whether or not this user is the master user.
- *
- * @return bool
- */
- public function isMaster() {
- $masterId = static::$ci->config['reserved_user_ids.master'];
-
- // Need to use loose comparison for now, because some DBs return `id` as a string
- return ($this->id == $masterId);
- }
-
- /**
- * Get the most recent activity for this user, based on the user's last_activity_id.
- *
- * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
- */
- public function lastActivity() {
- /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */
- $classMapper = static::$ci->classMapper;
-
- return $this->belongsTo($classMapper->getClassMapping('activity'), 'last_activity_id');
- }
-
- /**
- * Find the most recent activity for this user of a particular type.
- *
- * @param string $type
- * @return \Illuminate\Database\Eloquent\Builder
- */
- public function lastActivityOfType($type = NULL) {
- /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */
- $classMapper = static::$ci->classMapper;
-
- $query = $this->hasOne($classMapper->getClassMapping('activity'), 'user_id');
-
- if ($type) {
- $query = $query->where('type', $type);
- }
-
- return $query->latest('occurred_at');
- }
-
- /**
- * Get the most recent time for a specified activity type for this user.
- *
- * @param string $type
- * @return string|null The last activity time, as a SQL formatted time (YYYY-MM-DD HH:MM:SS), or null if an activity of this type doesn't exist.
- */
- public function lastActivityTime($type) {
- $result = $this->activities()
- ->where('type', $type)
- ->max('occurred_at');
- return $result ? $result : NULL;
- }
-
- /**
- * Performs tasks to be done after this user has been successfully authenticated.
- *
- * By default, adds a new sign-in activity and updates any legacy hash.
- * @param mixed[] $params Optional array of parameters used for this event handler.
- * @odo Transition to Laravel Event dispatcher to handle this
- */
- public function onLogin($params = []) {
- // Add a sign in activity (time is automatically set by database)
- static::$ci->userActivityLogger->info("User {$this->user_name} signed in.", [
- 'type' => 'sign_in'
- ]);
-
- // Update password if we had encountered an outdated hash
- $passwordType = Password::getHashType($this->password);
-
- if ($passwordType != 'modern') {
- if (!isset($params['password'])) {
- Debug::debug('Notice: Unhashed password must be supplied to update to modern password hashing.');
- } else {
- // Hash the user's password and update
- $passwordHash = Password::hash($params['password']);
- if ($passwordHash === NULL) {
- Debug::debug('Notice: outdated password hash could not be updated because the new hashing algorithm is not supported. Are you running PHP >= 5.3.7?');
- } else {
- $this->password = $passwordHash;
- Debug::debug('Notice: outdated password hash has been automatically updated to modern hashing.');
- }
- }
- }
-
- // Save changes
- $this->save();
-
- return $this;
- }
-
- /**
- * Performs tasks to be done after this user has been logged out.
- *
- * By default, adds a new sign-out activity.
- * @param mixed[] $params Optional array of parameters used for this event handler.
- * @do Transition to Laravel Event dispatcher to handle this
- */
- public function onLogout($params = []) {
- static::$ci->userActivityLogger->info("User {$this->user_name} signed out.", [
- 'type' => 'sign_out'
- ]);
-
- return $this;
- }
-
- /**
- * Get all password reset requests for this user.
- *
- * @return \Illuminate\Database\Eloquent\Relations\HasMany
- */
- public function passwordResets() {
- /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */
- $classMapper = static::$ci->classMapper;
-
- return $this->hasMany($classMapper->getClassMapping('password_reset'), 'user_id');
- }
-
- /**
- * Get all of the permissions this user has, via its roles.
- *
- * @return \UserFrosting\Sprinkle\Core\Database\Relations\BelongsToManyThrough
- */
- public function permissions() {
- /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */
- $classMapper = static::$ci->classMapper;
-
- return $this->belongsToManyThrough(
- $classMapper->getClassMapping('permission'),
- $classMapper->getClassMapping('role'),
- 'role_users',
- 'user_id',
- 'role_id',
- 'permission_roles',
- 'role_id',
- 'permission_id'
- );
- }
-
- /**
- * Get all roles to which this user belongs.
- *
- * @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
- */
- public function roles() {
- /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */
- $classMapper = static::$ci->classMapper;
-
- return $this->belongsToMany($classMapper->getClassMapping('role'), 'role_users', 'user_id', 'role_id')->withTimestamps();
- }
-
- /**
- * Query scope to get all users who have a specific role.
- *
- * @param \Illuminate\Database\Eloquent\Builder $query
- * @param int $roleId
- * @return \Illuminate\Database\Eloquent\Builder
- */
- public function scopeForRole($query, $roleId) {
- return $query->join('role_users', function ($join) use ($roleId) {
- $join->on('role_users.user_id', 'users.id')
- ->where('role_id', $roleId);
- });
- }
-
- /**
- * Joins the user's most recent activity directly, so we can do things like sort, search, paginate, etc.
- *
- * @param \Illuminate\Database\Eloquent\Builder $query
- * @return \Illuminate\Database\Eloquent\Builder
- */
- public function scopeJoinLastActivity($query) {
- $query = $query->select('users.*');
-
- $query = $query->leftJoin('activities', 'activities.id', '=', 'users.last_activity_id');
-
- return $query;
- }
-
- /**
- * Loads permissions for this user into a cached dictionary of slugs -> arrays of permissions,
- * so we don't need to keep requerying the DB for every call of checkAccess.
- *
- * @return array
- */
- protected function buildPermissionsDictionary() {
- $permissions = $this->permissions()->get();
- $cachedPermissions = [];
-
- foreach ($permissions as $permission) {
- $cachedPermissions[$permission->slug][] = $permission;
- }
-
- return $cachedPermissions;
- }
-}
diff --git a/main/app/sprinkles/account/src/Database/Models/Verification.php b/main/app/sprinkles/account/src/Database/Models/Verification.php deleted file mode 100644 index f642d77..0000000 --- a/main/app/sprinkles/account/src/Database/Models/Verification.php +++ /dev/null @@ -1,68 +0,0 @@ -<?php
-/**
- * UserFrosting (http://www.userfrosting.com)
- *
- * @link https://github.com/userfrosting/UserFrosting
- * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)
- */
-
-namespace UserFrosting\Sprinkle\Account\Database\Models;
-
-use Illuminate\Database\Capsule\Manager as Capsule;
-use UserFrosting\Sprinkle\Core\Database\Models\Model;
-
-/**
- * Verification Class
- *
- * Represents a pending email verification for a new user account.
- * @author Alex Weissman (https://alexanderweissman.com)
- * @property int user_id
- * @property hash token
- * @property bool completed
- * @property datetime expires_at
- * @property datetime completed_at
- */
-class Verification extends Model
-{
- /**
- * @var string The name of the table for the current model.
- */
- protected $table = "verifications";
-
- protected $fillable = [
- "user_id",
- "hash",
- "completed",
- "expires_at",
- "completed_at"
- ];
-
- /**
- * @var bool Enable timestamps for Verifications.
- */
- public $timestamps = TRUE;
-
- /**
- * Stores the raw (unhashed) token when created, so that it can be emailed out to the user. NOT persisted.
- */
- protected $token;
-
- public function getToken() {
- return $this->token;
- }
-
- public function setToken($value) {
- $this->token = $value;
- return $this;
- }
-
- /**
- * Get the user associated with this verification request.
- */
- public function user() {
- /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */
- $classMapper = static::$ci->classMapper;
-
- return $this->belongsTo($classMapper->getClassMapping('user'), 'user_id');
- }
-}
diff --git a/main/app/sprinkles/account/src/Error/Handler/AuthCompromisedExceptionHandler.php b/main/app/sprinkles/account/src/Error/Handler/AuthCompromisedExceptionHandler.php deleted file mode 100644 index ccefe72..0000000 --- a/main/app/sprinkles/account/src/Error/Handler/AuthCompromisedExceptionHandler.php +++ /dev/null @@ -1,34 +0,0 @@ -<?php
-/**
- * UserFrosting (http://www.userfrosting.com)
- *
- * @link https://github.com/userfrosting/UserFrosting
- * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)
- */
-
-namespace UserFrosting\Sprinkle\Account\Error\Handler;
-
-use UserFrosting\Sprinkle\Core\Error\Handler\HttpExceptionHandler;
-
-/**
- * Handler for AuthCompromisedExceptions.
- *
- * Warns the user that their account may have been compromised due to a stolen "remember me" cookie.
- * @author Alex Weissman (https://alexanderweissman.com)
- */
-class AuthCompromisedExceptionHandler extends HttpExceptionHandler
-{
- /**
- * Render a generic, user-friendly response without sensitive debugging information.
- *
- * @return ResponseInterface
- */
- public function renderGenericResponse() {
- $template = $this->ci->view->getEnvironment()->loadTemplate('pages/error/compromised.html.twig');
-
- return $this->response
- ->withStatus($this->statusCode)
- ->withHeader('Content-type', $this->contentType)
- ->write($template->render());
- }
-}
diff --git a/main/app/sprinkles/account/src/Error/Handler/AuthExpiredExceptionHandler.php b/main/app/sprinkles/account/src/Error/Handler/AuthExpiredExceptionHandler.php deleted file mode 100644 index fb04bd1..0000000 --- a/main/app/sprinkles/account/src/Error/Handler/AuthExpiredExceptionHandler.php +++ /dev/null @@ -1,50 +0,0 @@ -<?php
-/**
- * UserFrosting (http://www.userfrosting.com)
- *
- * @link https://github.com/userfrosting/UserFrosting
- * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)
- */
-
-namespace UserFrosting\Sprinkle\Account\Error\Handler;
-
-use UserFrosting\Sprinkle\Core\Error\Handler\HttpExceptionHandler;
-
-/**
- * Handler for AuthExpiredExceptions.
- *
- * Forwards the user to the login page when their session has expired.
- * @author Alex Weissman (https://alexanderweissman.com)
- */
-class AuthExpiredExceptionHandler extends HttpExceptionHandler
-{
- /**
- * Custom handling for requests that did not pass authentication.
- */
- public function handle() {
- // For auth expired exceptions, we always add messages to the alert stream.
- $this->writeAlerts();
-
- $response = $this->response;
-
- // For non-AJAX requests, we forward the user to the login page.
- if (!$this->request->isXhr()) {
- $uri = $this->request->getUri();
- $path = $uri->getPath();
- $query = $uri->getQuery();
- $fragment = $uri->getFragment();
-
- $path = $path
- . ($query ? '?' . $query : '')
- . ($fragment ? '#' . $fragment : '');
-
- $loginPage = $this->ci->router->pathFor('login', [], [
- 'redirect' => $path
- ]);
-
- $response = $response->withRedirect($loginPage);
- }
-
- return $response;
- }
-}
diff --git a/main/app/sprinkles/account/src/Error/Handler/ForbiddenExceptionHandler.php b/main/app/sprinkles/account/src/Error/Handler/ForbiddenExceptionHandler.php deleted file mode 100644 index 0166d2a..0000000 --- a/main/app/sprinkles/account/src/Error/Handler/ForbiddenExceptionHandler.php +++ /dev/null @@ -1,31 +0,0 @@ -<?php
-/**
- * UserFrosting (http://www.userfrosting.com)
- *
- * @link https://github.com/userfrosting/UserFrosting
- * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)
- */
-
-namespace UserFrosting\Sprinkle\Account\Error\Handler;
-
-use UserFrosting\Sprinkle\Core\Error\Handler\HttpExceptionHandler;
-use UserFrosting\Support\Message\UserMessage;
-
-/**
- * Handler for ForbiddenExceptions. Only really needed to override the default error message.
- *
- * @author Alex Weissman (https://alexanderweissman.com)
- */
-class ForbiddenExceptionHandler extends HttpExceptionHandler
-{
- /**
- * Resolve a list of error messages to present to the end user.
- *
- * @return array
- */
- protected function determineUserMessages() {
- return [
- new UserMessage("ACCOUNT.ACCESS_DENIED")
- ];
- }
-}
diff --git a/main/app/sprinkles/account/src/Facades/Password.php b/main/app/sprinkles/account/src/Facades/Password.php deleted file mode 100644 index ec300d3..0000000 --- a/main/app/sprinkles/account/src/Facades/Password.php +++ /dev/null @@ -1,28 +0,0 @@ -<?php
-/**
- * UserFrosting (http://www.userfrosting.com)
- *
- * @link https://github.com/userfrosting/UserFrosting
- * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)
- */
-
-namespace UserFrosting\Sprinkle\Account\Facades;
-
-use UserFrosting\System\Facade;
-
-/**
- * Implements facade for the "password" service
- *
- * @author Alex Weissman (https://alexanderweissman.com)
- */
-class Password extends Facade
-{
- /**
- * Get the registered name of the component.
- *
- * @return string
- */
- protected static function getFacadeAccessor() {
- return 'passwordHasher';
- }
-}
diff --git a/main/app/sprinkles/account/src/Log/UserActivityDatabaseHandler.php b/main/app/sprinkles/account/src/Log/UserActivityDatabaseHandler.php deleted file mode 100644 index eb57f43..0000000 --- a/main/app/sprinkles/account/src/Log/UserActivityDatabaseHandler.php +++ /dev/null @@ -1,33 +0,0 @@ -<?php
-/**
- * UserFrosting (http://www.userfrosting.com)
- *
- * @link https://github.com/userfrosting/UserFrosting
- * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)
- */
-
-namespace UserFrosting\Sprinkle\Account\Log;
-
-use UserFrosting\Sprinkle\Core\Log\DatabaseHandler;
-
-/**
- * Monolog handler for storing user activities to the database.
- *
- * @author Alex Weissman (https://alexanderweissman.com)
- */
-class UserActivityDatabaseHandler extends DatabaseHandler
-{
- /**
- * {@inheritDoc}
- */
- protected function write(array $record) {
- $log = $this->classMapper->createInstance($this->modelName, $record['extra']);
- $log->save();
-
- if (isset($record['extra']['user_id'])) {
- $user = $this->classMapper->staticMethod('user', 'find', $record['extra']['user_id']);
- $user->last_activity_id = $log->id;
- $user->save();
- }
- }
-}
diff --git a/main/app/sprinkles/account/src/Log/UserActivityProcessor.php b/main/app/sprinkles/account/src/Log/UserActivityProcessor.php deleted file mode 100644 index a5c0d98..0000000 --- a/main/app/sprinkles/account/src/Log/UserActivityProcessor.php +++ /dev/null @@ -1,44 +0,0 @@ -<?php
-/**
- * UserFrosting (http://www.userfrosting.com)
- *
- * @link https://github.com/userfrosting/UserFrosting
- * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)
- */
-
-namespace UserFrosting\Sprinkle\Account\Log;
-
-use Monolog\Logger;
-
-/**
- * Monolog processor for constructing the user activity message.
- *
- * @author Alex Weissman (https://alexanderweissman.com)
- */
-class UserActivityProcessor
-{
- /**
- * @var int
- */
- protected $userId;
-
- /**
- * @param int $userId The id of the user for whom we will be logging activities.
- */
- public function __construct($userId) {
- $this->userId = $userId;
- }
-
- public function __invoke(array $record) {
- $additionalFields = [
- 'ip_address' => $_SERVER['REMOTE_ADDR'],
- 'user_id' => $this->userId,
- 'occurred_at' => $record['datetime'],
- 'description' => $record['message']
- ];
-
- $record['extra'] = array_replace_recursive($record['extra'], $additionalFields, $record['context']);
-
- return $record;
- }
-}
diff --git a/main/app/sprinkles/account/src/Repository/PasswordResetRepository.php b/main/app/sprinkles/account/src/Repository/PasswordResetRepository.php deleted file mode 100644 index 06a37a8..0000000 --- a/main/app/sprinkles/account/src/Repository/PasswordResetRepository.php +++ /dev/null @@ -1,34 +0,0 @@ -<?php
-/**
- * UserFrosting (http://www.userfrosting.com)
- *
- * @link https://github.com/userfrosting/UserFrosting
- * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)
- */
-
-namespace UserFrosting\Sprinkle\Account\Repository;
-
-use UserFrosting\Sprinkle\Account\Facades\Password;
-
-/**
- * Token repository class for password reset requests.
- *
- * @author Alex Weissman (https://alexanderweissman.com)
- * @see https://learn.userfrosting.com/users/user-accounts
- */
-class PasswordResetRepository extends TokenRepository
-{
- /**
- * {@inheritDoc}
- */
- protected $modelIdentifier = 'password_reset';
-
- /**
- * {@inheritDoc}
- */
- protected function updateUser($user, $args) {
- $user->password = Password::hash($args['password']);
- // DO: generate user activity? or do this in controller?
- $user->save();
- }
-}
diff --git a/main/app/sprinkles/account/src/Repository/TokenRepository.php b/main/app/sprinkles/account/src/Repository/TokenRepository.php deleted file mode 100644 index 6b289bf..0000000 --- a/main/app/sprinkles/account/src/Repository/TokenRepository.php +++ /dev/null @@ -1,223 +0,0 @@ -<?php
-/**
- * UserFrosting (http://www.userfrosting.com)
- *
- * @link https://github.com/userfrosting/UserFrosting
- * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)
- */
-
-namespace UserFrosting\Sprinkle\Account\Repository;
-
-use Carbon\Carbon;
-use UserFrosting\Sprinkle\Account\Database\Models\User;
-use UserFrosting\Sprinkle\Core\Database\Models\Model;
-use UserFrosting\Sprinkle\Core\Util\ClassMapper;
-
-/**
- * An abstract class for interacting with a repository of time-sensitive user tokens.
- *
- * User tokens are used, for example, to perform password resets and new account email verifications.
- * @author Alex Weissman (https://alexanderweissman.com)
- * @see https://learn.userfrosting.com/users/user-accounts
- */
-abstract class TokenRepository
-{
-
- /**
- * @var ClassMapper
- */
- protected $classMapper;
-
- /**
- * @var string
- */
- protected $algorithm;
-
- /**
- * @var string
- */
- protected $modelIdentifier;
-
- /**
- * Create a new TokenRepository object.
- *
- * @param ClassMapper $classMapper Maps generic class identifiers to specific class names.
- * @param string $algorithm The hashing algorithm to use when storing generated tokens.
- */
- public function __construct(ClassMapper $classMapper, $algorithm = 'sha512') {
- $this->classMapper = $classMapper;
- $this->algorithm = $algorithm;
- }
-
- /**
- * Cancels a specified token by removing it from the database.
- *
- * @param int $token The token to remove.
- * @return Model|false
- */
- public function cancel($token) {
- // Hash the password reset token for the stored version
- $hash = hash($this->algorithm, $token);
-
- // Find an incomplete reset request for the specified hash
- $model = $this->classMapper
- ->staticMethod($this->modelIdentifier, 'where', 'hash', $hash)
- ->where('completed', FALSE)
- ->first();
-
- if ($model === NULL) {
- return FALSE;
- }
-
- $model->delete();
-
- return $model;
- }
-
- /**
- * Completes a token-based process, invoking updateUser() in the child object to do the actual action.
- *
- * @param int $token The token to complete.
- * @param mixed[] $userParams An optional list of parameters to pass to updateUser().
- * @return Model|false
- */
- public function complete($token, $userParams = []) {
- // Hash the token for the stored version
- $hash = hash($this->algorithm, $token);
-
- // Find an unexpired, incomplete token for the specified hash
- $model = $this->classMapper
- ->staticMethod($this->modelIdentifier, 'where', 'hash', $hash)
- ->where('completed', FALSE)
- ->where('expires_at', '>', Carbon::now())
- ->first();
-
- if ($model === NULL) {
- return FALSE;
- }
-
- // Fetch user for this token
- $user = $this->classMapper->staticMethod('user', 'find', $model->user_id);
-
- if (is_null($user)) {
- return FALSE;
- }
-
- $this->updateUser($user, $userParams);
-
- $model->fill([
- 'completed' => TRUE,
- 'completed_at' => Carbon::now()
- ]);
-
- $model->save();
-
- return $model;
- }
-
- /**
- * Create a new token for a specified user.
- *
- * @param User $user The user object to associate with this token.
- * @param int $timeout The time, in seconds, after which this token should expire.
- * @return Model The model (PasswordReset, Verification, etc) object that stores the token.
- */
- public function create(User $user, $timeout) {
- // Remove any previous tokens for this user
- $this->removeExisting($user);
-
- // Compute expiration time
- $expiresAt = Carbon::now()->addSeconds($timeout);
-
- $model = $this->classMapper->createInstance($this->modelIdentifier);
-
- // Generate a random token
- $model->setToken($this->generateRandomToken());
-
- // Hash the password reset token for the stored version
- $hash = hash($this->algorithm, $model->getToken());
-
- $model->fill([
- 'hash' => $hash,
- 'completed' => FALSE,
- 'expires_at' => $expiresAt
- ]);
-
- $model->user_id = $user->id;
-
- $model->save();
-
- return $model;
- }
-
- /**
- * Determine if a specified user has an incomplete and unexpired token.
- *
- * @param User $user The user object to look up.
- * @param int $token Optionally, try to match a specific token.
- * @return Model|false
- */
- public function exists(User $user, $token = NULL) {
- $model = $this->classMapper
- ->staticMethod($this->modelIdentifier, 'where', 'user_id', $user->id)
- ->where('completed', FALSE)
- ->where('expires_at', '>', Carbon::now());
-
- if ($token) {
- // get token hash
- $hash = hash($this->algorithm, $token);
- $model->where('hash', $hash);
- }
-
- return $model->first() ?: FALSE;
- }
-
- /**
- * Delete all existing tokens from the database for a particular user.
- *
- * @param User $user
- * @return int
- */
- protected function removeExisting(User $user) {
- return $this->classMapper
- ->staticMethod($this->modelIdentifier, 'where', 'user_id', $user->id)
- ->delete();
- }
-
- /**
- * Remove all expired tokens from the database.
- *
- * @return bool|null
- */
- public function removeExpired() {
- return $this->classMapper
- ->staticMethod($this->modelIdentifier, 'where', 'completed', FALSE)
- ->where('expires_at', '<', Carbon::now())
- ->delete();
- }
-
- /**
- * Generate a new random token for this user.
- *
- * This generates a token to use for verifying a new account, resetting a lost password, etc.
- * @param string $gen specify an existing token that, if we happen to generate the same value, we should regenerate on.
- * @return string
- */
- protected function generateRandomToken($gen = NULL) {
- do {
- $gen = md5(uniqid(mt_rand(), FALSE));
- } while ($this->classMapper
- ->staticMethod($this->modelIdentifier, 'where', 'hash', hash($this->algorithm, $gen))
- ->first());
- return $gen;
- }
-
- /**
- * Modify the user during the token completion process.
- *
- * This method is called during complete(), and is a way for concrete implementations to modify the user.
- * @param User $user the user object to modify.
- * @return mixed[] $args the list of parameters that were supplied to the call to `complete()`
- */
- abstract protected function updateUser($user, $args);
-}
diff --git a/main/app/sprinkles/account/src/Repository/VerificationRepository.php b/main/app/sprinkles/account/src/Repository/VerificationRepository.php deleted file mode 100644 index f7ee3e7..0000000 --- a/main/app/sprinkles/account/src/Repository/VerificationRepository.php +++ /dev/null @@ -1,31 +0,0 @@ -<?php
-/**
- * UserFrosting (http://www.userfrosting.com)
- *
- * @link https://github.com/userfrosting/UserFrosting
- * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)
- */
-
-namespace UserFrosting\Sprinkle\Account\Repository;
-
-/**
- * Token repository class for new account verifications.
- *
- * @author Alex Weissman (https://alexanderweissman.com)
- * @see https://learn.userfrosting.com/users/user-accounts
- */
-class VerificationRepository extends TokenRepository
-{
- /**
- * {@inheritDoc}
- */
- protected $modelIdentifier = 'verification';
-
- /**
- * {@inheritDoc}
- */
- protected function updateUser($user, $args) {
- $user->flag_verified = 1;
- $user->save();
- }
-}
diff --git a/main/app/sprinkles/account/src/ServicesProvider/ServicesProvider.php b/main/app/sprinkles/account/src/ServicesProvider/ServicesProvider.php deleted file mode 100644 index 1615d2e..0000000 --- a/main/app/sprinkles/account/src/ServicesProvider/ServicesProvider.php +++ /dev/null @@ -1,444 +0,0 @@ -<?php
-/**
- * UserFrosting (http://www.userfrosting.com)
- *
- * @link https://github.com/userfrosting/UserFrosting
- * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)
- */
-
-namespace UserFrosting\Sprinkle\Account\ServicesProvider;
-
-use Birke\Rememberme\Authenticator as RememberMe;
-use Illuminate\Database\Capsule\Manager as Capsule;
-use Monolog\Formatter\LineFormatter;
-use Monolog\Handler\ErrorLogHandler;
-use Monolog\Handler\StreamHandler;
-use Monolog\Logger;
-use Psr\Http\Message\ResponseInterface as Response;
-use Psr\Http\Message\ServerRequestInterface as Request;
-use UserFrosting\Sprinkle\Account\Authenticate\Authenticator;
-use UserFrosting\Sprinkle\Account\Authenticate\AuthGuard;
-use UserFrosting\Sprinkle\Account\Authenticate\Hasher;
-use UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager;
-use UserFrosting\Sprinkle\Account\Database\Models\User;
-use UserFrosting\Sprinkle\Account\Log\UserActivityDatabaseHandler;
-use UserFrosting\Sprinkle\Account\Log\UserActivityProcessor;
-use UserFrosting\Sprinkle\Account\Repository\PasswordResetRepository;
-use UserFrosting\Sprinkle\Account\Repository\VerificationRepository;
-use UserFrosting\Sprinkle\Account\Twig\AccountExtension;
-use UserFrosting\Sprinkle\Core\Facades\Debug;
-use UserFrosting\Sprinkle\Core\Log\MixedFormatter;
-
-/**
- * Registers services for the account sprinkle, such as currentUser, etc.
- *
- * @author Alex Weissman (https://alexanderweissman.com)
- */
-class ServicesProvider
-{
- /**
- * Register UserFrosting's account services.
- *
- * @param Container $container A DI container implementing ArrayAccess and container-interop.
- */
- public function register($container) {
- /**
- * Extend the asset manager service to see assets for the current user's theme.
- */
- $container->extend('assets', function ($assets, $c) {
-
- // Register paths for user theme, if a user is logged in
- // We catch any authorization-related exceptions, so that error pages can be rendered.
- try {
- /** @var UserFrosting\Sprinkle\Account\Authenticate\Authenticator $authenticator */
- $authenticator = $c->authenticator;
- $currentUser = $c->currentUser;
- } catch (\Exception $e) {
- return $assets;
- }
-
- if ($authenticator->check()) {
- $c->sprinkleManager->addResource('assets', $currentUser->theme);
- }
-
- return $assets;
- });
-
- /**
- * Extend the 'classMapper' service to register model classes.
- *
- * Mappings added: User, Group, Role, Permission, Activity, PasswordReset, Verification
- */
- $container->extend('classMapper', function ($classMapper, $c) {
- $classMapper->setClassMapping('user', 'UserFrosting\Sprinkle\Account\Database\Models\User');
- $classMapper->setClassMapping('group', 'UserFrosting\Sprinkle\Account\Database\Models\Group');
- $classMapper->setClassMapping('role', 'UserFrosting\Sprinkle\Account\Database\Models\Role');
- $classMapper->setClassMapping('permission', 'UserFrosting\Sprinkle\Account\Database\Models\Permission');
- $classMapper->setClassMapping('activity', 'UserFrosting\Sprinkle\Account\Database\Models\Activity');
- $classMapper->setClassMapping('password_reset', 'UserFrosting\Sprinkle\Account\Database\Models\PasswordReset');
- $classMapper->setClassMapping('verification', 'UserFrosting\Sprinkle\Account\Database\Models\Verification');
- return $classMapper;
- });
-
- /**
- * Extends the 'errorHandler' service with custom exception handlers.
- *
- * Custom handlers added: ForbiddenExceptionHandler
- */
- $container->extend('errorHandler', function ($handler, $c) {
- // Register the ForbiddenExceptionHandler.
- $handler->registerHandler('\UserFrosting\Support\Exception\ForbiddenException', '\UserFrosting\Sprinkle\Account\Error\Handler\ForbiddenExceptionHandler');
- // Register the AuthExpiredExceptionHandler
- $handler->registerHandler('\UserFrosting\Sprinkle\Account\Authenticate\Exception\AuthExpiredException', '\UserFrosting\Sprinkle\Account\Error\Handler\AuthExpiredExceptionHandler');
- // Register the AuthCompromisedExceptionHandler.
- $handler->registerHandler('\UserFrosting\Sprinkle\Account\Authenticate\Exception\AuthCompromisedException', '\UserFrosting\Sprinkle\Account\Error\Handler\AuthCompromisedExceptionHandler');
- return $handler;
- });
-
- /**
- * Extends the 'localePathBuilder' service, adding any locale files from the user theme.
- *
- */
- $container->extend('localePathBuilder', function ($pathBuilder, $c) {
- // Add paths for user theme, if a user is logged in
- // We catch any authorization-related exceptions, so that error pages can be rendered.
- try {
- /** @var UserFrosting\Sprinkle\Account\Authenticate\Authenticator $authenticator */
- $authenticator = $c->authenticator;
- $currentUser = $c->currentUser;
- } catch (\Exception $e) {
- return $pathBuilder;
- }
-
- if ($authenticator->check()) {
- // Add paths to locale files for user theme
- $themePath = $c->sprinkleManager->addResource('locale', $currentUser->theme);
-
- // Add user locale
- $pathBuilder->addLocales($currentUser->locale);
- }
-
- return $pathBuilder;
- });
-
- /**
- * Extends the 'view' service with the AccountExtension for Twig.
- *
- * Adds account-specific functions, globals, filters, etc to Twig, and the path to templates for the user theme.
- */
- $container->extend('view', function ($view, $c) {
- $twig = $view->getEnvironment();
- $extension = new AccountExtension($c);
- $twig->addExtension($extension);
-
- // Add paths for user theme, if a user is logged in
- // We catch any authorization-related exceptions, so that error pages can be rendered.
- try {
- /** @var UserFrosting\Sprinkle\Account\Authenticate\Authenticator $authenticator */
- $authenticator = $c->authenticator;
- $currentUser = $c->currentUser;
- } catch (\Exception $e) {
- return $view;
- }
-
- if ($authenticator->check()) {
- $theme = $currentUser->theme;
- $themePath = $c->sprinkleManager->addResource('templates', $theme);
- if ($themePath) {
- $loader = $twig->getLoader();
- $loader->prependPath($themePath);
- // Add namespaced path as well
- $loader->addPath($themePath, $theme);
- }
- }
-
- return $view;
- });
-
- /**
- * Authentication service.
- *
- * Supports logging in users, remembering their sessions, etc.
- */
- $container['authenticator'] = function ($c) {
- $classMapper = $c->classMapper;
- $config = $c->config;
- $session = $c->session;
- $cache = $c->cache;
-
- // Force database connection to boot up
- $c->db;
-
- // Fix RememberMe table name
- $config['remember_me.table.tableName'] = Capsule::connection()->getTablePrefix() . $config['remember_me.table.tableName'];
-
- $authenticator = new Authenticator($classMapper, $session, $config, $cache);
- return $authenticator;
- };
-
- /**
- * Sets up the AuthGuard middleware, used to limit access to authenticated users for certain routes.
- */
- $container['authGuard'] = function ($c) {
- $authenticator = $c->authenticator;
- return new AuthGuard($authenticator);
- };
-
- /**
- * Authorization check logging with Monolog.
- *
- * Extend this service to push additional handlers onto the 'auth' log stack.
- */
- $container['authLogger'] = function ($c) {
- $logger = new Logger('auth');
-
- $logFile = $c->get('locator')->findResource('log://userfrosting.log', TRUE, TRUE);
-
- $handler = new StreamHandler($logFile);
-
- $formatter = new MixedFormatter(NULL, NULL, TRUE);
-
- $handler->setFormatter($formatter);
- $logger->pushHandler($handler);
-
- return $logger;
- };
-
- /**
- * Authorization service.
- *
- * Determines permissions for user actions. Extend this service to add additional access condition callbacks.
- */
- $container['authorizer'] = function ($c) {
- $config = $c->config;
-
- // Default access condition callbacks. Add more in your sprinkle by using $container->extend(...)
- $callbacks = [
- /**
- * Unconditionally grant permission - use carefully!
- * @return bool returns true no matter what.
- */
- 'always' => function () {
- return TRUE;
- },
-
- /**
- * Check if the specified values are identical to one another (strict comparison).
- * @param mixed $val1 the first value to compare.
- * @param mixed $val2 the second value to compare.
- * @return bool true if the values are strictly equal, false otherwise.
- */
- 'equals' => function ($val1, $val2) {
- return ($val1 === $val2);
- },
-
- /**
- * Check if the specified values are numeric, and if so, if they are equal to each other.
- * @param mixed $val1 the first value to compare.
- * @param mixed $val2 the second value to compare.
- * @return bool true if the values are numeric and equal, false otherwise.
- */
- 'equals_num' => function ($val1, $val2) {
- if (!is_numeric($val1)) {
- return FALSE;
- }
- if (!is_numeric($val2)) {
- return FALSE;
- }
-
- return ($val1 == $val2);
- },
-
- /**
- * Check if the specified user (by user_id) has a particular role.
- *
- * @param int $user_id the id of the user.
- * @param int $role_id the id of the role.
- * @return bool true if the user has the role, false otherwise.
- */
- 'has_role' => function ($user_id, $role_id) {
- return Capsule::table('role_users')
- ->where('user_id', $user_id)
- ->where('role_id', $role_id)
- ->count() > 0;
- },
-
- /**
- * Check if the specified value $needle is in the values of $haystack.
- *
- * @param mixed $needle the value to look for in $haystack
- * @param array[mixed] $haystack the array of values to search.
- * @return bool true if $needle is present in the values of $haystack, false otherwise.
- */
- 'in' => function ($needle, $haystack) {
- return in_array($needle, $haystack);
- },
-
- /**
- * Check if the specified user (by user_id) is in a particular group.
- *
- * @param int $user_id the id of the user.
- * @param int $group_id the id of the group.
- * @return bool true if the user is in the group, false otherwise.
- */
- 'in_group' => function ($user_id, $group_id) {
- $user = User::find($user_id);
- return ($user->group_id == $group_id);
- },
-
- /**
- * Check if the specified user (by user_id) is the master user.
- *
- * @param int $user_id the id of the user.
- * @return bool true if the user id is equal to the id of the master account, false otherwise.
- */
- 'is_master' => function ($user_id) use ($config) {
- // Need to use loose comparison for now, because some DBs return `id` as a string
- return ($user_id == $config['reserved_user_ids.master']);
- },
-
- /**
- * Check if all values in the array $needle are present in the values of $haystack.
- *
- * @param array[mixed] $needle the array whose values we should look for in $haystack
- * @param array[mixed] $haystack the array of values to search.
- * @return bool true if every value in $needle is present in the values of $haystack, false otherwise.
- */
- 'subset' => function ($needle, $haystack) {
- return count($needle) == count(array_intersect($needle, $haystack));
- },
-
- /**
- * Check if all keys of the array $needle are present in the values of $haystack.
- *
- * This function is useful for whitelisting an array of key-value parameters.
- * @param array[mixed] $needle the array whose keys we should look for in $haystack
- * @param array[mixed] $haystack the array of values to search.
- * @return bool true if every key in $needle is present in the values of $haystack, false otherwise.
- */
- 'subset_keys' => function ($needle, $haystack) {
- return count($needle) == count(array_intersect(array_keys($needle), $haystack));
- }
- ];
-
- $authorizer = new AuthorizationManager($c, $callbacks);
- return $authorizer;
- };
-
- /**
- * Loads the User object for the currently logged-in user.
- */
- $container['currentUser'] = function ($c) {
- $authenticator = $c->authenticator;
-
- return $authenticator->user();
- };
-
- $container['passwordHasher'] = function ($c) {
- $hasher = new Hasher();
- return $hasher;
- };
-
- /**
- * Returns a callback that forwards to dashboard if user is already logged in.
- */
- $container['redirect.onAlreadyLoggedIn'] = function ($c) {
- /**
- * This method is invoked when a user attempts to perform certain public actions when they are already logged in.
- *
- * Forward to user's landing page or last visited page
- * @param \Psr\Http\Message\ServerRequestInterface $request
- * @param \Psr\Http\Message\ResponseInterface $response
- * @param array $args
- * @return \Psr\Http\Message\ResponseInterface
- */
- return function (Request $request, Response $response, array $args) use ($c) {
- $redirect = $c->router->pathFor('dashboard');
-
- return $response->withRedirect($redirect, 302);
- };
- };
-
- /**
- * Returns a callback that handles setting the `UF-Redirect` header after a successful login.
- */
- $container['redirect.onLogin'] = function ($c) {
- /**
- * This method is invoked when a user completes the login process.
- *
- * Returns a callback that handles setting the `UF-Redirect` header after a successful login.
- * @param \Psr\Http\Message\ServerRequestInterface $request
- * @param \Psr\Http\Message\ResponseInterface $response
- * @param array $args
- * @return \Psr\Http\Message\ResponseInterface
- */
- return function (Request $request, Response $response, array $args) use ($c) {
- // Backwards compatibility for the deprecated determineRedirectOnLogin service
- if ($c->has('determineRedirectOnLogin')) {
- $determineRedirectOnLogin = $c->determineRedirectOnLogin;
-
- return $determineRedirectOnLogin($response)->withStatus(200);
- }
-
- /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager */
- $authorizer = $c->authorizer;
-
- $currentUser = $c->authenticator->user();
-
- if ($authorizer->checkAccess($currentUser, 'uri_account_settings')) {
- return $response->withHeader('UF-Redirect', $c->router->pathFor('settings'));
- } else {
- return $response->withHeader('UF-Redirect', $c->router->pathFor('index'));
- }
- };
- };
-
- /**
- * Repository for password reset requests.
- */
- $container['repoPasswordReset'] = function ($c) {
- $classMapper = $c->classMapper;
- $config = $c->config;
-
- $repo = new PasswordResetRepository($classMapper, $config['password_reset.algorithm']);
- return $repo;
- };
-
- /**
- * Repository for verification requests.
- */
- $container['repoVerification'] = function ($c) {
- $classMapper = $c->classMapper;
- $config = $c->config;
-
- $repo = new VerificationRepository($classMapper, $config['verification.algorithm']);
- return $repo;
- };
-
- /**
- * Logger for logging the current user's activities to the database.
- *
- * Extend this service to push additional handlers onto the 'userActivity' log stack.
- */
- $container['userActivityLogger'] = function ($c) {
- $classMapper = $c->classMapper;
- $config = $c->config;
- $session = $c->session;
-
- $logger = new Logger('userActivity');
-
- $handler = new UserActivityDatabaseHandler($classMapper, 'activity');
-
- // Note that we get the user id from the session, not the currentUser service.
- // This is because the currentUser service may not reflect the actual user during login/logout requests.
- $currentUserIdKey = $config['session.keys.current_user_id'];
- $userId = isset($session[$currentUserIdKey]) ? $session[$currentUserIdKey] : $config['reserved_user_ids.guest'];
- $processor = new UserActivityProcessor($userId);
-
- $logger->pushProcessor($processor);
- $logger->pushHandler($handler);
-
- return $logger;
- };
- }
-}
diff --git a/main/app/sprinkles/account/src/Twig/AccountExtension.php b/main/app/sprinkles/account/src/Twig/AccountExtension.php deleted file mode 100644 index fc94a1a..0000000 --- a/main/app/sprinkles/account/src/Twig/AccountExtension.php +++ /dev/null @@ -1,62 +0,0 @@ -<?php
-/**
- * UserFrosting (http://www.userfrosting.com)
- *
- * @link https://github.com/userfrosting/UserFrosting
- * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)
- */
-
-namespace UserFrosting\Sprinkle\Account\Twig;
-
-use Interop\Container\ContainerInterface;
-use RocketTheme\Toolbox\ResourceLocator\UniformResourceLocator;
-use Slim\Http\Uri;
-
-/**
- * Extends Twig functionality for the Account sprinkle.
- *
- * @author Alex Weissman (https://alexanderweissman.com)
- */
-class AccountExtension extends \Twig_Extension implements \Twig_Extension_GlobalsInterface
-{
-
- protected $services;
- protected $config;
-
- public function __construct(ContainerInterface $services) {
- $this->services = $services;
- $this->config = $services->config;
- }
-
- public function getName() {
- return 'userfrosting/account';
- }
-
- public function getFunctions() {
- return array(
- // Add Twig function for checking permissions during dynamic menu rendering
- new \Twig_SimpleFunction('checkAccess', function ($slug, $params = []) {
- $authorizer = $this->services->authorizer;
- $currentUser = $this->services->currentUser;
-
- return $authorizer->checkAccess($currentUser, $slug, $params);
- }),
- new \Twig_SimpleFunction('checkAuthenticated', function () {
- $authenticator = $this->services->authenticator;
- return $authenticator->check();
- })
- );
- }
-
- public function getGlobals() {
- try {
- $currentUser = $this->services->currentUser;
- } catch (\Exception $e) {
- $currentUser = NULL;
- }
-
- return [
- 'current_user' => $currentUser
- ];
- }
-}
diff --git a/main/app/sprinkles/account/src/Util/HashFailedException.php b/main/app/sprinkles/account/src/Util/HashFailedException.php deleted file mode 100644 index 580bed1..0000000 --- a/main/app/sprinkles/account/src/Util/HashFailedException.php +++ /dev/null @@ -1,22 +0,0 @@ -<?php
-/**
- * UserFrosting (http://www.userfrosting.com)
- *
- * @link https://github.com/userfrosting/UserFrosting
- * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)
- */
-
-namespace UserFrosting\Sprinkle\Account\Util;
-
-use UserFrosting\Support\Exception\HttpException;
-
-/**
- * Password hash failure exception. Used when the supplied password could not be hashed for some reason.
- *
- * @author Alex Weissman (https://alexanderweissman.com)
- */
-class HashFailedException extends HttpException
-{
- protected $defaultMessage = 'PASSWORD.HASH_FAILED';
- protected $httpErrorCode = 500;
-}
diff --git a/main/app/sprinkles/account/src/Util/Util.php b/main/app/sprinkles/account/src/Util/Util.php deleted file mode 100644 index f3a08a2..0000000 --- a/main/app/sprinkles/account/src/Util/Util.php +++ /dev/null @@ -1,39 +0,0 @@ -<?php
-/**
- * UserFrosting (http://www.userfrosting.com)
- *
- * @link https://github.com/userfrosting/UserFrosting
- * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)
- */
-
-namespace UserFrosting\Sprinkle\Account\Util;
-
-use UserFrosting\Sprinkle\Core\Util\Util as CoreUtil;
-
-/**
- * Util Class
- *
- * Static utility functions for the account Sprinkle.
- *
- * @author Alex Weissman (https://alexanderweissman.com)
- */
-class Util
-{
- /**
- * Generate a random, unique username from a list of adjectives and nouns.
- */
- static public function randomUniqueUsername($classMapper, $maxLength, $maxTries = 10) {
- for ($n = 1; $n <= 3; $n++) {
- for ($m = 0; $m < 10; $m++) {
- // Generate a random phrase with $n adjectives
- $suggestion = CoreUtil::randomPhrase($n, $maxLength, $maxTries, '.');
- if (!$classMapper->staticMethod('user', 'where', 'user_name', $suggestion)->first()) {
- return $suggestion;
- }
- }
- }
-
- return '';
- }
-
-}
|