diff --git a/src/controller/meta.ts b/src/controller/meta.ts new file mode 100644 index 0000000..4ab39d2 --- /dev/null +++ b/src/controller/meta.ts @@ -0,0 +1,83 @@ +import { checkProjectAccess } from "@controller/projects"; +import { IKeyRole } from "@models/AccessKey"; +import { encryptClearField } from "@utils/decryption"; +import { ILicenseMetaType, IMetaData, MetaData } from "@models/MetaData"; +import { planLimits } from "../limits/plans"; + +export const isValidMetaType = (type: string, value: string) => { + if (type === ILicenseMetaType.TEXT) return true; + if (type === ILicenseMetaType.NUMBER) return !isNaN(Number(value)); + if (type === ILicenseMetaType.BOOLEAN) return value === "true" || value === "false"; + return false; +} + +export const listMetaData = async (userId: string, projectId: string) => { + const access = await checkProjectAccess(IKeyRole.VIEW)(userId, projectId); + if ("code" in access) return access; + + const meta = await MetaData.find({ projectId: encryptClearField(String(access._id)) }); + + return meta.map(meta => ({ + type: meta.type, name: meta.name, description: meta.description, defaultValue: meta.defaultValue, + public: meta.public + })); +}; + +export const getMetaData = async (userId: string, projectId: string, name: string) => { + const access = await checkProjectAccess(IKeyRole.VIEW)(userId, projectId); + if ("code" in access) return access; + + const meta = await MetaData.findOne({ projectId: encryptClearField(String(access._id)), name: encryptClearField(name) }); + if (meta === null) return { code: 8002, message: "The provided meta item could not be found" }; + + return { + type: meta.type, name: meta.name, description: meta.description, defaultValue: meta.defaultValue, + public: meta.public + } +} + +export const createMetaData = async (userId: string, projectId: string, config: IMetaData) => { + const access = await checkProjectAccess(IKeyRole.MANAGE)(userId, projectId); + if ("code" in access) return access; + + const count = await MetaData.countDocuments({ projectId: encryptClearField(String(access._id)) }); + if (count >= planLimits[access.plan].META) return { code: 95, message: "You have exceeded the meta item limit" }; + + const meta = await MetaData.findOne({ projectId: encryptClearField(String(access._id)), name: encryptClearField(config.name) }); + if (meta !== null) return { code: 8003, message: "The provided meta item name is already in use" }; + + if (config.defaultValue) { + if (!isValidMetaType(config.type, config.defaultValue)) return { code: 8004, message: "The provided default value is not valid for the provided type" }; + } + + await MetaData.create({ ...config, projectId }); + + return {}; +} + +export const deleteMetaData = async (userId: string, projectId: string, name: string) => { + const access = await checkProjectAccess(IKeyRole.MANAGE)(userId, projectId); + if ("code" in access) return access; + + const meta = await MetaData.findOne({ projectId: encryptClearField(String(access._id)), name: encryptClearField(name) }); + if (meta === null) return { code: 8002, message: "The provided meta item could not be found" }; + + meta.deleteOne(); +} + +export const updateMetaData = async (userId: string, projectId: string, name: string, config: IMetaData) => { + const access = await checkProjectAccess(IKeyRole.MANAGE)(userId, projectId); + if ("code" in access) return access; + + const meta = await MetaData.findOne({ projectId: encryptClearField(String(access._id)), name: encryptClearField(name) }); + if (meta === null) return { code: 8002, message: "The provided meta item could not be found" }; + + if (config.defaultValue) { + if (!isValidMetaType(config.type || meta.type, config.defaultValue)) + return { code: 8004, message: "The provided default value is not valid for the provided type" }; + } + + await meta.updateOne(config); + + return {}; +} \ No newline at end of file