diff --git a/mod/regmod.php b/mod/regmod.php index df1020b9f4..8c71490e0e 100644 --- a/mod/regmod.php +++ b/mod/regmod.php @@ -20,52 +20,12 @@ */ use Friendica\App; -use Friendica\Core\Worker; use Friendica\Database\DBA; use Friendica\DI; use Friendica\Model\Register; use Friendica\Model\User; use Friendica\Module\Security\Login; -function user_allow($hash) -{ - $register = Register::getByHash($hash); - if (!DBA::isResult($register)) { - return false; - } - - $user = User::getById($register['uid']); - if (!DBA::isResult($user)) { - exit(); - } - - Register::deleteByHash($hash); - - DBA::update('user', ['blocked' => false, 'verified' => true], ['uid' => $register['uid']]); - - $profile = DBA::selectFirst('profile', ['net-publish'], ['uid' => $register['uid']]); - - if (DBA::isResult($profile) && $profile['net-publish'] && DI::config()->get('system', 'directory')) { - $url = DI::baseUrl() . '/profile/' . $user['nickname']; - Worker::add(PRIORITY_LOW, "Directory", $url); - } - - $l10n = DI::l10n()->withLang($register['language']); - - $res = User::sendRegisterOpenEmail( - $l10n, - $user, - DI::config()->get('config', 'sitename'), - DI::baseUrl()->get(), - ($register['password'] ?? '') ?: 'Sent in a previous email' - ); - - if ($res) { - info(DI::l10n()->t('Account approved.') . EOL); - return true; - } -} - // This does not have to go through user_remove() and save the nickname // permanently against re-registration, as the person was not yet // allowed to have friends on this system @@ -114,7 +74,9 @@ function regmod_content(App $a) } if ($cmd === 'allow') { - user_allow($hash); + if (User::allow($hash)) { + info(DI::l10n()->t('Account approved.') . EOL); + } DI::baseUrl()->redirect('admin/users/'); } } diff --git a/src/Console/User.php b/src/Console/User.php index 6db2cf84ee..3166874e0c 100644 --- a/src/Console/User.php +++ b/src/Console/User.php @@ -24,8 +24,8 @@ namespace Friendica\Console; use Friendica\App; use Friendica\Core\L10n; use Friendica\Database\Database; +use Friendica\Model\Register; use Friendica\Model\User as UserModel; -use Friendica\Model\UserService; use RuntimeException; use Seld\CliPrompt\CliPrompt; @@ -50,8 +50,6 @@ class User extends \Asika\SimpleConsole\Console * @var Database */ private $dba; - /** @var UserService */ - private $userService; protected function getHelp() { @@ -60,6 +58,7 @@ console user - Modify user settings per console commands. Usage bin/console user password [] [-h|--help|-?] [-v] bin/console user add [ [ [ []]]] [-h|--help|-?] [-v] + bin/console user allow [] [-h|--help|-?] [-v] Description Modify user settings per console commands. @@ -71,14 +70,13 @@ HELP; return $help; } - public function __construct(App\Mode $appMode, L10n $l10n, Database $dba, UserService $userService, array $argv = null) + public function __construct(App\Mode $appMode, L10n $l10n, Database $dba, array $argv = null) { parent::__construct($argv); - $this->appMode = $appMode; - $this->l10n = $l10n; - $this->dba = $dba; - $this->userService = $userService; + $this->appMode = $appMode; + $this->l10n = $l10n; + $this->dba = $dba; } protected function doExecute() @@ -105,6 +103,8 @@ HELP; return $this->password(); case 'add': return $this->addUser(); + case 'allow': + return $this->allowUser(); default: throw new \Asika\SimpleConsole\CommandArgsException('Wrong command.'); } @@ -158,10 +158,10 @@ HELP; */ private function addUser() { - $name = $this->getArgument(1); - $nick = $this->getArgument(2); - $email= $this->getArgument(3); - $lang = $this->getArgument(4); + $name = $this->getArgument(1); + $nick = $this->getArgument(2); + $email = $this->getArgument(3); + $lang = $this->getArgument(4); if (empty($name)) { $this->out($this->l10n->t('Enter user name: ')); @@ -170,6 +170,7 @@ HELP; throw new RuntimeException('A name must be set.'); } } + if (empty($nick)) { $this->out($this->l10n->t('Enter user nickname: ')); $nick = CliPrompt::prompt(); @@ -177,6 +178,7 @@ HELP; throw new RuntimeException('A nick name must be set.'); } } + if (empty($email)) { $this->out($this->l10n->t('Enter user email address: ')); $email = CliPrompt::prompt(); @@ -191,9 +193,40 @@ HELP; } if (empty($lang)) { - return $this->userService->createMinimal($name, $email, $nick); + return UserModel::createMinimal($name, $email, $nick); } else { - return $this->userService->createMinimal($name, $email, $nick, $lang); + return UserModel::createMinimal($name, $email, $nick, $lang); } } + + /** + * Allows a user based on it's nickname + * + * @return bool True, if allow was successful + * @throws \Friendica\Network\HTTPException\InternalServerErrorException + */ + public function allowUser() + { + $nick = $this->getArgument(1); + + if (!$nick) { + $this->out($this->l10n->t('Enter user nickname: ')); + $nick = CliPrompt::prompt(); + if (empty($nick)) { + throw new RuntimeException('A nick name must be set.'); + } + } + + $user = $this->dba->selectFirst('user', ['uid'], ['nickname' => $nick]); + if (empty($user)) { + throw new RuntimeException($this->l10n->t('User not found')); + } + + $pending = Register::getPendingForUser($user['uid'] ?? 0); + if (empty($pending)) { + throw new RuntimeException($this->l10n->t('User is not pending.')); + } + + return UserModel::allow($pending['hash']); + } } diff --git a/src/DI.php b/src/DI.php index b1d2b82c1d..39efe2a97b 100644 --- a/src/DI.php +++ b/src/DI.php @@ -315,12 +315,6 @@ abstract class DI return self::$dice->create(Model\Storage\IStorage::class); } - /** @return Model\UserService */ - public static function userService() - { - return self::$dice->create(Model\UserService::class); - } - // // "Repository" namespace // diff --git a/src/Model/Register.php b/src/Model/Register.php index fa8fb7bdbb..88e424309e 100644 --- a/src/Model/Register.php +++ b/src/Model/Register.php @@ -48,6 +48,27 @@ class Register return DBA::toArray($stmt); } + /** + * Returns the pending user based on a given user id + * + * @param int $uid The user id + * + * @return array The pending user information + * + * @throws \Exception + */ + public static function getPendingForUser(int $uid) + { + return DBA::fetchFirst( + "SELECT `register`.*, `contact`.`name`, `contact`.`url`, `contact`.`micro`, `user`.`email` + FROM `register` + INNER JOIN `contact` ON `register`.`uid` = `contact`.`uid` + INNER JOIN `user` ON `register`.`uid` = `user`.`uid` + WHERE `register`.uid = ?", + $uid + ); + } + /** * Returns the pending registration count * diff --git a/src/Model/User.php b/src/Model/User.php index 27b87f9971..9c6f29ba01 100644 --- a/src/Model/User.php +++ b/src/Model/User.php @@ -24,6 +24,7 @@ namespace Friendica\Model; use DivineOmega\PasswordExposed; use Exception; use Friendica\Core\Hook; +use Friendica\Core\L10n; use Friendica\Core\Logger; use Friendica\Core\Protocol; use Friendica\Core\System; @@ -31,6 +32,7 @@ use Friendica\Core\Worker; use Friendica\Database\DBA; use Friendica\DI; use Friendica\Model\TwoFactor\AppSpecificPassword; +use Friendica\Network\HTTPException\InternalServerErrorException; use Friendica\Object\Image; use Friendica\Util\Crypto; use Friendica\Util\DateTimeFormat; @@ -279,7 +281,7 @@ class User * @param string $network network name * * @return int group id - * @throws \Friendica\Network\HTTPException\InternalServerErrorException + * @throws InternalServerErrorException */ public static function getDefaultGroup($uid, $network = '') { @@ -556,7 +558,7 @@ class User * * @param string $nickname The nickname that should be checked * @return boolean True is the nickname is blocked on the node - * @throws \Friendica\Network\HTTPException\InternalServerErrorException + * @throws InternalServerErrorException */ public static function isNicknameBlocked($nickname) { @@ -593,7 +595,7 @@ class User * @param array $data * @return array * @throws \ErrorException - * @throws \Friendica\Network\HTTPException\InternalServerErrorException + * @throws InternalServerErrorException * @throws \ImagickException * @throws Exception */ @@ -895,6 +897,123 @@ class User return DBA::update('user', ['blocked' => 0], ['uid' => $uid]); } + /** + * Allows a registration based on a hash + * + * @param string $hash + * + * @return bool True, if the allow was successful + * + * @throws InternalServerErrorException + * @throws Exception + */ + public static function allow(string $hash) + { + $register = Register::getByHash($hash); + if (!DBA::isResult($register)) { + return false; + } + + $user = User::getById($register['uid']); + if (!DBA::isResult($user)) { + return false; + } + + Register::deleteByHash($hash); + + DBA::update('user', ['blocked' => false, 'verified' => true], ['uid' => $register['uid']]); + + $profile = DBA::selectFirst('profile', ['net-publish'], ['uid' => $register['uid']]); + + if (DBA::isResult($profile) && $profile['net-publish'] && DI::config()->get('system', 'directory')) { + $url = DI::baseUrl() . '/profile/' . $user['nickname']; + Worker::add(PRIORITY_LOW, "Directory", $url); + } + + $l10n = DI::l10n()->withLang($register['language']); + + return User::sendRegisterOpenEmail( + $l10n, + $user, + DI::config()->get('config', 'sitename'), + DI::baseUrl()->get(), + ($register['password'] ?? '') ?: 'Sent in a previous email' + ); + } + + /** + * Creates a new user based on a minimal set and sends an email to this user + * + * @param string $name The user's name + * @param string $email The user's email address + * @param string $nick The user's nick name + * @param string $lang The user's language (default is english) + * + * @return bool True, if the user was created successfully + * @throws InternalServerErrorException + * @throws \ErrorException + * @throws \ImagickException + */ + public static function createMinimal(string $name, string $email, string $nick, string $lang = L10n::DEFAULT) + { + if (empty($name) || + empty($email) || + empty($nick)) { + throw new InternalServerErrorException('Invalid arguments.'); + } + + $result = self::create([ + 'username' => $name, + 'email' => $email, + 'nickname' => $nick, + 'verified' => 1, + 'language' => $lang + ]); + + $user = $result['user']; + $preamble = Strings::deindent(DI::l10n()->t(' + Dear %1$s, + the administrator of %2$s has set up an account for you.')); + $body = Strings::deindent(DI::l10n()->t(' + The login details are as follows: + + Site Location: %1$s + Login Name: %2$s + Password: %3$s + + You may change your password from your account "Settings" page after logging + in. + + Please take a few moments to review the other account settings on that page. + + You may also wish to add some basic information to your default profile + (on the "Profiles" page) so that other people can easily find you. + + We recommend setting your full name, adding a profile photo, + adding some profile "keywords" (very useful in making new friends) - and + perhaps what country you live in; if you do not wish to be more specific + than that. + + We fully respect your right to privacy, and none of these items are necessary. + If you are new and do not know anybody here, they may help + you to make some new and interesting friends. + + If you ever want to delete your account, you can do so at %1$s/removeme + + Thank you and welcome to %4$s.')); + + $preamble = sprintf($preamble, $user['username'], DI::config()->get('config', 'sitename')); + $body = sprintf($body, DI::baseUrl()->get(), $user['nickname'], $result['password'], DI::config()->get('config', 'sitename')); + + $email = DI::emailer() + ->newSystemMail() + ->withMessage(DI::l10n()->t('Registration details for %s', DI::config()->get('config', 'sitename')), $preamble, $body) + ->forUser($user) + ->withRecipient($user['email']) + ->build(); + return DI::emailer()->send($email); + } + /** * Sends pending registration confirmation email * @@ -903,7 +1022,7 @@ class User * @param string $siteurl * @param string $password Plaintext password * @return NULL|boolean from notification() and email() inherited - * @throws \Friendica\Network\HTTPException\InternalServerErrorException + * @throws InternalServerErrorException */ public static function sendRegisterPendingEmail($user, $sitename, $siteurl, $password) { @@ -946,7 +1065,7 @@ class User * @param string $password Plaintext password * * @return NULL|boolean from notification() and email() inherited - * @throws \Friendica\Network\HTTPException\InternalServerErrorException + * @throws InternalServerErrorException */ public static function sendRegisterOpenEmail(\Friendica\Core\L10n $l10n, $user, $sitename, $siteurl, $password) { @@ -1005,7 +1124,7 @@ class User /** * @param object $uid user to remove * @return bool - * @throws \Friendica\Network\HTTPException\InternalServerErrorException + * @throws InternalServerErrorException */ public static function remove($uid) { diff --git a/src/Model/UserService.php b/src/Model/UserService.php deleted file mode 100644 index 6da45e40e3..0000000000 --- a/src/Model/UserService.php +++ /dev/null @@ -1,125 +0,0 @@ -. - * - */ - -namespace Friendica\Model; - -use ErrorException; -use Friendica\App; -use Friendica\Core\Config\IConfig; -use Friendica\Core\L10n; -use Friendica\Network\HTTPException\InternalServerErrorException; -use Friendica\Util\Emailer; -use Friendica\Util\Strings; -use Friendica\Model\User as UserModel; -use ImagickException; - -class UserService -{ - /** @var L10n */ - private $l10n; - /** @var IConfig */ - private $config; - /** @var App\BaseURL */ - private $baseUrl; - /** @var Emailer */ - private $emailer; - - public function __construct(L10n $l10n, IConfig $config, Emailer $emailer, App\BaseURL $baseUrl) - { - $this->l10n = $l10n; - $this->config = $config; - $this->emailer = $emailer; - $this->baseUrl = $baseUrl; - } - - /** - * Creates a new user based on a minimal set and sends an email to this user - * - * @param string $name The user's name - * @param string $email The user's email address - * @param string $nick The user's nick name - * @param string $lang The user's language (default is english) - * - * @return bool True, if the user was created successfully - * @throws InternalServerErrorException - * @throws ErrorException - * @throws ImagickException - */ - public function createMinimal(string $name, string $email, string $nick, string $lang = L10n::DEFAULT) - { - if (empty($name) || - empty($email) || - empty($nick)) { - throw new InternalServerErrorException('Invalid arguments.'); - } - - $result = UserModel::create([ - 'username' => $name, - 'email' => $email, - 'nickname' => $nick, - 'verified' => 1, - 'language' => $lang - ]); - - $user = $result['user']; - $preamble = Strings::deindent($this->l10n->t(' - Dear %1$s, - the administrator of %2$s has set up an account for you.')); - $body = Strings::deindent($this->l10n->t(' - The login details are as follows: - - Site Location: %1$s - Login Name: %2$s - Password: %3$s - - You may change your password from your account "Settings" page after logging - in. - - Please take a few moments to review the other account settings on that page. - - You may also wish to add some basic information to your default profile - (on the "Profiles" page) so that other people can easily find you. - - We recommend setting your full name, adding a profile photo, - adding some profile "keywords" (very useful in making new friends) - and - perhaps what country you live in; if you do not wish to be more specific - than that. - - We fully respect your right to privacy, and none of these items are necessary. - If you are new and do not know anybody here, they may help - you to make some new and interesting friends. - - If you ever want to delete your account, you can do so at %1$s/removeme - - Thank you and welcome to %4$s.')); - - $preamble = sprintf($preamble, $user['username'], $this->config->get('config', 'sitename')); - $body = sprintf($body, $this->baseUrl->get(), $user['nickname'], $result['password'], $this->config->get('config', 'sitename')); - - $email = $this->emailer - ->newSystemMail() - ->withMessage($this->l10n->t('Registration details for %s', $this->config->get('config', 'sitename')), $preamble, $body) - ->forUser($user) - ->withRecipient($user['email']) - ->build(); - return $this->emailer->send($email); - } -} diff --git a/src/Module/Admin/Users.php b/src/Module/Admin/Users.php index 20a31333c2..5f21a07b21 100644 --- a/src/Module/Admin/Users.php +++ b/src/Module/Admin/Users.php @@ -28,7 +28,6 @@ use Friendica\DI; use Friendica\Model\Register; use Friendica\Model\User; use Friendica\Module\BaseAdmin; -use Friendica\Util\Strings; use Friendica\Util\Temporal; class Users extends BaseAdmin @@ -82,7 +81,7 @@ class Users extends BaseAdmin if (!empty($_POST['page_users_approve'])) { require_once 'mod/regmod.php'; foreach ($pending as $hash) { - user_allow($hash); + User::allow($hash); } }