Skip to content

ISSUE-345: privileges #149

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
},
"require": {
"php": "^8.1",
"phplist/core": "v5.0.0-alpha7",
"phplist/core": "dev-ISSUE-345",
"friendsofsymfony/rest-bundle": "*",
"symfony/test-pack": "^1.0",
"symfony/process": "^6.4",
Expand Down
24 changes: 24 additions & 0 deletions src/Identity/OpenApi/SwaggerSchemasRequest.php
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,18 @@
type: 'boolean',
example: false
),
new OA\Property(
property: 'privileges',
description: 'Array of privileges where keys are privilege names and values are booleans',
properties: [
new OA\Property(property: 'subscribers', type: 'boolean', example: true),
new OA\Property(property: 'campaigns', type: 'boolean', example: false),
new OA\Property(property: 'statistics', type: 'boolean', example: true),
new OA\Property(property: 'settings', type: 'boolean', example: false),
],
type: 'object',
example: ['subscribers' => true, 'campaigns' => false, 'statistics' => true, 'settings' => false]
),
],
type: 'object'
)]
Expand Down Expand Up @@ -68,6 +80,18 @@
type: 'boolean',
example: false
),
new OA\Property(
property: 'privileges',
description: 'Array of privileges where keys are privilege names and values are booleans',
properties: [
new OA\Property(property: 'subscribers', type: 'boolean', example: true),
new OA\Property(property: 'campaigns', type: 'boolean', example: false),
new OA\Property(property: 'statistics', type: 'boolean', example: true),
new OA\Property(property: 'settings', type: 'boolean', example: false),
],
type: 'object',
example: ['subscribers' => true, 'campaigns' => false, 'statistics' => true, 'settings' => false]
),
],
type: 'object'
)]
Expand Down
22 changes: 18 additions & 4 deletions src/Identity/Request/CreateAdministratorRequest.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

use PhpList\Core\Domain\Identity\Model\Administrator;
use PhpList\Core\Domain\Identity\Model\Dto\CreateAdministratorDto;
use PhpList\Core\Domain\Identity\Model\PrivilegeFlag;
use PhpList\RestBundle\Common\Request\RequestInterface;
use PhpList\RestBundle\Identity\Validator\Constraint\UniqueEmail;
use PhpList\RestBundle\Identity\Validator\Constraint\UniqueLoginName;
Expand All @@ -31,13 +32,26 @@ class CreateAdministratorRequest implements RequestInterface
#[Assert\Type('bool')]
public bool $superUser = false;

/**
* Array of privileges where keys are privilege names (from PrivilegeFlag enum) and values are booleans.
* Example: ['subscribers' => true, 'campaigns' => false, 'statistics' => true, 'settings' => false]
*/
#[Assert\Type('array')]
#[Assert\All([
'constraints' => [
new Assert\Type(['type' => 'bool']),
],
])]
public array $privileges = [];

public function getDto(): CreateAdministratorDto
{
return new CreateAdministratorDto(
$this->loginName,
$this->password,
$this->email,
$this->superUser
loginName: $this->loginName,
password: $this->password,
email: $this->email,
isSuperUser: $this->superUser,
privileges: $this->privileges
);
}
}
14 changes: 14 additions & 0 deletions src/Identity/Request/UpdateAdministratorRequest.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

use PhpList\Core\Domain\Identity\Model\Administrator;
use PhpList\Core\Domain\Identity\Model\Dto\UpdateAdministratorDto;
use PhpList\Core\Domain\Identity\Model\PrivilegeFlag;
use PhpList\RestBundle\Common\Request\RequestInterface;
use PhpList\RestBundle\Identity\Validator\Constraint\UniqueEmail;
use PhpList\RestBundle\Identity\Validator\Constraint\UniqueLoginName;
Expand All @@ -29,6 +30,18 @@ class UpdateAdministratorRequest implements RequestInterface
#[Assert\Type('bool')]
public ?bool $superAdmin = null;

/**
* Array of privileges where keys are privilege names (from PrivilegeFlag enum) and values are booleans.
* Example: ['subscribers' => true, 'campaigns' => false, 'statistics' => true, 'settings' => false]
*/
#[Assert\Type('array')]
#[Assert\All([
'constraints' => [
new Assert\Type(['type' => 'bool']),
],
])]
public array $privileges = [];

public function getDto(): UpdateAdministratorDto
{
return new UpdateAdministratorDto(
Expand All @@ -37,6 +50,7 @@ public function getDto(): UpdateAdministratorDto
password: $this->password,
email: $this->email,
superAdmin: $this->superAdmin,
privileges: $this->privileges
);
}
}
1 change: 1 addition & 0 deletions src/Identity/Serializer/AdministratorNormalizer.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ public function normalize($object, string $format = null, array $context = []):
'login_name' => $object->getLoginName(),
'email' => $object->getEmail(),
'super_admin' => $object->isSuperUser(),
'privileges' => $object->getPrivileges()->all(),
'created_at' => $object->getCreatedAt()?->format(DateTimeInterface::ATOM),
];
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,11 +60,24 @@ public function testCreateAdministratorWithValidDataReturnsCreated(): void
'loginName' => 'new.admin',
'password' => 'NewPassword123!',
'email' => '[email protected]',
'privileges' => [
'subscribers' => true,
'campaigns' => false,
'statistics' => true,
'settings' => false,
],
]));

$this->assertHttpCreated();
$data = $this->getDecodedJsonResponseContent();
self::assertSame('new.admin', $data['login_name']);

$administrator = $this->administratorRepository->findOneBy(['loginName' => 'new.admin']);
$privileges = $administrator->getPrivileges()->all();
self::assertTrue($privileges['subscribers']);
self::assertFalse($privileges['campaigns']);
self::assertTrue($privileges['statistics']);
self::assertFalse($privileges['settings']);
}

