Skip to content

Commit

Permalink
Merge branch 'b-7.2.x-change-module-status-OXDEV-8216' into b-7.2.x
Browse files Browse the repository at this point in the history
  • Loading branch information
MarcelOxid committed Aug 13, 2024
2 parents fd841fe + 423f2d3 commit 76c4e6a
Show file tree
Hide file tree
Showing 17 changed files with 505 additions and 15 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Theme list and filtering option on basis of theme name and status
- Module list and filtering option on basis of module name and status
- Activation of given theme by themeId
- Mutations to activate and deactive a module.

## [1.1.0] - 2024-07-05
This is stable release for v1.1.0. No changes have been made since v1.1.0-rc.1.
Expand Down
49 changes: 49 additions & 0 deletions src/Module/Controller/ModuleActivationController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
<?php

/**
* Copyright © OXID eSales AG. All rights reserved.
* See LICENSE file for license details.
*/

declare(strict_types=1);

namespace OxidEsales\GraphQL\ConfigurationAccess\Module\Controller;

use OxidEsales\GraphQL\ConfigurationAccess\Module\Service\ModuleActivationServiceInterface;
use TheCodingMachine\GraphQLite\Annotations\Logged;
use TheCodingMachine\GraphQLite\Annotations\Mutation;
use TheCodingMachine\GraphQLite\Annotations\Right;

class ModuleActivationController
{
public function __construct(
private readonly ModuleActivationServiceInterface $moduleActivationService
) {
}

/**
* Mutation of Configuration Access Module
* @param string $moduleId
* @return bool
*/
#[Mutation]
#[Logged]
#[Right('ACTIVATE_MODULE')]
public function activateModule(string $moduleId): bool
{
return $this->moduleActivationService->activateModule(moduleId: $moduleId);
}

/**
* Mutation of Configuration Access Module
* @param string $moduleId
* @return bool
*/
#[Mutation]
#[Logged]
#[Right('ACTIVATE_MODULE')]
public function deactivateModule(string $moduleId): bool
{
return $this->moduleActivationService->deactivateModule(moduleId: $moduleId);
}
}
22 changes: 22 additions & 0 deletions src/Module/Exception/ModuleActivationException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<?php

/**
* Copyright © OXID eSales AG. All rights reserved.
* See LICENSE file for license details.
*/

declare(strict_types=1);

namespace OxidEsales\GraphQL\ConfigurationAccess\Module\Exception;

use OxidEsales\GraphQL\Base\Exception\NotFound;

final class ModuleActivationException extends NotFound
{
private const EXCEPTION_MESSAGE = "An error occurred while activating the module.";

public function __construct()
{
parent::__construct(self::EXCEPTION_MESSAGE);
}
}
22 changes: 22 additions & 0 deletions src/Module/Exception/ModuleDeactivationException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<?php

/**
* Copyright © OXID eSales AG. All rights reserved.
* See LICENSE file for license details.
*/

declare(strict_types=1);

namespace OxidEsales\GraphQL\ConfigurationAccess\Module\Exception;

use OxidEsales\GraphQL\Base\Exception\NotFound;

final class ModuleDeactivationException extends NotFound
{
private const EXCEPTION_MESSAGE = "An error occurred while deactivating the module.";

public function __construct()
{
parent::__construct(self::EXCEPTION_MESSAGE);
}
}
1 change: 0 additions & 1 deletion src/Module/Infrastructure/ModuleListInfrastructure.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@

namespace OxidEsales\GraphQL\ConfigurationAccess\Module\Infrastructure;

use OxidEsales\EshopCommunity\Internal\Framework\Module\Configuration\DataObject\ModuleConfiguration;
use OxidEsales\EshopCommunity\Internal\Framework\Module\Configuration\Bridge\ShopConfigurationDaoBridgeInterface;
use OxidEsales\GraphQL\ConfigurationAccess\Module\Exception\ModulesNotFoundException;

Expand Down
56 changes: 56 additions & 0 deletions src/Module/Service/ModuleActivationService.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
<?php

/**
* Copyright © OXID eSales AG. All rights reserved.
* See LICENSE file for license details.
*/

declare(strict_types=1);

namespace OxidEsales\GraphQL\ConfigurationAccess\Module\Service;

