Skip to content

Commit 79301f1

Browse files
authored
Merge pull request #529 from dotkernel/issue-523
add the status "deleted" to the user table
2 parents 9d4fcec + ec0ad08 commit 79301f1

File tree

14 files changed

+67
-60
lines changed

14 files changed

+67
-60
lines changed

config/autoload/authentication.global.php

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,14 +20,10 @@
2020
'invalid_credential' => Message::INVALID_CREDENTIALS,
2121
],
2222
'options' => [
23-
'status' => [
23+
'status' => [
2424
'value' => UserStatusEnum::Active,
2525
'message' => Message::USER_NOT_ACTIVATED,
2626
],
27-
'isDeleted' => [
28-
'value' => false,
29-
'message' => Message::ACCOUNT_NOT_FOUND,
30-
],
3127
],
3228
],
3329
],

data/doctrine/migrations/Version20241120160406.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ public function up(Schema $schema): void
2121
{
2222
// this up() migration is auto-generated, please modify it to your needs
2323
$this->addSql('CREATE TABLE contact_message (uuid BINARY(16) NOT NULL, email VARCHAR(150) NOT NULL, name VARCHAR(150) NOT NULL, subject LONGTEXT NOT NULL, message LONGTEXT NOT NULL, platform LONGTEXT NOT NULL, created DATETIME NOT NULL, updated DATETIME DEFAULT NULL, PRIMARY KEY(uuid)) DEFAULT CHARACTER SET utf8mb4');
24-
$this->addSql('CREATE TABLE user (uuid BINARY(16) NOT NULL, identity VARCHAR(191) NOT NULL, password VARCHAR(191) NOT NULL, status ENUM(\'active\', \'pending\') DEFAULT \'pending\' NOT NULL, isDeleted TINYINT(1) NOT NULL, hash VARCHAR(64) NOT NULL, created DATETIME NOT NULL, updated DATETIME DEFAULT NULL, UNIQUE INDEX UNIQ_8D93D6496A95E9C4 (identity), UNIQUE INDEX UNIQ_8D93D649D1B862B8 (hash), PRIMARY KEY(uuid)) DEFAULT CHARACTER SET utf8mb4');
24+
$this->addSql('CREATE TABLE user (uuid BINARY(16) NOT NULL, identity VARCHAR(191) NOT NULL, password VARCHAR(191) NOT NULL, status ENUM(\'active\', \'pending\', \'deleted\') DEFAULT \'pending\' NOT NULL, hash VARCHAR(64) NOT NULL, created DATETIME NOT NULL, updated DATETIME DEFAULT NULL, UNIQUE INDEX UNIQ_8D93D6496A95E9C4 (identity), UNIQUE INDEX UNIQ_8D93D649D1B862B8 (hash), PRIMARY KEY(uuid)) DEFAULT CHARACTER SET utf8mb4');
2525
$this->addSql('CREATE TABLE user_roles (userUuid BINARY(16) NOT NULL, roleUuid BINARY(16) NOT NULL, INDEX IDX_54FCD59FD73087E9 (userUuid), INDEX IDX_54FCD59F88446210 (roleUuid), PRIMARY KEY(userUuid, roleUuid)) DEFAULT CHARACTER SET utf8mb4');
2626
$this->addSql('CREATE TABLE user_avatar (uuid BINARY(16) NOT NULL, name VARCHAR(191) NOT NULL, created DATETIME NOT NULL, updated DATETIME DEFAULT NULL, userUuid BINARY(16) NOT NULL, UNIQUE INDEX UNIQ_73256912D73087E9 (userUuid), PRIMARY KEY(uuid)) DEFAULT CHARACTER SET utf8mb4');
2727
$this->addSql('CREATE TABLE user_detail (uuid BINARY(16) NOT NULL, firstName VARCHAR(191) DEFAULT NULL, lastName VARCHAR(191) DEFAULT NULL, created DATETIME NOT NULL, updated DATETIME DEFAULT NULL, userUuid BINARY(16) NOT NULL, UNIQUE INDEX UNIQ_4B5464AED73087E9 (userUuid), PRIMARY KEY(uuid)) DEFAULT CHARACTER SET utf8mb4');

src/App/src/Middleware/RememberMeMiddleware.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ public function process(ServerRequestInterface $request, RequestHandlerInterface
4646
$hash === $rememberUser->getRememberMeToken() &&
4747
$rememberUser->getUserAgent() === $deviceType &&
4848
$rememberUser->getExpireDate() > new DateTimeImmutable('now') &&
49-
$user->getIsDeleted() === false
49+
$user->isDeleted() === false
5050
) {
5151
$userIdentity = UserIdentity::fromEntity($user);
5252
$this->authenticationService->getStorage()->write($userIdentity);

src/User/src/Adapter/AuthenticationAdapter.php

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
namespace Frontend\User\Adapter;
66

77
use Doctrine\ORM\EntityRepository;
8+
use Frontend\App\Common\Message;
89
use Frontend\User\Entity\UserIdentity;
910
use Frontend\User\Exception\AuthenticationAdapterException;
1011
use Laminas\Authentication\Adapter\AbstractAdapter;
@@ -39,6 +40,16 @@ public function authenticate(): Result
3940
);
4041
}
4142

