368 lines
12 KiB
TypeScript
368 lines
12 KiB
TypeScript
import { IExecuteFunctions, IHttpRequestOptions } from 'n8n-workflow';
|
|
import { ILoginRequest, ILoginResponse, IRefreshTokenRequest } from './Interfaces/LoginInterfaces';
|
|
import { IErrorResponse } from './Interfaces/ErrorInterfaces';
|
|
import { IProtectWithExternalRefIdRequest, IProtectWithExternalRefIdResponse, IProtectWithFileIdRequest, IProtectWithFileIdResponse, IProtectWithHotFolderRequest, IProtectWithHotFolderResponse } from './Interfaces/ProtectInterfaces';
|
|
import FormData from 'form-data';
|
|
import { IUnprotectRequest, IUnprotectResponse } from './Interfaces/UnprotectInterfaces';
|
|
import { IFileUploadResponse } from './Interfaces/FileStorageInterfaces';
|
|
|
|
export class SecloreDRMApiService {
|
|
private baseUrl: string;
|
|
|
|
constructor(private context: IExecuteFunctions, baseUrl: string) {
|
|
this.baseUrl = baseUrl;
|
|
}
|
|
|
|
/**
|
|
* Common error handler for HTTP responses
|
|
* @param error - The error object from httpRequest
|
|
* @param customMessages - Optional custom error messages for specific status codes
|
|
*/
|
|
private handleHttpError(error: any, customMessages?: { [statusCode: number]: string }): never {
|
|
const statusCode = error.statusCode;
|
|
const errorResponse = error.response?.body as IErrorResponse;
|
|
|
|
if (customMessages && customMessages[statusCode]) {
|
|
throw new Error(`${customMessages[statusCode]}: ${errorResponse?.errorMessage || 'Unknown error'}`);
|
|
}
|
|
|
|
// Default error handling
|
|
switch (statusCode) {
|
|
case 400:
|
|
throw new Error(`Bad Request: ${errorResponse?.errorMessage || 'Invalid request data'}`);
|
|
case 401:
|
|
throw new Error(`Unauthorized: ${errorResponse?.errorMessage || 'Invalid credentials'}`);
|
|
case 413:
|
|
throw new Error(`Payload Too Large: ${errorResponse?.errorMessage || 'File size exceeds limit'}`);
|
|
case 500:
|
|
throw new Error(`Server Error: ${errorResponse?.errorMessage || 'Internal server error'}`);
|
|
default:
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Login Endpoint to generate Access Token and Refresh Token for JWT Authorization.
|
|
* Upon successful login, all the existing previous tokens for that tenant will be invalidated.
|
|
*
|
|
* @param tenantId - The tenant ID
|
|
* @param tenantSecret - The tenant secret
|
|
* @param correlationId - Optional request ID for logging purpose
|
|
* @returns Promise<ILoginResponse> - Access token and refresh token
|
|
* @throws Error on authentication failure or server error
|
|
*/
|
|
async login(tenantId: string, tenantSecret: string, correlationId?: string): Promise<ILoginResponse> {
|
|
const requestBody: ILoginRequest = {
|
|
tenantId,
|
|
tenantSecret,
|
|
};
|
|
|
|
const headers: { [key: string]: string } = {
|
|
'Content-Type': 'application/json',
|
|
};
|
|
|
|
// Add correlation ID if provided
|
|
if (correlationId) {
|
|
headers['X-SECLORE-CORRELATION-ID'] = correlationId;
|
|
}
|
|
|
|
const options: IHttpRequestOptions = {
|
|
method: 'POST',
|
|
url: `${this.baseUrl}/seclore/drm/1.0/auth/login`,
|
|
headers,
|
|
body: requestBody,
|
|
json: true,
|
|
};
|
|
|
|
try {
|
|
const response = await this.context.helpers.httpRequest(options);
|
|
return response as ILoginResponse;
|
|
} catch (error: any) {
|
|
this.handleHttpError(error);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Endpoint for generating new Access Token and Refresh Token using an existing valid Refresh Token.
|
|
* Upon successful response, all the previous existing Access Tokens and Refresh Tokens of that tenant will be invalidated.
|
|
*
|
|
* @param refreshToken - The existing valid refresh token
|
|
* @param correlationId - Optional request ID for logging purpose
|
|
* @returns Promise<ILoginResponse> - New access token and refresh token
|
|
* @throws Error on authentication failure or server error
|
|
*/
|
|
async refreshToken(refreshToken: string, correlationId?: string): Promise<ILoginResponse> {
|
|
const requestBody: IRefreshTokenRequest = {
|
|
refreshToken,
|
|
};
|
|
|
|
const headers: { [key: string]: string } = {
|
|
'Content-Type': 'application/json',
|
|
};
|
|
|
|
// Add correlation ID if provided
|
|
if (correlationId) {
|
|
headers['X-SECLORE-CORRELATION-ID'] = correlationId;
|
|
}
|
|
|
|
const options: IHttpRequestOptions = {
|
|
method: 'POST',
|
|
url: `${this.baseUrl}/seclore/drm/1.0/auth/refresh`,
|
|
headers,
|
|
body: requestBody,
|
|
json: true,
|
|
};
|
|
|
|
try {
|
|
const response = await this.context.helpers.httpRequest(options);
|
|
return response as ILoginResponse;
|
|
} catch (error: any) {
|
|
this.handleHttpError(error, { 401: 'Unauthorized' });
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Protect file using external identifier of protected File and HotFolder with PS configured against the logged in Tenant in application.
|
|
*
|
|
* @param protectRequest - The protection request details
|
|
* @param accessToken - JWT access token for authorization
|
|
* @param correlationId - Optional request ID for logging purpose
|
|
* @returns Promise<IProtectWithExternalRefIdResponse> - File storage ID and Seclore file ID
|
|
* @throws Error on bad request, authentication failure or server error
|
|
*/
|
|
async protectWithExternalRefId(
|
|
protectRequest: IProtectWithExternalRefIdRequest,
|
|
accessToken: string,
|
|
correlationId?: string
|
|
): Promise<IProtectWithExternalRefIdResponse> {
|
|
const headers: { [key: string]: string } = {
|
|
'Content-Type': 'application/json',
|
|
'Authorization': `Bearer ${accessToken}`,
|
|
};
|
|
|
|
// Add correlation ID if provided
|
|
if (correlationId) {
|
|
headers['X-SECLORE-CORRELATION-ID'] = correlationId;
|
|
}
|
|
|
|
const options: IHttpRequestOptions = {
|
|
method: 'POST',
|
|
url: `${this.baseUrl}/seclore/drm/1.0/protect/externalref`,
|
|
headers,
|
|
body: protectRequest,
|
|
json: true,
|
|
};
|
|
|
|
try {
|
|
const response = await this.context.helpers.httpRequest(options);
|
|
return response as IProtectWithExternalRefIdResponse;
|
|
} catch (error: any) {
|
|
this.handleHttpError(error);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Protects file using File ID of already protected file with PS configured against the logged in Tenant in application.
|
|
*
|
|
* @param protectRequest - The protection request details with existing protected file ID
|
|
* @param accessToken - JWT access token for authorization
|
|
* @param correlationId - Optional request ID for logging purpose
|
|
* @returns Promise<IProtectWithFileIdResponse> - File storage ID and Seclore file ID
|
|
* @throws Error on bad request, authentication failure or server error
|
|
*/
|
|
async protectWithFileId(
|
|
protectRequest: IProtectWithFileIdRequest,
|
|
accessToken: string,
|
|
correlationId?: string
|
|
): Promise<IProtectWithFileIdResponse> {
|
|
const headers: { [key: string]: string } = {
|
|
'Content-Type': 'application/json',
|
|
'Authorization': `Bearer ${accessToken}`,
|
|
};
|
|
|
|
// Add correlation ID if provided
|
|
if (correlationId) {
|
|
headers['X-SECLORE-CORRELATION-ID'] = correlationId;
|
|
}
|
|
|
|
const options: IHttpRequestOptions = {
|
|
method: 'POST',
|
|
url: `${this.baseUrl}/seclore/drm/1.0/protect/fileid`,
|
|
headers,
|
|
body: protectRequest,
|
|
json: true,
|
|
};
|
|
|
|
try {
|
|
const response = await this.context.helpers.httpRequest(options);
|
|
return response as IProtectWithFileIdResponse;
|
|
} catch (error: any) {
|
|
this.handleHttpError(error);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Protects file using HotFolder ID with PS configured against the logged in Tenant in application.
|
|
*
|
|
* @param protectRequest - The protection request details with hotfolder ID
|
|
* @param accessToken - JWT access token for authorization
|
|
* @param correlationId - Optional request ID for logging purpose
|
|
* @returns Promise<IProtectWithHotFolderResponse> - File storage ID and Seclore file ID
|
|
* @throws Error on bad request, authentication failure or server error
|
|
*/
|
|
async protectWithHotFolder(
|
|
protectRequest: IProtectWithHotFolderRequest,
|
|
accessToken: string,
|
|
correlationId?: string
|
|
): Promise<IProtectWithHotFolderResponse> {
|
|
const headers: { [key: string]: string } = {
|
|
'Content-Type': 'application/json',
|
|
'Authorization': `Bearer ${accessToken}`,
|
|
};
|
|
|
|
// Add correlation ID if provided
|
|
if (correlationId) {
|
|
headers['X-SECLORE-CORRELATION-ID'] = correlationId;
|
|
}
|
|
|
|
const options: IHttpRequestOptions = {
|
|
method: 'POST',
|
|
url: `${this.baseUrl}/seclore/drm/1.0/protect/hf`,
|
|
headers,
|
|
body: protectRequest,
|
|
json: true,
|
|
};
|
|
|
|
try {
|
|
const response = await this.context.helpers.httpRequest(options);
|
|
return response as IProtectWithHotFolderResponse;
|
|
} catch (error: any) {
|
|
this.handleHttpError(error);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Unprotects file with PS configured against the logged in Tenant in application.
|
|
*
|
|
* @param unprotectRequest - The unprotect request details with file storage ID
|
|
* @param accessToken - JWT access token for authorization
|
|
* @param correlationId - Optional request ID for logging purpose
|
|
* @returns Promise<IUnprotectResponse> - File storage ID of unprotected file
|
|
* @throws Error on bad request, authentication failure or server error
|
|
*/
|
|
async unprotect(
|
|
unprotectRequest: IUnprotectRequest,
|
|
accessToken: string,
|
|
correlationId?: string
|
|
): Promise<IUnprotectResponse> {
|
|
const headers: { [key: string]: string } = {
|
|
'Content-Type': 'application/json',
|
|
'Authorization': `Bearer ${accessToken}`,
|
|
};
|
|
|
|
// Add correlation ID if provided
|
|
if (correlationId) {
|
|
headers['X-SECLORE-CORRELATION-ID'] = correlationId;
|
|
}
|
|
|
|
const options: IHttpRequestOptions = {
|
|
method: 'POST',
|
|
url: `${this.baseUrl}/seclore/drm/1.0/unprotect`,
|
|
headers,
|
|
body: unprotectRequest,
|
|
json: true,
|
|
};
|
|
|
|
try {
|
|
const response = await this.context.helpers.httpRequest(options);
|
|
return response as IUnprotectResponse;
|
|
} catch (error: any) {
|
|
this.handleHttpError(error);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Adds a new file to the file storage for currently logged in Tenant.
|
|
*
|
|
* @param fileBuffer - The file buffer data
|
|
* @param fileName - The name of the file
|
|
* @param accessToken - JWT access token for authorization
|
|
* @param correlationId - Optional request ID for logging purpose
|
|
* @returns Promise<IFileUploadResponse> - File storage details including file ID and metadata
|
|
* @throws Error on authentication failure, payload too large, or server error
|
|
*/
|
|
async uploadFile(
|
|
fileBuffer: Uint8Array,
|
|
fileName: string,
|
|
accessToken: string,
|
|
correlationId?: string
|
|
): Promise<IFileUploadResponse> {
|
|
const headers: { [key: string]: string } = {
|
|
'Authorization': `Bearer ${accessToken}`,
|
|
};
|
|
|
|
// Add correlation ID if provided
|
|
if (correlationId) {
|
|
headers['X-SECLORE-CORRELATION-ID'] = correlationId;
|
|
}
|
|
|
|
// Create FormData for multipart/form-data upload
|
|
const formData = new FormData();
|
|
formData.append('file', fileBuffer, fileName);
|
|
|
|
const options: IHttpRequestOptions = {
|
|
method: 'POST',
|
|
url: `${this.baseUrl}/seclore/drm/filestorage/1.0/upload`,
|
|
headers,
|
|
body: formData,
|
|
};
|
|
|
|
try {
|
|
const response = await this.context.helpers.httpRequest(options);
|
|
return response as IFileUploadResponse;
|
|
} catch (error: any) {
|
|
this.handleHttpError(error);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Downloads file with fileStorageId from file storage of currently logged in Tenant.
|
|
* NOTE: Files whose fileStorageId has 'DL_' prefix will be deleted from the file storage after download.
|
|
*
|
|
* @param fileStorageId - Storage ID of the file to be retrieved
|
|
* @param accessToken - JWT access token for authorization
|
|
* @param correlationId - Optional request ID for logging purpose
|
|
* @returns Promise<Uint8Array> - The downloaded file data
|
|
* @throws Error on authentication failure or server error
|
|
*/
|
|
async downloadFile(
|
|
fileStorageId: string,
|
|
accessToken: string,
|
|
correlationId?: string
|
|
): Promise<Uint8Array> {
|
|
const headers: { [key: string]: string } = {
|
|
'Authorization': `Bearer ${accessToken}`,
|
|
};
|
|
|
|
// Add correlation ID if provided
|
|
if (correlationId) {
|
|
headers['X-SECLORE-CORRELATION-ID'] = correlationId;
|
|
}
|
|
|
|
const options: IHttpRequestOptions = {
|
|
method: 'GET',
|
|
url: `${this.baseUrl}/seclore/drm/filestorage/1.0/download/${fileStorageId}`,
|
|
headers,
|
|
encoding: 'arraybuffer',
|
|
};
|
|
|
|
try {
|
|
const response = await this.context.helpers.httpRequest(options);
|
|
return new Uint8Array(response as ArrayBuffer);
|
|
} catch (error: any) {
|
|
this.handleHttpError(error);
|
|
}
|
|
}
|
|
|
|
}
|