use OxidEsales\EshopCommunity\Internal\Framework\Module\Setup\Bridge\ModuleActivationBridgeInterface;
use OxidEsales\EshopCommunity\Internal\Transition\Utility\ContextInterface;
use OxidEsales\GraphQL\ConfigurationAccess\Module\Exception\ModuleActivationException;
use OxidEsales\GraphQL\ConfigurationAccess\Module\Exception\ModuleDeactivationException;

class ModuleActivationService implements ModuleActivationServiceInterface
{
public function __construct(
private readonly ContextInterface $context,
private readonly ModuleActivationBridgeInterface $moduleActivationBridge
) {
}

/**
* @inheritDoc
*/
public function activateModule(string $moduleId): bool
{
$shopId = $this->context->getCurrentShopId();

try {
$this->moduleActivationBridge->activate(moduleId: $moduleId, shopId: $shopId);
} catch (\Exception $exception) {
throw new ModuleActivationException();
}

return true;
}

/**
* @inheritDoc
*/
public function deactivateModule(string $moduleId): bool
{
$shopId = $this->context->getCurrentShopId();

try {
$this->moduleActivationBridge->deactivate(moduleId: $moduleId, shopId: $shopId);
} catch (\Exception $exception) {
throw new ModuleDeactivationException();
}

return true;
}
}
24 changes: 24 additions & 0 deletions src/Module/Service/ModuleActivationServiceInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?php

/**
* Copyright © OXID eSales AG. All rights reserved.
* See LICENSE file for license details.
*/

namespace OxidEsales\GraphQL\ConfigurationAccess\Module\Service;

use OxidEsales\GraphQL\ConfigurationAccess\Module\Exception\ModuleActivationException;
use OxidEsales\GraphQL\ConfigurationAccess\Module\Exception\ModuleDeactivationException;

interface ModuleActivationServiceInterface
{
/**
* @throws ModuleActivationException
*/
public function activateModule(string $moduleId): bool;

/**
* @throws ModuleDeactivationException
*/
public function deactivateModule(string $moduleId): bool;
}
3 changes: 3 additions & 0 deletions src/Module/services.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,6 @@ services:

OxidEsales\GraphQL\ConfigurationAccess\Module\Service\ModuleListServiceInterface:
class: OxidEsales\GraphQL\ConfigurationAccess\Module\Service\ModuleListService

OxidEsales\GraphQL\ConfigurationAccess\Module\Service\ModuleActivationServiceInterface:
class: OxidEsales\GraphQL\ConfigurationAccess\Module\Service\ModuleActivationService
3 changes: 2 additions & 1 deletion src/Shared/Service/PermissionProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ public function getPermissions(): array
'oxidadmin' => [
'CHANGE_CONFIGURATION',
'LIST_THEMES',
'LIST_MODULES'
'LIST_MODULES',
'ACTIVATE_MODULE'
],
];
}
Expand Down
59 changes: 59 additions & 0 deletions tests/Codeception/Acceptance/Module/ModuleActivationCest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
<?php

/**
* Copyright © OXID eSales AG. All rights reserved.
* See LICENSE file for license details.
*/

declare(strict_types=1);

namespace OxidEsales\GraphQL\ConfigurationAccess\Tests\Codeception\Acceptance\Module;

use Codeception\Attribute\DataProvider;
use OxidEsales\GraphQL\ConfigurationAccess\Tests\Codeception\Acceptance\BaseCest;
use OxidEsales\GraphQL\ConfigurationAccess\Tests\Codeception\AcceptanceTester;

/**
* @group module_activation
* @group theme_switch
* @group setting_access
* @group oe_graphql_configuration_access
*/
final class ModuleActivationCest extends BaseCest
{
#[DataProvider('moduleDeActivationDataProvider')]
public function testModuleActivationAuthorized(AcceptanceTester $I, \Codeception\Example $example): void
{
$I->login($this->getAdminUsername(), $this->getAdminPassword());

$result = $this->runModuleMutation(
I: $I,
queryName: $example['queryName'],
field: $example['field']
);

$I->assertNotSame('You do not have sufficient rights to access this field', $result['errors'][0]['message']);
}

private function runModuleMutation(
AcceptanceTester $I,
string $queryName,
string $field
): array {
$I->login($this->getAdminUsername(), $this->getAdminPassword());
$I->sendGQLQuery(
'mutation {
' . $queryName . '(' . $field . ': "' . self::TEST_MODULE_ID . '")
}'
);

$I->seeResponseIsJson();
return $I->grabJsonResponseAsArray();
}