43+
$methodName = 'isDeleted';
44+
$this->checkMethod($identityClass, $methodName);
45+
if ($identityClass->$methodName()) {
46+
return new Result(
47+
Result::FAILURE_IDENTITY_NOT_FOUND,
48+
null,
49+
[Message::ACCOUNT_NOT_FOUND]
50+
);
51+
}
52+
4253
$getCredential = 'get' . ucfirst($this->config['credential_property']);
4354

4455
$this->checkMethod($identityClass, $getCredential);

src/User/src/Controller/AccountController.php

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -96,18 +96,13 @@ public function unregisterAction(): ResponseInterface
9696
return new RedirectResponse($this->router->generateUri('user', ['action' => 'login']));
9797
}
9898

99-
if ($user->getIsDeleted() === User::IS_DELETED_YES) {
100-
$this->messenger->addError(Message::USER_ALREADY_DEACTIVATED, 'user-login');
101-
return new RedirectResponse($this->router->generateUri('user', ['action' => 'login']));
102-
}
103-
10499
if (! $user->isPending()) {
105100
$this->messenger->addError(Message::USER_UNREGISTER_STATUS, 'user-login');
106101
return new RedirectResponse($this->router->generateUri('user', ['action' => 'login']));
107102
}
108103

109104
try {
110-
$this->userService->updateUser($user, ['isDeleted' => User::IS_DELETED_YES]);
105+
$this->userService->deleteUser($user);
111106
} catch (Exception $exception) {
112107
$this->messenger->addError($exception->getMessage(), 'user-login');
113108
return new RedirectResponse($this->router->generateUri('user', ['action' => 'login']));
@@ -423,10 +418,8 @@ public function deleteAccountAction(): ResponseInterface
423418
if (RequestMethodInterface::METHOD_POST === $this->request->getMethod()) {
424419
$form->setData($this->request->getParsedBody());
425420
if ($form->isValid()) {
426-
/** @var array $userData */
427-
$userData = $form->getData();
428421
try {
429-
$this->userService->updateUser($user, $userData);
422+
$this->userService->deleteUser($user);
430423
$this->userService->deleteAvatar($user);
431424
} catch (Exception $e) {
432425
$this->messenger->addData('shouldRebind', true);

src/User/src/Entity/User.php

Lines changed: 2 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -45,9 +45,6 @@ class User extends AbstractEntity implements UserInterface
4545
#[ORM\Column(type: 'user_status_enum', options: ['default' => UserStatusEnum::Pending])]
4646
protected UserStatusEnum $status = UserStatusEnum::Pending;
4747

48-
#[ORM\Column(name: 'isDeleted', type: 'boolean')]
49-
protected bool $isDeleted = self::IS_DELETED_NO;
50-
5148
#[ORM\Column(name: 'hash', type: 'string', length: 64, unique: true, nullable: false)]
5249
protected string $hash;
5350

@@ -138,18 +135,6 @@ public function setStatus(UserStatusEnum $status): self
138135
return $this;
139136
}
140137

141-
public function getIsDeleted(): bool
142-
{
143-
return $this->isDeleted;
144-
}
145-
146-
public function setIsDeleted(bool $isDeleted): self
147-
{
148-
$this->isDeleted = $isDeleted;
149-
150-
return $this;
151-
}
152-
153138
public function getHash(): string
154139
{
155140
return $this->hash;
@@ -213,11 +198,9 @@ public function isPending(): bool
213198
return $this->status === UserStatusEnum::Pending;
214199
}
215200

216-
public function markAsDeleted(): self
201+
public function isDeleted(): bool
217202
{
218-
$this->isDeleted = self::IS_DELETED_YES;
219-
220-
return $this;
203+
return $this->status === UserStatusEnum::Deleted;
221204
}
222205

223206
public function getName(): string

src/User/src/Entity/UserInterface.php

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,6 @@ public function addRole(UserRole $role): UserInterface;
3838

3939
public function removeRole(UserRole $role): UserInterface;
4040

41-
public function getIsDeleted(): bool;
42-
4341
public function getArrayCopy(): array;
4442

4543
public function activate(): UserInterface;

src/User/src/Enum/UserStatusEnum.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,5 @@ enum UserStatusEnum: string
88
{
99
case Active = 'active';
1010
case Pending = 'pending';
11+
case Deleted = 'deleted';
1112
}

src/User/src/Form/ProfileDeleteForm.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ public function init(): void
4444
'title' => 'Delete account',
4545
],
4646
'options' => [
47-
'label' => 'I want to delete account',
47+
'label' => 'I want to delete my account',
4848
'use_hidden_element' => false,
4949
'checked_value' => (string) User::IS_DELETED_YES,
5050
'unchecked_value' => (string) User::IS_DELETED_NO,

src/User/src/Repository/UserRepository.php

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
use Exception;
1212
use Frontend\User\Entity\User;
1313
use Frontend\User\Entity\UserRememberMe;
14+
use Frontend\User\Enum\UserStatusEnum;
1415
use Ramsey\Uuid\Uuid;
1516

1617
use function is_string;
@@ -36,6 +37,9 @@ public function findByUuid(string $uuid): ?User
3637
->where("user.uuid = :uuid")
3738
->setParameter('uuid', $uuid)
3839
->setMaxResults(1);
40+
41+
//ignore deleted users
42+
$qb->andWhere('user.status != :status')->setParameter('status', UserStatusEnum::Deleted);
3943
return $qb->getQuery()->useQueryCache(true)->getOneOrNullResult();
4044
}
4145

@@ -72,7 +76,10 @@ public function findByResetPasswordHash(string $hash): ?User
7276
$qb = $this->getEntityManager()->createQueryBuilder();
7377
$qb->select(['user', 'resetPasswords'])->from(User::class, 'user')
7478
->leftJoin('user.resetPasswords', 'resetPasswords')
75-
->andWhere('resetPasswords.hash = :hash')->setParameter('hash', $hash);
79+
->andWhere('resetPasswords.hash = :hash')
80+
->setParameter('hash', $hash)
81+
->andWhere('user.status != :deleted')
82+
->setParameter('deleted', UserStatusEnum::Deleted);
7683

7784
return $qb->getQuery()->useQueryCache(true)->getSingleResult();
7885
} catch (Exception) {
@@ -95,7 +102,9 @@ public function getRememberUser(string $token): ?UserRememberMe
95102
$qb->select('user_remember_me')
96103
->from(UserRememberMe::class, 'user_remember_me')
97104
->where('user_remember_me.rememberMeToken = :token')
98-
->setParameter('token', $token);
105+
->setParameter('token', $token)
106+
->andWhere('user.status != :deleted')
107+
->setParameter('deleted', UserStatusEnum::Deleted);
99108

100109
return $qb->getQuery()->useQueryCache(true)->getOneOrNullResult();
101110
}
@@ -111,7 +120,9 @@ public function findRememberMeUser(User $user, string $userAgent): ?UserRemember
111120
->where('user_remember_me.user = :uuid')
112121
->setParameter('uuid', $user->getUuid()->getBytes())
113122
->andWhere('user_remember_me.userAgent = :userAgent')
114-
->setParameter('userAgent', $userAgent);
123+
->setParameter('userAgent', $userAgent)
124+
->andWhere('user.status != :deleted')
125+
->setParameter('deleted', UserStatusEnum::Deleted);
115126

116127
return $qb->getQuery()->useQueryCache(true)->getOneOrNullResult();
117128
}

0 commit comments

Comments
 (0)