mirror of
https://github.com/strapi/strapi.git
synced 2025-11-01 18:33:55 +00:00
Handle ws connexion status code & fix token validation
This commit is contained in:
parent
d85c05d246
commit
d8614487de
@ -36,7 +36,7 @@ const FormTransferTokenContainer = ({
|
||||
value: 'push-pull',
|
||||
label: {
|
||||
id: 'Settings.transferTokens.types.push-pull',
|
||||
defaultMessage: 'Push & pull',
|
||||
defaultMessage: 'Full Access',
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
@ -24,6 +24,10 @@ module.exports = {
|
||||
DAYS_30: 30 * DAY_IN_MS,
|
||||
DAYS_90: 90 * DAY_IN_MS,
|
||||
},
|
||||
TRANSFER_TOKEN_TYPE: {
|
||||
PUSH: 'push',
|
||||
PULL: 'pull',
|
||||
},
|
||||
TRANSFER_TOKEN_LIFESPANS: {
|
||||
UNLIMITED: null,
|
||||
DAYS_7: 7 * DAY_IN_MS,
|
||||
|
||||
@ -8,7 +8,11 @@ const transferTokenCreationSchema = yup
|
||||
.shape({
|
||||
name: yup.string().min(1).required(),
|
||||
description: yup.string().optional(),
|
||||
permissions: yup.array().of(yup.string()).nullable(),
|
||||
permissions: yup
|
||||
.array()
|
||||
.min(1)
|
||||
.of(yup.string().oneOf(Object.values(constants.TRANSFER_TOKEN_TYPE)))
|
||||
.required(),
|
||||
lifespan: yup
|
||||
.number()
|
||||
.min(1)
|
||||
@ -23,7 +27,11 @@ const transferTokenUpdateSchema = yup
|
||||
.shape({
|
||||
name: yup.string().min(1).notNull(),
|
||||
description: yup.string().nullable(),
|
||||
permissions: yup.array().of(yup.string()).nullable(),
|
||||
permissions: yup
|
||||
.array()
|
||||
.min(1)
|
||||
.of(yup.string().oneOf(Object.values(constants.TRANSFER_TOKEN_TYPE)))
|
||||
.required(),
|
||||
})
|
||||
.noUnknown()
|
||||
.strict();
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import { PassThrough, Readable, Transform } from 'stream';
|
||||
import { PassThrough, Readable } from 'stream';
|
||||
import { WebSocket } from 'ws';
|
||||
import { once } from 'lodash/fp';
|
||||
|
||||
import type {
|
||||
IAsset,
|
||||
IMetadata,
|
||||
@ -11,7 +11,11 @@ import type {
|
||||
TransferStage,
|
||||
} from '../../../../types';
|
||||
import { client, server } from '../../../../types/remote/protocol';
|
||||
import { ProviderTransferError, ProviderValidationError } from '../../../errors/providers';
|
||||
import {
|
||||
ProviderInitializationError,
|
||||
ProviderTransferError,
|
||||
ProviderValidationError,
|
||||
} from '../../../errors/providers';
|
||||
import { TRANSFER_PATH } from '../../remote/constants';
|
||||
import { ILocalStrapiSourceProviderOptions } from '../local-source';
|
||||
import { createDispatcher } from '../utils';
|
||||
@ -168,6 +172,37 @@ class RemoteStrapiSourceProvider implements ISourceProvider {
|
||||
async initTransfer(): Promise<string> {
|
||||
return new Promise<string>((resolve, reject) => {
|
||||
this.ws
|
||||
?.on('unexpected-response', (_req, res) => {
|
||||
if (res.statusCode === 401) {
|
||||
return reject(
|
||||
new ProviderInitializationError(
|
||||
'Failed to initialize the connexion: Authentication Error'
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
if (res.statusCode === 403) {
|
||||
return reject(
|
||||
new ProviderInitializationError(
|
||||
'Failed to initialize the connexion: Authorization Error'
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
if (res.statusCode === 404) {
|
||||
return reject(
|
||||
new ProviderInitializationError(
|
||||
'Failed to initialize the connexion: Data transfer is not enabled on the remote host'
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
return reject(
|
||||
new ProviderInitializationError(
|
||||
`Failed to initialize the connexion: Unexpected server response ${res.statusCode}`
|
||||
)
|
||||
);
|
||||
})
|
||||
?.once('open', async () => {
|
||||
const query = this.dispatcher?.dispatchCommand({
|
||||
command: 'init',
|
||||
@ -187,7 +222,7 @@ class RemoteStrapiSourceProvider implements ISourceProvider {
|
||||
});
|
||||
}
|
||||
|
||||
async bootstrap?(): Promise<void> {
|
||||
async bootstrap(): Promise<void> {
|
||||
const { url, auth } = this.options;
|
||||
let ws: WebSocket;
|
||||
this.assertValidProtocol(url);
|
||||
@ -245,10 +280,6 @@ class RemoteStrapiSourceProvider implements ISourceProvider {
|
||||
return schemas;
|
||||
}
|
||||
|
||||
#startStepOnce(stage: client.TransferPullStep) {
|
||||
return once(() => this.#startStep(stage));
|
||||
}
|
||||
|
||||
async #startStep<T extends client.TransferPullStep>(step: T) {
|
||||
try {
|
||||
return await this.dispatcher?.dispatchTransferStep({ action: 'start', step });
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { Readable, Transform } from 'stream';
|
||||
import { Readable } from 'stream';
|
||||
import { randomUUID } from 'crypto';
|
||||
|
||||
import { Handler } from './abstract';
|
||||
@ -62,6 +62,10 @@ export const createPullController = handlerControllerFactory<Partial<PullHandler
|
||||
async onMessage(this: PullHandler, raw) {
|
||||
const msg = JSON.parse(raw.toString());
|
||||
|
||||
if (!isDataTransferMessage(msg)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!msg.uuid) {
|
||||
await this.respond(undefined, new Error('Missing uuid in message'));
|
||||
}
|
||||
@ -70,12 +74,17 @@ export const createPullController = handlerControllerFactory<Partial<PullHandler
|
||||
|
||||
// Regular command message (init, end, status)
|
||||
if (type === 'command') {
|
||||
const { command, params } = msg;
|
||||
const { command } = msg;
|
||||
|
||||
await this.executeAndRespond(uuid, () => {
|
||||
this.assertValidTransferCommand(command);
|
||||
|
||||
return this[command](params);
|
||||
// The status command don't have params
|
||||
if (command === 'status') {
|
||||
return this.status();
|
||||
}
|
||||
|
||||
return this[command](msg.params);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@ -143,15 +143,7 @@ export const handlerControllerFactory =
|
||||
},
|
||||
|
||||
send(message, cb) {
|
||||
let payload;
|
||||
|
||||
try {
|
||||
payload = JSON.stringify(message);
|
||||
} catch {
|
||||
payload = message;
|
||||
}
|
||||
|
||||
ws.send(payload as string, cb);
|
||||
ws.send(message, cb);
|
||||
},
|
||||
|
||||
confirm(message) {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user