feat: favorites (#2103)

* feat: favorites and templates(ee)

* rename migrations

* fix sidebar

* cleanup tabs

* fix

* turn off templates

* cleanup

* uuid validation
This commit is contained in:
Philip Okugbe
2026-04-12 22:06:25 +01:00
committed by GitHub
parent 57efb91bd3
commit d42091ccb1
90 changed files with 4557 additions and 187 deletions

View File

@@ -54,4 +54,8 @@ export class UpdateWorkspaceDto extends PartialType(CreateWorkspaceDto) {
@IsInt()
@Min(1)
trashRetentionDays: number;
@IsOptional()
@IsBoolean()
allowMemberTemplates: boolean;
}

View File

@@ -42,6 +42,7 @@ import { isPageEmbeddingsTableExists } from '@docmost/db/helpers/helpers';
import { CursorPaginationResult } from '@docmost/db/pagination/cursor-pagination';
import { ShareRepo } from '@docmost/db/repos/share/share.repo';
import { WatcherRepo } from '@docmost/db/repos/watcher/watcher.repo';
import { FavoriteRepo } from '@docmost/db/repos/favorite/favorite.repo';
import { AuditEvent, AuditResource } from '../../../common/events/audit-events';
import {
AUDIT_SERVICE,
@@ -64,6 +65,7 @@ export class WorkspaceService {
private licenseCheckService: LicenseCheckService,
private shareRepo: ShareRepo,
private watcherRepo: WatcherRepo,
private favoriteRepo: FavoriteRepo,
@InjectKysely() private readonly db: KyselyDB,
@InjectQueue(QueueName.ATTACHMENT_QUEUE) private attachmentQueue: Queue,
@InjectQueue(QueueName.BILLING_QUEUE) private billingQueue: Queue,
@@ -328,7 +330,8 @@ export class WorkspaceService {
typeof updateWorkspaceDto.disablePublicSharing !== 'undefined' ||
typeof updateWorkspaceDto.trashRetentionDays !== 'undefined' ||
typeof updateWorkspaceDto.mcpEnabled !== 'undefined' ||
typeof updateWorkspaceDto.restrictApiToAdmins !== 'undefined'
typeof updateWorkspaceDto.restrictApiToAdmins !== 'undefined' ||
typeof updateWorkspaceDto.allowMemberTemplates !== 'undefined'
) {
const ws = await this.db
.selectFrom('workspaces')
@@ -351,7 +354,8 @@ export class WorkspaceService {
if (
typeof updateWorkspaceDto.disablePublicSharing !== 'undefined' ||
typeof updateWorkspaceDto.trashRetentionDays !== 'undefined' ||
typeof updateWorkspaceDto.restrictApiToAdmins !== 'undefined'
typeof updateWorkspaceDto.restrictApiToAdmins !== 'undefined' ||
typeof updateWorkspaceDto.allowMemberTemplates !== 'undefined'
) {
if (!this.licenseCheckService.hasFeature(ws.licenseKey, Feature.SECURITY_SETTINGS, ws.plan)) {
throw new ForbiddenException(
@@ -458,6 +462,20 @@ export class WorkspaceService {
);
}
if (typeof updateWorkspaceDto.allowMemberTemplates !== 'undefined') {
const prev = settingsBefore?.templates?.allowMemberTemplates ?? false;
if (prev !== updateWorkspaceDto.allowMemberTemplates) {
before.allowMemberTemplates = prev;
after.allowMemberTemplates = updateWorkspaceDto.allowMemberTemplates;
}
await this.workspaceRepo.updateTemplateSettings(
workspaceId,
'allowMemberTemplates',
updateWorkspaceDto.allowMemberTemplates,
trx,
);
}
if (typeof updateWorkspaceDto.aiChat !== 'undefined') {
const prev = settingsBefore?.ai?.chat ?? false;
if (prev !== updateWorkspaceDto.aiChat) {
@@ -477,6 +495,7 @@ export class WorkspaceService {
delete updateWorkspaceDto.generativeAi;
delete updateWorkspaceDto.disablePublicSharing;
delete updateWorkspaceDto.mcpEnabled;
delete updateWorkspaceDto.allowMemberTemplates;
delete updateWorkspaceDto.aiChat;
await this.workspaceRepo.updateWorkspace(
@@ -808,6 +827,10 @@ export class WorkspaceService {
trx,
});
await this.favoriteRepo.deleteByUserAndWorkspace(userId, workspaceId, {
trx,
});
await this.userSessionRepo.revokeByUserId(userId, workspaceId, trx);
});