From faa362e2e2e3b6d74fb594b3855bb33544b640ac Mon Sep 17 00:00:00 2001 From: Hugo Sales Date: Sun, 11 Apr 2021 11:03:32 +0000 Subject: [PATCH] [DB] Remove unique constraint from GSActor.nickname and fix register and related functionality --- src/Controller/Security.php | 30 +++++++++++-------- src/Core/DB/DB.php | 6 ++++ src/Entity/GSActor.php | 5 +--- src/Entity/LocalUser.php | 2 +- src/Util/Exception/NicknameTakenException.php | 5 ++-- src/Util/Nickname.php | 6 ++-- 6 files changed, 31 insertions(+), 23 deletions(-) diff --git a/src/Controller/Security.php b/src/Controller/Security.php index 551c7d3277..51fa820100 100644 --- a/src/Controller/Security.php +++ b/src/Controller/Security.php @@ -14,7 +14,9 @@ use App\Entity\Note; use App\Security\Authenticator; use App\Security\EmailVerifier; use app\Util\Common; +use App\Util\Exception\NicknameTakenException; use App\Util\Nickname; +use Doctrine\DBAL\Exception\UniqueConstraintViolationException; use Symfony\Component\Form\Extension\Core\Type\EmailType; use Symfony\Component\Form\Extension\Core\Type\PasswordType; use Symfony\Component\Form\Extension\Core\Type\SubmitType; @@ -89,18 +91,22 @@ class Security extends Controller $valid_nickname = Nickname::normalize($data['nickname'], check_already_used: true); - $actor = GSActor::create(['nickname' => $data['nickname']]); - DB::persist($actor); - DB::flush(); - $id = $actor->getId(); - $user = LocalUser::create([ - 'id' => $id, - 'nickname' => $data['nickname'], - 'outgoing_email' => $data['email'], - 'incoming_email' => $data['email'], - 'password' => LocalUser::hashPassword($data['password']), - ]); - DB::persist($user); + try { + $actor = GSActor::create(['nickname' => $data['nickname']]); + DB::persist($actor); + DB::flush(); + $id = $actor->getId(); + $user = LocalUser::create([ + 'id' => $id, + 'nickname' => $data['nickname'], + 'outgoing_email' => $data['email'], + 'incoming_email' => $data['email'], + 'password' => LocalUser::hashPassword($data['password']), + ]); + DB::persist($user); + } catch (UniqueConstraintViolationException $e) { + throw new NicknameTakenException; + } // generate a signed url and email it to the user if (Common::config('site', 'use_email')) { diff --git a/src/Core/DB/DB.php b/src/Core/DB/DB.php index 55d0232fa1..35f6eb675b 100644 --- a/src/Core/DB/DB.php +++ b/src/Core/DB/DB.php @@ -149,6 +149,12 @@ abstract class DB } } + public static function count(string $table, array $criteria) + { + $repo = self::getRepository($table); + return $repo->count($table, $criteria); + } + /** * Intercept static function calls to allow refering to entities * without writing the namespace (which is deduced from the call diff --git a/src/Entity/GSActor.php b/src/Entity/GSActor.php index 8107888d2e..af4005e73f 100644 --- a/src/Entity/GSActor.php +++ b/src/Entity/GSActor.php @@ -296,10 +296,7 @@ class GSActor extends Entity 'modified' => ['type' => 'timestamp', 'not null' => true, 'default' => 'CURRENT_TIMESTAMP', 'description' => 'date this record was modified'], ], 'primary key' => ['id'], - 'unique keys' => [ - 'gsactor_nickname_uniq' => ['nickname'], - ], - 'indexes' => [ + 'indexes' => [ 'gsactor_nickname_idx' => ['nickname'], ], 'fulltext indexes' => [ diff --git a/src/Entity/LocalUser.php b/src/Entity/LocalUser.php index 8f07f81cd6..d4e4bf8289 100644 --- a/src/Entity/LocalUser.php +++ b/src/Entity/LocalUser.php @@ -358,7 +358,7 @@ class LocalUser extends Entity implements UserInterface 'description' => 'local users, bots, etc', 'fields' => [ 'id' => ['type' => 'int', 'foreign key' => true, 'target' => 'GSActor.id', 'multiplicity' => 'one to one', 'not null' => true, 'description' => 'foreign key to gsactor table'], - 'nickname' => ['type' => 'varchar', 'foreign key' => true, 'target' => 'GSActor.nickname', 'multiplicity' => 'one to one', 'not null' => true, 'length' => 64, 'description' => 'nickname or username, foreign key to gsactor'], + 'nickname' => ['type' => 'varchar', 'not null' => true, 'length' => 64, 'description' => 'nickname or username, foreign key to gsactor'], 'password' => ['type' => 'varchar', 'length' => 191, 'description' => 'salted password, can be null for users with federated authentication'], 'outgoing_email' => ['type' => 'varchar', 'length' => 191, 'description' => 'email address for password recovery, notifications, etc.'], 'incoming_email' => ['type' => 'varchar', 'length' => 191, 'description' => 'email address for post-by-email'], diff --git a/src/Util/Exception/NicknameTakenException.php b/src/Util/Exception/NicknameTakenException.php index 434b9a7df7..8cb33cb136 100644 --- a/src/Util/Exception/NicknameTakenException.php +++ b/src/Util/Exception/NicknameTakenException.php @@ -42,12 +42,13 @@ namespace App\Util\Exception; use function App\Core\I18n\_m; +use App\Entity\GSActor; class NicknameTakenException extends NicknameException { - public ?Profile $profile = null; // the Profile which occupies the nickname + public ?GSActor $profile = null; // the GSActor which occupies the nickname - public function __construct(Profile $profile, string $msg = null, int $code = 400) + public function __construct(?GSActor $profile = null, ?string $msg = null, int $code = 400) { $this->profile = $profile; parent::__construct($msg, $code); diff --git a/src/Util/Nickname.php b/src/Util/Nickname.php index 7fe2d493df..7f1b6f0cfb 100644 --- a/src/Util/Nickname.php +++ b/src/Util/Nickname.php @@ -22,7 +22,6 @@ namespace App\Util; use App\Core\DB\DB; -use App\Core\Log; use App\Entity\GSActor; use App\Entity\LocalGroup; use App\Entity\LocalUser; @@ -156,7 +155,6 @@ class Nickname if (mb_strlen($original_nickname) < 1) { throw new NicknameEmptyException(); } elseif (mb_strlen($original_nickname) < Common::config('nickname', 'min_length')) { - Log::critical(var_dump($original_nickname, mb_strlen($original_nickname), Common::config('nickname', 'min_length'), mb_strlen($original_nickname) < Common::config('nickname', 'min_length'))); throw new NicknameTooShortException(); } elseif (!self::isCanonical($original_nickname) && !filter_var($original_nickname, FILTER_VALIDATE_EMAIL)) { throw new NicknameInvalidException(); @@ -223,12 +221,12 @@ class Nickname { $found = DB::findBy('local_user', ['nickname' => $nickname]); if ($found instanceof LocalUser) { - return $found->getProfile(); + return $found->getGSActor(); } $found = DB::findBy('local_group', ['nickname' => $nickname]); if ($found instanceof LocalGroup) { - return $found->getProfile(); + return $found->getGSActor(); } return null;