protected function moduleDeActivationDataProvider(): \Generator
{
yield ['queryName' => 'activateModule', 'field' => 'moduleId'];
yield ['queryName' => 'deactivateModule', 'field' => 'moduleId'];
}
}
56 changes: 44 additions & 12 deletions tests/Codeception/Acceptance/NotAuthorizedAccessCest.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
/**
* @group theme_switch
* @group theme_list
* @group module_activation
* @group theme_setting
* @group setting_access
* @group oe_graphql_configuration_access
Expand All @@ -36,7 +37,7 @@ public function testGetSettingNotAuthorizedQuery(AcceptanceTester $I, \Codecepti
isList: false
);

$this->assertQueryFoundErrorInResult($I, $result);
$this->assertQueryNotFoundErrorInResult($I, $result);
}

#[DataProvider('listQueriesDataProvider')]
Expand All @@ -52,7 +53,7 @@ public function testGetSettingNotAuthorizedQueryList(AcceptanceTester $I, \Codec
isList: true
);

$this->assertQueryFoundErrorInResult($I, $result);
$this->assertQueryNotFoundErrorInResult($I, $result);
}

#[DataProvider('themeMutationsDataProvider')]
Expand All @@ -70,21 +71,54 @@ public function testGetSettingNotAuthorizedMutation(AcceptanceTester $I, \Codece
location: $example['location']
);

$this->assertQueryFoundErrorInResult($I, $result);
$this->assertQueryNotFoundErrorInResult($I, $result);
}


public function testSwitchThemeNotAuthorizedMutation(AcceptanceTester $I): void
#[DataProvider('mutationsReturnsBoolDataProvider')]
public function testMutationsReturnsBoolNotAuthorized(AcceptanceTester $I, \Codeception\Example $example): void
{
$I->login($this->getAgentUsername(), $this->getAgentPassword());
$result = $this->runSimplifiedAccessCheckMutationForBool(
I: $I,
queryName: $example['queryName'],
field: $example['field'],
value: $example['value']
);

$this->assertQueryNotFoundErrorInResult($I, $result);
}

private function runSimplifiedAccessCheckMutationForBool(
AcceptanceTester $I,
string $queryName,
string $field,
mixed $value,
): array {
$parameters = $field . ': "' . $value . '"';
$I->sendGQLQuery(
'mutation {
switchTheme(identifier : "test")
' . $queryName . '(' . $parameters . ')
}'
);

$I->seeResponseIsJson();
$this->assertQueryFoundErrorInResult($I, $I->grabJsonResponseAsArray());

return $I->grabJsonResponseAsArray();
}

protected function mutationsReturnsBoolDataProvider(): \Generator
{
yield [
'queryName' => 'activateModule',
'field' => 'moduleId',
'value' => 'test'
];

yield [
'queryName' => 'deactivateModule',
'field' => 'moduleId',
'value' => 'test'
];
}

protected function themeGettersDataProvider(): \Generator
Expand Down Expand Up @@ -139,8 +173,6 @@ protected function listQueriesDataProvider(): \Generator
yield ['queryName' => 'themeSettings', 'field' => 'name', 'location' => 'theme'];
yield ['queryName' => 'moduleSettings', 'field' => 'name', 'location' => 'module'];
yield ['queryName' => 'shopSettings', 'field' => 'name', 'location' => 'shop'];
yield ['queryName' => 'themesList', 'field' => 'title', 'location' => ''];
yield ['queryName' => 'modules', 'field' => 'title', 'location' => ''];
}

protected function moduleGettersDataProvider(): \Generator
Expand Down Expand Up @@ -264,16 +296,16 @@ private function runSimplifiedAccessCheckMutation(
return $I->grabJsonResponseAsArray();
}

private function getLocationParameterString(string $location): string
private function getLocationParameterString(string $location): ?string
{
return match ($location) {
'module' => 'moduleId: "testModule"',
'theme' => 'themeId: "testTheme"',
default => ''
default => null
};
}

protected function assertQueryFoundErrorInResult(AcceptanceTester $I, array $result): void
protected function assertQueryNotFoundErrorInResult(AcceptanceTester $I, array $result): void
{
$errorMessage = $result['errors'][0]['message'];
$I->assertSame(
Expand Down
Loading

0 comments on commit 76c4e6a

Please sign in to comment.