229 lines
8.6 KiB
TypeScript
229 lines
8.6 KiB
TypeScript
|
|
import type { Cloudly } from '../classes.cloudly.js';
|
||
|
|
import * as plugins from '../plugins.js';
|
||
|
|
import { PlatformBinding } from './classes.platformbinding.js';
|
||
|
|
import { PlatformProviderConfig } from './classes.platformproviderconfig.js';
|
||
|
|
|
||
|
|
export class CloudlyPlatformManager {
|
||
|
|
public typedrouter = new plugins.typedrequest.TypedRouter();
|
||
|
|
public cloudlyRef: Cloudly;
|
||
|
|
|
||
|
|
public capabilities: plugins.servezoneInterfaces.platform.IPlatformCapability[] = [
|
||
|
|
{ id: 'email', title: 'Email', accessMode: 'rpc', defaultProviderType: 'cloudly' },
|
||
|
|
{ id: 'sms', title: 'SMS', accessMode: 'rpc', defaultProviderType: 'cloudly' },
|
||
|
|
{ id: 'pushnotification', title: 'Push Notifications', accessMode: 'rpc', defaultProviderType: 'cloudly' },
|
||
|
|
{ id: 'letter', title: 'Letters', accessMode: 'rpc', defaultProviderType: 'cloudly' },
|
||
|
|
{ id: 'ai', title: 'AI', accessMode: 'rpc', defaultProviderType: 'cloudly' },
|
||
|
|
{ id: 'database', title: 'Database', accessMode: 'binding', defaultProviderType: 'docker' },
|
||
|
|
{ id: 'objectstorage', title: 'Object Storage', accessMode: 'binding', defaultProviderType: 's3' },
|
||
|
|
{ id: 'logging', title: 'Logging', accessMode: 'sidecar', defaultProviderType: 'corelog' },
|
||
|
|
{ id: 'backup', title: 'Backup', accessMode: 'internal', defaultProviderType: 'corebackup' },
|
||
|
|
{ id: 'sip', title: 'SIP', accessMode: 'rpc', defaultProviderType: 'cloudly' },
|
||
|
|
];
|
||
|
|
|
||
|
|
get db() {
|
||
|
|
return this.cloudlyRef.mongodbConnector.smartdataDb;
|
||
|
|
}
|
||
|
|
|
||
|
|
public CPlatformProviderConfig = plugins.smartdata.setDefaultManagerForDoc(
|
||
|
|
this,
|
||
|
|
PlatformProviderConfig,
|
||
|
|
);
|
||
|
|
public CPlatformBinding = plugins.smartdata.setDefaultManagerForDoc(this, PlatformBinding);
|
||
|
|
|
||
|
|
constructor(cloudlyRefArg: Cloudly) {
|
||
|
|
this.cloudlyRef = cloudlyRefArg;
|
||
|
|
this.cloudlyRef.typedrouter.addTypedRouter(this.typedrouter);
|
||
|
|
|
||
|
|
this.typedrouter.addTypedHandler(
|
||
|
|
new plugins.typedrequest.TypedHandler<plugins.servezoneInterfaces.requests.platform.IReq_Any_Cloudly_GetPlatformDesiredState>(
|
||
|
|
'getPlatformDesiredState',
|
||
|
|
async (requestData) => {
|
||
|
|
await this.passValidIdentity(requestData);
|
||
|
|
return await this.getPlatformDesiredState();
|
||
|
|
},
|
||
|
|
),
|
||
|
|
);
|
||
|
|
|
||
|
|
this.typedrouter.addTypedHandler(
|
||
|
|
new plugins.typedrequest.TypedHandler<plugins.servezoneInterfaces.requests.platform.IReq_Any_Cloudly_GetPlatformCapabilities>(
|
||
|
|
'getPlatformCapabilities',
|
||
|
|
async (requestData) => {
|
||
|
|
await this.passValidIdentity(requestData);
|
||
|
|
return {
|
||
|
|
capabilities: this.capabilities,
|
||
|
|
};
|
||
|
|
},
|
||
|
|
),
|
||
|
|
);
|
||
|
|
|
||
|
|
this.typedrouter.addTypedHandler(
|
||
|
|
new plugins.typedrequest.TypedHandler<plugins.servezoneInterfaces.requests.platform.IReq_Any_Cloudly_GetPlatformProviderConfigs>(
|
||
|
|
'getPlatformProviderConfigs',
|
||
|
|
async (requestData) => {
|
||
|
|
await this.passValidIdentity(requestData);
|
||
|
|
const query = requestData.capability ? { capability: requestData.capability } : {};
|
||
|
|
return {
|
||
|
|
providerConfigs: await this.getProviderConfigs(query),
|
||
|
|
};
|
||
|
|
},
|
||
|
|
),
|
||
|
|
);
|
||
|
|
|
||
|
|
this.typedrouter.addTypedHandler(
|
||
|
|
new plugins.typedrequest.TypedHandler<plugins.servezoneInterfaces.requests.platform.IReq_Any_Cloudly_UpsertPlatformProviderConfig>(
|
||
|
|
'upsertPlatformProviderConfig',
|
||
|
|
async (requestData) => {
|
||
|
|
await this.passAdminIdentity(requestData);
|
||
|
|
const providerConfig = await PlatformProviderConfig.upsertProviderConfig(
|
||
|
|
requestData.providerConfig,
|
||
|
|
);
|
||
|
|
return {
|
||
|
|
providerConfig: await providerConfig.createSavableObject(),
|
||
|
|
};
|
||
|
|
},
|
||
|
|
),
|
||
|
|
);
|
||
|
|
|
||
|
|
this.typedrouter.addTypedHandler(
|
||
|
|
new plugins.typedrequest.TypedHandler<plugins.servezoneInterfaces.requests.platform.IReq_Any_Cloudly_DeletePlatformProviderConfigById>(
|
||
|
|
'deletePlatformProviderConfigById',
|
||
|
|
async (requestData) => {
|
||
|
|
await this.passAdminIdentity(requestData);
|
||
|
|
const providerConfig = await PlatformProviderConfig.getInstance({
|
||
|
|
id: requestData.providerConfigId,
|
||
|
|
});
|
||
|
|
if (providerConfig) {
|
||
|
|
await providerConfig.delete();
|
||
|
|
}
|
||
|
|
return {
|
||
|
|
success: true,
|
||
|
|
};
|
||
|
|
},
|
||
|
|
),
|
||
|
|
);
|
||
|
|
|
||
|
|
this.typedrouter.addTypedHandler(
|
||
|
|
new plugins.typedrequest.TypedHandler<plugins.servezoneInterfaces.requests.platform.IReq_Any_Cloudly_GetPlatformBindings>(
|
||
|
|
'getPlatformBindings',
|
||
|
|
async (requestData) => {
|
||
|
|
await this.passValidIdentity(requestData);
|
||
|
|
return {
|
||
|
|
bindings: await this.getBindings({
|
||
|
|
...(requestData.serviceId ? { serviceId: requestData.serviceId } : {}),
|
||
|
|
...(requestData.capability ? { capability: requestData.capability } : {}),
|
||
|
|
}),
|
||
|
|
};
|
||
|
|
},
|
||
|
|
),
|
||
|
|
);
|
||
|
|
|
||
|
|
this.typedrouter.addTypedHandler(
|
||
|
|
new plugins.typedrequest.TypedHandler<plugins.servezoneInterfaces.requests.platform.IReq_Any_Cloudly_UpsertPlatformBinding>(
|
||
|
|
'upsertPlatformBinding',
|
||
|
|
async (requestData) => {
|
||
|
|
await this.passAdminIdentity(requestData);
|
||
|
|
const binding = await PlatformBinding.upsertBinding(requestData.binding);
|
||
|
|
return {
|
||
|
|
binding: await binding.createSavableObject(),
|
||
|
|
};
|
||
|
|
},
|
||
|
|
),
|
||
|
|
);
|
||
|
|
|
||
|
|
this.typedrouter.addTypedHandler(
|
||
|
|
new plugins.typedrequest.TypedHandler<plugins.servezoneInterfaces.requests.platform.IReq_Any_Cloudly_UpdatePlatformBindingStatus>(
|
||
|
|
'updatePlatformBindingStatus',
|
||
|
|
async (requestData) => {
|
||
|
|
await this.passAdminOrClusterIdentity(requestData);
|
||
|
|
const binding = await PlatformBinding.getInstance({
|
||
|
|
id: requestData.bindingId,
|
||
|
|
});
|
||
|
|
if (!binding) {
|
||
|
|
throw new plugins.typedrequest.TypedResponseError(
|
||
|
|
`Platform binding ${requestData.bindingId} not found`,
|
||
|
|
);
|
||
|
|
}
|
||
|
|
binding.status = requestData.status;
|
||
|
|
binding.updatedAt = Date.now();
|
||
|
|
if (requestData.endpoints) {
|
||
|
|
binding.endpoints = requestData.endpoints;
|
||
|
|
}
|
||
|
|
if (requestData.credentials) {
|
||
|
|
binding.credentials = requestData.credentials;
|
||
|
|
}
|
||
|
|
if (requestData.errorText !== undefined) {
|
||
|
|
binding.errorText = requestData.errorText;
|
||
|
|
}
|
||
|
|
await binding.save();
|
||
|
|
return {
|
||
|
|
binding: await binding.createSavableObject(),
|
||
|
|
};
|
||
|
|
},
|
||
|
|
),
|
||
|
|
);
|
||
|
|
|
||
|
|
this.typedrouter.addTypedHandler(
|
||
|
|
new plugins.typedrequest.TypedHandler<plugins.servezoneInterfaces.requests.platform.IReq_Any_Cloudly_DeletePlatformBindingById>(
|
||
|
|
'deletePlatformBindingById',
|
||
|
|
async (requestData) => {
|
||
|
|
await this.passAdminIdentity(requestData);
|
||
|
|
const binding = await PlatformBinding.getInstance({
|
||
|
|
id: requestData.bindingId,
|
||
|
|
});
|
||
|
|
if (binding) {
|
||
|
|
await binding.delete();
|
||
|
|
}
|
||
|
|
return {
|
||
|
|
success: true,
|
||
|
|
};
|
||
|
|
},
|
||
|
|
),
|
||
|
|
);
|
||
|
|
}
|
||
|
|
|
||
|
|
public async start() {}
|
||
|
|
|
||
|
|
public async stop() {}
|
||
|
|
|
||
|
|
public async getPlatformDesiredState() {
|
||
|
|
return {
|
||
|
|
capabilities: this.capabilities,
|
||
|
|
providerConfigs: await this.getProviderConfigs(),
|
||
|
|
bindings: await this.getBindings(),
|
||
|
|
};
|
||
|
|
}
|
||
|
|
|
||
|
|
public async getProviderConfigs(queryArg: Record<string, unknown> = {}) {
|
||
|
|
const providerConfigs = await this.CPlatformProviderConfig.getInstances(queryArg);
|
||
|
|
return await Promise.all(
|
||
|
|
providerConfigs.map((providerConfig) => providerConfig.createSavableObject()),
|
||
|
|
);
|
||
|
|
}
|
||
|
|
|
||
|
|
public async getBindings(queryArg: Record<string, unknown> = {}) {
|
||
|
|
const bindings = await this.CPlatformBinding.getInstances(queryArg);
|
||
|
|
return await Promise.all(bindings.map((binding) => binding.createSavableObject()));
|
||
|
|
}
|
||
|
|
|
||
|
|
private async passValidIdentity(requestData: { identity: plugins.servezoneInterfaces.data.IIdentity }) {
|
||
|
|
await plugins.smartguard.passGuardsOrReject(requestData, [
|
||
|
|
this.cloudlyRef.authManager.validIdentityGuard,
|
||
|
|
]);
|
||
|
|
}
|
||
|
|
|
||
|
|
private async passAdminIdentity(requestData: { identity: plugins.servezoneInterfaces.data.IIdentity }) {
|
||
|
|
await plugins.smartguard.passGuardsOrReject(requestData, [
|
||
|
|
this.cloudlyRef.authManager.adminIdentityGuard,
|
||
|
|
]);
|
||
|
|
}
|
||
|
|
|
||
|
|
private async passAdminOrClusterIdentity(requestData: {
|
||
|
|
identity: plugins.servezoneInterfaces.data.IIdentity;
|
||
|
|
}) {
|
||
|
|
await this.passValidIdentity(requestData);
|
||
|
|
if (requestData.identity.role !== 'admin' && requestData.identity.role !== 'cluster') {
|
||
|
|
throw new plugins.typedrequest.TypedResponseError('identity must be admin or cluster');
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|