Skip to content
Draft
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
3 changes: 3 additions & 0 deletions UPGRADE.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
# NEXT

- The Admin API no longer exposes `swag_migration_connection.credentialFields`. Use `GET /api/_action/migration/get-connection-credentials?connectionId=<id>` with `swag_migration.editor` permission to retrieve credentials.
- Supplying replacement `credentialFields` to `POST /api/_action/migration/check-connection` now requires `swag_migration.editor`. Checking stored credentials still requires only `swag_migration.viewer`.

- [BREAKING] [#202](https://github.com/shopware/SwagMigrationAssistant/pull/202) - fix!: replace native time reads with an injected clock
- [BREAKING] Added required constructor parameter `Psr\Clock\ClockInterface $clock` to `\SwagMigrationAssistant\Profile\Shopware\Converter\ShippingMethodConverter`
- [BREAKING] [#190](https://github.com/shopware/SwagMigrationAssistant/pull/190) - fix!: update product.sales during migration
Expand Down
28 changes: 28 additions & 0 deletions src/Controller/StatusController.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

namespace SwagMigrationAssistant\Controller;

use Shopware\Core\Framework\Api\ApiException;
use Shopware\Core\Framework\Context;
use Shopware\Core\Framework\DataAbstractionLayer\EntityRepository;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
Expand Down Expand Up @@ -92,7 +93,7 @@
}

if ($currentProfile === null) {
return new Response();

Check failure on line 96 in src/Controller/StatusController.php

View workflow job for this annotation

GitHub Actions / Extension Verifier (lowest)

phpstan/shopware.noEmptyResponse

Response with empty body. Return meaningful content or use a status code like 204 (No Content) for intentionally empty responses.
}

$profile = $this->profileRegistry->getProfile($profileName);
Expand All @@ -114,7 +115,7 @@
}

if ($currentGateway === null) {
return new Response();

Check failure on line 118 in src/Controller/StatusController.php

View workflow job for this annotation

GitHub Actions / Extension Verifier (lowest)

phpstan/shopware.noEmptyResponse

Response with empty body. Return meaningful content or use a status code like 204 (No Content) for intentionally empty responses.
}

return new JsonResponse(
Expand Down Expand Up @@ -179,6 +180,29 @@
return new JsonResponse($gatewayNames);
}

#[Route(
path: '/api/_action/migration/get-connection-credentials',
name: 'api.admin.migration.get-connection-credentials',
defaults: [PlatformRequest::ATTRIBUTE_ACL => ['swag_migration.editor']],
methods: [Request::METHOD_GET]
)]
public function getConnectionCredentials(Request $request, Context $context): JsonResponse
{
$connectionId = $request->query->getAlnum('connectionId');

if ($connectionId === '') {
throw RoutingException::missingRequestParameter('connectionId');
}

$connection = $this->migrationConnectionRepo->search(new Criteria([$connectionId]), $context)->getEntities()->first();

if ($connection === null) {
throw MigrationException::noConnectionFound();
}

return new JsonResponse($connection->getCredentialFields() ?? [], Response::HTTP_OK, ['Cache-Control' => 'no-store']);
}

#[Route(
path: '/api/_action/migration/update-connection-credentials',
name: 'api.admin.migration.update-connection-credentials',
Expand All @@ -203,7 +227,7 @@

$this->runService->updateConnectionCredentials($context, $connectionId, $credentialFields);

return new Response();

Check failure on line 230 in src/Controller/StatusController.php

View workflow job for this annotation

GitHub Actions / Extension Verifier (lowest)

phpstan/shopware.noEmptyResponse

Response with empty body. Return meaningful content or use a status code like 204 (No Content) for intentionally empty responses.
}

#[Route(
Expand Down Expand Up @@ -303,6 +327,10 @@
$credentialFields = $request->request->all('credentialFields');

if ($credentialFields !== []) {
if (!$context->isAllowed('swag_migration.editor')) {
throw ApiException::missingPrivileges(['swag_migration.editor']);
}

$connection->setCredentialFields($credentialFields);
}

Expand Down Expand Up @@ -411,7 +439,7 @@

$this->runService->startCleanupMappingChecksums($connectionId, $context);

return new Response();

Check failure on line 442 in src/Controller/StatusController.php

View workflow job for this annotation

GitHub Actions / Extension Verifier (lowest)

phpstan/shopware.noEmptyResponse

Response with empty body. Return meaningful content or use a status code like 204 (No Content) for intentionally empty responses.
}

#[Route(
Expand All @@ -424,7 +452,7 @@
{
$this->runService->startTruncateMigrationData($context);

return new Response();

Check failure on line 455 in src/Controller/StatusController.php

View workflow job for this annotation

GitHub Actions / Extension Verifier (lowest)

phpstan/shopware.noEmptyResponse

Response with empty body. Return meaningful content or use a status code like 204 (No Content) for intentionally empty responses.
}

