diff --git a/apps/backend/src/migrations/0025-add-internal-projects-fields.ts b/apps/backend/src/migrations/0025-add-internal-projects-fields.ts new file mode 100644 index 00000000..5580dc03 --- /dev/null +++ b/apps/backend/src/migrations/0025-add-internal-projects-fields.ts @@ -0,0 +1,31 @@ +import type { Kysely } from 'kysely'; + +export async function up(db: Kysely): Promise { + await db.schema + .alterTable('projects_files') + .addColumn('message_id', 'uuid', col => col.references('messages.id').onDelete('restrict')) + .execute(); + + await db.schema + .createIndex('projects_files_message_id_index') + .on('projects_files') + .column('message_id') + .execute(); + + await db.schema + .alterTable('projects') + .addColumn('internal', 'boolean', col => col.notNull().defaultTo(false)) + .execute(); +} + +export async function down(db: Kysely): Promise { + await db.schema + .alterTable('projects') + .dropColumn('internal') + .execute(); + + await db.schema + .alterTable('projects_files') + .dropColumn('message_id') + .execute(); +} diff --git a/apps/backend/src/migrations/index.ts b/apps/backend/src/migrations/index.ts index 68b07027..c2071745 100644 --- a/apps/backend/src/migrations/index.ts +++ b/apps/backend/src/migrations/index.ts @@ -23,6 +23,7 @@ import * as dropUniqueNameFromS3Assets from './0021-drop-unique-name-from-s3-ass import * as addIdToProjectFilesTable from './0022-add-id-to-project-files-table'; import * as addProjectsEmbeddingsTable from './0023-add-projects-embeddings-table'; import * as dropUnusedImagesTable from './0024-drop-unused-images-table'; +import * as addInternalProjectsFields from './0025-add-internal-projects-fields'; export const DB_MIGRATIONS = { '0000-add-users-tables': addUsersTables, @@ -50,4 +51,5 @@ export const DB_MIGRATIONS = { '0022-add-id-to-project-files-table': addIdToProjectFilesTable, '0023-add-projects-embeddings-table': addProjectsEmbeddingsTable, '0024-drop-unused-images-table': dropUnusedImagesTable, + '0025-add-internal-projects-fields': addInternalProjectsFields, }; diff --git a/apps/backend/src/modules/projects-files/projects-files.repo.ts b/apps/backend/src/modules/projects-files/projects-files.repo.ts index 789e4dd0..2044bcbc 100644 --- a/apps/backend/src/modules/projects-files/projects-files.repo.ts +++ b/apps/backend/src/modules/projects-files/projects-files.repo.ts @@ -97,6 +97,8 @@ export class ProjectsFilesRepo extends createDatabaseRepo('projects_files') { s3_resource_created_at: s3ResourceCreatedAt, s3_resource_updated_at: s3ResourceUpdatedAt, + message_id: messageId, + ...item }): ProjectFileTableRowWithRelations => ({ ...camelcaseKeys(item), @@ -114,11 +116,15 @@ export class ProjectsFilesRepo extends createDatabaseRepo('projects_files') { name: bucketName, }, }, - project: { id: projectId, name: projectName, }, + message: messageId + ? { + id: messageId, + } + : null, })), ), ); diff --git a/apps/backend/src/modules/projects-files/projects-files.tables.ts b/apps/backend/src/modules/projects-files/projects-files.tables.ts index 167ffcae..c9799eb5 100644 --- a/apps/backend/src/modules/projects-files/projects-files.tables.ts +++ b/apps/backend/src/modules/projects-files/projects-files.tables.ts @@ -5,6 +5,8 @@ import type { NormalizeSelectTableRow, TableId, TableRowWithIdName, + TableRowWithUuid, + TableUuid, TableWithDefaultColumns, } from '../database'; import type { S3ResourcesTableRowWithRelations } from '../s3'; @@ -14,6 +16,7 @@ export type ProjectsFilesTable = & { project_id: ColumnType; s3_resource_id: ColumnType; + message_id: ColumnType; }; export type ProjectFileTableRow = NormalizeSelectTableRow; @@ -21,9 +24,10 @@ export type ProjectFileTableRow = NormalizeSelectTableRow; export type ProjectFileTableInsertRow = NormalizeInsertTableRow; export type ProjectFileTableRowWithRelations = - & Omit + & Omit & { resource: S3ResourcesTableRowWithRelations; project: TableRowWithIdName; + message: TableRowWithUuid | null; description: string | null; }; diff --git a/apps/backend/src/modules/projects/elasticsearch/projects-es-index.repo.ts b/apps/backend/src/modules/projects/elasticsearch/projects-es-index.repo.ts index 0c99438c..17f7e068 100644 --- a/apps/backend/src/modules/projects/elasticsearch/projects-es-index.repo.ts +++ b/apps/backend/src/modules/projects/elasticsearch/projects-es-index.repo.ts @@ -29,6 +29,9 @@ const ProjectsAbstractEsIndexRepo = createElasticsearchIndexRepo({ ...createBaseAutocompleteFieldMappings(), ...createArchivedRecordMappings(), organization: createIdNameObjectMapping(), + internal: { + type: 'keyword', + }, description: { type: 'text', analyzer: 'folded_lowercase_analyzer', diff --git a/apps/backend/src/modules/projects/elasticsearch/projects-es-search.repo.ts b/apps/backend/src/modules/projects/elasticsearch/projects-es-search.repo.ts index 89d29821..591f6825 100644 --- a/apps/backend/src/modules/projects/elasticsearch/projects-es-search.repo.ts +++ b/apps/backend/src/modules/projects/elasticsearch/projects-es-search.repo.ts @@ -20,6 +20,10 @@ import { ProjectsEsIndexRepo, } from './projects-es-index.repo'; +type InternalSearchProjectsInputT = SdKSearchProjectsInputT & { + excludeInternal?: boolean; +}; + @injectable() export class ProjectsEsSearchRepo { constructor( @@ -31,7 +35,7 @@ export class ProjectsEsSearchRepo { TE.map(ProjectsEsSearchRepo.mapOutputHit), ); - search = (dto: SdKSearchProjectsInputT) => + search = (dto: InternalSearchProjectsInputT) => pipe( this.indexRepo.search( ProjectsEsSearchRepo.createEsRequestSearchBody(dto).toJSON(), @@ -53,11 +57,12 @@ export class ProjectsEsSearchRepo { private static createEsRequestSearchFilters = ( { + excludeInternal = true, phrase, ids, organizationIds, archived, - }: SdKSearchProjectsInputT, + }: InternalSearchProjectsInputT, ): esb.Query => esb.boolQuery().must( rejectFalsyItems([ @@ -73,6 +78,7 @@ export class ProjectsEsSearchRepo { .minimumShouldMatch(1) ), !isNil(archived) && esb.termQuery('archived', archived), + excludeInternal && esb.termQuery('internal', false), ]), ); diff --git a/apps/backend/src/modules/projects/projects.service.ts b/apps/backend/src/modules/projects/projects.service.ts index 6d4d15c9..84742da4 100644 --- a/apps/backend/src/modules/projects/projects.service.ts +++ b/apps/backend/src/modules/projects/projects.service.ts @@ -76,10 +76,11 @@ export class ProjectsService implements WithAuthFirewall { search = this.esSearchRepo.search; - create = ({ organization, ...values }: SdkCreateProjectInputT) => pipe( + create = ({ internal, organization, ...values }: SdkCreateProjectInputT & { internal?: boolean; }) => pipe( this.repo.create({ value: { ...values, + internal: !!internal, organizationId: organization.id, }, }), diff --git a/apps/backend/src/modules/projects/projects.tables.ts b/apps/backend/src/modules/projects/projects.tables.ts index e7e4d1d9..38042cc5 100644 --- a/apps/backend/src/modules/projects/projects.tables.ts +++ b/apps/backend/src/modules/projects/projects.tables.ts @@ -15,6 +15,7 @@ export type ProjectsTable = organization_id: ColumnType; name: string; description: string | null; + internal: boolean; }; export type ProjectTableRow = NormalizeSelectTableRow;