You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
tailchat/server/services/openapi/app.service.ts

159 lines
3.3 KiB
TypeScript

import {
TcService,
config,
TcDbService,
TcContext,
EntityError,
} from 'tailchat-server-sdk';
import _ from 'lodash';
import {
filterAvailableAppCapability,
OpenAppDocument,
OpenAppModel,
} from '../../models/openapi/app';
import { Types } from 'mongoose';
import { nanoid } from 'nanoid';
interface OpenAppService
extends TcService,
TcDbService<OpenAppDocument, OpenAppModel> {}
class OpenAppService extends TcService {
get serviceName(): string {
return 'openapi.app';
}
onInit(): void {
if (!config.enableOpenapi) {
return;
}
this.registerLocalDb(require('../../models/openapi/app').default);
this.registerAction('all', this.all);
this.registerAction('create', this.create, {
params: {
appName: 'string',
appDesc: 'string',
appIcon: 'string',
},
});
this.registerAction('setAppCapability', this.setAppCapability, {
params: {
appId: 'string',
capability: { type: 'array', items: 'string' },
},
});
this.registerAction('setAppOAuthInfo', this.setAppOAuthInfo, {
params: {
appId: 'string',
fieldName: 'string',
fieldValue: 'any',
},
});
}
/**
*
*/
async all(ctx: TcContext<{}>) {
const apps = await this.adapter.model.find({
owner: ctx.meta.userId,
});
return await this.transformDocuments(ctx, {}, apps);
}
/**
*
*/
async create(
ctx: TcContext<{
appName: string;
appDesc: string;
appIcon: string;
}>
) {
const { appName, appDesc, appIcon } = ctx.params;
const userId = ctx.meta.userId;
if (!appName) {
throw new EntityError();
}
const doc = await this.adapter.model.create({
owner: String(userId),
appId: `tc_${new Types.ObjectId().toString()}`,
appSecret: nanoid(32),
appName,
appDesc,
appIcon,
});
return await this.transformDocuments(ctx, {}, doc);
}
/**
*
*/
async setAppCapability(
ctx: TcContext<{
appId: string;
capability: string[];
}>
) {
const { appId, capability } = ctx.params;
const { userId } = ctx.meta;
const openapp = await this.adapter.model.findAppByIdAndOwner(appId, userId);
if (!openapp) {
throw new Error('Not found openapp');
}
await openapp
.updateOne({
capability: filterAvailableAppCapability(_.uniq(capability)),
})
.exec();
return true;
}
/**
* OAuth
*/
async setAppOAuthInfo(
ctx: TcContext<{
appId: string;
fieldName: string;
fieldValue: any;
}>
) {
const { appId, fieldName, fieldValue } = ctx.params;
const { userId } = ctx.meta;
if (!['redirectUrls'].includes(fieldName)) {
throw new Error('Not allowed fields');
}
if (fieldName === 'redirectUrls') {
if (!Array.isArray(fieldValue)) {
throw new Error('`redirectUrls` should be an array');
}
}
await this.adapter.model.findOneAndUpdate(
{
appId,
owner: userId,
},
{
$set: {
[`oauth.${fieldName}`]: fieldValue,
},
}
);
}
}
export default OpenAppService;