#[Route(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

use Shopware\Core\Framework\DataAbstractionLayer\EntityDefinition;
use Shopware\Core\Framework\DataAbstractionLayer\Field\CreatedAtField;
use Shopware\Core\Framework\DataAbstractionLayer\Field\Flag\ApiAware;
use Shopware\Core\Framework\DataAbstractionLayer\Field\Flag\PrimaryKey;
use Shopware\Core\Framework\DataAbstractionLayer\Field\Flag\Required;
use Shopware\Core\Framework\DataAbstractionLayer\Field\Flag\WriteProtected;
Expand Down Expand Up @@ -50,7 +51,7 @@ protected function defineFields(): FieldCollection
return new FieldCollection([
(new IdField('id', 'id'))->addFlags(new PrimaryKey(), new Required()),
(new StringField('name', 'name'))->addFlags(new Required()),
(new JsonField('credential_fields', 'credentialFields'))->addFlags(new WriteProtected(MigrationContext::SOURCE_CONTEXT)),
(new JsonField('credential_fields', 'credentialFields'))->removeFlag(ApiAware::class)->addFlags(new WriteProtected(MigrationContext::SOURCE_CONTEXT)),
new PremappingField('premapping', 'premapping'),
(new StringField('profile_name', 'profileName'))->addFlags(new Required()),
(new StringField('gateway_name', 'gatewayName'))->addFlags(new Required()),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,21 @@ export default class MigrationApiService extends ApiService {
return this.handleResponse(response) as MigrationEnvironmentInformation;
}

async getConnectionCredentials(
connectionId: string,
additionalHeaders: AdditionalHeaders = {},
): Promise<MigrationCredentials> {
const response = await this.apiService.httpClient.get<MigrationCredentials>(
this.getActionPath('get-connection-credentials'),
{
params: { connectionId },
headers: this.getHeaders(additionalHeaders),
},
);

return this.handleResponse(response) as MigrationCredentials;
}

async updateConnectionCredentials(
connectionId: string,
credentialFields: MigrationCredentials,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -536,24 +536,26 @@ export default Shopware.Component.wrapComponentConfig({
await this.fetchConnection(items.first().selectedConnectionId);
},

fetchConnection(connectionId: string) {
return new Promise((resolve) => {
const criteria = new Criteria(1, 1);
criteria.addFilter(Criteria.equals('id', connectionId));
async fetchConnection(connectionId: string) {
const criteria = new Criteria(1, 1);
criteria.addFilter(Criteria.equals('id', connectionId));

this.migrationConnectionRepository.search(criteria, this.context).then((connectionResponse) => {
if (connectionResponse.length === 0 || connectionResponse.first().id === null) {
this.isLoading = false;
this.onNoConnectionSelected();
resolve(null);
return;
}
try {
const connectionResponse = await this.migrationConnectionRepository.search(criteria, this.context);

this.connection = connectionResponse.first();
this.isLoading = false;
resolve(null);
});
});
if (connectionResponse.length === 0 || connectionResponse.first().id === null) {
this.onNoConnectionSelected();
return;
}

const connection = connectionResponse.first();
connection.credentialFields = await this.migrationApiService.getConnectionCredentials(connection.id);
this.connection = connection;
} catch (error) {
this.onResponseError(error.response.data.errors[0].code);
} finally {
this.isLoading = false;
}
},

onNoConnectionSelected() {
Expand Down Expand Up @@ -625,14 +627,17 @@ export default Shopware.Component.wrapComponentConfig({
setting.selectedConnectionId = connection.id;
this.migrationGeneralSettingRepository
.save(setting, this.context)
.then(() => {
.then(async () => {
connection.credentialFields = await this.migrationApiService.getConnectionCredentials(
connection.id,
);
this.connection = connection;
this.isLoading = false;
resolve(null);
})
.catch(() => {
.catch((error) => {
this.isLoading = false;
reject();
reject(error);
});
})
.catch(() => {
Expand Down
2 changes: 1 addition & 1 deletion src/Resources/app/administration/src/type/types.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ type MigrationConnection = {
id: string;
profile?: MigrationProfile;
gateway?: MigrationGateway;
credentialsFields?: MigrationCredentials;
credentialFields?: MigrationCredentials;
};

type MigrationError = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ const migrationApiServiceMock = {
getProfiles: jest.fn(() => Promise.resolve([])),
getGateways: jest.fn(() => Promise.resolve([])),
getEnvironmentInformation: jest.fn(() => Promise.resolve(environementInformationSuccessMock)),
getConnectionCredentials: jest.fn(() => Promise.resolve({ apiKey, apiUser, endpoint })),
createNewConnection: jest.fn(() => Promise.resolve(environementInformationSuccessMock)),
};

Expand Down
Loading