public function testUpdateAdministratorReturnsOk(): void
Expand All @@ -73,11 +86,24 @@ public function testUpdateAdministratorReturnsOk(): void

$this->authenticatedJsonRequest('put', '/api/v2/administrators/1', [], [], [], json_encode([
'email' => '[email protected]',
'privileges' => [
'subscribers' => false,
'campaigns' => true,
'statistics' => false,
'settings' => true,
],
]));

$this->assertHttpOkay();
$data = $this->getDecodedJsonResponseContent();
self::assertSame('[email protected]', $data['email']);

$administrator = $this->administratorRepository->find(1);
$privileges = $administrator->getPrivileges()->all();
self::assertFalse($privileges['subscribers']);
self::assertTrue($privileges['campaigns']);
self::assertFalse($privileges['statistics']);
self::assertTrue($privileges['settings']);
}

public function testDeleteAdministratorReturnsNoContent(): void
Expand Down Expand Up @@ -116,4 +142,32 @@ public function testPutAdministratorWithInvalidIdReturns404(): void

$this->assertHttpNotFound();
}

public function testUpdateAdministratorPrivilegesOnly(): void
{
$this->loadFixtures([AdministratorFixture::class]);

$originalAdmin = $this->administratorRepository->find(1);
$originalEmail = $originalAdmin->getEmail();

$this->authenticatedJsonRequest('put', '/api/v2/administrators/1', [], [], [], json_encode([
'privileges' => [
'subscribers' => true,
'campaigns' => true,
'statistics' => true,
'settings' => true,
],
]));

$this->assertHttpOkay();

$updatedAdmin = $this->administratorRepository->find(1);
self::assertSame($originalEmail, $updatedAdmin->getEmail());

$privileges = $updatedAdmin->getPrivileges()->all();
self::assertTrue($privileges['subscribers']);
self::assertTrue($privileges['campaigns']);
self::assertTrue($privileges['statistics']);
self::assertTrue($privileges['settings']);
}
}
13 changes: 13 additions & 0 deletions tests/Unit/Identity/Request/CreateAdministratorRequestTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,25 @@ public function testGetDtoReturnsCorrectDto(): void
$request->password = 'password123';
$request->email = '[email protected]';
$request->superUser = true;
$request->privileges = [
'subscribers' => true,
'campaigns' => false,
'statistics' => true,
'settings' => false,
];

$dto = $request->getDto();

$this->assertEquals('testuser', $dto->loginName);
$this->assertEquals('password123', $dto->password);
$this->assertEquals('[email protected]', $dto->email);
$this->assertTrue($dto->isSuperUser);
$this->assertEquals([
'subscribers' => true,
'campaigns' => false,
'statistics' => true,
'settings' => false,
], $dto->privileges);
}

public function testGetDtoWithDefaultSuperUserValue(): void
Expand All @@ -38,5 +50,6 @@ public function testGetDtoWithDefaultSuperUserValue(): void
$this->assertEquals('password123', $dto->password);
$this->assertEquals('[email protected]', $dto->email);
$this->assertFalse($dto->isSuperUser);
$this->assertEquals([], $dto->privileges);
}
}
13 changes: 13 additions & 0 deletions tests/Unit/Identity/Request/UpdateAdministratorRequestTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,12 @@ public function testGetDtoReturnsCorrectDto(): void
$request->password = 'password123';
$request->email = '[email protected]';
$request->superAdmin = true;
$request->privileges = [
'subscribers' => true,
'campaigns' => false,
'statistics' => true,
'settings' => false,
];

$dto = $request->getDto();

Expand All @@ -26,6 +32,12 @@ public function testGetDtoReturnsCorrectDto(): void
$this->assertEquals('password123', $dto->password);
$this->assertEquals('[email protected]', $dto->email);
$this->assertTrue($dto->superAdmin);
$this->assertEquals([
'subscribers' => true,
'campaigns' => false,
'statistics' => true,
'settings' => false,
], $dto->privileges);
}

public function testGetDtoWithNullValues(): void
Expand All @@ -40,5 +52,6 @@ public function testGetDtoWithNullValues(): void
$this->assertNull($dto->password);
$this->assertNull($dto->email);
$this->assertNull($dto->superAdmin);
$this->assertEquals([], $dto->privileges);
}
}
13 changes: 13 additions & 0 deletions tests/Unit/Identity/Serializer/AdministratorNormalizerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
use DateTime;
use InvalidArgumentException;
use PhpList\Core\Domain\Identity\Model\Administrator;
use PhpList\Core\Domain\Identity\Model\Privileges;
use PhpList\RestBundle\Identity\Serializer\AdministratorNormalizer;
use PHPUnit\Framework\TestCase;

Expand All @@ -20,6 +21,12 @@ public function testNormalizeValidAdministrator(): void
$admin->method('getEmail')->willReturn('[email protected]');
$admin->method('isSuperUser')->willReturn(true);
$admin->method('getCreatedAt')->willReturn(new DateTime('2024-01-01T10:00:00+00:00'));
$admin->method('getPrivileges')->willReturn(new Privileges([
'subscribers' => true,
'campaigns' => false,
'statistics' => true,
'settings' => false,
]));

$normalizer = new AdministratorNormalizer();
$data = $normalizer->normalize($admin);
Expand All @@ -30,6 +37,12 @@ public function testNormalizeValidAdministrator(): void
'login_name' => 'admin',
'email' => '[email protected]',
'super_admin' => true,
'privileges' => [
'subscribers' => true,
'campaigns' => false,
'statistics' => true,
'settings' => false,
],
'created_at' => '2024-01-01T10:00:00+00:00',
], $data);
}
Expand Down
Loading