[permissions] Place lab + billing behind settings/workspace permission gates (#10354)

This commit is contained in:
Marie
2025-02-20 16:31:11 +01:00
committed by GitHub
parent 3c80e2601f
commit b2bbf88e28
8 changed files with 767 additions and 249 deletions

View File

@ -34,6 +34,7 @@ import { FeatureFlagModule } from 'src/engine/core-modules/feature-flag/feature-
import { MessageQueueModule } from 'src/engine/core-modules/message-queue/message-queue.module';
import { UserWorkspace } from 'src/engine/core-modules/user-workspace/user-workspace.entity';
import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity';
import { PermissionsModule } from 'src/engine/metadata-modules/permissions/permissions.module';
@Module({
imports: [
@ -41,6 +42,7 @@ import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity';
StripeModule,
DomainManagerModule,
MessageQueueModule,
PermissionsModule,
TypeOrmModule.forFeature(
[
BillingSubscription,

View File

@ -1,9 +1,10 @@
/* @license Enterprise */
import { UseGuards } from '@nestjs/common';
import { UseFilters, UseGuards } from '@nestjs/common';
import { Args, Mutation, Query, Resolver } from '@nestjs/graphql';
import { GraphQLError } from 'graphql';
import { SettingsFeatures } from 'twenty-shared';
import { BillingCheckoutSessionInput } from 'src/engine/core-modules/billing/dtos/inputs/billing-checkout-session.input';
import { BillingProductInput } from 'src/engine/core-modules/billing/dtos/inputs/billing-product.input';
@ -26,10 +27,13 @@ import { User } from 'src/engine/core-modules/user/user.entity';
import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity';
import { AuthUser } from 'src/engine/decorators/auth/auth-user.decorator';
import { AuthWorkspace } from 'src/engine/decorators/auth/auth-workspace.decorator';
import { SettingsPermissionsGuard } from 'src/engine/guards/settings-permissions.guard';
import { UserAuthGuard } from 'src/engine/guards/user-auth.guard';
import { WorkspaceAuthGuard } from 'src/engine/guards/workspace-auth.guard';
import { PermissionsGraphqlApiExceptionFilter } from 'src/engine/metadata-modules/permissions/utils/permissions-graphql-api-exception.filter';
@Resolver()
@UseFilters(PermissionsGraphqlApiExceptionFilter)
export class BillingResolver {
constructor(
private readonly billingSubscriptionService: BillingSubscriptionService,
@ -55,7 +59,10 @@ export class BillingResolver {
}
@Query(() => BillingSessionOutput)
@UseGuards(WorkspaceAuthGuard)
@UseGuards(
WorkspaceAuthGuard,
SettingsPermissionsGuard(SettingsFeatures.WORKSPACE),
)
async billingPortalSession(
@AuthWorkspace() workspace: Workspace,
@Args() { returnUrlPath }: BillingSessionInput,
@ -134,7 +141,10 @@ export class BillingResolver {
}
@Mutation(() => BillingUpdateOutput)
@UseGuards(WorkspaceAuthGuard)
@UseGuards(
WorkspaceAuthGuard,
SettingsPermissionsGuard(SettingsFeatures.WORKSPACE),
)
async updateBillingSubscription(@AuthWorkspace() workspace: Workspace) {
await this.billingSubscriptionService.applyBillingSubscription(workspace);

View File

@ -2,14 +2,20 @@ import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { FeatureFlag } from 'src/engine/core-modules/feature-flag/feature-flag.entity';
import { FeatureFlagModule } from 'src/engine/core-modules/feature-flag/feature-flag.module';
import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity';
import { PermissionsModule } from 'src/engine/metadata-modules/permissions/permissions.module';
import { LabResolver } from './lab.resolver';
import { LabService } from './services/lab.service';
@Module({
imports: [TypeOrmModule.forFeature([FeatureFlag, Workspace], 'core')],
imports: [
TypeOrmModule.forFeature([FeatureFlag, Workspace], 'core'),
FeatureFlagModule,
PermissionsModule,
],
providers: [LabService, LabResolver],
exports: [LabService],
})

View File

@ -1,16 +1,21 @@
import { UseFilters, UseGuards } from '@nestjs/common';
import { Args, Mutation, Resolver } from '@nestjs/graphql';
import { SettingsFeatures } from 'twenty-shared';
import { AuthGraphqlApiExceptionFilter } from 'src/engine/core-modules/auth/filters/auth-graphql-api-exception.filter';
import { FeatureFlag } from 'src/engine/core-modules/feature-flag/feature-flag.entity';
import { UpdateLabPublicFeatureFlagInput } from 'src/engine/core-modules/lab/dtos/update-lab-public-feature-flag.input';
import { LabService } from 'src/engine/core-modules/lab/services/lab.service';
import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity';
import { AuthWorkspace } from 'src/engine/decorators/auth/auth-workspace.decorator';
import { SettingsPermissionsGuard } from 'src/engine/guards/settings-permissions.guard';
import { WorkspaceAuthGuard } from 'src/engine/guards/workspace-auth.guard';
import { PermissionsGraphqlApiExceptionFilter } from 'src/engine/metadata-modules/permissions/utils/permissions-graphql-api-exception.filter';
@Resolver()
@UseFilters(AuthGraphqlApiExceptionFilter)
@UseFilters(AuthGraphqlApiExceptionFilter, PermissionsGraphqlApiExceptionFilter)
@UseGuards(SettingsPermissionsGuard(SettingsFeatures.WORKSPACE))
export class LabResolver {
constructor(private labService: LabService) {}