From e1b799eac2378ed0002ba71b7b085ad56ab3ce69 Mon Sep 17 00:00:00 2001 From: nichenqin Date: Thu, 15 Aug 2024 22:46:58 +0800 Subject: [PATCH] fix: fix invitation --- apps/backend/drizzle/0002_fixed_lockjaw.sql | 2 + apps/backend/drizzle/meta/0002_snapshot.json | 1796 +++++++++++++++++ apps/backend/drizzle/meta/_journal.json | 7 + apps/backend/package.json | 2 + apps/backend/src/modules/mail/mail.ts | 39 +- bun.lockb | Bin 573880 -> 579072 bytes .../src/space-member/space-member.service.ts | 4 +- packages/env/src/index.ts | 3 + packages/persistence/src/tables.ts | 3 +- 9 files changed, 1842 insertions(+), 14 deletions(-) create mode 100644 apps/backend/drizzle/0002_fixed_lockjaw.sql create mode 100644 apps/backend/drizzle/meta/0002_snapshot.json diff --git a/apps/backend/drizzle/0002_fixed_lockjaw.sql b/apps/backend/drizzle/0002_fixed_lockjaw.sql new file mode 100644 index 000000000..a13a77fc1 --- /dev/null +++ b/apps/backend/drizzle/0002_fixed_lockjaw.sql @@ -0,0 +1,2 @@ +DROP INDEX IF EXISTS `undb_invitation_email_unique`;--> statement-breakpoint +CREATE UNIQUE INDEX `invitation_unique_idx` ON `undb_invitation` (`email`,`space_id`); \ No newline at end of file diff --git a/apps/backend/drizzle/meta/0002_snapshot.json b/apps/backend/drizzle/meta/0002_snapshot.json new file mode 100644 index 000000000..e53fcb061 --- /dev/null +++ b/apps/backend/drizzle/meta/0002_snapshot.json @@ -0,0 +1,1796 @@ +{ + "version": "6", + "dialect": "sqlite", + "id": "6f6c207c-336b-486f-8a37-c44c56a85fb6", + "prevId": "647dbce1-ba47-4cc7-bfdf-f950d08a3aba", + "tables": { + "undb_api_token": { + "name": "undb_api_token", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "space_id": { + "name": "space_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "token": { + "name": "token", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + } + }, + "indexes": { + "undb_api_token_user_id_unique": { + "name": "undb_api_token_user_id_unique", + "columns": [ + "user_id" + ], + "isUnique": true + }, + "undb_api_token_token_unique": { + "name": "undb_api_token_token_unique", + "columns": [ + "token" + ], + "isUnique": true + }, + "api_token_space_id_idx": { + "name": "api_token_space_id_idx", + "columns": [ + "space_id" + ], + "isUnique": false + }, + "api_token_user_id_idx": { + "name": "api_token_user_id_idx", + "columns": [ + "user_id" + ], + "isUnique": false + } + }, + "foreignKeys": { + "undb_api_token_user_id_undb_user_id_fk": { + "name": "undb_api_token_user_id_undb_user_id_fk", + "tableFrom": "undb_api_token", + "tableTo": "undb_user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + }, + "undb_api_token_space_id_undb_space_id_fk": { + "name": "undb_api_token_space_id_undb_space_id_fk", + "tableFrom": "undb_api_token", + "tableTo": "undb_space", + "columnsFrom": [ + "space_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "undb_attachment_mapping": { + "name": "undb_attachment_mapping", + "columns": { + "attachment_id": { + "name": "attachment_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "table_id": { + "name": "table_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "record_id": { + "name": "record_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "field_id": { + "name": "field_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + } + }, + "indexes": {}, + "foreignKeys": { + "undb_attachment_mapping_attachment_id_undb_attachment_id_fk": { + "name": "undb_attachment_mapping_attachment_id_undb_attachment_id_fk", + "tableFrom": "undb_attachment_mapping", + "tableTo": "undb_attachment", + "columnsFrom": [ + "attachment_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + }, + "undb_attachment_mapping_table_id_undb_table_id_fk": { + "name": "undb_attachment_mapping_table_id_undb_table_id_fk", + "tableFrom": "undb_attachment_mapping", + "tableTo": "undb_table", + "columnsFrom": [ + "table_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "undb_attachment_mapping_attachment_id_table_id_record_id_field_id_pk": { + "columns": [ + "attachment_id", + "table_id", + "record_id", + "field_id" + ], + "name": "undb_attachment_mapping_attachment_id_table_id_record_id_field_id_pk" + } + }, + "uniqueConstraints": {} + }, + "undb_attachment": { + "name": "undb_attachment", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "size": { + "name": "size", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "mime_type": { + "name": "mime_type", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "url": { + "name": "url", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "token": { + "name": "token", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "created_by": { + "name": "created_by", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "space_id": { + "name": "space_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + } + }, + "indexes": { + "attachment_size_idx": { + "name": "attachment_size_idx", + "columns": [ + "size" + ], + "isUnique": false + }, + "attachment_space_id_idx": { + "name": "attachment_space_id_idx", + "columns": [ + "space_id" + ], + "isUnique": false + } + }, + "foreignKeys": { + "undb_attachment_created_by_undb_user_id_fk": { + "name": "undb_attachment_created_by_undb_user_id_fk", + "tableFrom": "undb_attachment", + "tableTo": "undb_user", + "columnsFrom": [ + "created_by" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + }, + "undb_attachment_space_id_undb_space_id_fk": { + "name": "undb_attachment_space_id_undb_space_id_fk", + "tableFrom": "undb_attachment", + "tableTo": "undb_space", + "columnsFrom": [ + "space_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "undb_audit": { + "name": "undb_audit", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "timestamp": { + "name": "timestamp", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "detail": { + "name": "detail", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "meta": { + "name": "meta", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "op": { + "name": "op", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "table_id": { + "name": "table_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "record_id": { + "name": "record_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "operator_id": { + "name": "operator_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "space_id": { + "name": "space_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + } + }, + "indexes": { + "audit_table_id_idx": { + "name": "audit_table_id_idx", + "columns": [ + "table_id" + ], + "isUnique": false + }, + "audit_space_id_idx": { + "name": "audit_space_id_idx", + "columns": [ + "space_id" + ], + "isUnique": false + }, + "audit_record_id_idx": { + "name": "audit_record_id_idx", + "columns": [ + "record_id" + ], + "isUnique": false + } + }, + "foreignKeys": { + "undb_audit_space_id_undb_space_id_fk": { + "name": "undb_audit_space_id_undb_space_id_fk", + "tableFrom": "undb_audit", + "tableTo": "undb_space", + "columnsFrom": [ + "space_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "undb_base": { + "name": "undb_base", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "space_id": { + "name": "space_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(CURRENT_TIMESTAMP)" + }, + "created_by": { + "name": "created_by", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "updated_at": { + "name": "updated_at", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "updated_by": { + "name": "updated_by", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + } + }, + "indexes": { + "base_space_id_idx": { + "name": "base_space_id_idx", + "columns": [ + "space_id" + ], + "isUnique": false + }, + "base_name_unique_idx": { + "name": "base_name_unique_idx", + "columns": [ + "name", + "space_id" + ], + "isUnique": true + } + }, + "foreignKeys": { + "undb_base_space_id_undb_space_id_fk": { + "name": "undb_base_space_id_undb_space_id_fk", + "tableFrom": "undb_base", + "tableTo": "undb_space", + "columnsFrom": [ + "space_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + }, + "undb_base_created_by_undb_user_id_fk": { + "name": "undb_base_created_by_undb_user_id_fk", + "tableFrom": "undb_base", + "tableTo": "undb_user", + "columnsFrom": [ + "created_by" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + }, + "undb_base_updated_by_undb_user_id_fk": { + "name": "undb_base_updated_by_undb_user_id_fk", + "tableFrom": "undb_base", + "tableTo": "undb_user", + "columnsFrom": [ + "updated_by" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "undb_email_verification_code": { + "name": "undb_email_verification_code", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": true + }, + "code": { + "name": "code", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "email": { + "name": "email", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "expires_at": { + "name": "expires_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + } + }, + "indexes": { + "undb_email_verification_code_user_id_unique": { + "name": "undb_email_verification_code_user_id_unique", + "columns": [ + "user_id" + ], + "isUnique": true + } + }, + "foreignKeys": { + "undb_email_verification_code_user_id_undb_user_id_fk": { + "name": "undb_email_verification_code_user_id_undb_user_id_fk", + "tableFrom": "undb_email_verification_code", + "tableTo": "undb_user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "undb_invitation": { + "name": "undb_invitation", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "email": { + "name": "email", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "role": { + "name": "role", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "space_id": { + "name": "space_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "invited_at": { + "name": "invited_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "inviter_id": { + "name": "inviter_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + } + }, + "indexes": { + "invitation_space_id_idx": { + "name": "invitation_space_id_idx", + "columns": [ + "space_id" + ], + "isUnique": false + }, + "invitation_unique_idx": { + "name": "invitation_unique_idx", + "columns": [ + "email", + "space_id" + ], + "isUnique": true + } + }, + "foreignKeys": { + "undb_invitation_space_id_undb_space_id_fk": { + "name": "undb_invitation_space_id_undb_space_id_fk", + "tableFrom": "undb_invitation", + "tableTo": "undb_space", + "columnsFrom": [ + "space_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + }, + "undb_invitation_inviter_id_undb_user_id_fk": { + "name": "undb_invitation_inviter_id_undb_user_id_fk", + "tableFrom": "undb_invitation", + "tableTo": "undb_user", + "columnsFrom": [ + "inviter_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "undb_oauth_account": { + "name": "undb_oauth_account", + "columns": { + "provider_id": { + "name": "provider_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "provider_user_id": { + "name": "provider_user_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + } + }, + "indexes": {}, + "foreignKeys": { + "undb_oauth_account_user_id_undb_user_id_fk": { + "name": "undb_oauth_account_user_id_undb_user_id_fk", + "tableFrom": "undb_oauth_account", + "tableTo": "undb_user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "undb_oauth_account_provider_id_provider_user_id_pk": { + "columns": [ + "provider_id", + "provider_user_id" + ], + "name": "undb_oauth_account_provider_id_provider_user_id_pk" + } + }, + "uniqueConstraints": {} + }, + "undb_outbox": { + "name": "undb_outbox", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "payload": { + "name": "payload", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "meta": { + "name": "meta", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "timestamp": { + "name": "timestamp", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "operator_id": { + "name": "operator_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "space_id": { + "name": "space_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + } + }, + "indexes": { + "outbox_space_id_idx": { + "name": "outbox_space_id_idx", + "columns": [ + "space_id" + ], + "isUnique": false + } + }, + "foreignKeys": { + "undb_outbox_space_id_undb_space_id_fk": { + "name": "undb_outbox_space_id_undb_space_id_fk", + "tableFrom": "undb_outbox", + "tableTo": "undb_space", + "columnsFrom": [ + "space_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "undb_password_reset_token": { + "name": "undb_password_reset_token", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": true + }, + "token": { + "name": "token", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "expires_at": { + "name": "expires_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + } + }, + "indexes": { + "undb_password_reset_token_token_unique": { + "name": "undb_password_reset_token_token_unique", + "columns": [ + "token" + ], + "isUnique": true + }, + "password_reset_token_user_id_idx": { + "name": "password_reset_token_user_id_idx", + "columns": [ + "user_id" + ], + "isUnique": false + } + }, + "foreignKeys": { + "undb_password_reset_token_user_id_undb_user_id_fk": { + "name": "undb_password_reset_token_user_id_undb_user_id_fk", + "tableFrom": "undb_password_reset_token", + "tableTo": "undb_user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "undb_reference_id_mapping": { + "name": "undb_reference_id_mapping", + "columns": { + "field_id": { + "name": "field_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "table_id": { + "name": "table_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "symmetric_field_id": { + "name": "symmetric_field_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "foreign_table_id": { + "name": "foreign_table_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + } + }, + "indexes": { + "reference_id_mapping_unique_idx": { + "name": "reference_id_mapping_unique_idx", + "columns": [ + "field_id", + "table_id", + "symmetric_field_id", + "foreign_table_id" + ], + "isUnique": true + } + }, + "foreignKeys": { + "undb_reference_id_mapping_table_id_undb_table_id_fk": { + "name": "undb_reference_id_mapping_table_id_undb_table_id_fk", + "tableFrom": "undb_reference_id_mapping", + "tableTo": "undb_table", + "columnsFrom": [ + "table_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + }, + "undb_reference_id_mapping_foreign_table_id_undb_table_id_fk": { + "name": "undb_reference_id_mapping_foreign_table_id_undb_table_id_fk", + "tableFrom": "undb_reference_id_mapping", + "tableTo": "undb_table", + "columnsFrom": [ + "foreign_table_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "undb_rollup_id_mapping": { + "name": "undb_rollup_id_mapping", + "columns": { + "field_id": { + "name": "field_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "table_id": { + "name": "table_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "rollup_id": { + "name": "rollup_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "rollup_table_id": { + "name": "rollup_table_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + } + }, + "indexes": {}, + "foreignKeys": { + "undb_rollup_id_mapping_table_id_undb_table_id_fk": { + "name": "undb_rollup_id_mapping_table_id_undb_table_id_fk", + "tableFrom": "undb_rollup_id_mapping", + "tableTo": "undb_table", + "columnsFrom": [ + "table_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + }, + "undb_rollup_id_mapping_rollup_table_id_undb_table_id_fk": { + "name": "undb_rollup_id_mapping_rollup_table_id_undb_table_id_fk", + "tableFrom": "undb_rollup_id_mapping", + "tableTo": "undb_table", + "columnsFrom": [ + "rollup_table_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "undb_rollup_id_mapping_field_id_rollup_id_pk": { + "columns": [ + "field_id", + "rollup_id" + ], + "name": "undb_rollup_id_mapping_field_id_rollup_id_pk" + } + }, + "uniqueConstraints": {} + }, + "undb_session": { + "name": "undb_session", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "expires_at": { + "name": "expires_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "space_id": { + "name": "space_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + } + }, + "indexes": {}, + "foreignKeys": { + "undb_session_user_id_undb_user_id_fk": { + "name": "undb_session_user_id_undb_user_id_fk", + "tableFrom": "undb_session", + "tableTo": "undb_user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + }, + "undb_session_space_id_undb_space_id_fk": { + "name": "undb_session_space_id_undb_space_id_fk", + "tableFrom": "undb_session", + "tableTo": "undb_space", + "columnsFrom": [ + "space_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "undb_share": { + "name": "undb_share", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "target_type": { + "name": "target_type", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "target_id": { + "name": "target_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "enabled": { + "name": "enabled", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "space_id": { + "name": "space_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + } + }, + "indexes": { + "share_space_id_idx": { + "name": "share_space_id_idx", + "columns": [ + "space_id" + ], + "isUnique": false + }, + "share_unique_idx": { + "name": "share_unique_idx", + "columns": [ + "target_type", + "target_id" + ], + "isUnique": true + } + }, + "foreignKeys": { + "undb_share_space_id_undb_space_id_fk": { + "name": "undb_share_space_id_undb_space_id_fk", + "tableFrom": "undb_share", + "tableTo": "undb_space", + "columnsFrom": [ + "space_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "undb_space": { + "name": "undb_space", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "is_personal": { + "name": "is_personal", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "avatar": { + "name": "avatar", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(CURRENT_TIMESTAMP)" + }, + "created_by": { + "name": "created_by", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "updated_at": { + "name": "updated_at", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "updated_by": { + "name": "updated_by", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "deleted_at": { + "name": "deleted_at", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "deleted_by": { + "name": "deleted_by", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + } + }, + "indexes": { + "space_name_idx": { + "name": "space_name_idx", + "columns": [ + "name" + ], + "isUnique": false + } + }, + "foreignKeys": { + "undb_space_created_by_undb_user_id_fk": { + "name": "undb_space_created_by_undb_user_id_fk", + "tableFrom": "undb_space", + "tableTo": "undb_user", + "columnsFrom": [ + "created_by" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + }, + "undb_space_updated_by_undb_user_id_fk": { + "name": "undb_space_updated_by_undb_user_id_fk", + "tableFrom": "undb_space", + "tableTo": "undb_user", + "columnsFrom": [ + "updated_by" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + }, + "undb_space_deleted_by_undb_user_id_fk": { + "name": "undb_space_deleted_by_undb_user_id_fk", + "tableFrom": "undb_space", + "tableTo": "undb_user", + "columnsFrom": [ + "deleted_by" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "undb_space_member": { + "name": "undb_space_member", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "role": { + "name": "role", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "space_id": { + "name": "space_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + } + }, + "indexes": { + "space_member_unique_idx": { + "name": "space_member_unique_idx", + "columns": [ + "user_id", + "space_id" + ], + "isUnique": true + } + }, + "foreignKeys": { + "undb_space_member_user_id_undb_user_id_fk": { + "name": "undb_space_member_user_id_undb_user_id_fk", + "tableFrom": "undb_space_member", + "tableTo": "undb_user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + }, + "undb_space_member_space_id_undb_space_id_fk": { + "name": "undb_space_member_space_id_undb_space_id_fk", + "tableFrom": "undb_space_member", + "tableTo": "undb_space", + "columnsFrom": [ + "space_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "undb_table_id_mapping": { + "name": "undb_table_id_mapping", + "columns": { + "table_id": { + "name": "table_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "subject_id": { + "name": "subject_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + } + }, + "indexes": {}, + "foreignKeys": { + "undb_table_id_mapping_table_id_undb_table_id_fk": { + "name": "undb_table_id_mapping_table_id_undb_table_id_fk", + "tableFrom": "undb_table_id_mapping", + "tableTo": "undb_table", + "columnsFrom": [ + "table_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "undb_table_id_mapping_table_id_subject_id_pk": { + "columns": [ + "table_id", + "subject_id" + ], + "name": "undb_table_id_mapping_table_id_subject_id_pk" + } + }, + "uniqueConstraints": {} + }, + "undb_table": { + "name": "undb_table", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "base_id": { + "name": "base_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "space_id": { + "name": "space_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "schema": { + "name": "schema", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "views": { + "name": "views", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "forms": { + "name": "forms", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "rls": { + "name": "rls", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(CURRENT_TIMESTAMP)" + }, + "created_by": { + "name": "created_by", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "updated_at": { + "name": "updated_at", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "updated_by": { + "name": "updated_by", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + } + }, + "indexes": { + "table_base_id_idx": { + "name": "table_base_id_idx", + "columns": [ + "base_id" + ], + "isUnique": false + }, + "table_space_id_idx": { + "name": "table_space_id_idx", + "columns": [ + "space_id" + ], + "isUnique": false + }, + "table_name_unique_idx": { + "name": "table_name_unique_idx", + "columns": [ + "name", + "base_id" + ], + "isUnique": true + } + }, + "foreignKeys": { + "undb_table_base_id_undb_base_id_fk": { + "name": "undb_table_base_id_undb_base_id_fk", + "tableFrom": "undb_table", + "tableTo": "undb_base", + "columnsFrom": [ + "base_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + }, + "undb_table_space_id_undb_space_id_fk": { + "name": "undb_table_space_id_undb_space_id_fk", + "tableFrom": "undb_table", + "tableTo": "undb_space", + "columnsFrom": [ + "space_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + }, + "undb_table_created_by_undb_user_id_fk": { + "name": "undb_table_created_by_undb_user_id_fk", + "tableFrom": "undb_table", + "tableTo": "undb_user", + "columnsFrom": [ + "created_by" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + }, + "undb_table_updated_by_undb_user_id_fk": { + "name": "undb_table_updated_by_undb_user_id_fk", + "tableFrom": "undb_table", + "tableTo": "undb_user", + "columnsFrom": [ + "updated_by" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "undb_user": { + "name": "undb_user", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "username": { + "name": "username", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "email": { + "name": "email", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "email_verified": { + "name": "email_verified", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": false + }, + "password": { + "name": "password", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "avatar": { + "name": "avatar", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + } + }, + "indexes": { + "undb_user_email_unique": { + "name": "undb_user_email_unique", + "columns": [ + "email" + ], + "isUnique": true + }, + "user_username_idx": { + "name": "user_username_idx", + "columns": [ + "username" + ], + "isUnique": false + }, + "user_email_idx": { + "name": "user_email_idx", + "columns": [ + "email" + ], + "isUnique": false + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "undb_webhook": { + "name": "undb_webhook", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "url": { + "name": "url", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "method": { + "name": "method", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "enabled": { + "name": "enabled", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "table_id": { + "name": "table_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "headers": { + "name": "headers", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "condition": { + "name": "condition", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "event": { + "name": "event", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "space_id": { + "name": "space_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + } + }, + "indexes": { + "webhook_table_id_idx": { + "name": "webhook_table_id_idx", + "columns": [ + "table_id" + ], + "isUnique": false + }, + "webhook_space_id_idx": { + "name": "webhook_space_id_idx", + "columns": [ + "space_id" + ], + "isUnique": false + }, + "webhook_url_idx": { + "name": "webhook_url_idx", + "columns": [ + "url" + ], + "isUnique": false + } + }, + "foreignKeys": { + "undb_webhook_table_id_undb_table_id_fk": { + "name": "undb_webhook_table_id_undb_table_id_fk", + "tableFrom": "undb_webhook", + "tableTo": "undb_table", + "columnsFrom": [ + "table_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + }, + "undb_webhook_space_id_undb_space_id_fk": { + "name": "undb_webhook_space_id_undb_space_id_fk", + "tableFrom": "undb_webhook", + "tableTo": "undb_space", + "columnsFrom": [ + "space_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "no action", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + } + }, + "enums": {}, + "_meta": { + "schemas": {}, + "tables": {}, + "columns": {} + }, + "internal": { + "indexes": {} + } +} \ No newline at end of file diff --git a/apps/backend/drizzle/meta/_journal.json b/apps/backend/drizzle/meta/_journal.json index edc7e63f5..9de325ad8 100644 --- a/apps/backend/drizzle/meta/_journal.json +++ b/apps/backend/drizzle/meta/_journal.json @@ -15,6 +15,13 @@ "when": 1723706193281, "tag": "0001_familiar_joshua_kane", "breakpoints": true + }, + { + "idx": 2, + "version": "6", + "when": 1723731591583, + "tag": "0002_fixed_lockjaw", + "breakpoints": true } ] } \ No newline at end of file diff --git a/apps/backend/package.json b/apps/backend/package.json index b1cdc9a1d..2e85f4ced 100644 --- a/apps/backend/package.json +++ b/apps/backend/package.json @@ -48,6 +48,7 @@ "minio": "^8.0.1", "nanoid": "^5.0.7", "nodemailer": "^6.9.14", + "nodemailer-mailgun-transport": "^2.1.5", "oslo": "^1.2.1", "radash": "^12.1.0", "reflect-metadata": "^0.2.2", @@ -56,6 +57,7 @@ }, "devDependencies": { "@types/nodemailer": "^6.4.15", + "@types/nodemailer-mailgun-transport": "^1.4.6", "@types/uuid": "^10.0.0", "bun-types": "latest", "kysely": "^0.27.4" diff --git a/apps/backend/src/modules/mail/mail.ts b/apps/backend/src/modules/mail/mail.ts index d709c6d0d..5dc63956a 100644 --- a/apps/backend/src/modules/mail/mail.ts +++ b/apps/backend/src/modules/mail/mail.ts @@ -3,19 +3,35 @@ import { env } from "@undb/env" import { createLogger } from "@undb/logger" import { IMailService, ISendInput } from "@undb/mail" import { createTransport } from "nodemailer" +import mg from "nodemailer-mailgun-transport" +import SMTPConnection from "nodemailer/lib/smtp-connection" import { compile } from "./templates/compile" function createMailerTransport() { - return createTransport({ - host: env.UNDB_MAIL_HOST, - port: env.UNDB_MAIL_PORT ? parseInt(env.UNDB_MAIL_PORT, 10) : undefined, - secure: env.UNDB_MAIL_SECURE, - auth: { - user: env.UNDB_MAIL_USER, - pass: env.UNDB_MAIL_PASS, - }, - debug: Bun.env.NODE_ENV !== "production", - }) + if (env.UNDB_MAIL_PROVIDER === "nodemailer" || !env.UNDB_MAIL_PROVIDER) { + const options: SMTPConnection.Options = { + host: env.UNDB_MAIL_HOST, + port: 465, + // port: env.UNDB_MAIL_PORT ? parseInt(env.UNDB_MAIL_PORT, 10) : undefined, + secure: env.UNDB_MAIL_SECURE, + auth: { + user: env.UNDB_MAIL_USER, + pass: env.UNDB_MAIL_PASS, + }, + debug: Bun.env.NODE_ENV !== "production", + } + + return createTransport(options) + } + + return createTransport( + mg({ + auth: { + api_key: env.UNDB_MAILGUN_API_KEY!, + domain: env.UNDB_MAILGUN_DOMAIN!, + }, + }), + ) } @singleton() @@ -24,11 +40,12 @@ export class NodemailerService implements IMailService { private readonly transport = createMailerTransport() async send(input: ISendInput): Promise { + const html = await compile(input.template, input.data) await this.transport.sendMail({ from: input.from || env.UNDB_MAIL_DEFAULT_FROM, to: input.to, subject: input.subject, - html: await compile(input.template, input.data), + html, }) } } diff --git a/bun.lockb b/bun.lockb index 24549dce61bfcdf5fae909e56901ba548afc8381..2dcc5e87568e4660ae40b30f2de93b7b2e98db8c 100755 GIT binary patch delta 37797 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 delta 34890 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 diff --git a/packages/authz/src/space-member/space-member.service.ts b/packages/authz/src/space-member/space-member.service.ts index 5fbde171b..050cac7b6 100644 --- a/packages/authz/src/space-member/space-member.service.ts +++ b/packages/authz/src/space-member/space-member.service.ts @@ -12,7 +12,7 @@ import { type IInvitationRepository, } from "./invitation.repository" import { InvitationMailService, type IInvitationMailService } from "./invitation.service" -import { WithEmail, WithInvitedAt, WithRole, WithStatus } from "./invitation.specification" +import { WithEmail, WithInvitedAt, WithRole, WithSpaceId, WithStatus } from "./invitation.specification" import { SpaceMember, type ISpaceMemberRole } from "./space-member" import type { SpaceMemberComositeSpecification } from "./space-member.composite-specification" import { injectSpaceMemberRepository, type ISpaceMemberRepository } from "./space-member.repository" @@ -75,7 +75,7 @@ export class SpaceMemberService implements ISpaceMemberService { throw new Error("Cannot invite to personal space") } - const spec = new WithEmail(dto.email) + const spec = new WithEmail(dto.email).and(new WithSpaceId(space.unwrap().id.value)) const existInvitation = await this.invitationQueryRepository.findOne(spec) if (existInvitation.isSome()) { const invitation = existInvitation.unwrap() diff --git a/packages/env/src/index.ts b/packages/env/src/index.ts index a88fcc01b..d2bca181b 100644 --- a/packages/env/src/index.ts +++ b/packages/env/src/index.ts @@ -68,6 +68,7 @@ const storageEnv = createEnv({ const emailEnv = createEnv({ server: { + UNDB_MAIL_PROVIDER: z.enum(["nodemailer", "mailgun"]).default("nodemailer").optional(), UNDB_MAIL_HOST: z.string().optional(), UNDB_MAIL_PORT: z.string().optional(), UNDB_MAIL_DEFAULT_FROM: z.string().optional(), @@ -88,6 +89,8 @@ const emailEnv = createEnv({ message: "UNDB_VERIFY_EMAIL must be a boolean", }) .transform((v) => v === "true"), + UNDB_MAILGUN_API_KEY: z.string().optional(), + UNDB_MAILGUN_DOMAIN: z.string().optional(), }, runtimeEnv: import.meta.env, emptyStringAsUndefined: true, diff --git a/packages/persistence/src/tables.ts b/packages/persistence/src/tables.ts index 9c742fa12..5e83cd87e 100644 --- a/packages/persistence/src/tables.ts +++ b/packages/persistence/src/tables.ts @@ -390,7 +390,7 @@ export const invitations = sqliteTable( "invitation", { id: text("id").notNull().primaryKey(), - email: text("email").notNull().unique(), + email: text("email").notNull(), role: text("role").notNull().$type(), status: text("status").notNull().$type(), spaceId: text("space_id") @@ -404,6 +404,7 @@ export const invitations = sqliteTable( (table) => { return { spaceIdIdx: index("invitation_space_id_idx").on(table.spaceId), + uniqueIdx: unique("invitation_unique_idx").on(table.email, table.spaceId), } }, )