diff --git a/bun.lockb b/bun.lockb index 6f29d82..7be0be7 100755 Binary files a/bun.lockb and b/bun.lockb differ diff --git a/package.json b/package.json index 41be9ed..0843ceb 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,6 @@ "author": "Nico Schett ", "dependencies": { "@devoxa/prisma-relay-cursor-connection": "^3.1.2", - "@getcronit/prisma-extended-models": "^0.0.42", "@getcronit/pylon": "^2.8.0", "@hono/node-server": "^1.13.7", "@prisma/client": "^5.22.0", diff --git a/prisma/migrations/20241211104911_dev/migration.sql b/prisma/migrations/20241211104911_dev/migration.sql new file mode 100644 index 0000000..636db5b --- /dev/null +++ b/prisma/migrations/20241211104911_dev/migration.sql @@ -0,0 +1,8 @@ +/* + Warnings: + + - You are about to drop the column `envelopeId` on the `EmailTemplate` table. All the data in the column will be lost. + +*/ +-- AlterTable +ALTER TABLE "EmailTemplate" DROP COLUMN "envelopeId"; diff --git a/prisma/schema.prisma b/prisma/schema.prisma index ee4f7c4..805e66e 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -100,8 +100,7 @@ model EmailTemplate { verifyReplyTo Boolean? transformer String? - envelope EmailEnvelope? - envelopeId String? + envelope EmailEnvelope? parent EmailTemplate? @relation("EmailTemplateParent", fields: [parentId], references: [id]) parentId String? @db.Uuid diff --git a/pylon.d.ts b/pylon.d.ts index b5eabcc..6063fdf 100644 --- a/pylon.d.ts +++ b/pylon.d.ts @@ -1,5 +1,5 @@ import "@getcronit/pylon"; -import { User } from "./src/repository/models/User"; +import { User } from "./src/client"; declare module "@getcronit/pylon" { interface Bindings {} diff --git a/src/client.ts b/src/client.ts new file mode 100644 index 0000000..dcf1b30 --- /dev/null +++ b/src/client.ts @@ -0,0 +1,675 @@ +import * as Sentry from "@sentry/node"; +import { $Enums, Prisma, PrismaClient } from "@prisma/client"; +import { + ConnectionArguments, + findManyCursorConnection, +} from "@devoxa/prisma-relay-cursor-connection"; +import { ServiceError } from "@getcronit/pylon"; +import * as oidcGoogle from "./services/oauth/google"; +import * as oidcAzure from "./services/oauth/azure"; +import { PYLON_URL } from "./config"; +import { SMTPOptions, verifySMTP } from "./services/mailer/smtp"; +import { encrypt } from "./services/crypt"; + +Sentry.addIntegration(Sentry.prismaIntegration); + +export const client = new PrismaClient().$extends({ + result: { + user: { + email: { + needs: {}, + compute(data) { + console.log(data); + + return async () => { + const rtn = await client.email.findFirst({ + where: { + userId: data.id, + }, + }); + + return rtn; + }; + }, + }, + organization: { + needs: {}, + compute(data) { + return async () => { + const rtn = await client.organization.findFirstOrThrow({ + where: { + id: data.organizationId, + }, + }); + + return rtn; + }; + }, + }, + $createEmailTemplate: { + needs: {}, + compute(data) { + return async (input: { + content: string; + description: string; + variables: { + name: string; + isRequired?: boolean; + isConstant?: boolean; + description?: string; + defaultValue?: string; + }[]; + + envelope: { + subject?: string; + to?: string[]; + replyTo?: string; + }; + }) => { + console.log("Creating email template", input); + const rtn = await client.emailTemplate.create({ + data: { + content: input.content, + description: input.description, + variables: { + createMany: { + data: input.variables || [], + }, + }, + envelope: { + create: { + to: ["test"], + subject: "test", + replyTo: "test", + }, + }, + creator: { + connect: { + id: data.id, + }, + }, + }, + }); + + console.log("Created email template", rtn); + + return rtn; + }; + }, + }, + $deleteEmailTemplate: { + needs: {}, + compute(data) { + return async (id: string) => { + await client.emailTemplate.delete({ + where: { + id, + creatorId: data.id, + }, + }); + + return true; + }; + }, + }, + $updateEmailTemplate: { + needs: {}, + compute(data) { + return async ( + id: string, + input: { + parentId?: string; + content?: string; + verifyReplyTo?: boolean; + description?: string; + variables: { + name: string; + + isRequired?: boolean; + isConstant?: boolean; + description?: string; + defaultValue?: string; + }[]; + + envelope: { + subject?: string; + to?: string[]; + replyTo?: string; + }; + } + ) => { + const rtn = await client.emailTemplate.update({ + where: { + id, + creatorId: data.id, + }, + data: { + content: input.content, + description: input.description, + parentId: input.parentId, + verifyReplyTo: input.verifyReplyTo, + variables: { + deleteMany: { + emailTemplateId: id, + NOT: input.variables.map((v) => ({ name: v.name })), + }, + upsert: input.variables.map((variable) => ({ + create: { + name: variable.name, + isRequired: variable.isRequired, + isConstant: variable.isConstant, + description: variable.description, + defaultValue: variable.defaultValue, + }, + update: { + name: variable.name, + isRequired: variable.isRequired, + isConstant: variable.isConstant, + description: variable.description, + defaultValue: variable.defaultValue, + }, + where: { + emailTemplateId_name: { + emailTemplateId: id, + name: variable.name, + }, + }, + })), + }, + envelope: { + upsert: { + create: { + subject: input.envelope.subject, + to: input.envelope.to, + replyTo: input.envelope.replyTo, + }, + update: { + subject: input.envelope.subject, + to: input.envelope.to, + replyTo: input.envelope.replyTo, + }, + }, + }, + }, + }); + + return rtn; + }; + }, + }, + $addEmail: { + needs: { + id: true, + }, + compute(data) { + return async (email: string) => { + return await client.email.create({ + data: { + email, + userId: data.id, + }, + }); + }; + }, + }, + $deleteEmail: { + needs: { + id: true, + }, + compute(data) { + return async () => { + return await client.email.delete({ + where: { + userId: data.id, + }, + }); + }; + }, + }, + $updateEmail: { + needs: { + id: true, + }, + compute(data) { + return async (email: string) => { + return await client.email.update({ + where: { + userId: data.id, + }, + data: { + email, + }, + }); + }; + }, + }, + }, + email: { + creator: { + needs: { + userId: true, + }, + compute(data) { + return async () => { + const rtn = await client.user.findFirst({ + where: { + id: data.userId!, + }, + }); + + return rtn; + }; + }, + }, + smtpConfig: { + needs: { + id: true, + }, + compute(data) { + return async () => { + const rtn = await client.sMTPConfig.findFirst({ + where: { + emailId: data.id, + }, + }); + + return rtn; + }; + }, + }, + oauthConfig: { + needs: { + id: true, + }, + compute(data) { + return async () => { + const rtn = await client.oAuthConfig.findFirst({ + where: { + emailId: data.id, + }, + }); + + return rtn; + }; + }, + }, + $addSMTPConfig: { + needs: { + id: true, + email: true, + }, + compute(data) { + return async (config: SMTPOptions) => { + try { + await verifySMTP(config); + } catch (e: any) { + throw new ServiceError("Failed to verify SMTP configuration", { + code: "SMTP_CONFIG_FAILED", + statusCode: 400, + details: { + description: e.message, + }, + }); + } + + if (config.password) { + config.password = encrypt(config.password); + } + + const rtn = await client.sMTPConfig.upsert({ + where: { + emailId: data.id, + }, + create: { + emailId: data.id, + username: data.email, + password: config.password, + host: config.host, + port: config.port, + secure: config.secure, + }, + update: { + emailId: data.id, + username: data.email, + password: config.password, + host: config.host, + port: config.port, + secure: config.secure, + }, + }); + + return rtn; + }; + }, + }, + }, + oAuthConfig: { + $freshAccessToken: { + needs: { + id: true, + provider: true, + accessTokenExpiresAt: true, + accessToken: true, + refreshToken: true, + }, + compute(data) { + return async () => { + const organization = await client.organization.findFirstOrThrow({ + where: { + users: { + some: { + email: { + oauthConfig: { + id: data.id, + }, + }, + }, + }, + }, + }); + + if (data.provider === "GOOGLE") { + try { + if (data.accessTokenExpiresAt > new Date()) { + return data.accessToken; + } + + const { client: googleClient } = await oidcGoogle.getClient( + organization.id + ); + + const tokenSet = await googleClient.refresh(data.refreshToken); + + await client.oAuthConfig.update({ + where: { + id: data.id, + }, + data: { + accessToken: tokenSet.access_token, + accessTokenExpiresAt: new Date(tokenSet.expires_at! * 1000), + }, + }); + + return tokenSet.access_token!; + } catch (e) { + console.error(e); + + throw new ServiceError("Failed to refresh token", { + code: "FAILED_TO_REFRESH_TOKEN", + statusCode: 500, + details: { + description: + "Failed to refresh token. Please re-authenticate.", + loginUrl: `${PYLON_URL}/oauth/google`, + provider: "GOOGLE", + }, + }); + } + } else if (data.provider === "AZURE") { + try { + if (data.accessTokenExpiresAt > new Date()) { + return data.accessToken; + } + + const { client: azureClient } = await oidcAzure.getClient( + organization.id + ); + + const tokenSet = await azureClient.refresh(data.refreshToken); + + await client.oAuthConfig.update({ + where: { + id: data.id, + }, + data: { + accessToken: tokenSet.access_token, + accessTokenExpiresAt: new Date(tokenSet.expires_at! * 1000), + }, + }); + + return tokenSet.access_token!; + } catch (e) { + console.error(e); + + throw new ServiceError("Failed to refresh token", { + code: "FAILED_TO_REFRESH_TOKEN", + statusCode: 500, + details: { + description: + "Failed to refresh token. Please re-authenticate.", + loginUrl: `${PYLON_URL}/oauth/azure`, + provider: "AZURE", + }, + }); + } + } + + throw new Error(`Provider ${this.provider} not supported`); + }; + }, + }, + }, + emailTemplate: { + envelope: { + needs: { + id: true, + }, + compute(data) { + return async () => { + const rtn = await client.emailEnvelope.findFirst({ + where: { + emailTemplateId: data.id, + }, + }); + + return rtn; + }; + }, + }, + variables: { + needs: { + id: true, + }, + compute(data) { + return async () => { + const rtn = await client.variableDefinition.findMany({ + where: { + emailTemplateId: data.id!, + }, + }); + + return rtn; + }; + }, + }, + parent: { + needs: { + parentId: true, + }, + compute(data) { + return async () => { + const rtn = await client.emailTemplate.findFirst({ + where: { + id: data.parentId!, + }, + }); + + return rtn; + }; + }, + }, + senderEmail: { + needs: { + id: true, + creatorId: true, + }, + compute(data) { + return async () => { + const rtn = await client.email.findFirst({ + where: { + organization: { + users: { + some: { + id: data.creatorId, + }, + }, + }, + }, + }); + + return rtn as Email; + }; + }, + }, + links: { + needs: { + id: true, + }, + compute(data) { + return async () => { + const rtn = await client.emailTemplate.findMany({ + where: { + parentId: data.id, + }, + }); + + return rtn; + }; + }, + }, + $setTransformer: { + needs: {}, + compute(data) { + return async (transformer: string) => { + const rtn = await client.emailTemplate.update({ + where: { + id: data.id, + }, + data: { + transformer, + }, + }); + + return rtn; + }; + }, + }, + }, + organization: { + emailTemplate: { + needs: {}, + compute(data) { + return async (id: string) => { + const rtn = await client.emailTemplate.findFirst({ + where: { + id, + creator: { + organizationId: data.id, + }, + }, + }); + + return rtn; + }; + }, + }, + emailTemplates: { + needs: {}, + compute(data) { + return async ( + after: ConnectionArguments["after"], + before: ConnectionArguments["before"], + first: ConnectionArguments["first"], + last: ConnectionArguments["last"], + filters?: {} + ) => { + const baseArgs = { + where: { + creator: { + organizationId: data.id, + }, + }, + }; + + const result = await findManyCursorConnection( + (args) => + client.emailTemplate.findMany({ + ...args, + ...baseArgs, + }), + () => client.emailTemplate.count({ ...baseArgs }), + { first, last, before, after } + ); + + return result; + }; + }, + }, + $addEmail: { + needs: {}, + compute(data) { + return async (email: string) => { + return await client.email.create({ + data: { + email, + organization: { + connect: { + id: data.id, + }, + }, + }, + }); + }; + }, + }, + $createOAuthApp: { + needs: {}, + compute(data) { + return async ( + clientId: string, + clientSecret: string, + type: $Enums.OAuthProvider + ) => { + return await client.oAuthApp.create({ + data: { + clientId, + clientSecret, + type, + organization: { + connect: { + id: data.id, + }, + }, + }, + }); + }; + }, + }, + $deleteOAuthApp: { + needs: {}, + compute(data) { + return async (id: string) => { + return await client.oAuthApp.delete({ + where: { + id, + organizationId: data.id, + }, + }); + }; + }, + }, + }, + }, +}); + +export interface User + extends Prisma.Result {} + +export interface Email + extends Prisma.Result {} + +export interface EmailTemplate + extends Prisma.Result {} + +export interface Organization + extends Prisma.Result {} diff --git a/src/helper/get-user-from-ctx.ts b/src/helper/get-user-from-ctx.ts index 8ff7632..02c22b1 100644 --- a/src/helper/get-user-from-ctx.ts +++ b/src/helper/get-user-from-ctx.ts @@ -1,7 +1,6 @@ import { getContext } from "@getcronit/pylon"; -import { User } from "../repository/models/User"; -export const getUserFromCtx = (): User => { +export const getUserFromCtx = () => { const ctx = getContext(); const user = ctx.get("user"); diff --git a/src/index.ts b/src/index.ts index 81b67b9..843a64e 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,42 +1,16 @@ -import { app, auth, getContext } from "@getcronit/pylon"; +import { app, auth, getContext, ID, requireAuth } from "@getcronit/pylon"; import { serve } from "@hono/node-server"; import * as dotenv from "dotenv"; // see https://github.com/motdotla/dotenv#how-do-i-use-dotenv-with-import -import { EmailTemplate } from "./repository/models/EmailTemplate"; -import { OAuthApp } from "./repository/models/OAuthApp"; -import { Organization } from "./repository/models/Organization"; -import { User } from "./repository/models/User"; import { MailFactory } from "./services/mail-factory"; import * as oidcAzure from "./services/oauth/azure"; import * as oidcGoogle from "./services/oauth/google"; +import { client, EmailTemplate, Organization, User } from "./client"; +import { SMTPOptions } from "./services/mailer/smtp"; dotenv.config(); -export const graphql = { - Query: { - me: User.me, - template: EmailTemplate.get, - allTemplate: EmailTemplate.all, - }, - Mutation: { - templateCreate: EmailTemplate.create, - templateUpdate: EmailTemplate.update, - templateDelete: EmailTemplate.delete, - templateTransformer: EmailTemplate.setTransformer, - userEmailCreate: User.createEmail, - userEmailUpdate: User.updateEmail, - userEmailDelete: User.deleteEmail, - organizationSetSenderEmail: Organization.setSenderEmail, - - oauthAppCreate: OAuthApp.create, - oauthAppDelete: OAuthApp.delete, - - sendMail: MailFactory.sendMail, - sendTemplateMail: MailFactory.sendTemplateMail, - }, -}; - app.use("*", auth.initialize()); app.use("*", async (c, next) => { @@ -45,34 +19,30 @@ app.use("*", async (c, next) => { const auth = ctx.get("auth"); if (auth?.active) { - console.log("Authenticated user", auth); - const organizationId = auth[ "urn:zitadel:iam:user:resourceowner:id" ] as string; - const user = await User.objects.upsert( - { + const user = await client.user.upsert({ + where: { + id: auth.sub, + organizationId, + }, + create: { id: auth.sub, organization: { connectOrCreate: { - create: { + where: { id: organizationId, }, - where: { + create: { id: organizationId, }, }, }, }, - {}, - { - id: auth.sub, - organizationId, - } - ); - - console.log("Authenticated user", user); + update: {}, + }); // Add user to context ctx.set("user", user); @@ -81,6 +51,157 @@ app.use("*", async (c, next) => { return next(); }); +export const graphql = { + Query: { + me: requireAuth({ roles: ["mailpress:admin"] })(async () => { + const ctx = getContext(); + + return ctx.get("user")!; + }), + template: requireAuth({ roles: ["mailpress:admin"] })( + async (...args: Parameters) => { + const ctx = getContext(); + + const user = ctx.get("user")!; + + const org = await user.organization(); + + return org.emailTemplate(...args); + } + ), + allTemplate: requireAuth({ roles: ["mailpress:admin"] })( + async (...args: Parameters) => { + const ctx = getContext(); + + const user = ctx.get("user")!; + + const org = await user.organization(); + + return org.emailTemplates(...args); + } + ), + }, + Mutation: { + templateCreate: requireAuth({ roles: ["mailpress:admin"] })( + async (...args: Parameters) => { + const ctx = getContext(); + + const user = ctx.get("user")!; + + console.log("User", user); + + return user.$createEmailTemplate(...args); + } + ), + templateUpdate: requireAuth({ roles: ["mailpress:admin"] })( + async (...args: Parameters) => { + const ctx = getContext(); + + const user = ctx.get("user")!; + + return user.$updateEmailTemplate(...args); + } + ), + templateDelete: requireAuth({ roles: ["mailpress:admin"] })( + async (...args: Parameters) => { + const ctx = getContext(); + + const user = ctx.get("user")!; + + return user.$deleteEmailTemplate(...args); + } + ), + organizationSetEmail: requireAuth({ roles: ["mailpress:admin"] })( + async (email: string, config: Omit) => { + const ctx = getContext(); + + const user = ctx.get("user")!; + + const org = await user.organization(); + + const emailObject = await org.$addEmail(email); + + return await emailObject.$addSMTPConfig({ + ...config, + user: email, + }); + } + ), + userEmailCreate: requireAuth()( + async (email: string, config: Omit) => { + const ctx = getContext(); + + const user = ctx.get("user")!; + + const emailObject = await user.$addEmail(email); + + return await emailObject.$addSMTPConfig({ + ...config, + user: email, + }); + } + ), + userEmailDelete: requireAuth()(async () => { + const ctx = getContext(); + + const user = ctx.get("user")!; + + return user.$deleteEmail(); + }), + userEmailUpdate: requireAuth()( + async (email: string, config: Omit) => { + const ctx = getContext(); + + const user = ctx.get("user")!; + + const updatedEmail = await user.$updateEmail(email); + + return updatedEmail.$addSMTPConfig({ + ...config, + user: email, + }); + } + ), + templateTransformer: requireAuth({ + roles: ["mailpress:unsafe-transformer"], + })(async (id: ID, transformer: string) => { + const ctx = getContext(); + + const user = ctx.get("user")!; + + const org = await user.organization(); + + const template = await org.emailTemplate(id)!; + + if (!template) { + throw new Error("Template not found"); + } + + return template.$setTransformer(transformer); + }), + oauthAppCreate: requireAuth({ roles: ["mailpress:admin"] })( + async (...args: Parameters) => { + const user = getContext().get("user")!; + + const organization = await user.organization(); + + return organization.$createOAuthApp(...args); + } + ), + oauthAppDelete: requireAuth({ roles: ["mailpress:admin"] })( + async (...args: Parameters) => { + const user = getContext().get("user")!; + + const organization = await user.organization(); + + return organization.$deleteOAuthApp(...args); + } + ), + sendEmail: MailFactory.sendMail, + sendTemplateMail: MailFactory.sendTemplateMail, + }, +}; + app.use("/oauth/google", oidcGoogle.handler); app.use("/oauth/google/callback", oidcGoogle.handlerCb); diff --git a/src/repository/.generated.ts b/src/repository/.generated.ts deleted file mode 100644 index dba6631..0000000 --- a/src/repository/.generated.ts +++ /dev/null @@ -1,1326 +0,0 @@ -// @ts-ignore -import type {$Enums} from "@prisma/client"; - -import { Prisma } from "@prisma/client"; -import { Repository, NullableGetFunction, NullablePaginateFunction } from "@getcronit/prisma-extended-models"; - -import {Organization as OrganizationModel} from "./models/Organization"; -import {OAuthApp as OAuthAppModel} from "./models/OAuthApp"; -import {User as UserModel} from "./models/User"; -import {Email as EmailModel} from "./models/Email"; -import {SMTPConfig as SMTPConfigModel} from "./models/SMTPConfig"; -import {OAuthConfig as OAuthConfigModel} from "./models/OAuthConfig"; -import {EmailTemplate as EmailTemplateModel} from "./models/EmailTemplate"; -import {VariableDefinition as VariableDefinitionModel} from "./models/VariableDefinition"; -import {EmailEnvelope as EmailEnvelopeModel} from "./models/EmailEnvelope"; - -export abstract class OrganizationRepository extends Repository { - - constructor(data: Prisma.OrganizationCreateInput) { - super(); - - const hiddenFields: string[] = ["emailId"]; - - this.$boostrap(this, data, hiddenFields); - } - - - id!: string; -async users (pagination?: Parameters[0], where?: Parameters[1], orderBy?: Parameters[2]) { - - - - const _where = { - ...where, - organizationId:this.id - } - - const Model = (await require('./models/User')).User as typeof UserModel; - - try { - return await Model.objects.paginate( - pagination, _where, orderBy - ); - } catch (e) { - throw e; - } - - - }; - -async user (where: Parameters[0]) { - - - where = {...where, organizationId:this.id}; - - const Model = (await require('./models/User')).User as typeof UserModel; - - try { - return await Model.objects.get(where); - } - catch (e) { - throw e; - } - }; - -async $usersAdd (data: Omit ) { - const Model = (await require('./models/User')).User as typeof UserModel; - - try { - return await Model.objects.create({...data, organizationId: this.id } as any); - } catch (e) { - throw e - } - } - -async $usersUpdate (data: Prisma.UserUpdateArgs['data'], where: Prisma.UserUpdateArgs['where']) { - const Model = (await require('./models/User')).User as typeof UserModel; - - try { - return await Model.objects.update(data, {...where, organizationId: this.id || undefined}); - } catch (e) { - throw e - } - - - } - -async $usersDelete (where: Omit) { - const Model = (await require('./models/User')).User as typeof UserModel; - - try { - return await Model.objects.delete({...where, organizationId: this.id || undefined} as any); - } catch (e) { - throw e - } - } - async email (where?: Parameters>[0], orderBy?: Parameters>[1]) { - if (!this.$emailId) return null; - - - const _where = { - ...where, - id:this.$emailId - } - - const Model = (await require('./models/Email')).Email as typeof EmailModel; - - try { - return await Model.objects.get( - _where, orderBy - ); - } catch (e) { - return null; - } - - - }; - -async $emailAdd (data: Omit ) { - const Model = (await require('./models/Email')).Email as typeof EmailModel; - - try { - return await Model.objects.create({...data, id: this.$emailId } as any); - } catch (e) { - throw e - } - } - -async $emailUpdate (data: Prisma.EmailUpdateArgs['data'], where: Prisma.EmailUpdateArgs['where']) { - const Model = (await require('./models/Email')).Email as typeof EmailModel; - - try { - return await Model.objects.update(data, {...where, id: this.$emailId || undefined}); - } catch (e) { - throw e - } - - - } - -async $emailDelete (where: Omit) { - const Model = (await require('./models/Email')).Email as typeof EmailModel; - - try { - return await Model.objects.delete({...where, id: this.$emailId || undefined} as any); - } catch (e) { - throw e - } - } - $emailId!: string | null; -async oAuthApps (pagination?: Parameters[0], where?: Parameters[1], orderBy?: Parameters[2]) { - - - - const _where = { - ...where, - organizationId:this.id - } - - const Model = (await require('./models/OAuthApp')).OAuthApp as typeof OAuthAppModel; - - try { - return await Model.objects.paginate( - pagination, _where, orderBy - ); - } catch (e) { - throw e; - } - - - }; - -async oAuthApp (where: Parameters[0]) { - - - where = {...where, organizationId:this.id}; - - const Model = (await require('./models/OAuthApp')).OAuthApp as typeof OAuthAppModel; - - try { - return await Model.objects.get(where); - } - catch (e) { - throw e; - } - }; - -async $oAuthAppsAdd (data: Omit ) { - const Model = (await require('./models/OAuthApp')).OAuthApp as typeof OAuthAppModel; - - try { - return await Model.objects.create({...data, organizationId: this.id } as any); - } catch (e) { - throw e - } - } - -async $oAuthAppsUpdate (data: Prisma.OAuthAppUpdateArgs['data'], where: Prisma.OAuthAppUpdateArgs['where']) { - const Model = (await require('./models/OAuthApp')).OAuthApp as typeof OAuthAppModel; - - try { - return await Model.objects.update(data, {...where, organizationId: this.id || undefined}); - } catch (e) { - throw e - } - - - } - -async $oAuthAppsDelete (where: Omit) { - const Model = (await require('./models/OAuthApp')).OAuthApp as typeof OAuthAppModel; - - try { - return await Model.objects.delete({...where, organizationId: this.id || undefined} as any); - } catch (e) { - throw e - } - } - redirectUrl!: string | null; - - } - -export abstract class OAuthAppRepository extends Repository { - - constructor(data: Prisma.OAuthAppCreateInput) { - super(); - - const hiddenFields: string[] = ["clientSecret","organizationId"]; - - this.$boostrap(this, data, hiddenFields); - } - - - id!: string; -clientId!: string; -$clientSecret!: string; -type!: $Enums.OAuthProvider; -async organization (where?: Parameters[0], orderBy?: Parameters[1]) { - if (!this.$organizationId) throw new Error("Relation organizationId is required"); - - - const _where = { - ...where, - id:this.$organizationId - } - - const Model = (await require('./models/Organization')).Organization as typeof OrganizationModel; - - try { - return await Model.objects.get( - _where, orderBy - ); - } catch (e) { - throw e; - } - - - }; - -async $organizationAdd (data: Omit ) { - const Model = (await require('./models/Organization')).Organization as typeof OrganizationModel; - - try { - return await Model.objects.create({...data, id: this.$organizationId } as any); - } catch (e) { - throw e - } - } - -async $organizationUpdate (data: Prisma.OrganizationUpdateArgs['data'], where: Prisma.OrganizationUpdateArgs['where']) { - const Model = (await require('./models/Organization')).Organization as typeof OrganizationModel; - - try { - return await Model.objects.update(data, {...where, id: this.$organizationId || undefined}); - } catch (e) { - throw e - } - - - } - -async $organizationDelete (where: Omit) { - const Model = (await require('./models/Organization')).Organization as typeof OrganizationModel; - - try { - return await Model.objects.delete({...where, id: this.$organizationId || undefined} as any); - } catch (e) { - throw e - } - } - $organizationId!: string; - - } - -export abstract class UserRepository extends Repository { - - constructor(data: Prisma.UserCreateInput) { - super(); - - const hiddenFields: string[] = ["organizationId"]; - - this.$boostrap(this, data, hiddenFields); - } - - - id!: string; -$organizationId!: string; -async emailTemplates (pagination?: Parameters[0], where?: Parameters[1], orderBy?: Parameters[2]) { - - - - const _where = { - ...where, - creatorId:this.id - } - - const Model = (await require('./models/EmailTemplate')).EmailTemplate as typeof EmailTemplateModel; - - try { - return await Model.objects.paginate( - pagination, _where, orderBy - ); - } catch (e) { - throw e; - } - - - }; - -async emailTemplate (where: Parameters[0]) { - - - where = {...where, creatorId:this.id}; - - const Model = (await require('./models/EmailTemplate')).EmailTemplate as typeof EmailTemplateModel; - - try { - return await Model.objects.get(where); - } - catch (e) { - throw e; - } - }; - -async $emailTemplatesAdd (data: Omit ) { - const Model = (await require('./models/EmailTemplate')).EmailTemplate as typeof EmailTemplateModel; - - try { - return await Model.objects.create({...data, creatorId: this.id } as any); - } catch (e) { - throw e - } - } - -async $emailTemplatesUpdate (data: Prisma.EmailTemplateUpdateArgs['data'], where: Prisma.EmailTemplateUpdateArgs['where']) { - const Model = (await require('./models/EmailTemplate')).EmailTemplate as typeof EmailTemplateModel; - - try { - return await Model.objects.update(data, {...where, creatorId: this.id || undefined}); - } catch (e) { - throw e - } - - - } - -async $emailTemplatesDelete (where: Omit) { - const Model = (await require('./models/EmailTemplate')).EmailTemplate as typeof EmailTemplateModel; - - try { - return await Model.objects.delete({...where, creatorId: this.id || undefined} as any); - } catch (e) { - throw e - } - } - async email (where?: Parameters>[0], orderBy?: Parameters>[1]) { - - - - const _where = { - ...where, - userId:this.id - } - - const Model = (await require('./models/Email')).Email as typeof EmailModel; - - try { - return await Model.objects.get( - _where, orderBy - ); - } catch (e) { - return null; - } - - - }; - -async $emailAdd (data: Omit ) { - const Model = (await require('./models/Email')).Email as typeof EmailModel; - - try { - return await Model.objects.create({...data, userId: this.id } as any); - } catch (e) { - throw e - } - } - -async $emailUpdate (data: Prisma.EmailUpdateArgs['data'], where: Prisma.EmailUpdateArgs['where']) { - const Model = (await require('./models/Email')).Email as typeof EmailModel; - - try { - return await Model.objects.update(data, {...where, userId: this.id || undefined}); - } catch (e) { - throw e - } - - - } - -async $emailDelete (where: Omit) { - const Model = (await require('./models/Email')).Email as typeof EmailModel; - - try { - return await Model.objects.delete({...where, userId: this.id || undefined} as any); - } catch (e) { - throw e - } - } - async organization (where?: Parameters[0], orderBy?: Parameters[1]) { - if (!this.$organizationId) throw new Error("Relation organizationId is required"); - - - const _where = { - ...where, - id:this.$organizationId - } - - const Model = (await require('./models/Organization')).Organization as typeof OrganizationModel; - - try { - return await Model.objects.get( - _where, orderBy - ); - } catch (e) { - throw e; - } - - - }; - -async $organizationAdd (data: Omit ) { - const Model = (await require('./models/Organization')).Organization as typeof OrganizationModel; - - try { - return await Model.objects.create({...data, id: this.$organizationId } as any); - } catch (e) { - throw e - } - } - -async $organizationUpdate (data: Prisma.OrganizationUpdateArgs['data'], where: Prisma.OrganizationUpdateArgs['where']) { - const Model = (await require('./models/Organization')).Organization as typeof OrganizationModel; - - try { - return await Model.objects.update(data, {...where, id: this.$organizationId || undefined}); - } catch (e) { - throw e - } - - - } - -async $organizationDelete (where: Omit) { - const Model = (await require('./models/Organization')).Organization as typeof OrganizationModel; - - try { - return await Model.objects.delete({...where, id: this.$organizationId || undefined} as any); - } catch (e) { - throw e - } - } - - } - -export abstract class EmailRepository extends Repository { - - constructor(data: Prisma.EmailCreateInput) { - super(); - - const hiddenFields: string[] = ["userId"]; - - this.$boostrap(this, data, hiddenFields); - } - - - id!: string; -isEnabled!: boolean; -email!: string; -async smtpConfig (where?: Parameters>[0], orderBy?: Parameters>[1]) { - - - - const _where = { - ...where, - emailId:this.id - } - - const Model = (await require('./models/SMTPConfig')).SMTPConfig as typeof SMTPConfigModel; - - try { - return await Model.objects.get( - _where, orderBy - ); - } catch (e) { - return null; - } - - - }; - -async $smtpConfigAdd (data: Omit ) { - const Model = (await require('./models/SMTPConfig')).SMTPConfig as typeof SMTPConfigModel; - - try { - return await Model.objects.create({...data, emailId: this.id } as any); - } catch (e) { - throw e - } - } - -async $smtpConfigUpdate (data: Prisma.SMTPConfigUpdateArgs['data'], where: Prisma.SMTPConfigUpdateArgs['where']) { - const Model = (await require('./models/SMTPConfig')).SMTPConfig as typeof SMTPConfigModel; - - try { - return await Model.objects.update(data, {...where, emailId: this.id || undefined}); - } catch (e) { - throw e - } - - - } - -async $smtpConfigDelete (where: Omit) { - const Model = (await require('./models/SMTPConfig')).SMTPConfig as typeof SMTPConfigModel; - - try { - return await Model.objects.delete({...where, emailId: this.id || undefined} as any); - } catch (e) { - throw e - } - } - async oauthConfig (where?: Parameters>[0], orderBy?: Parameters>[1]) { - - - - const _where = { - ...where, - emailId:this.id - } - - const Model = (await require('./models/OAuthConfig')).OAuthConfig as typeof OAuthConfigModel; - - try { - return await Model.objects.get( - _where, orderBy - ); - } catch (e) { - return null; - } - - - }; - -async $oauthConfigAdd (data: Omit ) { - const Model = (await require('./models/OAuthConfig')).OAuthConfig as typeof OAuthConfigModel; - - try { - return await Model.objects.create({...data, emailId: this.id } as any); - } catch (e) { - throw e - } - } - -async $oauthConfigUpdate (data: Prisma.OAuthConfigUpdateArgs['data'], where: Prisma.OAuthConfigUpdateArgs['where']) { - const Model = (await require('./models/OAuthConfig')).OAuthConfig as typeof OAuthConfigModel; - - try { - return await Model.objects.update(data, {...where, emailId: this.id || undefined}); - } catch (e) { - throw e - } - - - } - -async $oauthConfigDelete (where: Omit) { - const Model = (await require('./models/OAuthConfig')).OAuthConfig as typeof OAuthConfigModel; - - try { - return await Model.objects.delete({...where, emailId: this.id || undefined} as any); - } catch (e) { - throw e - } - } - async user (where?: Parameters>[0], orderBy?: Parameters>[1]) { - if (!this.$userId) return null; - - - const _where = { - ...where, - id:this.$userId - } - - const Model = (await require('./models/User')).User as typeof UserModel; - - try { - return await Model.objects.get( - _where, orderBy - ); - } catch (e) { - return null; - } - - - }; - -async $userAdd (data: Omit ) { - const Model = (await require('./models/User')).User as typeof UserModel; - - try { - return await Model.objects.create({...data, id: this.$userId } as any); - } catch (e) { - throw e - } - } - -async $userUpdate (data: Prisma.UserUpdateArgs['data'], where: Prisma.UserUpdateArgs['where']) { - const Model = (await require('./models/User')).User as typeof UserModel; - - try { - return await Model.objects.update(data, {...where, id: this.$userId || undefined}); - } catch (e) { - throw e - } - - - } - -async $userDelete (where: Omit) { - const Model = (await require('./models/User')).User as typeof UserModel; - - try { - return await Model.objects.delete({...where, id: this.$userId || undefined} as any); - } catch (e) { - throw e - } - } - $userId!: string | null; -async organization (where?: Parameters>[0], orderBy?: Parameters>[1]) { - - - - const _where = { - ...where, - emailId:this.id - } - - const Model = (await require('./models/Organization')).Organization as typeof OrganizationModel; - - try { - return await Model.objects.get( - _where, orderBy - ); - } catch (e) { - return null; - } - - - }; - -async $organizationAdd (data: Omit ) { - const Model = (await require('./models/Organization')).Organization as typeof OrganizationModel; - - try { - return await Model.objects.create({...data, emailId: this.id } as any); - } catch (e) { - throw e - } - } - -async $organizationUpdate (data: Prisma.OrganizationUpdateArgs['data'], where: Prisma.OrganizationUpdateArgs['where']) { - const Model = (await require('./models/Organization')).Organization as typeof OrganizationModel; - - try { - return await Model.objects.update(data, {...where, emailId: this.id || undefined}); - } catch (e) { - throw e - } - - - } - -async $organizationDelete (where: Omit) { - const Model = (await require('./models/Organization')).Organization as typeof OrganizationModel; - - try { - return await Model.objects.delete({...where, emailId: this.id || undefined} as any); - } catch (e) { - throw e - } - } - - } - -export abstract class SMTPConfigRepository extends Repository { - - constructor(data: Prisma.SMTPConfigCreateInput) { - super(); - - const hiddenFields: string[] = ["emailId"]; - - this.$boostrap(this, data, hiddenFields); - } - - - id!: string; -host!: string; -port!: number; -username!: string; -password!: string; -secure!: boolean; -async email (where?: Parameters[0], orderBy?: Parameters[1]) { - if (!this.$emailId) throw new Error("Relation emailId is required"); - - - const _where = { - ...where, - id:this.$emailId - } - - const Model = (await require('./models/Email')).Email as typeof EmailModel; - - try { - return await Model.objects.get( - _where, orderBy - ); - } catch (e) { - throw e; - } - - - }; - -async $emailAdd (data: Omit ) { - const Model = (await require('./models/Email')).Email as typeof EmailModel; - - try { - return await Model.objects.create({...data, id: this.$emailId } as any); - } catch (e) { - throw e - } - } - -async $emailUpdate (data: Prisma.EmailUpdateArgs['data'], where: Prisma.EmailUpdateArgs['where']) { - const Model = (await require('./models/Email')).Email as typeof EmailModel; - - try { - return await Model.objects.update(data, {...where, id: this.$emailId || undefined}); - } catch (e) { - throw e - } - - - } - -async $emailDelete (where: Omit) { - const Model = (await require('./models/Email')).Email as typeof EmailModel; - - try { - return await Model.objects.delete({...where, id: this.$emailId || undefined} as any); - } catch (e) { - throw e - } - } - $emailId!: string; - - } - -export abstract class OAuthConfigRepository extends Repository { - - constructor(data: Prisma.OAuthConfigCreateInput) { - super(); - - const hiddenFields: string[] = ["accessToken","refreshToken","emailId"]; - - this.$boostrap(this, data, hiddenFields); - } - - - id!: string; -provider!: $Enums.OAuthProvider; -$accessToken!: string; -accessTokenExpiresAt!: Date; -$refreshToken!: string; -async email (where?: Parameters[0], orderBy?: Parameters[1]) { - if (!this.$emailId) throw new Error("Relation emailId is required"); - - - const _where = { - ...where, - id:this.$emailId - } - - const Model = (await require('./models/Email')).Email as typeof EmailModel; - - try { - return await Model.objects.get( - _where, orderBy - ); - } catch (e) { - throw e; - } - - - }; - -async $emailAdd (data: Omit ) { - const Model = (await require('./models/Email')).Email as typeof EmailModel; - - try { - return await Model.objects.create({...data, id: this.$emailId } as any); - } catch (e) { - throw e - } - } - -async $emailUpdate (data: Prisma.EmailUpdateArgs['data'], where: Prisma.EmailUpdateArgs['where']) { - const Model = (await require('./models/Email')).Email as typeof EmailModel; - - try { - return await Model.objects.update(data, {...where, id: this.$emailId || undefined}); - } catch (e) { - throw e - } - - - } - -async $emailDelete (where: Omit) { - const Model = (await require('./models/Email')).Email as typeof EmailModel; - - try { - return await Model.objects.delete({...where, id: this.$emailId || undefined} as any); - } catch (e) { - throw e - } - } - $emailId!: string; - - } - -export abstract class EmailTemplateRepository extends Repository { - - constructor(data: Prisma.EmailTemplateCreateInput) { - super(); - - const hiddenFields: string[] = ["parentId","creatorId"]; - - this.$boostrap(this, data, hiddenFields); - } - - - id!: string; -description!: string; -content!: string; -verifyReplyTo!: boolean | null; -transformer!: string | null; -async envelope (where?: Parameters>[0], orderBy?: Parameters>[1]) { - - - - const _where = { - ...where, - emailTemplateId:this.id - } - - const Model = (await require('./models/EmailEnvelope')).EmailEnvelope as typeof EmailEnvelopeModel; - - try { - return await Model.objects.get( - _where, orderBy - ); - } catch (e) { - return null; - } - - - }; - -async $envelopeAdd (data: Omit ) { - const Model = (await require('./models/EmailEnvelope')).EmailEnvelope as typeof EmailEnvelopeModel; - - try { - return await Model.objects.create({...data, emailTemplateId: this.id } as any); - } catch (e) { - throw e - } - } - -async $envelopeUpdate (data: Prisma.EmailEnvelopeUpdateArgs['data'], where: Prisma.EmailEnvelopeUpdateArgs['where']) { - const Model = (await require('./models/EmailEnvelope')).EmailEnvelope as typeof EmailEnvelopeModel; - - try { - return await Model.objects.update(data, {...where, emailTemplateId: this.id || undefined}); - } catch (e) { - throw e - } - - - } - -async $envelopeDelete (where: Omit) { - const Model = (await require('./models/EmailEnvelope')).EmailEnvelope as typeof EmailEnvelopeModel; - - try { - return await Model.objects.delete({...where, emailTemplateId: this.id || undefined} as any); - } catch (e) { - throw e - } - } - envelopeId!: string | null; -async parent (where?: Parameters>[0], orderBy?: Parameters>[1]) { - if (!this.$parentId) return null; - - - const _where = { - ...where, - id:this.$parentId - } - - const Model = (await require('./models/EmailTemplate')).EmailTemplate as typeof EmailTemplateModel; - - try { - return await Model.objects.get( - _where, orderBy - ); - } catch (e) { - return null; - } - - - }; - -async $parentAdd (data: Omit ) { - const Model = (await require('./models/EmailTemplate')).EmailTemplate as typeof EmailTemplateModel; - - try { - return await Model.objects.create({...data, id: this.$parentId } as any); - } catch (e) { - throw e - } - } - -async $parentUpdate (data: Prisma.EmailTemplateUpdateArgs['data'], where: Prisma.EmailTemplateUpdateArgs['where']) { - const Model = (await require('./models/EmailTemplate')).EmailTemplate as typeof EmailTemplateModel; - - try { - return await Model.objects.update(data, {...where, id: this.$parentId || undefined}); - } catch (e) { - throw e - } - - - } - -async $parentDelete (where: Omit) { - const Model = (await require('./models/EmailTemplate')).EmailTemplate as typeof EmailTemplateModel; - - try { - return await Model.objects.delete({...where, id: this.$parentId || undefined} as any); - } catch (e) { - throw e - } - } - $parentId!: string | null; -async links (pagination?: Parameters[0], where?: Parameters[1], orderBy?: Parameters[2]) { - - - - const _where = { - ...where, - parentId:this.id - } - - const Model = (await require('./models/EmailTemplate')).EmailTemplate as typeof EmailTemplateModel; - - try { - return await Model.objects.paginate( - pagination, _where, orderBy - ); - } catch (e) { - throw e; - } - - - }; - -async link (where: Parameters[0]) { - - - where = {...where, parentId:this.id}; - - const Model = (await require('./models/EmailTemplate')).EmailTemplate as typeof EmailTemplateModel; - - try { - return await Model.objects.get(where); - } - catch (e) { - throw e; - } - }; - -async $linksAdd (data: Omit ) { - const Model = (await require('./models/EmailTemplate')).EmailTemplate as typeof EmailTemplateModel; - - try { - return await Model.objects.create({...data, parentId: this.id } as any); - } catch (e) { - throw e - } - } - -async $linksUpdate (data: Prisma.EmailTemplateUpdateArgs['data'], where: Prisma.EmailTemplateUpdateArgs['where']) { - const Model = (await require('./models/EmailTemplate')).EmailTemplate as typeof EmailTemplateModel; - - try { - return await Model.objects.update(data, {...where, parentId: this.id || undefined}); - } catch (e) { - throw e - } - - - } - -async $linksDelete (where: Omit) { - const Model = (await require('./models/EmailTemplate')).EmailTemplate as typeof EmailTemplateModel; - - try { - return await Model.objects.delete({...where, parentId: this.id || undefined} as any); - } catch (e) { - throw e - } - } - async variables (pagination?: Parameters[0], where?: Parameters[1], orderBy?: Parameters[2]) { - - - - const _where = { - ...where, - emailTemplateId:this.id - } - - const Model = (await require('./models/VariableDefinition')).VariableDefinition as typeof VariableDefinitionModel; - - try { - return await Model.objects.paginate( - pagination, _where, orderBy - ); - } catch (e) { - throw e; - } - - - }; - -async variable (where: Parameters[0]) { - - - where = {...where, emailTemplateId:this.id}; - - const Model = (await require('./models/VariableDefinition')).VariableDefinition as typeof VariableDefinitionModel; - - try { - return await Model.objects.get(where); - } - catch (e) { - throw e; - } - }; - -async $variablesAdd (data: Omit ) { - const Model = (await require('./models/VariableDefinition')).VariableDefinition as typeof VariableDefinitionModel; - - try { - return await Model.objects.create({...data, emailTemplateId: this.id } as any); - } catch (e) { - throw e - } - } - -async $variablesUpdate (data: Prisma.VariableDefinitionUpdateArgs['data'], where: Prisma.VariableDefinitionUpdateArgs['where']) { - const Model = (await require('./models/VariableDefinition')).VariableDefinition as typeof VariableDefinitionModel; - - try { - return await Model.objects.update(data, {...where, emailTemplateId: this.id || undefined}); - } catch (e) { - throw e - } - - - } - -async $variablesDelete (where: Omit) { - const Model = (await require('./models/VariableDefinition')).VariableDefinition as typeof VariableDefinitionModel; - - try { - return await Model.objects.delete({...where, emailTemplateId: this.id || undefined} as any); - } catch (e) { - throw e - } - } - createdAt!: Date; -updatedAt!: Date; -async creator (where?: Parameters[0], orderBy?: Parameters[1]) { - if (!this.$creatorId) throw new Error("Relation creatorId is required"); - - - const _where = { - ...where, - id:this.$creatorId - } - - const Model = (await require('./models/User')).User as typeof UserModel; - - try { - return await Model.objects.get( - _where, orderBy - ); - } catch (e) { - throw e; - } - - - }; - -async $creatorAdd (data: Omit ) { - const Model = (await require('./models/User')).User as typeof UserModel; - - try { - return await Model.objects.create({...data, id: this.$creatorId } as any); - } catch (e) { - throw e - } - } - -async $creatorUpdate (data: Prisma.UserUpdateArgs['data'], where: Prisma.UserUpdateArgs['where']) { - const Model = (await require('./models/User')).User as typeof UserModel; - - try { - return await Model.objects.update(data, {...where, id: this.$creatorId || undefined}); - } catch (e) { - throw e - } - - - } - -async $creatorDelete (where: Omit) { - const Model = (await require('./models/User')).User as typeof UserModel; - - try { - return await Model.objects.delete({...where, id: this.$creatorId || undefined} as any); - } catch (e) { - throw e - } - } - $creatorId!: string; - - } - -export abstract class VariableDefinitionRepository extends Repository { - - constructor(data: Prisma.VariableDefinitionCreateInput) { - super(); - - const hiddenFields: string[] = ["emailTemplateId"]; - - this.$boostrap(this, data, hiddenFields); - } - - - id!: string; -name!: string; -description!: string | null; -defaultValue!: string | null; -isRequired!: boolean | null; -isConstant!: boolean | null; -async emailTemplate (where?: Parameters>[0], orderBy?: Parameters>[1]) { - if (!this.$emailTemplateId) return null; - - - const _where = { - ...where, - id:this.$emailTemplateId - } - - const Model = (await require('./models/EmailTemplate')).EmailTemplate as typeof EmailTemplateModel; - - try { - return await Model.objects.get( - _where, orderBy - ); - } catch (e) { - return null; - } - - - }; - -async $emailTemplateAdd (data: Omit ) { - const Model = (await require('./models/EmailTemplate')).EmailTemplate as typeof EmailTemplateModel; - - try { - return await Model.objects.create({...data, id: this.$emailTemplateId } as any); - } catch (e) { - throw e - } - } - -async $emailTemplateUpdate (data: Prisma.EmailTemplateUpdateArgs['data'], where: Prisma.EmailTemplateUpdateArgs['where']) { - const Model = (await require('./models/EmailTemplate')).EmailTemplate as typeof EmailTemplateModel; - - try { - return await Model.objects.update(data, {...where, id: this.$emailTemplateId || undefined}); - } catch (e) { - throw e - } - - - } - -async $emailTemplateDelete (where: Omit) { - const Model = (await require('./models/EmailTemplate')).EmailTemplate as typeof EmailTemplateModel; - - try { - return await Model.objects.delete({...where, id: this.$emailTemplateId || undefined} as any); - } catch (e) { - throw e - } - } - $emailTemplateId!: string | null; - - } - -export abstract class EmailEnvelopeRepository extends Repository { - - constructor(data: Prisma.EmailEnvelopeCreateInput) { - super(); - - const hiddenFields: string[] = ["emailTemplateId"]; - - this.$boostrap(this, data, hiddenFields); - } - - - id!: string; -subject!: string | null; -to!: string[]; -replyTo!: string | null; -async emailTemplate (where?: Parameters[0], orderBy?: Parameters[1]) { - if (!this.$emailTemplateId) throw new Error("Relation emailTemplateId is required"); - - - const _where = { - ...where, - id:this.$emailTemplateId - } - - const Model = (await require('./models/EmailTemplate')).EmailTemplate as typeof EmailTemplateModel; - - try { - return await Model.objects.get( - _where, orderBy - ); - } catch (e) { - throw e; - } - - - }; - -async $emailTemplateAdd (data: Omit ) { - const Model = (await require('./models/EmailTemplate')).EmailTemplate as typeof EmailTemplateModel; - - try { - return await Model.objects.create({...data, id: this.$emailTemplateId } as any); - } catch (e) { - throw e - } - } - -async $emailTemplateUpdate (data: Prisma.EmailTemplateUpdateArgs['data'], where: Prisma.EmailTemplateUpdateArgs['where']) { - const Model = (await require('./models/EmailTemplate')).EmailTemplate as typeof EmailTemplateModel; - - try { - return await Model.objects.update(data, {...where, id: this.$emailTemplateId || undefined}); - } catch (e) { - throw e - } - - - } - -async $emailTemplateDelete (where: Omit) { - const Model = (await require('./models/EmailTemplate')).EmailTemplate as typeof EmailTemplateModel; - - try { - return await Model.objects.delete({...where, id: this.$emailTemplateId || undefined} as any); - } catch (e) { - throw e - } - } - $emailTemplateId!: string; - - } - diff --git a/src/repository/client.ts b/src/repository/client.ts deleted file mode 100644 index c78253e..0000000 --- a/src/repository/client.ts +++ /dev/null @@ -1,5 +0,0 @@ -import * as Sentry from "@sentry/bun"; -import { PrismaClient } from "@prisma/client"; -export const client = new PrismaClient(); - -Sentry.addIntegration(Sentry.prismaIntegration); diff --git a/src/repository/models/Email.ts b/src/repository/models/Email.ts deleted file mode 100644 index 471e9ee..0000000 --- a/src/repository/models/Email.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { ObjectManager } from "@getcronit/prisma-extended-models"; - -import { EmailRepository } from "../.generated"; -import { client } from "../client"; - -export class Email extends EmailRepository { - static objects = new ObjectManager<"Email", typeof Email>( - client.email, - Email - ); -} diff --git a/src/repository/models/EmailEnvelope.ts b/src/repository/models/EmailEnvelope.ts deleted file mode 100644 index caf1c2c..0000000 --- a/src/repository/models/EmailEnvelope.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { ObjectManager } from "@getcronit/prisma-extended-models"; - -import { client } from "../client"; -import { EmailEnvelopeRepository } from "../.generated"; - -export class EmailEnvelope extends EmailEnvelopeRepository { - static objects = new ObjectManager<"EmailEnvelope", typeof EmailEnvelope>( - client.emailEnvelope, - EmailEnvelope - ); - - // Custom logic here... -} diff --git a/src/repository/models/EmailTemplate.ts b/src/repository/models/EmailTemplate.ts deleted file mode 100644 index afba38c..0000000 --- a/src/repository/models/EmailTemplate.ts +++ /dev/null @@ -1,228 +0,0 @@ -import { ObjectManager } from "@getcronit/prisma-extended-models"; -import { ServiceError, requireAuth } from "@getcronit/pylon"; - -import { client } from "../client"; -import { EmailTemplateRepository } from "../.generated"; -import { Prisma } from "@prisma/client"; -import { User } from "./User"; -import { getUserFromCtx } from "../../helper/get-user-from-ctx"; - -export class EmailTemplate extends EmailTemplateRepository { - static objects = new ObjectManager<"EmailTemplate", typeof EmailTemplate>( - client.emailTemplate, - EmailTemplate - ); - - @requireAuth({ - roles: ["mailpress:admin"], - }) - static async get(id: string) { - const user = getUserFromCtx(); - - return EmailTemplate.objects.get({ - id, - creator: { - organizationId: user.$organizationId, - }, - }); - } - - @requireAuth({ - roles: ["mailpress:admin"], - }) - static async all( - pagination?: Parameters[0], - where?: Parameters[1], - orderBy?: Parameters[2] - ) { - const user = getUserFromCtx(); - - return EmailTemplate.objects.paginate( - pagination, - { - ...where, - creator: { - organizationId: user.$organizationId, - }, - }, - orderBy - ); - } - - @requireAuth({ - roles: ["mailpress:admin"], - }) - static async create(data: { - content: string; - description: string; - variables: { - name: string; - isRequired?: boolean; - isConstant?: boolean; - description?: string; - defaultValue?: string; - }[]; - - envelope: { - subject?: string; - to?: string[]; - replyTo?: string; - }; - }) { - const user = getUserFromCtx(); - - return user.$emailTemplatesAdd({ - content: data.content, - description: data.description, - variables: { - createMany: { - data: data.variables || [], - }, - }, - envelope: { - create: { - subject: data.envelope.subject, - to: data.envelope.to, - replyTo: data.envelope.replyTo, - }, - }, - }); - } - - @requireAuth({ - roles: ["mailpress:admin"], - }) - static async update( - id: string, - data: { - parentId?: string; - content?: string; - verifyReplyTo?: boolean; - description?: string; - variables: { - name: string; - - isRequired?: boolean; - isConstant?: boolean; - description?: string; - defaultValue?: string; - }[]; - - envelope: { - subject?: string; - to?: string[]; - replyTo?: string; - }; - } - ) { - const user = getUserFromCtx(); - - return EmailTemplate.objects.update( - { - content: data.content, - description: data.description, - parentId: data.parentId, - verifyReplyTo: data.verifyReplyTo, - variables: { - deleteMany: { - emailTemplateId: id, - NOT: data.variables.map((v) => ({ name: v.name })), - }, - upsert: data.variables.map((variable) => ({ - create: { - name: variable.name, - isRequired: variable.isRequired, - isConstant: variable.isConstant, - description: variable.description, - defaultValue: variable.defaultValue, - }, - update: { - name: variable.name, - isRequired: variable.isRequired, - isConstant: variable.isConstant, - description: variable.description, - defaultValue: variable.defaultValue, - }, - where: { - emailTemplateId_name: { - emailTemplateId: id, - name: variable.name, - }, - }, - })), - }, - envelope: { - upsert: { - create: { - subject: data.envelope.subject, - to: data.envelope.to, - replyTo: data.envelope.replyTo, - }, - update: { - subject: data.envelope.subject, - to: data.envelope.to, - replyTo: data.envelope.replyTo, - }, - }, - }, - }, - { - id, - creator: { - organizationId: user.$organizationId, - }, - } - ); - } - - @requireAuth({ roles: ["mailpress:unsafe-transformer"] }) - static async setTransformer(id: string, transformer: string) { - const user = getUserFromCtx(); - - return EmailTemplate.objects.update( - { - transformer, - }, - { - id, - creator: { - organizationId: user.$organizationId, - }, - } - ); - } - - @requireAuth({ - roles: ["mailpress:admin"], - }) - static async delete(id: string) { - const user = getUserFromCtx(); - - return EmailTemplate.objects.delete({ - id, - creator: { - organizationId: user.$organizationId, - }, - }); - } - - async creator( - where?: Prisma.UserWhereInput | undefined, - orderBy?: - | Prisma.UserOrderByWithRelationInput - | Prisma.UserOrderByWithRelationInput[] - | undefined - ): Promise { - const user = getUserFromCtx(); - - // Check if userId is owned by the user - if (this.$creatorId !== user.id) { - throw new ServiceError("Unauthorized", { - code: "UNAUTHORIZED", - statusCode: 401, - }); - } - - return super.creator(where, orderBy); - } -} diff --git a/src/repository/models/OAuthApp.ts b/src/repository/models/OAuthApp.ts deleted file mode 100644 index d092b47..0000000 --- a/src/repository/models/OAuthApp.ts +++ /dev/null @@ -1,46 +0,0 @@ -import { ObjectManager } from "@getcronit/prisma-extended-models"; - -import { client } from "../client"; -import { OAuthAppRepository } from "../.generated"; -import { requireAuth } from "@getcronit/pylon"; -import { $Enums } from "@prisma/client"; -import { getUserFromCtx } from "../../helper/get-user-from-ctx"; - -export class OAuthApp extends OAuthAppRepository { - static objects = new ObjectManager<"OAuthApp", typeof OAuthApp>( - client.oAuthApp, - OAuthApp - ); - - // Custom logic here... - - @requireAuth({ - roles: ["mailpress:admin"], - }) - static async create( - clientId: string, - clientSecret: string, - type: $Enums.OAuthProvider - ) { - const user = getUserFromCtx(); - - return await OAuthApp.objects.create({ - clientId, - clientSecret, - type, - organizationId: user.$organizationId, - }); - } - - @requireAuth({ - roles: ["mailpress:admin"], - }) - static async delete(id: string) { - const user = getUserFromCtx(); - - return await OAuthApp.objects.delete({ - id, - organizationId: user.$organizationId, - }); - } -} diff --git a/src/repository/models/OAuthConfig.ts b/src/repository/models/OAuthConfig.ts deleted file mode 100644 index 13b3737..0000000 --- a/src/repository/models/OAuthConfig.ts +++ /dev/null @@ -1,110 +0,0 @@ -import { ObjectManager } from "@getcronit/prisma-extended-models"; - -import * as oidcGoogle from "../../services/oauth/google"; -import * as oidcAzure from "../../services/oauth/azure"; -import { client } from "../client"; -import { OAuthConfigRepository } from "../.generated"; -import { ServiceError } from "@getcronit/pylon"; -import { PYLON_URL } from "../../config"; -import { Organization } from "./Organization"; - -export class OAuthConfig extends OAuthConfigRepository { - static objects = new ObjectManager<"OAuthConfig", typeof OAuthConfig>( - client.oAuthConfig, - OAuthConfig - ); - - // Custom logic here... - - async $freshAccessToken() { - // Get fresh token set - - const organization = await Organization.objects.get({ - users: { - some: { - email: { - oauthConfig: { - id: this.id, - }, - }, - }, - }, - }); - - if (this.provider === "GOOGLE") { - // Get token set from Google - - if (this.accessTokenExpiresAt > new Date()) { - // Token is still valid - return this.$accessToken; - } - - try { - const { client } = await oidcGoogle.getClient(organization); - - const tokenSet = await client.refresh(this.$refreshToken); - - await OAuthConfig.objects.update( - { - accessToken: tokenSet.access_token, - accessTokenExpiresAt: new Date(tokenSet.expires_at! * 1000), - }, - { - id: this.id, - } - ); - - return tokenSet.access_token!; - } catch (e) { - console.error(e); - - throw new ServiceError("Failed to refresh token", { - code: "FAILED_TO_REFRESH_TOKEN", - statusCode: 500, - details: { - description: "Failed to refresh token. Please re-authenticate.", - loginUrl: `${PYLON_URL}/oauth/google`, - provider: "GOOGLE", - }, - }); - } - } else if (this.provider === "AZURE") { - // Get token set from Azure - - if (this.accessTokenExpiresAt > new Date()) { - // Token is still valid - return this.$accessToken; - } - - try { - const { client } = await oidcAzure.getClient(organization); - - const tokenSet = await client.refresh(this.$refreshToken); - - await OAuthConfig.objects.update( - { - accessToken: tokenSet.access_token, - accessTokenExpiresAt: new Date(tokenSet.expires_at! * 1000), - }, - { - id: this.id, - } - ); - - return tokenSet.access_token!; - } catch (e) { - throw new ServiceError("Failed to refresh token", { - code: "FAILED_TO_REFRESH_TOKEN", - statusCode: 500, - details: { - description: "Failed to refresh token. Please re-authenticate.", - loginUrl: `${PYLON_URL}/oauth/azure`, - provider: "AZURE", - }, - }); - } - } - - throw new Error(`Provider ${this.provider} not supported`); - } -} diff --git a/src/repository/models/Organization.ts b/src/repository/models/Organization.ts deleted file mode 100644 index a26b814..0000000 --- a/src/repository/models/Organization.ts +++ /dev/null @@ -1,43 +0,0 @@ -import { ObjectManager } from "@getcronit/prisma-extended-models"; - -import { OrganizationRepository } from "../.generated"; -import { client } from "../client"; -import { requireAuth } from "@getcronit/pylon"; -import { $Enums } from "@prisma/client"; -import { Email } from "./Email"; -import { getUserFromCtx } from "../../helper/get-user-from-ctx"; - -export class Organization extends OrganizationRepository { - static objects = new ObjectManager<"Organization", typeof Organization>( - client.organization, - Organization - ); - - @requireAuth({ - roles: ["mailpress:admin"], - }) - static async setSenderEmail( - email: string, - smtpConfig?: { - host: string; - port: number; - secure: boolean; - username: string; - password: string; - } - ) { - const user = getUserFromCtx(); - - return await Email.objects.create({ - email, - smtpConfig: { - create: smtpConfig, - }, - organization: { - connect: { - id: user.$organizationId, - }, - }, - }); - } -} diff --git a/src/repository/models/SMTPConfig.ts b/src/repository/models/SMTPConfig.ts deleted file mode 100644 index db7fad9..0000000 --- a/src/repository/models/SMTPConfig.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { ObjectManager } from "@getcronit/prisma-extended-models"; - -import { client } from "../client"; -import { SMTPConfigRepository } from "../.generated"; -import { requireAuth } from "@getcronit/pylon"; - -export class SMTPConfig extends SMTPConfigRepository { - static objects = new ObjectManager<"SMTPConfig", typeof SMTPConfig>( - client.sMTPConfig, - SMTPConfig - ); - - // Custom logic here... -} diff --git a/src/repository/models/User.ts b/src/repository/models/User.ts deleted file mode 100644 index 81e29ef..0000000 --- a/src/repository/models/User.ts +++ /dev/null @@ -1,151 +0,0 @@ -import { ObjectManager } from "@getcronit/prisma-extended-models"; -import { getContext, requireAuth, ServiceError } from "@getcronit/pylon"; - -import { client } from "../client"; -import { UserRepository } from "../.generated"; -import { Email } from "./Email"; -import { encrypt } from "../../services/crypt"; -import { getUserFromCtx } from "../../helper/get-user-from-ctx"; -import { verifySMTP } from "../../services/mailer/smtp"; - -export class User extends UserRepository { - static objects = new ObjectManager<"User", typeof User>(client.user, User); - - // Custom logic here... - - @requireAuth({}) - static async me() { - const user = getUserFromCtx(); - return user; - } - - @requireAuth({}) - static async createEmail( - email: string, - smtpConfig?: { - host: string; - port: number; - secure: boolean; - username: string; - password: string; - } - ) { - if (smtpConfig) { - try { - await verifySMTP({ - host: smtpConfig.host, - port: smtpConfig.port, - secure: smtpConfig.secure, - user: smtpConfig.username, - password: smtpConfig.password, - }); - } catch (e) { - if (e instanceof Error) { - throw new ServiceError( - e.message, - { - code: "INVALID_SMTP_CONFIG", - statusCode: 400, - }, - e - ); - } - - throw e; - } - } - - const user = getUserFromCtx(); - - if (smtpConfig?.password) { - smtpConfig.password = encrypt(smtpConfig.password); - } - - return await Email.objects.upsert( - { - userId: user.id, - email: email, - smtpConfig: { - create: smtpConfig, - }, - }, - { - email: email, - smtpConfig: { - update: smtpConfig, - }, - }, - { - userId: user.id, - } - ); - } - - @requireAuth({}) - static async updateEmail( - id: string, - data: { - email?: string; - smtpConfig?: { - host?: string; - port?: number; - secure?: boolean; - username?: string; - password?: string; - }; - } - ) { - const user = getUserFromCtx(); - - if (data.smtpConfig?.password) { - data.smtpConfig.password = encrypt(data.smtpConfig.password); - } - - return await user.$emailUpdate( - { - email: data.email, - smtpConfig: { - update: data.smtpConfig, - }, - }, - { id } - ); - } - - @requireAuth({}) - static async deleteEmail(id: string) { - const user = getUserFromCtx(); - - return await user.$emailDelete({ id }); - } - - @requireAuth({}) - async $getAuthenticatedEmail() { - const ctx = getContext(); - - const baseUrl = process.env.AUTH_ISSUER; - - const res = await fetch(`${baseUrl}/auth/v1/users/me/email`, { - headers: { - Authorization: `Bearer ${ctx.req.header("authorization")}`, - }, - }); - - if (!res.ok) { - throw new Error("Failed to fetch user email"); - } - - const data = (await res.json()) as { - email: { - email: string; - isEmailVerified: boolean; - }; - }; - - if (!data.email.isEmailVerified) { - throw new Error("User email is not verified"); - } - - return data.email.email; - } -} diff --git a/src/repository/models/VariableDefinition.ts b/src/repository/models/VariableDefinition.ts deleted file mode 100644 index 4659ab2..0000000 --- a/src/repository/models/VariableDefinition.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { ObjectManager } from "@getcronit/prisma-extended-models"; - -import { client } from "../client"; -import { VariableDefinitionRepository } from "../.generated"; - -export class VariableDefinition extends VariableDefinitionRepository { - static objects = new ObjectManager< - "VariableDefinition", - typeof VariableDefinition - >(client.variableDefinition, VariableDefinition); - - // Custom logic here... -} diff --git a/src/services/mail-factory.ts b/src/services/mail-factory.ts index b2a7601..2c6679f 100644 --- a/src/services/mail-factory.ts +++ b/src/services/mail-factory.ts @@ -1,8 +1,6 @@ import { ServiceError, getContext, requireAuth } from "@getcronit/pylon"; import { htmlToText } from "html-to-text"; -import { Email } from "../repository/models/Email"; -import { EmailTemplate } from "../repository/models/EmailTemplate"; import { EmailTemplateFactory } from "../services/email-template-factory"; import { sendMail as sendMailAzure } from "../services/mailer/azure"; import { sendMail as sendMailGoogle } from "../services/mailer/google"; @@ -10,6 +8,7 @@ import { sendMail as sendMailSMTP } from "../services/mailer/smtp"; import { executeInSandbox } from "../services/transformer-sandbox"; import { decrypt } from "./crypt"; import { getUserFromCtx } from "../helper/get-user-from-ctx"; +import { client, Email } from "../client"; export class MailFactory { private static async send( @@ -123,7 +122,12 @@ export class MailFactory { [variableName: string]: any; } ) { - const emailTemplate = await EmailTemplate.objects.get({ id }); + console.log("Sending template mail", id, envelope, values); + const emailTemplate = await client.emailTemplate.findFirstOrThrow({ + where: { + id, + }, + }); const emailEnvelope = await emailTemplate.envelope(); @@ -144,7 +148,7 @@ export class MailFactory { const bodyHTML = EmailTemplateFactory.render( { content: emailTemplate?.content, - variables: Object.values(variables.nodes).reduce( + variables: Object.values(variables).reduce( (acc, variable) => ({ ...acc, [variable.name]: variable, @@ -205,20 +209,12 @@ export class MailFactory { } } - const senderEmail = await Email.objects.get({ - organization: { - users: { - some: { - id: emailTemplate.$creatorId, - }, - }, - }, - }); + const senderEmail = await emailTemplate.senderEmail(); MailFactory.send(senderEmail, combinedEnvelope, body, bodyHTML); // Call links - const links = (await emailTemplate.links()).nodes; + const links = await emailTemplate.links(); for (const link of links) { await MailFactory.sendTemplateMail(link.id, combinedEnvelope, values); diff --git a/src/services/mailer/smtp.ts b/src/services/mailer/smtp.ts index 475b37f..23ccf50 100644 --- a/src/services/mailer/smtp.ts +++ b/src/services/mailer/smtp.ts @@ -2,10 +2,11 @@ import * as nodemailer from "nodemailer"; import inlineBase64 from "nodemailer-plugin-inline-base64"; import { SentMessageInfo } from "nodemailer/lib/smtp-connection"; import { MailOptions } from "./types"; +import { Int } from "@getcronit/pylon"; export interface SMTPOptions { host: string; - port: number; + port: Int; secure: boolean; user: string; password: string; @@ -62,8 +63,8 @@ export async function sendMail( console.log(mailOptions); - if(mailOptions.html && !mailOptions.text){ - mailOptions.text = mailOptions.html + if (mailOptions.html && !mailOptions.text) { + mailOptions.text = mailOptions.html; } const mail = await connection.sendMail(mailOptions); diff --git a/src/services/oauth/azure.ts b/src/services/oauth/azure.ts index 328bfc3..6eb4c16 100644 --- a/src/services/oauth/azure.ts +++ b/src/services/oauth/azure.ts @@ -2,12 +2,16 @@ import { Handler } from "hono"; import { getSignedCookie, setSignedCookie } from "hono/cookie"; import { Issuer, generators } from "openid-client"; import { PYLON_SECRET, PYLON_URL } from "../../config"; -import { client as prisma } from "../../repository/client"; -import { Organization } from "../../repository/models/Organization"; -import { User } from "../../repository/models/User"; +import { client as prisma } from "../../client"; +import { ID } from "@getcronit/pylon"; -export const getClient = async (organization: Organization) => { - const app = await organization.oAuthApp({ type: "AZURE" }); +export const getClient = async (organizationId: ID) => { + const app = await prisma.oAuthApp.findFirstOrThrow({ + where: { + organizationId, + type: "GOOGLE", + }, + }); const issuer = await Issuer.discover( "https://login.microsoftonline.com/common/v2.0" @@ -15,7 +19,7 @@ export const getClient = async (organization: Organization) => { const client = new issuer.Client({ client_id: app.clientId, - client_secret: app.$clientSecret, + client_secret: app.clientSecret, redirect_uris: [`${PYLON_URL}/oauth/azure/callback`], response_types: ["code"], }); @@ -28,16 +32,12 @@ export const handler: Handler = async (c) => { const organizationId = _a["urn:zitadel:iam:user:resourceowner:id"] as string; - const user = await User.objects.upsert( - { + const user = await prisma.user.findFirstOrThrow({ + where: { id: _a.sub, organizationId, }, - {}, - { - id: _a.sub, - } - ); + }); // store the userId in your framework's session mechanism, if it is a cookie based solution // it should be httpOnly (not readable by javascript) and encrypted. @@ -83,7 +83,7 @@ export const handler: Handler = async (c) => { } ); - const { client } = await getClient(organization); + const { client } = await getClient(organization.id); const url = client.authorizationUrl({ scope: "openid email profile Mail.send offline_access", @@ -108,10 +108,12 @@ export const handlerCb: Handler = async (c) => { return new Response("Invalid state", { status: 400 }); } - const organization = await Organization.objects.get({ - users: { - some: { - id: sub, + const organization = await prisma.organization.findFirstOrThrow({ + where: { + users: { + some: { + id: sub, + }, }, }, }); @@ -122,7 +124,7 @@ export const handlerCb: Handler = async (c) => { "google-azure-redirect-url" ); - const { client } = await getClient(organization); + const { client } = await getClient(organization.id); const params = client.callbackParams(c.req.url); diff --git a/src/services/oauth/google.ts b/src/services/oauth/google.ts index 9aa5460..df06b68 100644 --- a/src/services/oauth/google.ts +++ b/src/services/oauth/google.ts @@ -1,21 +1,24 @@ import { Issuer, generators } from "openid-client"; import { Handler } from "hono"; import { setSignedCookie, getSignedCookie } from "hono/cookie"; -import { ServiceError, auth } from "@getcronit/pylon"; -import { client as prisma } from "../../repository/client"; +import { ID, ServiceError, auth } from "@getcronit/pylon"; +import { client as prisma } from "../../client"; import { PYLON_SECRET, PYLON_URL } from "../../config"; -import { Organization } from "../../repository/models/Organization"; -import { User } from "../../repository/models/User"; -export const getClient = async (organization: Organization) => { +export const getClient = async (organizationId: ID) => { try { - const app = await organization.oAuthApp({ type: "GOOGLE" }); + const app = await prisma.oAuthApp.findFirstOrThrow({ + where: { + organizationId, + type: "GOOGLE", + }, + }); const issuer = await Issuer.discover("https://accounts.google.com"); const client = new issuer.Client({ client_id: app.clientId, - client_secret: app.$clientSecret, + client_secret: app.clientSecret, redirect_uris: [`${PYLON_URL}/oauth/google/callback`], response_types: ["code"], }); @@ -52,16 +55,12 @@ export const handler: Handler = async (c) => { const organizationId = _a["urn:zitadel:iam:user:resourceowner:id"] as string; - const user = await User.objects.upsert( - { + const user = await prisma.user.findFirstOrThrow({ + where: { id: _a.sub, organizationId, }, - {}, - { - id: _a.sub, - } - ); + }); // store the userId in your framework's session mechanism, if it is a cookie based solution // it should be httpOnly (not readable by javascript) and encrypted. @@ -107,7 +106,7 @@ export const handler: Handler = async (c) => { } ); - const { client } = await getClient(organization); + const { client } = await getClient(organization.id); const url = client.authorizationUrl({ scope: "openid email profile https://www.googleapis.com/auth/gmail.send", @@ -132,10 +131,12 @@ export const handlerCb: Handler = async (c) => { return new Response("Invalid state", { status: 400 }); } - const organization = await Organization.objects.get({ - users: { - some: { - id: sub, + const organization = await prisma.organization.findFirstOrThrow({ + where: { + users: { + some: { + id: sub, + }, }, }, }); @@ -146,7 +147,7 @@ export const handlerCb: Handler = async (c) => { "google-oauth-redirect-url" ); - const { client } = await getClient(organization); + const { client } = await getClient(organization.id); const params = client.callbackParams(c.req.url); diff --git a/src/services/transformer-sandbox.ts b/src/services/transformer-sandbox.ts index 50bcc93..714e84e 100644 --- a/src/services/transformer-sandbox.ts +++ b/src/services/transformer-sandbox.ts @@ -1,6 +1,6 @@ // import ivm from "isolated-vm"; -import { EmailTemplate } from "../repository/models/EmailTemplate"; -import { EmailEnvelope } from "../repository/models/EmailEnvelope"; + +import { EmailTemplate } from "../client"; export interface SandboxTemplate { id: string; diff --git a/src/types.ts b/src/types.ts deleted file mode 100644 index 5596c21..0000000 --- a/src/types.ts +++ /dev/null @@ -1,20 +0,0 @@ -// type EmailOrUUID = string; - -// export interface EmailEnvelop { -// to?: EmailOrUUID; -// from?: EmailOrUUID; -// subject?: string; -// replyTo?: EmailOrUUID; -// fromIsPrimary?: boolean; -// toIsPrimary?: boolean; -// } - -// export interface EmailTemplate { -// id: string; -// values?: Values; -// envelop?: EmailEnvelop; -// } - -// interface Values { -// [variableName: string]: string; -// }