0
Fork 0
mirror of https://github.com/logto-io/logto.git synced 2025-03-17 22:31:28 -05:00

refactor(core,toolkit): relocate customJwt local vm handler (#6524)

relocate customJwt local vm handler
This commit is contained in:
simeng-li 2024-09-02 11:36:35 +08:00 committed by GitHub
parent ee1947ac4d
commit a0807d7e5a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 53 additions and 43 deletions

View file

@ -1,4 +1,3 @@
import { buildErrorResponse, runScriptFunctionInLocalVm } from '@logto/core-kit/custom-jwt';
import {
LogtoJwtTokenKeyType,
jwtCustomizerUserContextGuard,
@ -22,6 +21,8 @@ import type Queries from '#src/tenants/Queries.js';
import {
LocalVmError,
getJwtCustomizerScripts,
runScriptFunctionInLocalVm,
buildLocalVmErrorBody,
type CustomJwtDeployRequestBody,
} from '#src/utils/custom-jwt/index.js';
@ -53,7 +54,7 @@ export class JwtCustomizerLibrary {
}
throw new LocalVmError(
buildErrorResponse(error),
buildLocalVmErrorBody(error),
error instanceof SyntaxError || error instanceof TypeError ? 422 : 500
);
}

View file

@ -1,10 +0,0 @@
import { LogtoJwtTokenKey, type JwtCustomizerType } from '@logto/schemas';
import { type CustomJwtDeployRequestBody } from './types.js';
export const getJwtCustomizerScripts = (jwtCustomizers: Partial<JwtCustomizerType>) => {
// eslint-disable-next-line no-restricted-syntax -- enable to infer the type using `Object.fromEntries`
return Object.fromEntries(
Object.values(LogtoJwtTokenKey).map((key) => [key, { production: jwtCustomizers[key]?.script }])
) as CustomJwtDeployRequestBody;
};

View file

@ -1,3 +1,13 @@
export * from './custom-jwt.js';
import { LogtoJwtTokenKey, type JwtCustomizerType } from '@logto/schemas';
import { type CustomJwtDeployRequestBody } from './types.js';
export * from './types.js';
export * from './local-vm-error.js';
export * from './local-vm.js';
export const getJwtCustomizerScripts = (jwtCustomizers: Partial<JwtCustomizerType>) => {
// eslint-disable-next-line no-restricted-syntax -- enable to infer the type using `Object.fromEntries`
return Object.fromEntries(
Object.values(LogtoJwtTokenKey).map((key) => [key, { production: jwtCustomizers[key]?.script }])
) as CustomJwtDeployRequestBody;
};

View file

@ -1,17 +0,0 @@
import { ResponseError } from '@withtyped/client';
// Extend the ResponseError from @withtyped/client, so that we can unify the error handling and display logic for both OSS version and Cloud version.
export class LocalVmError extends ResponseError {
constructor(errorBody: Record<string, unknown>, statusCode: number) {
super(
new Response(
new Blob([JSON.stringify(errorBody)], {
type: 'application/json',
}),
{
status: statusCode,
}
)
);
}
}

View file

@ -1,5 +1,28 @@
import { types } from 'node:util';
import { runInNewContext } from 'node:vm';
import { ResponseError } from '@withtyped/client';
/**
* Extend the ResponseError from @withtyped/client.
* This class is used to parse the error from the local VM to the WithTyped client response error.
* So we can unify the error handling and display logic for both local VM and Cloud version.
*/
export class LocalVmError extends ResponseError {
constructor(errorBody: Record<string, unknown>, statusCode: number) {
super(
new Response(
new Blob([JSON.stringify(errorBody)], {
type: 'application/json',
}),
{
status: statusCode,
}
)
);
}
}
/**
* This function is used to execute a named function in a customized code script in a local
* virtual machine with the given payload as input.
@ -39,3 +62,18 @@ export const runScriptFunctionInLocalVm = async (
return result;
};
/**
* Build the error body for the local VM error.
*
* @remarks
*
* Catch the error from vm module, and build the error body.
* Use `isNativeError` to check if the error is an instance of `Error`.
* If the error comes from `node:vm` module, then it will not be an instance of `Error` but can be captured by `isNativeError`.
*
*/
export const buildLocalVmErrorBody = (error: unknown) =>
types.isNativeError(error)
? { message: error.message, stack: error.stack }
: { message: String(error) };

View file

@ -1,10 +0,0 @@
import { types } from 'node:util';
export const buildErrorResponse = (error: unknown) =>
/**
* Use `isNativeError` to check if the error is an instance of `Error`.
* If the error comes from `node:vm` module, then it will not be an instance of `Error` but can be captured by `isNativeError`.
*/
types.isNativeError(error)
? { message: error.message, stack: error.stack }
: { message: String(error) };

View file

@ -1,2 +0,0 @@
export * from './script-execution.js';
export * from './error-handling.js';