Skip to content

Commit

Permalink
Merge pull request #1 from rigonlucas/bitwise-access-role
Browse files Browse the repository at this point in the history
Bitwise access control
  • Loading branch information
rigonlucas authored Aug 22, 2024
2 parents 802c1a5 + b783afb commit fc8c122
Show file tree
Hide file tree
Showing 24 changed files with 274 additions and 38 deletions.
2 changes: 1 addition & 1 deletion .env.testing
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ APP_ENV=testing
APP_KEY=base64:dzLwRWVSB10asrK3As1sT/IsoV7MFQ5YGjxIVWfmlvs=
APP_DEBUG=true
APP_TIMEZONE=UTC
APP_URL=http://localhost
APP_URL=http://localhost:8080

APP_LOCALE=en
APP_FALLBACK_LOCALE=en
Expand Down
5 changes: 4 additions & 1 deletion app/Http/Controllers/V1/User/ShowUserController.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
namespace App\Http\Controllers\V1\User;

use App\Http\Controllers\Controller;
use Core\Application\Account\Commons\Gateways\AccountRepositoryInterface;
use Core\Application\User\Show\ShowUserUseCase;
use Core\Presentation\Http\Errors\ErrorPresenter;
use Core\Presentation\Http\User\UserDetaisPresenter;
Expand All @@ -15,6 +16,7 @@ class ShowUserController extends Controller
{
public function __construct(
private readonly UserRepository $userRepository,
private readonly AccountRepositoryInterface $accountRepository,
private readonly FrameworkContract $frameworkService
) {
}
Expand All @@ -24,7 +26,8 @@ public function __invoke(string $uuid)
try {
$useCase = new ShowUserUseCase(
framework: $this->frameworkService,
userRepository: $this->userRepository
userRepository: $this->userRepository,
accountRepository: $this->accountRepository
);
$userEntity = $useCase->execute(uuid: $uuid);
} catch (OutputErrorException $outputErrorException) {
Expand Down
1 change: 1 addition & 0 deletions app/Models/User.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
* @property mixed|string $email
* @property mixed|string $name
* @property mixed|string $uuid
* @property mixed|int $role
* @property mixed|int $id
* @property mixed accounts
* @property int|mixed|null $account_id
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@

interface AccountRepositoryInterface
{
public function findByid(int $id): ?AccountEntity;

public function findByUuid(string $uuid): ?AccountEntity;

public function findByAccessCode(string $code): ?AccountEntity;
Expand Down
7 changes: 6 additions & 1 deletion core/Application/User/Show/ShowUserUseCase.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace Core\Application\User\Show;

use Core\Application\Account\Commons\Gateways\AccountRepositoryInterface;
use Core\Application\User\Commons\Exceptions\UserNotFountException;
use Core\Application\User\Commons\Gateways\UserRepositoryInterface;
use Core\Domain\Entities\User\UserEntity;
Expand All @@ -12,7 +13,8 @@ class ShowUserUseCase
{
public function __construct(
private readonly FrameworkContract $framework,
private readonly UserRepositoryInterface $userRepository
private readonly UserRepositoryInterface $userRepository,
private readonly AccountRepositoryInterface $accountRepository
) {
}

Expand All @@ -29,6 +31,9 @@ public function execute(string $uuid): UserEntity
);
}

$accountEntity = $this->accountRepository->findByid($userEntity->getAccount()->getId());
$userEntity->setAccount($accountEntity);

return $userEntity;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -34,4 +34,13 @@ public static function forDetail(

return $account;
}

public static function forIdentify(
int $id
): AccountEntity {
$account = new AccountEntity();
$account->setId($id);

return $account;
}
}
17 changes: 13 additions & 4 deletions core/Domain/Entities/User/Traits/HasUserEntityBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ public static function forCreate(
?AccountEntity $account,
UuidInterface $uuid = null,
?DateTimeInterface $birthday = null,
int $role = 0
): UserEntity {
$userEntity = new UserEntity();
$userEntity->setBirthday($birthday);
Expand All @@ -43,14 +44,18 @@ public static function forDetail(
string $name,
string $email,
UuidInterface $uuid,
?DateTimeInterface $birthday = null
AccountEntity $account,
?DateTimeInterface $birthday = null,
int $role = 0
): UserEntity {
$userEntity = new UserEntity();
$userEntity->setId($id);
$userEntity->setName($name);
$userEntity->setEmail(new EmailValueObject($email, false));
$userEntity->setBirthday($birthday);
$userEntity->setAccount($account);
$userEntity->setUuid($uuid);
$userEntity->setRole($role);

return $userEntity;
}
Expand All @@ -64,30 +69,34 @@ public static function forUpdate(
string $email,
#[SensitiveParameter]
string $password,
?DateTimeInterface $birthday = null
?DateTimeInterface $birthday = null,
int $role = 0
): UserEntity {
$userEntity = new UserEntity();
$userEntity->setBirthday($birthday);
$userEntity->setId($id);
$userEntity->setName($name);
$userEntity->setEmail(new EmailValueObject($email, false));
$userEntity->setPassword($password);
$userEntity->setRole($role);

return $userEntity;
}

public static function forDelete(int $id): UserEntity
public static function forDelete(int $id, int $role = 0): UserEntity
{
$userEntity = new UserEntity();
$userEntity->setId($id);
$userEntity->setRole($role);

return $userEntity;
}

public static function forIdentify(int $id): UserEntity
public static function forIdentify(int $id, int $role = 0): UserEntity
{
$userEntity = new UserEntity();
$userEntity->setId($id);
$userEntity->setRole($role);

return $userEntity;
}
Expand Down
2 changes: 1 addition & 1 deletion core/Domain/Entities/User/Traits/UserEntityAcessors.php
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ public function getBirthday(): ?DateTimeInterface
return $this->birthday;
}

public function setBirthday(DateTimeInterface $birthday): self
public function setBirthday(?DateTimeInterface $birthday): self
{
$this->birthday = $birthday;
return $this;
Expand Down
2 changes: 2 additions & 0 deletions core/Domain/Entities/User/UserEntity.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
use Core\Domain\Entities\User\Traits\HasUserEntityBuilder;
use Core\Domain\Entities\User\Traits\UserEntityAcessors;
use Core\Domain\ValueObjects\EmailValueObject;
use Core\Support\Permissions\HasUserRoleTrait;
use DateTime;
use DateTimeInterface;
use Ramsey\Uuid\UuidInterface;
Expand All @@ -14,6 +15,7 @@ class UserEntity
{
use HasUserEntityBuilder;
use UserEntityAcessors;
use HasUserRoleTrait;

private ?int $id = null;
private string $name;
Expand Down
8 changes: 8 additions & 0 deletions core/Support/Exceptions/InvalidRoleException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?php

namespace Core\Support\Exceptions;

class InvalidRoleException extends OutputErrorException
{

}
11 changes: 11 additions & 0 deletions core/Support/Permissions/Access/GeneralPermissions.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<?php

namespace Core\Support\Permissions\Access;

class GeneralPermissions
{
public const int READ = 1 << 0; // 0001
public const int WRITE = 1 << 1; // 0010
public const int DELETE = 1 << 2; // 0100
public const int EXECUTE = 1 << 3; // 1000
}
10 changes: 10 additions & 0 deletions core/Support/Permissions/Access/UserRoles.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?php

namespace Core\Support\Permissions\Access;

class UserRoles
{
public const int ADMIN = GeneralPermissions::READ | GeneralPermissions::WRITE | GeneralPermissions::DELETE | GeneralPermissions::EXECUTE;
public const int EDITOR = GeneralPermissions::READ | GeneralPermissions::WRITE;
public const int VIEWER = GeneralPermissions::READ;
}
57 changes: 57 additions & 0 deletions core/Support/Permissions/HasUserRoleTrait.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
<?php

namespace Core\Support\Permissions;

use Core\Support\Exceptions\InvalidRoleException;
use Core\Support\Http\ResponseStatusCodeEnum;
use Core\Support\Permissions\Access\UserRoles;

trait HasUserRoleTrait
{
private int $permissions = 0;
private int $role = 0;

public function hasPermission(int $permission): bool
{
return ($this->permissions & $permission) === $permission;
}

public function getPermissions(): int
{
return $this->permissions;
}

public function setPermissions(int $permissions): void
{
$this->permissions = $permissions;
}

public function getRole(): int
{
return $this->role;
}

public function setRole(int $role): void
{
$this->role = $role;
$this->permissions = $role;
}

public function hasRolePermission(int $permission): bool
{
return ($this->role & $permission) === $permission;
}

/**
* @throws InvalidRoleException
*/
public function getRoleName(): string
{
return match ($this->role) {
UserRoles::ADMIN => 'ADMIN',
UserRoles::EDITOR => 'EDITOR',
UserRoles::VIEWER => 'VIEWER',
default => throw new InvalidRoleException("Invalid role", ResponseStatusCodeEnum::FORBIDDEN->value),
};
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ public function up(): void
->default(null)
->constrained()
->onDelete('cascade');
$table->integer('role')->default(0);
$table->string('name');
$table->string('email')->unique();
$table->date('birthday')->nullable();
Expand Down
13 changes: 13 additions & 0 deletions infra/Database/Account/Repository/AccountRepository.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,19 @@

class AccountRepository implements AccountRepositoryInterface
{
public function findByid(int $id): ?AccountEntity
{
$accountModel = Account::query()->where('id', $id)->first();
if (!$accountModel) {
return null;
}

return AccountEntity::forDetail(
id: $accountModel->id,
name: $accountModel->name,
uuid: $accountModel->uuid
);
}

public function findByUuid(string $uuid): ?AccountEntity
{
Expand Down
27 changes: 22 additions & 5 deletions infra/Database/User/Repository/UserRepository.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,21 @@

use App\Models\User;
use Core\Application\User\Commons\Gateways\UserRepositoryInterface;
use Core\Domain\Entities\Account\AccountEntity;
use Core\Domain\Entities\User\UserEntity;
use Core\Support\Exceptions\InvalidEmailException;
use DateTime;
use Infra\Services\Framework\FrameworkService;

class UserRepository implements UserRepositoryInterface
{
/**
* @throws InvalidEmailException
*/
public function findById(int $id): ?UserEntity
{
$userModel = User::query()
->select(['id', 'name', 'email', 'birthday', 'uuid'])
->select(['id', 'name', 'email', 'birthday', 'uuid', 'account_id', 'role'])
->find($id);
if (!$userModel) {
return null;
Expand All @@ -24,14 +29,19 @@ public function findById(int $id): ?UserEntity
name: $userModel->name,
email: $userModel->email,
uuid: FrameworkService::getInstance()->uuid()->uuidFromString($userModel->uuid),
birthday: new DateTime($userModel->birthday)
account: AccountEntity::forIdentify($userModel->account_id),
birthday: new DateTime($userModel->birthday),
role: $userModel->role
);
}

/**
* @throws InvalidEmailException
*/
public function findByUuid(string $uuid): ?UserEntity
{
$userModel = User::query()
->select(['id', 'name', 'email', 'birthday', 'uuid'])
->select(['id', 'name', 'email', 'birthday', 'uuid', 'account_id', 'role'])
->where('uuid', '=', $uuid)
->first();
if (!$userModel) {
Expand All @@ -43,14 +53,19 @@ public function findByUuid(string $uuid): ?UserEntity
name: $userModel->name,
email: $userModel->email,
uuid: FrameworkService::getInstance()->uuid()->uuidFromString($userModel->uuid),
account: AccountEntity::forIdentify($userModel->account_id),
birthday: new DateTime($userModel->birthday),
role: $userModel->role
);
}

/**
* @throws InvalidEmailException
*/
public function findByEmail(string $email): ?UserEntity
{
$userModel = User::query()
->select(['id', 'name', 'email', 'birthday', 'uuid'])
->select(['id', 'name', 'email', 'birthday', 'uuid', 'account_id', 'role'])
->where('email', '=', $email)
->first();
if (!$userModel) {
Expand All @@ -62,7 +77,9 @@ public function findByEmail(string $email): ?UserEntity
name: $userModel->name,
email: $userModel->email,
uuid: FrameworkService::getInstance()->uuid()->uuidFromString($userModel->uuid),
birthday: new DateTime($userModel->birthday)
account: AccountEntity::forIdentify($userModel->account_id),
birthday: new DateTime($userModel->birthday),
role: $userModel->role
);
}

Expand Down
4 changes: 2 additions & 2 deletions infra/Handlers/UseCases/User/Create/CreateUserHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,8 @@ public function handle(CreateUserInput $createUserInput, AccountInput $accountIn
accountRepository: $this->accountRepositoryInterface
);

$accountInput->setUserNane($userEntity->getName());
$accountInput->setUserId($userEntity->getId());
$accountInput->setUserNane(userNane: $userEntity->getName());
$accountInput->setUserId(userId: $userEntity->getId());

$accountEntity = $createAccountUseCase->execute(input: $accountInput);

Expand Down
Loading

0 comments on commit fc8c122

Please sign in to comment.