diff --git a/packages/backend/server/src/app.module.ts b/packages/backend/server/src/app.module.ts index 1b3154b5fd..7c00ab56c5 100644 --- a/packages/backend/server/src/app.module.ts +++ b/packages/backend/server/src/app.module.ts @@ -12,6 +12,7 @@ import { AuthModule } from './core/auth'; import { ADD_ENABLED_FEATURES, ServerConfigModule } from './core/config'; import { DocModule } from './core/doc'; import { FeatureModule } from './core/features'; +import { PermissionModule } from './core/permission'; import { QuotaModule } from './core/quota'; import { SelfhostModule } from './core/selfhost'; import { StorageModule } from './core/storage'; @@ -41,7 +42,6 @@ import { ENABLED_PLUGINS } from './plugins/registry'; export const FunctionalityModules = [ ConfigModule.forRoot(), - ScheduleModule.forRoot(), EventModule, CacheModule, MutexModule, @@ -147,12 +147,12 @@ export function buildAppModule() { const factor = new AppModuleBuilder(AFFiNE); factor - // common fundamental modules + // basic .use(...FunctionalityModules) .useIf(config => config.flavor.sync, WebSocketModule) // auth - .use(UserModule, AuthModule) + .use(UserModule, AuthModule, PermissionModule) // business modules .use(DocModule) @@ -163,9 +163,10 @@ export function buildAppModule() { // graphql server only .useIf( config => config.flavor.graphql, - ServerConfigModule, + ScheduleModule.forRoot(), GqlModule, StorageModule, + ServerConfigModule, WorkspaceModule, FeatureModule, QuotaModule diff --git a/packages/backend/server/src/core/doc/history.ts b/packages/backend/server/src/core/doc/history.ts index a4471440d0..d0ba7cedc8 100644 --- a/packages/backend/server/src/core/doc/history.ts +++ b/packages/backend/server/src/core/doc/history.ts @@ -11,10 +11,9 @@ import { DocNotFound, metrics, OnEvent, - WorkspaceNotFound, } from '../../fundamentals'; +import { PermissionService } from '../permission'; import { QuotaService } from '../quota'; -import { Permission } from '../workspaces/types'; import { isEmptyBuffer } from './manager'; @Injectable() @@ -23,7 +22,8 @@ export class DocHistoryManager { constructor( private readonly config: Config, private readonly db: PrismaClient, - private readonly quota: QuotaService + private readonly quota: QuotaService, + private readonly permission: PermissionService ) {} @OnEvent('workspace.deleted') @@ -235,21 +235,8 @@ export class DocHistoryManager { } async getExpiredDateFromNow(workspaceId: string) { - const permission = await this.db.workspaceUserPermission.findFirst({ - select: { - userId: true, - }, - where: { - workspaceId, - type: Permission.Owner, - }, - }); - - if (!permission) { - throw new WorkspaceNotFound({ workspaceId }); - } - - const quota = await this.quota.getUserQuota(permission.userId); + const owner = await this.permission.getWorkspaceOwner(workspaceId); + const quota = await this.quota.getUserQuota(owner.id); return quota.feature.historyPeriodFromNow; } diff --git a/packages/backend/server/src/core/doc/index.ts b/packages/backend/server/src/core/doc/index.ts index 0fe915483d..5c9720c070 100644 --- a/packages/backend/server/src/core/doc/index.ts +++ b/packages/backend/server/src/core/doc/index.ts @@ -2,12 +2,13 @@ import './config'; import { Module } from '@nestjs/common'; +import { PermissionModule } from '../permission'; import { QuotaModule } from '../quota'; import { DocHistoryManager } from './history'; import { DocManager } from './manager'; @Module({ - imports: [QuotaModule], + imports: [QuotaModule, PermissionModule], providers: [DocManager, DocHistoryManager], exports: [DocManager, DocHistoryManager], }) diff --git a/packages/backend/server/src/core/permission/index.ts b/packages/backend/server/src/core/permission/index.ts new file mode 100644 index 0000000000..01f47d7c33 --- /dev/null +++ b/packages/backend/server/src/core/permission/index.ts @@ -0,0 +1,12 @@ +import { Module } from '@nestjs/common'; + +import { PermissionService } from './service'; + +@Module({ + providers: [PermissionService], + exports: [PermissionService], +}) +export class PermissionModule {} + +export { PermissionService } from './service'; +export { Permission, PublicPageMode } from './types'; diff --git a/packages/backend/server/src/core/workspaces/permission.ts b/packages/backend/server/src/core/permission/service.ts similarity index 95% rename from packages/backend/server/src/core/workspaces/permission.ts rename to packages/backend/server/src/core/permission/service.ts index 4fe95e2c1f..31cb7c324e 100644 --- a/packages/backend/server/src/core/workspaces/permission.ts +++ b/packages/backend/server/src/core/permission/service.ts @@ -2,13 +2,12 @@ import { Injectable } from '@nestjs/common'; import type { Prisma } from '@prisma/client'; import { PrismaClient } from '@prisma/client'; -import { DocAccessDenied, WorkspaceAccessDenied } from '../../fundamentals'; -import { Permission } from './types'; - -export enum PublicPageMode { - Page, - Edgeless, -} +import { + DocAccessDenied, + WorkspaceAccessDenied, + WorkspaceOwnerNotFound, +} from '../../fundamentals'; +import { Permission, PublicPageMode } from './types'; @Injectable() export class PermissionService { @@ -59,7 +58,7 @@ export class PermissionService { } async getWorkspaceOwner(workspaceId: string) { - return this.prisma.workspaceUserPermission.findFirstOrThrow({ + const owner = await this.prisma.workspaceUserPermission.findFirst({ where: { workspaceId, type: Permission.Owner, @@ -68,6 +67,12 @@ export class PermissionService { user: true, }, }); + + if (!owner) { + throw new WorkspaceOwnerNotFound({ workspaceId }); + } + + return owner.user; } async tryGetWorkspaceOwner(workspaceId: string) { @@ -195,6 +200,17 @@ export class PermissionService { return false; } + async allowUrlPreview(ws: string) { + const count = await this.prisma.workspace.count({ + where: { + id: ws, + public: true, + }, + }); + + return count > 0; + } + async grant( ws: string, user: string, diff --git a/packages/backend/server/src/core/permission/types.ts b/packages/backend/server/src/core/permission/types.ts new file mode 100644 index 0000000000..05ec00c2b5 --- /dev/null +++ b/packages/backend/server/src/core/permission/types.ts @@ -0,0 +1,11 @@ +export enum Permission { + Read = 0, + Write = 1, + Admin = 10, + Owner = 99, +} + +export enum PublicPageMode { + Page, + Edgeless, +} diff --git a/packages/backend/server/src/core/quota/index.ts b/packages/backend/server/src/core/quota/index.ts index 80b28f6d80..1cf61cf5df 100644 --- a/packages/backend/server/src/core/quota/index.ts +++ b/packages/backend/server/src/core/quota/index.ts @@ -1,8 +1,8 @@ import { Module } from '@nestjs/common'; import { FeatureModule } from '../features'; +import { PermissionModule } from '../permission'; import { StorageModule } from '../storage'; -import { PermissionService } from '../workspaces/permission'; import { QuotaManagementResolver } from './resolver'; import { QuotaService } from './service'; import { QuotaManagementService } from './storage'; @@ -14,13 +14,8 @@ import { QuotaManagementService } from './storage'; * - quota statistics */ @Module({ - imports: [FeatureModule, StorageModule], - providers: [ - PermissionService, - QuotaService, - QuotaManagementResolver, - QuotaManagementService, - ], + imports: [FeatureModule, StorageModule, PermissionModule], + providers: [QuotaService, QuotaManagementResolver, QuotaManagementService], exports: [QuotaService, QuotaManagementService], }) export class QuotaModule {} diff --git a/packages/backend/server/src/core/quota/storage.ts b/packages/backend/server/src/core/quota/storage.ts index 7a42f754ef..18a3c9a1c6 100644 --- a/packages/backend/server/src/core/quota/storage.ts +++ b/packages/backend/server/src/core/quota/storage.ts @@ -1,9 +1,8 @@ import { Injectable, Logger } from '@nestjs/common'; -import { WorkspaceOwnerNotFound } from '../../fundamentals'; import { FeatureService, FeatureType } from '../features'; +import { PermissionService } from '../permission'; import { WorkspaceBlobStorage } from '../storage'; -import { PermissionService } from '../workspaces/permission'; import { OneGB } from './constant'; import { QuotaService } from './service'; import { formatSize, QuotaQueryType } from './types'; @@ -113,9 +112,7 @@ export class QuotaManagementService { // get workspace's owner quota and total size of used // quota was apply to owner's account async getWorkspaceUsage(workspaceId: string): Promise { - const { user: owner } = - await this.permissions.getWorkspaceOwner(workspaceId); - if (!owner) throw new WorkspaceOwnerNotFound({ workspaceId }); + const owner = await this.permissions.getWorkspaceOwner(workspaceId); const { feature: { name, diff --git a/packages/backend/server/src/core/sync/events/events.gateway.ts b/packages/backend/server/src/core/sync/events/events.gateway.ts index 73aa53e372..fab58df40b 100644 --- a/packages/backend/server/src/core/sync/events/events.gateway.ts +++ b/packages/backend/server/src/core/sync/events/events.gateway.ts @@ -23,9 +23,8 @@ import { } from '../../../fundamentals'; import { Auth, CurrentUser } from '../../auth'; import { DocManager } from '../../doc'; +import { Permission, PermissionService } from '../../permission'; import { DocID } from '../../utils/doc'; -import { PermissionService } from '../../workspaces/permission'; -import { Permission } from '../../workspaces/types'; const SubscribeMessage = (event: string) => applyDecorators( diff --git a/packages/backend/server/src/core/sync/events/events.module.ts b/packages/backend/server/src/core/sync/events/events.module.ts index 82681955ce..ca2eaa888e 100644 --- a/packages/backend/server/src/core/sync/events/events.module.ts +++ b/packages/backend/server/src/core/sync/events/events.module.ts @@ -1,11 +1,11 @@ import { Module } from '@nestjs/common'; import { DocModule } from '../../doc'; -import { PermissionService } from '../../workspaces/permission'; +import { PermissionModule } from '../../permission'; import { EventsGateway } from './events.gateway'; @Module({ - imports: [DocModule], - providers: [EventsGateway, PermissionService], + imports: [DocModule, PermissionModule], + providers: [EventsGateway], }) export class EventsModule {} diff --git a/packages/backend/server/src/core/workspaces/controller.ts b/packages/backend/server/src/core/workspaces/controller.ts index acb6a1cfbd..4d6903eb98 100644 --- a/packages/backend/server/src/core/workspaces/controller.ts +++ b/packages/backend/server/src/core/workspaces/controller.ts @@ -13,10 +13,9 @@ import { } from '../../fundamentals'; import { CurrentUser, Public } from '../auth'; import { DocHistoryManager, DocManager } from '../doc'; +import { Permission, PermissionService, PublicPageMode } from '../permission'; import { WorkspaceBlobStorage } from '../storage'; import { DocID } from '../utils/doc'; -import { PermissionService, PublicPageMode } from './permission'; -import { Permission } from './types'; @Controller('/api/workspaces') export class WorkspacesController { diff --git a/packages/backend/server/src/core/workspaces/index.ts b/packages/backend/server/src/core/workspaces/index.ts index 95c7b4bdb4..bac47e148a 100644 --- a/packages/backend/server/src/core/workspaces/index.ts +++ b/packages/backend/server/src/core/workspaces/index.ts @@ -2,12 +2,12 @@ import { Module } from '@nestjs/common'; import { DocModule } from '../doc'; import { FeatureModule } from '../features'; +import { PermissionModule } from '../permission'; import { QuotaModule } from '../quota'; import { StorageModule } from '../storage'; import { UserModule } from '../user'; import { WorkspacesController } from './controller'; import { WorkspaceManagementResolver } from './management'; -import { PermissionService } from './permission'; import { DocHistoryResolver, PagePermissionResolver, @@ -16,17 +16,22 @@ import { } from './resolvers'; @Module({ - imports: [DocModule, FeatureModule, QuotaModule, StorageModule, UserModule], + imports: [ + DocModule, + FeatureModule, + QuotaModule, + StorageModule, + UserModule, + PermissionModule, + ], controllers: [WorkspacesController], providers: [ WorkspaceResolver, WorkspaceManagementResolver, - PermissionService, PagePermissionResolver, DocHistoryResolver, WorkspaceBlobResolver, ], - exports: [PermissionService], }) export class WorkspaceModule {} diff --git a/packages/backend/server/src/core/workspaces/management.ts b/packages/backend/server/src/core/workspaces/management.ts index e4e230f948..8627fee483 100644 --- a/packages/backend/server/src/core/workspaces/management.ts +++ b/packages/backend/server/src/core/workspaces/management.ts @@ -12,7 +12,7 @@ import { ActionForbidden } from '../../fundamentals'; import { CurrentUser } from '../auth'; import { Admin } from '../common'; import { FeatureManagementService, FeatureType } from '../features'; -import { PermissionService } from './permission'; +import { PermissionService } from '../permission'; import { WorkspaceType } from './types'; @Resolver(() => WorkspaceType) @@ -61,7 +61,7 @@ export class WorkspaceManagementResolver { const owner = await this.permission.getWorkspaceOwner(workspaceId); const availableFeatures = await this.availableFeatures(user); - if (owner.user.id !== user.id || !availableFeatures.includes(feature)) { + if (owner.id !== user.id || !availableFeatures.includes(feature)) { throw new ActionForbidden(); } diff --git a/packages/backend/server/src/core/workspaces/resolvers/blob.ts b/packages/backend/server/src/core/workspaces/resolvers/blob.ts index cd55d3f112..82c8f6c1ca 100644 --- a/packages/backend/server/src/core/workspaces/resolvers/blob.ts +++ b/packages/backend/server/src/core/workspaces/resolvers/blob.ts @@ -19,10 +19,10 @@ import { PreventCache, } from '../../../fundamentals'; import { CurrentUser } from '../../auth'; +import { Permission, PermissionService } from '../../permission'; import { QuotaManagementService } from '../../quota'; import { WorkspaceBlobStorage } from '../../storage'; -import { PermissionService } from '../permission'; -import { Permission, WorkspaceBlobSizes, WorkspaceType } from '../types'; +import { WorkspaceBlobSizes, WorkspaceType } from '../types'; @UseGuards(CloudThrottlerGuard) @Resolver(() => WorkspaceType) diff --git a/packages/backend/server/src/core/workspaces/resolvers/history.ts b/packages/backend/server/src/core/workspaces/resolvers/history.ts index 3128210744..cdeb9ee812 100644 --- a/packages/backend/server/src/core/workspaces/resolvers/history.ts +++ b/packages/backend/server/src/core/workspaces/resolvers/history.ts @@ -13,9 +13,9 @@ import type { SnapshotHistory } from '@prisma/client'; import { CurrentUser } from '../../auth'; import { DocHistoryManager } from '../../doc'; +import { Permission, PermissionService } from '../../permission'; import { DocID } from '../../utils/doc'; -import { PermissionService } from '../permission'; -import { Permission, WorkspaceType } from '../types'; +import { WorkspaceType } from '../types'; @ObjectType() class DocHistoryType implements Partial { diff --git a/packages/backend/server/src/core/workspaces/resolvers/page.ts b/packages/backend/server/src/core/workspaces/resolvers/page.ts index c9177a4d2e..7b8a411f44 100644 --- a/packages/backend/server/src/core/workspaces/resolvers/page.ts +++ b/packages/backend/server/src/core/workspaces/resolvers/page.ts @@ -17,9 +17,13 @@ import { PageIsNotPublic, } from '../../../fundamentals'; import { CurrentUser } from '../../auth'; +import { + Permission, + PermissionService, + PublicPageMode, +} from '../../permission'; import { DocID } from '../../utils/doc'; -import { PermissionService, PublicPageMode } from '../permission'; -import { Permission, WorkspaceType } from '../types'; +import { WorkspaceType } from '../types'; registerEnumType(PublicPageMode, { name: 'PublicPageMode', diff --git a/packages/backend/server/src/core/workspaces/resolvers/workspace.ts b/packages/backend/server/src/core/workspaces/resolvers/workspace.ts index 302d056c49..c624401e26 100644 --- a/packages/backend/server/src/core/workspaces/resolvers/workspace.ts +++ b/packages/backend/server/src/core/workspaces/resolvers/workspace.ts @@ -26,17 +26,15 @@ import { UserNotFound, WorkspaceAccessDenied, WorkspaceNotFound, - WorkspaceOwnerNotFound, } from '../../../fundamentals'; import { CurrentUser, Public } from '../../auth'; +import { Permission, PermissionService } from '../../permission'; import { QuotaManagementService, QuotaQueryType } from '../../quota'; import { WorkspaceBlobStorage } from '../../storage'; import { UserService, UserType } from '../../user'; -import { PermissionService } from '../permission'; import { InvitationType, InviteUserType, - Permission, UpdateWorkspaceInput, WorkspaceType, } from '../types'; @@ -101,9 +99,7 @@ export class WorkspaceResolver { complexity: 2, }) async owner(@Parent() workspace: WorkspaceType) { - const data = await this.permissions.getWorkspaceOwner(workspace.id); - - return data.user; + return this.permissions.getWorkspaceOwner(workspace.id); } @ResolveField(() => [InviteUserType], { @@ -449,7 +445,7 @@ export class WorkspaceResolver { avatar: avatar || defaultWorkspaceAvatar, id: workspaceId, }, - user: owner.user, + user: owner, invitee: invitee.user, }; } @@ -507,12 +503,8 @@ export class WorkspaceResolver { const owner = await this.permissions.getWorkspaceOwner(workspaceId); - if (!owner.user) { - throw new WorkspaceOwnerNotFound({ workspaceId: workspaceId }); - } - if (sendLeaveMail) { - await this.mailer.sendLeaveWorkspaceEmail(owner.user.email, { + await this.mailer.sendLeaveWorkspaceEmail(owner.email, { workspaceName, inviteeName: user.name, }); diff --git a/packages/backend/server/src/core/workspaces/types.ts b/packages/backend/server/src/core/workspaces/types.ts index f85a5a6f22..06a1f90301 100644 --- a/packages/backend/server/src/core/workspaces/types.ts +++ b/packages/backend/server/src/core/workspaces/types.ts @@ -11,15 +11,9 @@ import { import type { Workspace } from '@prisma/client'; import { SafeIntResolver } from 'graphql-scalars'; +import { Permission } from '../permission'; import { UserType } from '../user/types'; -export enum Permission { - Read = 0, - Write = 1, - Admin = 10, - Owner = 99, -} - registerEnumType(Permission, { name: 'Permission', description: 'User permission in workspace', diff --git a/packages/backend/server/src/fundamentals/error/def.ts b/packages/backend/server/src/fundamentals/error/def.ts index 2a65225489..d65950dd99 100644 --- a/packages/backend/server/src/fundamentals/error/def.ts +++ b/packages/backend/server/src/fundamentals/error/def.ts @@ -198,6 +198,10 @@ export const USER_FRIENDLY_ERRORS = { type: 'too_many_requests', message: 'Too many requests.', }, + not_found: { + type: 'resource_not_found', + message: 'Resource not found.', + }, // User Errors user_not_found: { diff --git a/packages/backend/server/src/fundamentals/error/errors.gen.ts b/packages/backend/server/src/fundamentals/error/errors.gen.ts index 9c9ed2f66e..4066ed57d4 100644 --- a/packages/backend/server/src/fundamentals/error/errors.gen.ts +++ b/packages/backend/server/src/fundamentals/error/errors.gen.ts @@ -16,6 +16,12 @@ export class TooManyRequest extends UserFriendlyError { } } +export class NotFound extends UserFriendlyError { + constructor(message?: string) { + super('resource_not_found', 'not_found', message); + } +} + export class UserNotFound extends UserFriendlyError { constructor(message?: string) { super('resource_not_found', 'user_not_found', message); @@ -508,6 +514,7 @@ export class CannotDeleteOwnAccount extends UserFriendlyError { export enum ErrorNames { INTERNAL_SERVER_ERROR, TOO_MANY_REQUEST, + NOT_FOUND, USER_NOT_FOUND, USER_AVATAR_NOT_FOUND, EMAIL_ALREADY_USED, diff --git a/packages/backend/server/src/fundamentals/error/index.ts b/packages/backend/server/src/fundamentals/error/index.ts index 56e9abb6d0..eb62f90ae8 100644 --- a/packages/backend/server/src/fundamentals/error/index.ts +++ b/packages/backend/server/src/fundamentals/error/index.ts @@ -40,5 +40,3 @@ export class ErrorModule implements OnModuleInit { export { UserFriendlyError } from './def'; export * from './errors.gen'; -export * from './payment-required'; -export * from './too-many-requests'; diff --git a/packages/backend/server/src/fundamentals/error/payment-required.ts b/packages/backend/server/src/fundamentals/error/payment-required.ts deleted file mode 100644 index 5ebd901908..0000000000 --- a/packages/backend/server/src/fundamentals/error/payment-required.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { HttpException, HttpStatus } from '@nestjs/common'; - -export class PaymentRequiredException extends HttpException { - constructor(desc?: string, code: string = 'Payment Required') { - super( - HttpException.createBody(desc ?? code, code, HttpStatus.PAYMENT_REQUIRED), - HttpStatus.PAYMENT_REQUIRED - ); - } -} diff --git a/packages/backend/server/src/fundamentals/error/too-many-requests.ts b/packages/backend/server/src/fundamentals/error/too-many-requests.ts deleted file mode 100644 index 3a4a96130d..0000000000 --- a/packages/backend/server/src/fundamentals/error/too-many-requests.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { HttpException, HttpStatus } from '@nestjs/common'; - -export class TooManyRequestsException extends HttpException { - constructor(desc?: string, code: string = 'Too Many Requests') { - super( - HttpException.createBody( - desc ?? code, - code, - HttpStatus.TOO_MANY_REQUESTS - ), - HttpStatus.TOO_MANY_REQUESTS - ); - } -} diff --git a/packages/backend/server/src/fundamentals/nestjs/exception.ts b/packages/backend/server/src/fundamentals/nestjs/exception.ts index e553d22da1..945d3e973d 100644 --- a/packages/backend/server/src/fundamentals/nestjs/exception.ts +++ b/packages/backend/server/src/fundamentals/nestjs/exception.ts @@ -1,4 +1,9 @@ -import { ArgumentsHost, Catch, Logger } from '@nestjs/common'; +import { + ArgumentsHost, + Catch, + Logger, + NotFoundException, +} from '@nestjs/common'; import { BaseExceptionFilter } from '@nestjs/core'; import { GqlContextType } from '@nestjs/graphql'; import { ThrottlerException } from '@nestjs/throttler'; @@ -9,6 +14,7 @@ import { Socket } from 'socket.io'; import { InternalServerError, + NotFound, TooManyRequest, UserFriendlyError, } from '../error'; @@ -19,6 +25,8 @@ export function mapAnyError(error: any): UserFriendlyError { return error; } else if (error instanceof ThrottlerException) { return new TooManyRequest(); + } else if (error instanceof NotFoundException) { + return new NotFound(); } else { const e = new InternalServerError(); e.cause = error; diff --git a/packages/backend/server/src/plugins/copilot/index.ts b/packages/backend/server/src/plugins/copilot/index.ts index 79d0b8cb52..01bbeb6b46 100644 --- a/packages/backend/server/src/plugins/copilot/index.ts +++ b/packages/backend/server/src/plugins/copilot/index.ts @@ -2,8 +2,8 @@ import './config'; import { ServerFeature } from '../../core/config'; import { FeatureModule } from '../../core/features'; +import { PermissionModule } from '../../core/permission'; import { QuotaModule } from '../../core/quota'; -import { PermissionService } from '../../core/workspaces/permission'; import { Plugin } from '../registry'; import { CopilotController } from './controller'; import { ChatMessageCache } from './message'; @@ -29,9 +29,8 @@ registerCopilotProvider(OpenAIProvider); @Plugin({ name: 'copilot', - imports: [FeatureModule, QuotaModule], + imports: [FeatureModule, QuotaModule, PermissionModule], providers: [ - PermissionService, ChatSessionService, CopilotResolver, ChatMessageCache, diff --git a/packages/backend/server/src/plugins/copilot/resolver.ts b/packages/backend/server/src/plugins/copilot/resolver.ts index a98a55dd40..29e1aa54ce 100644 --- a/packages/backend/server/src/plugins/copilot/resolver.ts +++ b/packages/backend/server/src/plugins/copilot/resolver.ts @@ -21,8 +21,8 @@ import GraphQLUpload from 'graphql-upload/GraphQLUpload.mjs'; import { CurrentUser } from '../../core/auth'; import { Admin } from '../../core/common'; +import { PermissionService } from '../../core/permission'; import { UserType } from '../../core/user'; -import { PermissionService } from '../../core/workspaces/permission'; import { CopilotFailedToCreateMessage, FileUpload, diff --git a/packages/backend/server/src/plugins/oauth/index.ts b/packages/backend/server/src/plugins/oauth/index.ts index a426d20cbd..abfc3aab2e 100644 --- a/packages/backend/server/src/plugins/oauth/index.ts +++ b/packages/backend/server/src/plugins/oauth/index.ts @@ -21,6 +21,6 @@ import { OAuthService } from './service'; ], controllers: [OAuthController], contributesTo: ServerFeature.OAuth, - if: config => !!config.plugins.oauth, + if: config => config.flavor.graphql && !!config.plugins.oauth, }) export class OAuthModule {} diff --git a/packages/backend/server/src/schema.gql b/packages/backend/server/src/schema.gql index cf53902eef..e816313fef 100644 --- a/packages/backend/server/src/schema.gql +++ b/packages/backend/server/src/schema.gql @@ -239,6 +239,7 @@ enum ErrorNames { MAILER_SERVICE_IS_NOT_CONFIGURED MEMBER_QUOTA_EXCEEDED MISSING_OAUTH_QUERY_PARAMETER + NOT_FOUND NOT_IN_WORKSPACE NO_COPILOT_PROVIDER_AVAILABLE OAUTH_ACCOUNT_ALREADY_CONNECTED diff --git a/packages/backend/server/tests/feature.spec.ts b/packages/backend/server/tests/feature.spec.ts index ef0d8a2855..b99fc0e7bc 100644 --- a/packages/backend/server/tests/feature.spec.ts +++ b/packages/backend/server/tests/feature.spec.ts @@ -12,9 +12,9 @@ import { FeatureService, FeatureType, } from '../src/core/features'; +import { Permission } from '../src/core/permission'; import { UserType } from '../src/core/user/types'; import { WorkspaceResolver } from '../src/core/workspaces/resolvers'; -import { Permission } from '../src/core/workspaces/types'; import { Config, ConfigModule } from '../src/fundamentals/config'; import { createTestingApp } from './utils'; diff --git a/packages/backend/server/tests/history.spec.ts b/packages/backend/server/tests/history.spec.ts index 0d32fcf0b4..b795b3c985 100644 --- a/packages/backend/server/tests/history.spec.ts +++ b/packages/backend/server/tests/history.spec.ts @@ -5,6 +5,7 @@ import test from 'ava'; import * as Sinon from 'sinon'; import { DocHistoryManager } from '../src/core/doc'; +import { PermissionModule } from '../src/core/permission'; import { QuotaModule } from '../src/core/quota'; import { StorageModule } from '../src/core/storage'; import type { EventPayload } from '../src/fundamentals/event'; @@ -17,7 +18,7 @@ let db: PrismaClient; // cleanup database before each test test.beforeEach(async () => { m = await createTestingModule({ - imports: [StorageModule, QuotaModule], + imports: [StorageModule, QuotaModule, PermissionModule], providers: [DocHistoryManager], });