refactor(twenty-orm): migrate 23 grandfathered entities to WorkspaceScopedRepository (#20987)

## Summary

Follow-up to #20953. Migrates 23 of the 30 entities that were left in
`WORKSPACE_SCOPED_EXEMPTIONS` last time, so the lint rule's
workspaceId-enforcement default now covers most of the core/metadata
schema.

### Migrated (23 entities, 88 files, 22 commits)

| Family | Entities |
|---|---|
| Trivial caches | `NavigationMenuItem`, `Skill`, `DataSource`,
`Webhook`, `CommandMenuItem`, `IndexMetadata` |
| Views | `View`, `ViewField`, `ViewFieldGroup`, `ViewFilter`,
`ViewFilterGroup`, `ViewGroup`, `ViewSort` |
| Layouts | `PageLayout`, `PageLayoutTab`, `PageLayoutWidget` |
| Roles & permissions | `Role`, `RoleTarget`, `PermissionFlag`,
`ObjectPermission`, `FieldPermission`, `RowLevelPermissionPredicate`,
`RowLevelPermissionPredicateGroup` |

For each entity: swap `@InjectRepository(X)` →
`@InjectWorkspaceScopedRepository(X)` (and the field type →
`WorkspaceScopedRepository<X>`); rewrite every call site to pass
`workspaceId` as the first arg (stripped from `where`/criteria — the
wrapper throws if you include it now); register
`provideWorkspaceScopedRepository(X)` in every owning NestJS module;
update affected spec providers to
`getWorkspaceScopedRepositoryToken(X)`.

### Rule update

- `ApplicationRegistrationVariableEntity` was misclassified — moved to
`STRUCTURAL_EXEMPTIONS` (no `workspaceId` column; it's keyed on
`applicationRegistrationId` at the instance level).
- 22 of the 23 migrated entities removed from
`WORKSPACE_SCOPED_EXEMPTIONS` entirely (zero remaining raw
`@InjectRepository` sites).
- `RoleTargetEntity` also removed; one call site in
`user-workspace.service.ts` keeps a raw injection with an
`eslint-disable` + reason because `softRemove(...)` is not on the
wrapper API yet (the migration would require threading `workspaceId`
through `deleteUserWorkspace`'s three callers).

### Still exempted (7 entities, follow-up PRs)

| Entity | Why deferred |
|---|---|
| `ApplicationEntity` | ~50 sites with several cross-workspace lookups
by id (auth, OAuth, file-storage, cleanup) |
| `CalendarChannelEntity` / `MessageChannelEntity` | Use
`.increment(...)` (not on wrapper) and
`repository.manager.transaction(...)` — wrapper needs to grow
`.increment` + the transaction sites need `withManager` or dual-inject |
| `FieldMetadataEntity` / `ObjectMetadataEntity` | The metadata services
`extends TypeOrmQueryService<X>` and `super(rawRepo)` — requires
dual-inject or reworking the inheritance |
| `KeyValuePairEntity` | Allows `workspaceId: IsNull()` for
instance-level config; wrapper rejects null |
| `UpgradeMigrationEntity` | Same — instance-level + cross-workspace
ledger |

## Test plan

- [x] `npx nx typecheck twenty-server` — clean
- [x] `npx nx lint twenty-server` — clean (0/0)
- [x] All 10 affected unit specs pass (115 tests) — api-key, agent-role,
permissions, workspace-roles-permissions-cache, view-filter-group,
workflow-version-step-operations, two-factor-authentication (service +
resolver), user-workspace, file
- [ ] Server integration tests in CI
This commit is contained in:
Félix Malfait
2026-05-28 20:46:21 +02:00
committed by GitHub
parent 865ca697ca
commit f4ead89956
99 changed files with 1037 additions and 663 deletions

View File

@@ -2,12 +2,18 @@ import { defineRule } from '@oxlint/plugins';
export const RULE_NAME = 'prefer-workspace-scoped-repository';
// Entities that legitimately do not carry a workspaceId column.
// Entities that do not fit the scoped wrapper: workspace itself, pivots,
// nullable-workspaceId rows (instance-level config / migrations / tokens),
// and global tables with no workspaceId column at all.
const STRUCTURAL_EXEMPTIONS = new Set<string>([
'WorkspaceEntity',
'UserWorkspaceEntity',
'AppTokenEntity',
'ApplicationRegistrationEntity',
'ApplicationRegistrationVariableEntity',
// nullable workspaceId — both rows support instance-level and per-workspace use
'KeyValuePairEntity',
'UpgradeMigrationEntity',
'ApplicationVariableEntity',
'BillingMeterEntity',
@@ -25,39 +31,25 @@ const STRUCTURAL_EXEMPTIONS = new Set<string>([
'WorkspaceSSOIdentityProviderEntity',
]);
// Workspace-scoped entities exempted from the wrapper at the call site.
// Workspace-scoped entities the wrapper could technically wrap, but where
// the dominant access patterns are cross-workspace (request routing, auth,
// metadata sync, file storage, transaction-bound channel updates) and the
// payoff doesn't justify dual-injecting every call site or growing the
// wrapper API. Treat as a "deliberately not migrated" list, not a backlog.
const WORKSPACE_SCOPED_EXEMPTIONS = new Set<string>([
// Resolved by id alone at auth/request-routing time and inside file-storage
// transactions; very few of the ~50 call sites carry a workspaceId.
'ApplicationEntity',
'ApplicationRegistrationVariableEntity',
// 20+ call sites across calendar/messaging modules; staged for a dedicated PR.
'CalendarChannelEntity',
'CommandMenuItemEntity',
'DataSourceEntity',
'FieldMetadataEntity',
'FieldPermissionEntity',
'IndexMetadataEntity',
'KeyValuePairEntity',
'MessageChannelEntity',
'NavigationMenuItemEntity',
// The owning services `extends TypeOrmQueryService<E>` and pass the raw
// repo to `super(...)`; the superclass type doesn't accept the wrapper.
'FieldMetadataEntity',
'ObjectMetadataEntity',
'ObjectPermissionEntity',
'PageLayoutEntity',
'PageLayoutTabEntity',
'PageLayoutWidgetEntity',
'PermissionFlagEntity',
'RoleEntity',
'RoleTargetEntity',
'RowLevelPermissionPredicateEntity',
'RowLevelPermissionPredicateGroupEntity',
'SkillEntity',
'UpgradeMigrationEntity',
'ViewEntity',
'ViewFieldEntity',
'ViewFieldGroupEntity',
'ViewFilterEntity',
'ViewFilterGroupEntity',
'ViewGroupEntity',
'ViewSortEntity',
'WebhookEntity',
// Only injection lives in a frozen historical upgrade-version-command
// directory that CI's mutation-guard refuses to let us edit.
'DataSourceEntity',
]);
// Everything else must use @InjectWorkspaceScopedRepository.

View File

@@ -36,6 +36,8 @@ import { WorkspaceEntity } from 'src/engine/core-modules/workspace/workspace.ent
import { WorkspaceModule } from 'src/engine/core-modules/workspace/workspace.module';
import { FieldMetadataModule } from 'src/engine/metadata-modules/field-metadata/field-metadata.module';
import { ObjectMetadataModule } from 'src/engine/metadata-modules/object-metadata/object-metadata.module';
import { RoleEntity } from 'src/engine/metadata-modules/role/role.entity';
import { provideWorkspaceScopedRepository } from 'src/engine/twenty-orm/workspace-scoped-repository/provide-workspace-scoped-repository';
import { TrashCleanupModule } from 'src/engine/trash-cleanup/trash-cleanup.module';
import { WorkspaceCacheStorageModule } from 'src/engine/workspace-cache-storage/workspace-cache-storage.module';
import { WorkspaceCacheModule } from 'src/engine/workspace-cache/workspace-cache.module';
@@ -52,7 +54,7 @@ import { AutomatedTriggerModule } from 'src/modules/workflow/workflow-trigger/au
@Module({
imports: [
UpgradeVersionCommandModule,
TypeOrmModule.forFeature([WorkspaceEntity]),
TypeOrmModule.forFeature([WorkspaceEntity, RoleEntity]),
WorkspaceExportModule,
// Cron command dependencies
MessagingImportManagerModule,
@@ -102,6 +104,7 @@ import { AutomatedTriggerModule } from 'src/modules/workflow/workflow-trigger/au
UpgradeStatusCommand,
RebuildApplicationDefaultDepsCommand,
InstallPreInstalledAppsCommand,
provideWorkspaceScopedRepository(RoleEntity),
],
})
export class DatabaseCommandModule {}

View File

@@ -44,6 +44,8 @@ import { ApiKeyController } from './controllers/api-key.controller';
WorkspaceApiKeyMapCacheService,
GenerateApiKeyCommand,
provideWorkspaceScopedRepository(ApiKeyEntity),
provideWorkspaceScopedRepository(RoleEntity),
provideWorkspaceScopedRepository(RoleTargetEntity),
],
controllers: [ApiKeyController],
exports: [

View File

@@ -13,6 +13,8 @@ import { ApiKeyService } from 'src/engine/core-modules/api-key/services/api-key.
import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service';
import { WorkspaceEntity } from 'src/engine/core-modules/workspace/workspace.entity';
import { RoleEntity } from 'src/engine/metadata-modules/role/role.entity';
import { InjectWorkspaceScopedRepository } from 'src/engine/twenty-orm/workspace-scoped-repository/inject-workspace-scoped-repository.decorator';
import { WorkspaceScopedRepository } from 'src/engine/twenty-orm/workspace-scoped-repository/workspace-scoped-repository';
import { STANDARD_ROLE } from 'src/engine/workspace-manager/twenty-standard-application/constants/standard-role.constant';
type GenerateApiKeyCommandOptions = {
@@ -33,8 +35,8 @@ export class GenerateApiKeyCommand extends CommandRunner {
constructor(
@InjectRepository(WorkspaceEntity)
private readonly workspaceRepository: Repository<WorkspaceEntity>,
@InjectRepository(RoleEntity)
private readonly roleRepository: Repository<RoleEntity>,
@InjectWorkspaceScopedRepository(RoleEntity)
private readonly roleRepository: WorkspaceScopedRepository<RoleEntity>,
private readonly apiKeyService: ApiKeyService,
private readonly twentyConfigService: TwentyConfigService,
) {
@@ -104,9 +106,8 @@ export class GenerateApiKeyCommand extends CommandRunner {
return;
}
const adminRole = await this.roleRepository.findOne({
const adminRole = await this.roleRepository.findOne(workspace.id, {
where: {
workspaceId: workspace.id,
universalIdentifier: STANDARD_ROLE.admin.universalIdentifier,
},
});

View File

@@ -1,5 +1,5 @@
import { Test, type TestingModule } from '@nestjs/testing';
import { getDataSourceToken, getRepositoryToken } from '@nestjs/typeorm';
import { getDataSourceToken } from '@nestjs/typeorm';
import { IsNull } from 'typeorm';
@@ -101,7 +101,7 @@ describe('ApiKeyService', () => {
useValue: mockRoleTargetService,
},
{
provide: getRepositoryToken(RoleTargetEntity),
provide: getWorkspaceScopedRepositoryToken(RoleTargetEntity),
useValue: mockroleTargetRepository,
},
{

View File

@@ -1,8 +1,7 @@
import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { isDefined } from 'twenty-shared/utils';
import { In, IsNull, Not, Repository } from 'typeorm';
import { In, IsNull, Not } from 'typeorm';
import { ApiKeyEntity } from 'src/engine/core-modules/api-key/api-key.entity';
import {
@@ -23,10 +22,10 @@ import { WorkspaceCacheService } from 'src/engine/workspace-cache/services/works
@Injectable()
export class ApiKeyRoleService {
constructor(
@InjectRepository(RoleTargetEntity)
private readonly roleTargetRepository: Repository<RoleTargetEntity>,
@InjectRepository(RoleEntity)
private readonly roleRepository: Repository<RoleEntity>,
@InjectWorkspaceScopedRepository(RoleTargetEntity)
private readonly roleTargetRepository: WorkspaceScopedRepository<RoleTargetEntity>,
@InjectWorkspaceScopedRepository(RoleEntity)
private readonly roleRepository: WorkspaceScopedRepository<RoleEntity>,
@InjectWorkspaceScopedRepository(ApiKeyEntity)
private readonly apiKeyRepository: WorkspaceScopedRepository<ApiKeyEntity>,
@@ -141,8 +140,8 @@ export class ApiKeyRoleService {
);
}
const role = await this.roleRepository.findOne({
where: { id: roleId, workspaceId },
const role = await this.roleRepository.findOne(workspaceId, {
where: { id: roleId },
});
if (!role) {
@@ -159,13 +158,15 @@ export class ApiKeyRoleService {
);
}
const existingRoleTarget = await this.roleTargetRepository.findOne({
where: {
apiKeyId,
roleId,
workspaceId,
const existingRoleTarget = await this.roleTargetRepository.findOne(
workspaceId,
{
where: {
apiKeyId,
roleId,
},
},
});
);
return {
roleToAssignIsSameAsCurrentRole: Boolean(existingRoleTarget),
@@ -183,10 +184,9 @@ export class ApiKeyRoleService {
return new Map();
}
const roleTargets = await this.roleTargetRepository.find({
const roleTargets = await this.roleTargetRepository.find(workspaceId, {
where: {
apiKeyId: In(apiKeyIds),
workspaceId,
},
relations: ['role'],
});
@@ -209,10 +209,9 @@ export class ApiKeyRoleService {
roleId: string,
workspaceId: string,
): Promise<ApiKeyEntity[]> {
const roleTargets = await this.roleTargetRepository.find({
const roleTargets = await this.roleTargetRepository.find(workspaceId, {
where: {
roleId,
workspaceId,
apiKeyId: Not(IsNull()),
},
});

View File

@@ -39,6 +39,7 @@ import { WorkspaceCacheModule } from 'src/engine/workspace-cache/workspace-cache
ApplicationService,
WorkspaceFlatApplicationMapCacheService,
provideWorkspaceScopedRepository(AgentEntity),
provideWorkspaceScopedRepository(CommandMenuItemEntity),
],
})
export class ApplicationModule {}

View File

@@ -43,8 +43,8 @@ export class ApplicationService {
private readonly agentRepository: WorkspaceScopedRepository<AgentEntity>,
@InjectRepository(FrontComponentEntity)
private readonly frontComponentRepository: Repository<FrontComponentEntity>,
@InjectRepository(CommandMenuItemEntity)
private readonly commandMenuItemRepository: Repository<CommandMenuItemEntity>,
@InjectWorkspaceScopedRepository(CommandMenuItemEntity)
private readonly commandMenuItemRepository: WorkspaceScopedRepository<CommandMenuItemEntity>,
@InjectRepository(ObjectMetadataEntity)
private readonly objectMetadataRepository: Repository<ObjectMetadataEntity>,
@InjectRepository(ApplicationVariableEntity)
@@ -206,8 +206,8 @@ export class ApplicationService {
this.frontComponentRepository.find({
where: { applicationId: application.id, workspaceId },
}),
this.commandMenuItemRepository.find({
where: { applicationId: application.id, workspaceId },
this.commandMenuItemRepository.find(workspaceId, {
where: { applicationId: application.id },
}),
this.objectMetadataRepository.find({
where: { applicationId: application.id, workspaceId },

View File

@@ -51,6 +51,8 @@ export class UserWorkspaceService extends TypeOrmQueryService<UserWorkspaceEntit
private readonly userWorkspaceRepository: Repository<UserWorkspaceEntity>,
@InjectRepository(UserEntity)
private readonly userRepository: Repository<UserEntity>,
// softRemove is not supported by WorkspaceScopedRepository.
// eslint-disable-next-line twenty/prefer-workspace-scoped-repository
@InjectRepository(RoleTargetEntity)
private readonly roleTargetRepository: Repository<RoleTargetEntity>,
private readonly roleValidationService: RoleValidationService,
@@ -311,6 +313,9 @@ export class UserWorkspaceService extends TypeOrmQueryService<UserWorkspaceEntit
return await this.userWorkspaceRepository.count({ where: { userId } });
}
// TODO migrate roleTargetRepository to WorkspaceScopedRepository once workspaceId
// is threaded through all deleteUserWorkspace callers (user.service.ts does not
// currently have it at the call site).
async deleteUserWorkspace({
userWorkspaceId,
softDelete = false,

View File

@@ -14,6 +14,7 @@ import { AiModelsModule } from 'src/engine/metadata-modules/ai/ai-models/ai-mode
import { PermissionsModule } from 'src/engine/metadata-modules/permissions/permissions.module';
import { RoleTargetEntity } from 'src/engine/metadata-modules/role-target/role-target.entity';
import { UserRoleModule } from 'src/engine/metadata-modules/user-role/user-role.module';
import { provideWorkspaceScopedRepository } from 'src/engine/twenty-orm/workspace-scoped-repository/provide-workspace-scoped-repository';
import { WorkspaceCacheModule } from 'src/engine/workspace-cache/workspace-cache.module';
import { AgentMessagePartEntity } from './entities/agent-message-part.entity';
@@ -49,6 +50,7 @@ import { AgentAsyncExecutorService } from './services/agent-async-executor.servi
AgentAsyncExecutorService,
AgentActorContextService,
AgentMessagePartResolver,
provideWorkspaceScopedRepository(RoleTargetEntity),
],
exports: [
AgentAsyncExecutorService,

View File

@@ -45,6 +45,8 @@ import {
} from 'src/engine/metadata-modules/ai/ai.exception';
import { RoleTargetEntity } from 'src/engine/metadata-modules/role-target/role-target.entity';
import { type RolePermissionConfig } from 'src/engine/twenty-orm/types/role-permission-config';
import { InjectWorkspaceScopedRepository } from 'src/engine/twenty-orm/workspace-scoped-repository/inject-workspace-scoped-repository.decorator';
import { WorkspaceScopedRepository } from 'src/engine/twenty-orm/workspace-scoped-repository/workspace-scoped-repository';
const EMPTY_USAGE: LanguageModelUsage = {
inputTokens: 0,
@@ -75,8 +77,8 @@ export class AgentAsyncExecutorService {
private readonly nativeToolBinder: NativeToolBinderService,
private readonly aiBillingService: AiBillingService,
private readonly billingUsageService: BillingUsageService,
@InjectRepository(RoleTargetEntity)
private readonly roleTargetRepository: Repository<RoleTargetEntity>,
@InjectWorkspaceScopedRepository(RoleTargetEntity)
private readonly roleTargetRepository: WorkspaceScopedRepository<RoleTargetEntity>,
@InjectRepository(WorkspaceEntity)
private readonly workspaceRepository: Repository<WorkspaceEntity>,
) {}
@@ -104,10 +106,9 @@ export class AgentAsyncExecutorService {
workspaceId: string,
rolePermissionConfig?: RolePermissionConfig,
): Promise<RolePermissionConfig | undefined> {
const roleTarget = await this.roleTargetRepository.findOne({
const roleTarget = await this.roleTargetRepository.findOne(workspaceId, {
where: {
agentId,
workspaceId,
},
select: ['roleId'],
});

View File

@@ -1,7 +1,4 @@
import { Test, type TestingModule } from '@nestjs/testing';
import { getRepositoryToken } from '@nestjs/typeorm';
import { type Repository } from 'typeorm';
import {
AiException,
@@ -20,8 +17,8 @@ import { AiAgentRoleService } from './ai-agent-role.service';
describe('AiAgentRoleService', () => {
let service: AiAgentRoleService;
let agentRepository: WorkspaceScopedRepository<AgentEntity>;
let roleRepository: Repository<RoleEntity>;
let roleTargetRepository: Repository<RoleTargetEntity>;
let roleRepository: WorkspaceScopedRepository<RoleEntity>;
let roleTargetRepository: WorkspaceScopedRepository<RoleTargetEntity>;
let roleTargetService: RoleTargetService;
const testWorkspaceId = 'test-workspace-id';
@@ -42,19 +39,20 @@ describe('AiAgentRoleService', () => {
},
},
{
provide: getRepositoryToken(RoleEntity),
provide: getWorkspaceScopedRepositoryToken(RoleEntity),
useValue: {
findOne: jest.fn(),
save: jest.fn(),
},
},
{
provide: getRepositoryToken(RoleTargetEntity),
provide: getWorkspaceScopedRepositoryToken(RoleTargetEntity),
useValue: {
findOne: jest.fn(),
save: jest.fn(),
delete: jest.fn(),
find: jest.fn(),
count: jest.fn(),
},
},
{
@@ -71,12 +69,12 @@ describe('AiAgentRoleService', () => {
agentRepository = module.get<WorkspaceScopedRepository<AgentEntity>>(
getWorkspaceScopedRepositoryToken(AgentEntity),
);
roleRepository = module.get<Repository<RoleEntity>>(
getRepositoryToken(RoleEntity),
);
roleTargetRepository = module.get<Repository<RoleTargetEntity>>(
getRepositoryToken(RoleTargetEntity),
roleRepository = module.get<WorkspaceScopedRepository<RoleEntity>>(
getWorkspaceScopedRepositoryToken(RoleEntity),
);
roleTargetRepository = module.get<
WorkspaceScopedRepository<RoleTargetEntity>
>(getWorkspaceScopedRepositoryToken(RoleTargetEntity));
roleTargetService = module.get<RoleTargetService>(RoleTargetService);
// Setup test data
@@ -153,16 +151,18 @@ describe('AiAgentRoleService', () => {
expect(agentRepository.findOne).toHaveBeenCalledWith(testWorkspaceId, {
where: { id: testAgent.id },
});
expect(roleRepository.findOne).toHaveBeenCalledWith({
where: { id: testRole.id, workspaceId: testWorkspaceId },
expect(roleRepository.findOne).toHaveBeenCalledWith(testWorkspaceId, {
where: { id: testRole.id },
});
expect(roleTargetRepository.findOne).toHaveBeenCalledWith({
where: {
agentId: testAgent.id,
roleId: testRole.id,
workspaceId: testWorkspaceId,
expect(roleTargetRepository.findOne).toHaveBeenCalledWith(
testWorkspaceId,
{
where: {
agentId: testAgent.id,
roleId: testRole.id,
},
},
});
);
expect(roleTargetService.create).toHaveBeenCalledWith({
createRoleTargetInput: {
roleId: testRole.id,
@@ -335,12 +335,14 @@ describe('AiAgentRoleService', () => {
});
// Assert
expect(roleTargetRepository.findOne).toHaveBeenCalledWith({
where: {
agentId: testAgent.id,
workspaceId: testWorkspaceId,
expect(roleTargetRepository.findOne).toHaveBeenCalledWith(
testWorkspaceId,
{
where: {
agentId: testAgent.id,
},
},
});
);
expect(roleTargetService.delete).toHaveBeenCalledWith({
id: existingRoleTarget.id,
workspaceId: testWorkspaceId,

View File

@@ -16,6 +16,8 @@ import { AiAgentRoleService } from './ai-agent-role.service';
providers: [
AiAgentRoleService,
provideWorkspaceScopedRepository(AgentEntity),
provideWorkspaceScopedRepository(RoleEntity),
provideWorkspaceScopedRepository(RoleTargetEntity),
],
exports: [AiAgentRoleService],
})

View File

@@ -1,8 +1,7 @@
import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { isDefined } from 'twenty-shared/utils';
import { In, IsNull, Not, Repository } from 'typeorm';
import { In, IsNull, Not } from 'typeorm';
import {
AiException,
@@ -19,10 +18,10 @@ export class AiAgentRoleService {
constructor(
@InjectWorkspaceScopedRepository(AgentEntity)
private readonly agentRepository: WorkspaceScopedRepository<AgentEntity>,
@InjectRepository(RoleEntity)
private readonly roleRepository: Repository<RoleEntity>,
@InjectRepository(RoleTargetEntity)
private readonly roleTargetRepository: Repository<RoleTargetEntity>,
@InjectWorkspaceScopedRepository(RoleEntity)
private readonly roleRepository: WorkspaceScopedRepository<RoleEntity>,
@InjectWorkspaceScopedRepository(RoleTargetEntity)
private readonly roleTargetRepository: WorkspaceScopedRepository<RoleTargetEntity>,
private readonly roleTargetService: RoleTargetService,
) {}
@@ -62,12 +61,14 @@ export class AiAgentRoleService {
workspaceId: string;
agentId: string;
}): Promise<void> {
const existingRoleTarget = await this.roleTargetRepository.findOne({
where: {
agentId,
workspaceId,
const existingRoleTarget = await this.roleTargetRepository.findOne(
workspaceId,
{
where: {
agentId,
},
},
});
);
if (!isDefined(existingRoleTarget)) {
throw new AiException(
@@ -86,10 +87,9 @@ export class AiAgentRoleService {
roleId: string,
workspaceId: string,
): Promise<AgentEntity[]> {
const roleTargets = await this.roleTargetRepository.find({
const roleTargets = await this.roleTargetRepository.find(workspaceId, {
where: {
roleId,
workspaceId,
agentId: Not(IsNull()),
},
});
@@ -129,8 +129,8 @@ export class AiAgentRoleService {
);
}
const role = await this.roleRepository.findOne({
where: { id: roleId, workspaceId },
const role = await this.roleRepository.findOne(workspaceId, {
where: { id: roleId },
});
if (!role) {
@@ -147,13 +147,15 @@ export class AiAgentRoleService {
);
}
const existingRoleTarget = await this.roleTargetRepository.findOne({
where: {
agentId,
roleId,
workspaceId,
const existingRoleTarget = await this.roleTargetRepository.findOne(
workspaceId,
{
where: {
agentId,
roleId,
},
},
});
);
return {
roleToAssignIsSameAsCurrentRole: Boolean(existingRoleTarget),
@@ -169,8 +171,8 @@ export class AiAgentRoleService {
roleTargetId: string;
workspaceId: string;
}): Promise<void> {
const role = await this.roleRepository.findOne({
where: { id: roleId, workspaceId },
const role = await this.roleRepository.findOne(workspaceId, {
where: { id: roleId },
});
if (
@@ -182,16 +184,18 @@ export class AiAgentRoleService {
return;
}
const remainingAssignments = await this.roleTargetRepository.count({
where: {
roleId,
workspaceId,
id: Not(roleTargetId),
const remainingAssignments = await this.roleTargetRepository.count(
workspaceId,
{
where: {
roleId,
id: Not(roleTargetId),
},
},
});
);
if (remainingAssignments === 0) {
await this.roleRepository.delete({ id: roleId, workspaceId });
await this.roleRepository.delete(workspaceId, { id: roleId });
}
}
}

View File

@@ -23,6 +23,8 @@ import { provideWorkspaceScopedRepository } from 'src/engine/twenty-orm/workspac
WorkspaceFlatAgentMapCacheService,
WorkspaceFlatRoleTargetByAgentIdService,
provideWorkspaceScopedRepository(AgentEntity),
provideWorkspaceScopedRepository(RoleEntity),
provideWorkspaceScopedRepository(RoleTargetEntity),
],
exports: [
WorkspaceFlatAgentMapCacheService,

View File

@@ -11,6 +11,8 @@ import { FlatRoleTargetByAgentIdMaps } from 'src/engine/metadata-modules/flat-ag
import { fromRoleTargetEntityToFlatRoleTarget } from 'src/engine/metadata-modules/flat-role-target/utils/from-role-target-entity-to-flat-role-target.util';
import { RoleTargetEntity } from 'src/engine/metadata-modules/role-target/role-target.entity';
import { RoleEntity } from 'src/engine/metadata-modules/role/role.entity';
import { InjectWorkspaceScopedRepository } from 'src/engine/twenty-orm/workspace-scoped-repository/inject-workspace-scoped-repository.decorator';
import { WorkspaceScopedRepository } from 'src/engine/twenty-orm/workspace-scoped-repository/workspace-scoped-repository';
import { WorkspaceCache } from 'src/engine/workspace-cache/decorators/workspace-cache.decorator';
import { createIdToUniversalIdentifierMap } from 'src/engine/workspace-cache/utils/create-id-to-universal-identifier-map.util';
@@ -18,12 +20,12 @@ import { createIdToUniversalIdentifierMap } from 'src/engine/workspace-cache/uti
@WorkspaceCache('flatRoleTargetByAgentIdMaps')
export class WorkspaceFlatRoleTargetByAgentIdService extends WorkspaceCacheProvider<FlatRoleTargetByAgentIdMaps> {
constructor(
@InjectRepository(RoleTargetEntity)
private readonly roleTargetRepository: Repository<RoleTargetEntity>,
@InjectWorkspaceScopedRepository(RoleTargetEntity)
private readonly roleTargetRepository: WorkspaceScopedRepository<RoleTargetEntity>,
@InjectRepository(ApplicationEntity)
private readonly applicationRepository: Repository<ApplicationEntity>,
@InjectRepository(RoleEntity)
private readonly roleRepository: Repository<RoleEntity>,
@InjectWorkspaceScopedRepository(RoleEntity)
private readonly roleRepository: WorkspaceScopedRepository<RoleEntity>,
) {
super();
}
@@ -32,9 +34,8 @@ export class WorkspaceFlatRoleTargetByAgentIdService extends WorkspaceCacheProvi
workspaceId: string,
): Promise<FlatRoleTargetByAgentIdMaps> {
const [roleTargetEntities, applications, roles] = await Promise.all([
this.roleTargetRepository.find({
this.roleTargetRepository.find(workspaceId, {
where: {
workspaceId,
agentId: Not(IsNull()),
},
withDeleted: true,
@@ -44,8 +45,7 @@ export class WorkspaceFlatRoleTargetByAgentIdService extends WorkspaceCacheProvi
select: ['id', 'universalIdentifier'],
withDeleted: true,
}),
this.roleRepository.find({
where: { workspaceId },
this.roleRepository.find(workspaceId, {
select: ['id', 'universalIdentifier'],
withDeleted: true,
}),

View File

@@ -8,6 +8,7 @@ import { WorkspaceManyOrAllFlatEntityMapsCacheModule } from 'src/engine/metadata
import { FrontComponentEntity } from 'src/engine/metadata-modules/front-component/entities/front-component.entity';
import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
import { PageLayoutEntity } from 'src/engine/metadata-modules/page-layout/entities/page-layout.entity';
import { provideWorkspaceScopedRepository } from 'src/engine/twenty-orm/workspace-scoped-repository/provide-workspace-scoped-repository';
@Module({
imports: [
@@ -20,7 +21,11 @@ import { PageLayoutEntity } from 'src/engine/metadata-modules/page-layout/entiti
]),
WorkspaceManyOrAllFlatEntityMapsCacheModule,
],
providers: [WorkspaceFlatCommandMenuItemMapCacheService],
providers: [
WorkspaceFlatCommandMenuItemMapCacheService,
provideWorkspaceScopedRepository(CommandMenuItemEntity),
provideWorkspaceScopedRepository(PageLayoutEntity),
],
exports: [WorkspaceFlatCommandMenuItemMapCacheService],
})
export class FlatCommandMenuItemModule {}

View File

@@ -13,6 +13,8 @@ import { createEmptyFlatEntityMaps } from 'src/engine/metadata-modules/flat-enti
import { FrontComponentEntity } from 'src/engine/metadata-modules/front-component/entities/front-component.entity';
import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
import { PageLayoutEntity } from 'src/engine/metadata-modules/page-layout/entities/page-layout.entity';
import { InjectWorkspaceScopedRepository } from 'src/engine/twenty-orm/workspace-scoped-repository/inject-workspace-scoped-repository.decorator';
import { WorkspaceScopedRepository } from 'src/engine/twenty-orm/workspace-scoped-repository/workspace-scoped-repository';
import { WorkspaceCache } from 'src/engine/workspace-cache/decorators/workspace-cache.decorator';
import { createIdToUniversalIdentifierMap } from 'src/engine/workspace-cache/utils/create-id-to-universal-identifier-map.util';
import { addFlatEntityToFlatEntityMapsThroughMutationOrThrow } from 'src/engine/workspace-manager/workspace-migration/utils/add-flat-entity-to-flat-entity-maps-through-mutation-or-throw.util';
@@ -21,16 +23,16 @@ import { addFlatEntityToFlatEntityMapsThroughMutationOrThrow } from 'src/engine/
@WorkspaceCache('flatCommandMenuItemMaps')
export class WorkspaceFlatCommandMenuItemMapCacheService extends WorkspaceCacheProvider<FlatCommandMenuItemMaps> {
constructor(
@InjectRepository(CommandMenuItemEntity)
private readonly commandMenuItemRepository: Repository<CommandMenuItemEntity>,
@InjectWorkspaceScopedRepository(CommandMenuItemEntity)
private readonly commandMenuItemRepository: WorkspaceScopedRepository<CommandMenuItemEntity>,
@InjectRepository(ApplicationEntity)
private readonly applicationRepository: Repository<ApplicationEntity>,
@InjectRepository(ObjectMetadataEntity)
private readonly objectMetadataRepository: Repository<ObjectMetadataEntity>,
@InjectRepository(FrontComponentEntity)
private readonly frontComponentRepository: Repository<FrontComponentEntity>,
@InjectRepository(PageLayoutEntity)
private readonly pageLayoutRepository: Repository<PageLayoutEntity>,
@InjectWorkspaceScopedRepository(PageLayoutEntity)
private readonly pageLayoutRepository: WorkspaceScopedRepository<PageLayoutEntity>,
) {
super();
}
@@ -43,8 +45,7 @@ export class WorkspaceFlatCommandMenuItemMapCacheService extends WorkspaceCacheP
frontComponents,
pageLayouts,
] = await Promise.all([
this.commandMenuItemRepository.find({
where: { workspaceId },
this.commandMenuItemRepository.find(workspaceId, {
withDeleted: true,
}),
this.applicationRepository.find({
@@ -62,8 +63,7 @@ export class WorkspaceFlatCommandMenuItemMapCacheService extends WorkspaceCacheP
select: ['id', 'universalIdentifier'],
withDeleted: true,
}),
this.pageLayoutRepository.find({
where: { workspaceId },
this.pageLayoutRepository.find(workspaceId, {
select: ['id', 'universalIdentifier'],
withDeleted: true,
}),

View File

@@ -44,6 +44,7 @@ import { ViewFilterEntity } from 'src/engine/metadata-modules/view-filter/entiti
import { ViewGroupEntity } from 'src/engine/metadata-modules/view-group/entities/view-group.entity';
import { ViewSortEntity } from 'src/engine/metadata-modules/view-sort/entities/view-sort.entity';
import { ViewEntity } from 'src/engine/metadata-modules/view/entities/view.entity';
import { provideWorkspaceScopedRepository } from 'src/engine/twenty-orm/workspace-scoped-repository/provide-workspace-scoped-repository';
import { WorkspaceCacheModule } from 'src/engine/workspace-cache/workspace-cache.module';
@Module({
@@ -96,6 +97,23 @@ import { WorkspaceCacheModule } from 'src/engine/workspace-cache/workspace-cache
WorkspaceFlatPageLayoutWidgetMapCacheService,
WorkspaceFlatRowLevelPermissionPredicateMapCacheService,
WorkspaceFlatRowLevelPermissionPredicateGroupMapCacheService,
provideWorkspaceScopedRepository(PermissionFlagEntity),
provideWorkspaceScopedRepository(IndexMetadataEntity),
provideWorkspaceScopedRepository(ViewEntity),
provideWorkspaceScopedRepository(ViewFieldEntity),
provideWorkspaceScopedRepository(ViewFieldGroupEntity),
provideWorkspaceScopedRepository(ViewFilterEntity),
provideWorkspaceScopedRepository(ViewFilterGroupEntity),
provideWorkspaceScopedRepository(ViewGroupEntity),
provideWorkspaceScopedRepository(ViewSortEntity),
provideWorkspaceScopedRepository(PageLayoutEntity),
provideWorkspaceScopedRepository(PageLayoutTabEntity),
provideWorkspaceScopedRepository(PageLayoutWidgetEntity),
provideWorkspaceScopedRepository(ObjectPermissionEntity),
provideWorkspaceScopedRepository(FieldPermissionEntity),
provideWorkspaceScopedRepository(RoleEntity),
provideWorkspaceScopedRepository(RowLevelPermissionPredicateEntity),
provideWorkspaceScopedRepository(RowLevelPermissionPredicateGroupEntity),
],
exports: [
WorkspaceManyOrAllFlatEntityMapsCacheService,

View File

@@ -18,6 +18,8 @@ import { ViewFieldEntity } from 'src/engine/metadata-modules/view-field/entities
import { ViewFilterEntity } from 'src/engine/metadata-modules/view-filter/entities/view-filter.entity';
import { ViewGroupEntity } from 'src/engine/metadata-modules/view-group/entities/view-group.entity';
import { ViewEntity } from 'src/engine/metadata-modules/view/entities/view.entity';
import { InjectWorkspaceScopedRepository } from 'src/engine/twenty-orm/workspace-scoped-repository/inject-workspace-scoped-repository.decorator';
import { WorkspaceScopedRepository } from 'src/engine/twenty-orm/workspace-scoped-repository/workspace-scoped-repository';
import { WorkspaceCache } from 'src/engine/workspace-cache/decorators/workspace-cache.decorator';
import { createIdToUniversalIdentifierMap } from 'src/engine/workspace-cache/utils/create-id-to-universal-identifier-map.util';
import { regroupEntitiesByRelatedEntityId } from 'src/engine/workspace-cache/utils/regroup-entities-by-related-entity-id';
@@ -32,22 +34,22 @@ export class WorkspaceFlatFieldMetadataMapCacheService extends WorkspaceCachePro
constructor(
@InjectRepository(FieldMetadataEntity)
private readonly fieldMetadataRepository: Repository<FieldMetadataEntity>,
@InjectRepository(IndexMetadataEntity)
private readonly indexMetadataRepository: Repository<IndexMetadataEntity>,
@InjectWorkspaceScopedRepository(IndexMetadataEntity)
private readonly indexMetadataRepository: WorkspaceScopedRepository<IndexMetadataEntity>,
@InjectRepository(ObjectMetadataEntity)
private readonly objectMetadataRepository: Repository<ObjectMetadataEntity>,
@InjectRepository(ApplicationEntity)
private readonly applicationRepository: Repository<ApplicationEntity>,
@InjectRepository(ViewFieldEntity)
private readonly viewFieldRepository: Repository<ViewFieldEntity>,
@InjectRepository(ViewFilterEntity)
private readonly viewFilterRepository: Repository<ViewFilterEntity>,
@InjectRepository(ViewGroupEntity)
private readonly viewGroupRepository: Repository<ViewGroupEntity>,
@InjectRepository(ViewSortEntity)
private readonly viewSortRepository: Repository<ViewSortEntity>,
@InjectRepository(ViewEntity)
private readonly viewRepository: Repository<ViewEntity>,
@InjectWorkspaceScopedRepository(ViewFieldEntity)
private readonly viewFieldRepository: WorkspaceScopedRepository<ViewFieldEntity>,
@InjectWorkspaceScopedRepository(ViewFilterEntity)
private readonly viewFilterRepository: WorkspaceScopedRepository<ViewFilterEntity>,
@InjectWorkspaceScopedRepository(ViewGroupEntity)
private readonly viewGroupRepository: WorkspaceScopedRepository<ViewGroupEntity>,
@InjectWorkspaceScopedRepository(ViewSortEntity)
private readonly viewSortRepository: WorkspaceScopedRepository<ViewSortEntity>,
@InjectWorkspaceScopedRepository(ViewEntity)
private readonly viewRepository: WorkspaceScopedRepository<ViewEntity>,
) {
super();
}
@@ -69,8 +71,8 @@ export class WorkspaceFlatFieldMetadataMapCacheService extends WorkspaceCachePro
where: { workspaceId },
withDeleted: true,
}),
this.indexMetadataRepository.find({
where: { workspaceId, isUnique: true },
this.indexMetadataRepository.find(workspaceId, {
where: { isUnique: true },
relations: ['indexFieldMetadatas'],
withDeleted: true,
}),
@@ -84,23 +86,19 @@ export class WorkspaceFlatFieldMetadataMapCacheService extends WorkspaceCachePro
select: ['id', 'universalIdentifier'],
withDeleted: true,
}),
this.viewFieldRepository.find({
where: { workspaceId },
this.viewFieldRepository.find(workspaceId, {
select: ['id', 'universalIdentifier', 'fieldMetadataId'],
withDeleted: true,
}),
this.viewFilterRepository.find({
where: { workspaceId },
this.viewFilterRepository.find(workspaceId, {
select: ['id', 'universalIdentifier', 'fieldMetadataId'],
withDeleted: true,
}),
this.viewSortRepository.find({
where: { workspaceId },
this.viewSortRepository.find(workspaceId, {
select: ['id', 'universalIdentifier', 'fieldMetadataId'],
withDeleted: true,
}),
this.viewRepository.find({
where: { workspaceId },
this.viewRepository.find(workspaceId, {
select: [
'id',
'universalIdentifier',

View File

@@ -11,6 +11,8 @@ import { fromFieldPermissionEntityToFlatFieldPermission } from 'src/engine/metad
import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
import { FieldPermissionEntity } from 'src/engine/metadata-modules/object-permission/field-permission/field-permission.entity';
import { RoleEntity } from 'src/engine/metadata-modules/role/role.entity';
import { InjectWorkspaceScopedRepository } from 'src/engine/twenty-orm/workspace-scoped-repository/inject-workspace-scoped-repository.decorator';
import { WorkspaceScopedRepository } from 'src/engine/twenty-orm/workspace-scoped-repository/workspace-scoped-repository';
import { WorkspaceCache } from 'src/engine/workspace-cache/decorators/workspace-cache.decorator';
import { WorkspaceCacheProvider } from 'src/engine/workspace-cache/interfaces/workspace-cache-provider.service';
import { createIdToUniversalIdentifierMap } from 'src/engine/workspace-cache/utils/create-id-to-universal-identifier-map.util';
@@ -20,12 +22,12 @@ import { addFlatEntityToFlatEntityMapsThroughMutationOrThrow } from 'src/engine/
@WorkspaceCache('flatFieldPermissionMaps')
export class WorkspaceFlatFieldPermissionMapCacheService extends WorkspaceCacheProvider<FlatFieldPermissionMaps> {
constructor(
@InjectRepository(FieldPermissionEntity)
private readonly fieldPermissionRepository: Repository<FieldPermissionEntity>,
@InjectWorkspaceScopedRepository(FieldPermissionEntity)
private readonly fieldPermissionRepository: WorkspaceScopedRepository<FieldPermissionEntity>,
@InjectRepository(ApplicationEntity)
private readonly applicationRepository: Repository<ApplicationEntity>,
@InjectRepository(RoleEntity)
private readonly roleRepository: Repository<RoleEntity>,
@InjectWorkspaceScopedRepository(RoleEntity)
private readonly roleRepository: WorkspaceScopedRepository<RoleEntity>,
@InjectRepository(ObjectMetadataEntity)
private readonly objectMetadataRepository: Repository<ObjectMetadataEntity>,
@InjectRepository(FieldMetadataEntity)
@@ -42,8 +44,7 @@ export class WorkspaceFlatFieldPermissionMapCacheService extends WorkspaceCacheP
objectMetadatas,
fieldMetadatas,
] = await Promise.all([
this.fieldPermissionRepository.find({
where: { workspaceId },
this.fieldPermissionRepository.find(workspaceId, {
withDeleted: true,
}),
this.applicationRepository.find({
@@ -51,8 +52,7 @@ export class WorkspaceFlatFieldPermissionMapCacheService extends WorkspaceCacheP
select: ['id', 'universalIdentifier'],
withDeleted: true,
}),
this.roleRepository.find({
where: { workspaceId },
this.roleRepository.find(workspaceId, {
select: ['id', 'universalIdentifier'],
withDeleted: true,
}),

View File

@@ -13,6 +13,8 @@ import { FlatIndexMetadata } from 'src/engine/metadata-modules/flat-index-metada
import { fromIndexMetadataEntityToFlatIndexMetadata } from 'src/engine/metadata-modules/flat-index-metadata/utils/from-index-metadata-entity-to-flat-index-metadata.util';
import { IndexMetadataEntity } from 'src/engine/metadata-modules/index-metadata/index-metadata.entity';
import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
import { InjectWorkspaceScopedRepository } from 'src/engine/twenty-orm/workspace-scoped-repository/inject-workspace-scoped-repository.decorator';
import { WorkspaceScopedRepository } from 'src/engine/twenty-orm/workspace-scoped-repository/workspace-scoped-repository';
import { WorkspaceCache } from 'src/engine/workspace-cache/decorators/workspace-cache.decorator';
import { createIdToUniversalIdentifierMap } from 'src/engine/workspace-cache/utils/create-id-to-universal-identifier-map.util';
import { addFlatEntityToFlatEntityMapsThroughMutationOrThrow } from 'src/engine/workspace-manager/workspace-migration/utils/add-flat-entity-to-flat-entity-maps-through-mutation-or-throw.util';
@@ -23,8 +25,8 @@ export class WorkspaceFlatIndexMapCacheService extends WorkspaceCacheProvider<
FlatEntityMaps<FlatIndexMetadata>
> {
constructor(
@InjectRepository(IndexMetadataEntity)
private readonly indexMetadataRepository: Repository<IndexMetadataEntity>,
@InjectWorkspaceScopedRepository(IndexMetadataEntity)
private readonly indexMetadataRepository: WorkspaceScopedRepository<IndexMetadataEntity>,
@InjectRepository(ApplicationEntity)
private readonly applicationRepository: Repository<ApplicationEntity>,
@InjectRepository(ObjectMetadataEntity)
@@ -40,10 +42,7 @@ export class WorkspaceFlatIndexMapCacheService extends WorkspaceCacheProvider<
): Promise<FlatEntityMaps<FlatIndexMetadata>> {
const [indexes, applications, objectMetadatas, fieldMetadatas] =
await Promise.all([
this.indexMetadataRepository.find({
where: {
workspaceId,
},
this.indexMetadataRepository.find(workspaceId, {
withDeleted: true,
relationLoadStrategy: 'join',
relations: ['indexFieldMetadatas'],

View File

@@ -8,6 +8,7 @@ import { NavigationMenuItemEntity } from 'src/engine/metadata-modules/navigation
import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
import { PageLayoutEntity } from 'src/engine/metadata-modules/page-layout/entities/page-layout.entity';
import { ViewEntity } from 'src/engine/metadata-modules/view/entities/view.entity';
import { provideWorkspaceScopedRepository } from 'src/engine/twenty-orm/workspace-scoped-repository/provide-workspace-scoped-repository';
@Module({
imports: [
@@ -20,7 +21,12 @@ import { ViewEntity } from 'src/engine/metadata-modules/view/entities/view.entit
]),
WorkspaceManyOrAllFlatEntityMapsCacheModule,
],
providers: [WorkspaceFlatNavigationMenuItemMapCacheService],
providers: [
WorkspaceFlatNavigationMenuItemMapCacheService,
provideWorkspaceScopedRepository(NavigationMenuItemEntity),
provideWorkspaceScopedRepository(ViewEntity),
provideWorkspaceScopedRepository(PageLayoutEntity),
],
exports: [WorkspaceFlatNavigationMenuItemMapCacheService],
})
export class FlatNavigationMenuItemModule {}

View File

@@ -14,6 +14,8 @@ import { NavigationMenuItemEntity } from 'src/engine/metadata-modules/navigation
import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
import { PageLayoutEntity } from 'src/engine/metadata-modules/page-layout/entities/page-layout.entity';
import { ViewEntity } from 'src/engine/metadata-modules/view/entities/view.entity';
import { InjectWorkspaceScopedRepository } from 'src/engine/twenty-orm/workspace-scoped-repository/inject-workspace-scoped-repository.decorator';
import { WorkspaceScopedRepository } from 'src/engine/twenty-orm/workspace-scoped-repository/workspace-scoped-repository';
import { WorkspaceCache } from 'src/engine/workspace-cache/decorators/workspace-cache.decorator';
import { createIdToUniversalIdentifierMap } from 'src/engine/workspace-cache/utils/create-id-to-universal-identifier-map.util';
@@ -21,16 +23,16 @@ import { createIdToUniversalIdentifierMap } from 'src/engine/workspace-cache/uti
@WorkspaceCache('flatNavigationMenuItemMaps')
export class WorkspaceFlatNavigationMenuItemMapCacheService extends WorkspaceCacheProvider<FlatNavigationMenuItemMaps> {
constructor(
@InjectRepository(NavigationMenuItemEntity)
private readonly navigationMenuItemRepository: Repository<NavigationMenuItemEntity>,
@InjectWorkspaceScopedRepository(NavigationMenuItemEntity)
private readonly navigationMenuItemRepository: WorkspaceScopedRepository<NavigationMenuItemEntity>,
@InjectRepository(ApplicationEntity)
private readonly applicationRepository: Repository<ApplicationEntity>,
@InjectRepository(ObjectMetadataEntity)
private readonly objectMetadataRepository: Repository<ObjectMetadataEntity>,
@InjectRepository(ViewEntity)
private readonly viewRepository: Repository<ViewEntity>,
@InjectRepository(PageLayoutEntity)
private readonly pageLayoutRepository: Repository<PageLayoutEntity>,
@InjectWorkspaceScopedRepository(ViewEntity)
private readonly viewRepository: WorkspaceScopedRepository<ViewEntity>,
@InjectWorkspaceScopedRepository(PageLayoutEntity)
private readonly pageLayoutRepository: WorkspaceScopedRepository<PageLayoutEntity>,
) {
super();
}
@@ -45,8 +47,7 @@ export class WorkspaceFlatNavigationMenuItemMapCacheService extends WorkspaceCac
views,
pageLayouts,
] = await Promise.all([
this.navigationMenuItemRepository.find({
where: { workspaceId },
this.navigationMenuItemRepository.find(workspaceId, {
withDeleted: true,
}),
this.applicationRepository.find({
@@ -59,13 +60,11 @@ export class WorkspaceFlatNavigationMenuItemMapCacheService extends WorkspaceCac
select: ['id', 'universalIdentifier'],
withDeleted: true,
}),
this.viewRepository.find({
where: { workspaceId },
this.viewRepository.find(workspaceId, {
select: ['id', 'universalIdentifier'],
withDeleted: true,
}),
this.pageLayoutRepository.find({
where: { workspaceId },
this.pageLayoutRepository.find(workspaceId, {
select: ['id', 'universalIdentifier'],
withDeleted: true,
}),

View File

@@ -15,6 +15,8 @@ import { IndexMetadataEntity } from 'src/engine/metadata-modules/index-metadata/
import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
import { ObjectPermissionEntity } from 'src/engine/metadata-modules/object-permission/object-permission.entity';
import { ViewEntity } from 'src/engine/metadata-modules/view/entities/view.entity';
import { InjectWorkspaceScopedRepository } from 'src/engine/twenty-orm/workspace-scoped-repository/inject-workspace-scoped-repository.decorator';
import { WorkspaceScopedRepository } from 'src/engine/twenty-orm/workspace-scoped-repository/workspace-scoped-repository';
import { WorkspaceCache } from 'src/engine/workspace-cache/decorators/workspace-cache.decorator';
import { createIdToUniversalIdentifierMap } from 'src/engine/workspace-cache/utils/create-id-to-universal-identifier-map.util';
import { regroupEntitiesByRelatedEntityId } from 'src/engine/workspace-cache/utils/regroup-entities-by-related-entity-id';
@@ -32,12 +34,12 @@ export class WorkspaceFlatObjectMetadataMapCacheService extends WorkspaceCachePr
private readonly applicationRepository: Repository<ApplicationEntity>,
@InjectRepository(FieldMetadataEntity)
private readonly fieldMetadataRepository: Repository<FieldMetadataEntity>,
@InjectRepository(IndexMetadataEntity)
private readonly indexMetadataRepository: Repository<IndexMetadataEntity>,
@InjectRepository(ViewEntity)
private readonly viewRepository: Repository<ViewEntity>,
@InjectRepository(ObjectPermissionEntity)
private readonly objectPermissionRepository: Repository<ObjectPermissionEntity>,
@InjectWorkspaceScopedRepository(IndexMetadataEntity)
private readonly indexMetadataRepository: WorkspaceScopedRepository<IndexMetadataEntity>,
@InjectWorkspaceScopedRepository(ViewEntity)
private readonly viewRepository: WorkspaceScopedRepository<ViewEntity>,
@InjectWorkspaceScopedRepository(ObjectPermissionEntity)
private readonly objectPermissionRepository: WorkspaceScopedRepository<ObjectPermissionEntity>,
) {
super();
}
@@ -67,18 +69,15 @@ export class WorkspaceFlatObjectMetadataMapCacheService extends WorkspaceCachePr
select: ['id', 'universalIdentifier', 'objectMetadataId'],
withDeleted: true,
}),
this.indexMetadataRepository.find({
where: { workspaceId },
this.indexMetadataRepository.find(workspaceId, {
select: ['id', 'universalIdentifier', 'objectMetadataId'],
withDeleted: true,
}),
this.viewRepository.find({
where: { workspaceId },
this.viewRepository.find(workspaceId, {
select: ['id', 'universalIdentifier', 'objectMetadataId'],
withDeleted: true,
}),
this.objectPermissionRepository.find({
where: { workspaceId },
this.objectPermissionRepository.find(workspaceId, {
select: ['id', 'universalIdentifier', 'objectMetadataId'],
withDeleted: true,
}),

View File

@@ -10,6 +10,8 @@ import { fromObjectPermissionEntityToFlatObjectPermission } from 'src/engine/met
import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
import { ObjectPermissionEntity } from 'src/engine/metadata-modules/object-permission/object-permission.entity';
import { RoleEntity } from 'src/engine/metadata-modules/role/role.entity';
import { InjectWorkspaceScopedRepository } from 'src/engine/twenty-orm/workspace-scoped-repository/inject-workspace-scoped-repository.decorator';
import { WorkspaceScopedRepository } from 'src/engine/twenty-orm/workspace-scoped-repository/workspace-scoped-repository';
import { WorkspaceCache } from 'src/engine/workspace-cache/decorators/workspace-cache.decorator';
import { WorkspaceCacheProvider } from 'src/engine/workspace-cache/interfaces/workspace-cache-provider.service';
import { createIdToUniversalIdentifierMap } from 'src/engine/workspace-cache/utils/create-id-to-universal-identifier-map.util';
@@ -19,12 +21,12 @@ import { addFlatEntityToFlatEntityMapsThroughMutationOrThrow } from 'src/engine/
@WorkspaceCache('flatObjectPermissionMaps')
export class WorkspaceFlatObjectPermissionMapCacheService extends WorkspaceCacheProvider<FlatObjectPermissionMaps> {
constructor(
@InjectRepository(ObjectPermissionEntity)
private readonly objectPermissionRepository: Repository<ObjectPermissionEntity>,
@InjectWorkspaceScopedRepository(ObjectPermissionEntity)
private readonly objectPermissionRepository: WorkspaceScopedRepository<ObjectPermissionEntity>,
@InjectRepository(ApplicationEntity)
private readonly applicationRepository: Repository<ApplicationEntity>,
@InjectRepository(RoleEntity)
private readonly roleRepository: Repository<RoleEntity>,
@InjectWorkspaceScopedRepository(RoleEntity)
private readonly roleRepository: WorkspaceScopedRepository<RoleEntity>,
@InjectRepository(ObjectMetadataEntity)
private readonly objectMetadataRepository: Repository<ObjectMetadataEntity>,
) {
@@ -36,8 +38,7 @@ export class WorkspaceFlatObjectPermissionMapCacheService extends WorkspaceCache
): Promise<FlatObjectPermissionMaps> {
const [objectPermissions, applications, roles, objectMetadatas] =
await Promise.all([
this.objectPermissionRepository.find({
where: { workspaceId },
this.objectPermissionRepository.find(workspaceId, {
withDeleted: true,
}),
this.applicationRepository.find({
@@ -45,8 +46,7 @@ export class WorkspaceFlatObjectPermissionMapCacheService extends WorkspaceCache
select: ['id', 'universalIdentifier'],
withDeleted: true,
}),
this.roleRepository.find({
where: { workspaceId },
this.roleRepository.find(workspaceId, {
select: ['id', 'universalIdentifier'],
withDeleted: true,
}),

View File

@@ -7,6 +7,7 @@ import { WorkspaceFlatPageLayoutTabMapCacheService } from 'src/engine/metadata-m
import { PageLayoutTabEntity } from 'src/engine/metadata-modules/page-layout-tab/entities/page-layout-tab.entity';
import { PageLayoutWidgetEntity } from 'src/engine/metadata-modules/page-layout-widget/entities/page-layout-widget.entity';
import { PageLayoutEntity } from 'src/engine/metadata-modules/page-layout/entities/page-layout.entity';
import { provideWorkspaceScopedRepository } from 'src/engine/twenty-orm/workspace-scoped-repository/provide-workspace-scoped-repository';
@Module({
imports: [
@@ -18,7 +19,12 @@ import { PageLayoutEntity } from 'src/engine/metadata-modules/page-layout/entiti
]),
WorkspaceManyOrAllFlatEntityMapsCacheModule,
],
providers: [WorkspaceFlatPageLayoutTabMapCacheService],
providers: [
WorkspaceFlatPageLayoutTabMapCacheService,
provideWorkspaceScopedRepository(PageLayoutEntity),
provideWorkspaceScopedRepository(PageLayoutTabEntity),
provideWorkspaceScopedRepository(PageLayoutWidgetEntity),
],
exports: [WorkspaceFlatPageLayoutTabMapCacheService],
})
export class FlatPageLayoutTabModule {}

View File

@@ -12,6 +12,8 @@ import { transformPageLayoutTabEntityToFlatPageLayoutTab } from 'src/engine/meta
import { PageLayoutTabEntity } from 'src/engine/metadata-modules/page-layout-tab/entities/page-layout-tab.entity';
import { PageLayoutWidgetEntity } from 'src/engine/metadata-modules/page-layout-widget/entities/page-layout-widget.entity';
import { PageLayoutEntity } from 'src/engine/metadata-modules/page-layout/entities/page-layout.entity';
import { InjectWorkspaceScopedRepository } from 'src/engine/twenty-orm/workspace-scoped-repository/inject-workspace-scoped-repository.decorator';
import { WorkspaceScopedRepository } from 'src/engine/twenty-orm/workspace-scoped-repository/workspace-scoped-repository';
import { WorkspaceCache } from 'src/engine/workspace-cache/decorators/workspace-cache.decorator';
import { createIdToUniversalIdentifierMap } from 'src/engine/workspace-cache/utils/create-id-to-universal-identifier-map.util';
import { regroupEntitiesByRelatedEntityId } from 'src/engine/workspace-cache/utils/regroup-entities-by-related-entity-id';
@@ -21,14 +23,14 @@ import { addFlatEntityToFlatEntityMapsThroughMutationOrThrow } from 'src/engine/
@WorkspaceCache('flatPageLayoutTabMaps')
export class WorkspaceFlatPageLayoutTabMapCacheService extends WorkspaceCacheProvider<FlatPageLayoutTabMaps> {
constructor(
@InjectRepository(PageLayoutTabEntity)
private readonly pageLayoutTabRepository: Repository<PageLayoutTabEntity>,
@InjectRepository(PageLayoutWidgetEntity)
private readonly pageLayoutWidgetRepository: Repository<PageLayoutWidgetEntity>,
@InjectWorkspaceScopedRepository(PageLayoutTabEntity)
private readonly pageLayoutTabRepository: WorkspaceScopedRepository<PageLayoutTabEntity>,
@InjectWorkspaceScopedRepository(PageLayoutWidgetEntity)
private readonly pageLayoutWidgetRepository: WorkspaceScopedRepository<PageLayoutWidgetEntity>,
@InjectRepository(ApplicationEntity)
private readonly applicationRepository: Repository<ApplicationEntity>,
@InjectRepository(PageLayoutEntity)
private readonly pageLayoutRepository: Repository<PageLayoutEntity>,
@InjectWorkspaceScopedRepository(PageLayoutEntity)
private readonly pageLayoutRepository: WorkspaceScopedRepository<PageLayoutEntity>,
) {
super();
}
@@ -36,12 +38,10 @@ export class WorkspaceFlatPageLayoutTabMapCacheService extends WorkspaceCachePro
async computeForCache(workspaceId: string): Promise<FlatPageLayoutTabMaps> {
const [pageLayoutTabs, pageLayoutWidgets, applications, pageLayouts] =
await Promise.all([
this.pageLayoutTabRepository.find({
where: { workspaceId },
this.pageLayoutTabRepository.find(workspaceId, {
withDeleted: true,
}),
this.pageLayoutWidgetRepository.find({
where: { workspaceId },
this.pageLayoutWidgetRepository.find(workspaceId, {
select: ['id', 'universalIdentifier', 'pageLayoutTabId'],
withDeleted: true,
}),
@@ -50,8 +50,7 @@ export class WorkspaceFlatPageLayoutTabMapCacheService extends WorkspaceCachePro
select: ['id', 'universalIdentifier'],
withDeleted: true,
}),
this.pageLayoutRepository.find({
where: { workspaceId },
this.pageLayoutRepository.find(workspaceId, {
select: ['id', 'universalIdentifier'],
withDeleted: true,
}),

View File

@@ -10,6 +10,7 @@ import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadat
import { PageLayoutTabEntity } from 'src/engine/metadata-modules/page-layout-tab/entities/page-layout-tab.entity';
import { PageLayoutWidgetEntity } from 'src/engine/metadata-modules/page-layout-widget/entities/page-layout-widget.entity';
import { ViewEntity } from 'src/engine/metadata-modules/view/entities/view.entity';
import { provideWorkspaceScopedRepository } from 'src/engine/twenty-orm/workspace-scoped-repository/provide-workspace-scoped-repository';
@Module({
imports: [
@@ -26,6 +27,9 @@ import { ViewEntity } from 'src/engine/metadata-modules/view/entities/view.entit
providers: [
WorkspaceFlatPageLayoutWidgetMapCacheService,
FlatPageLayoutWidgetTypeValidatorService,
provideWorkspaceScopedRepository(PageLayoutTabEntity),
provideWorkspaceScopedRepository(PageLayoutWidgetEntity),
provideWorkspaceScopedRepository(ViewEntity),
],
exports: [
WorkspaceFlatPageLayoutWidgetMapCacheService,

View File

@@ -15,6 +15,8 @@ import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadat
import { PageLayoutTabEntity } from 'src/engine/metadata-modules/page-layout-tab/entities/page-layout-tab.entity';
import { PageLayoutWidgetEntity } from 'src/engine/metadata-modules/page-layout-widget/entities/page-layout-widget.entity';
import { ViewEntity } from 'src/engine/metadata-modules/view/entities/view.entity';
import { InjectWorkspaceScopedRepository } from 'src/engine/twenty-orm/workspace-scoped-repository/inject-workspace-scoped-repository.decorator';
import { WorkspaceScopedRepository } from 'src/engine/twenty-orm/workspace-scoped-repository/workspace-scoped-repository';
import { WorkspaceCache } from 'src/engine/workspace-cache/decorators/workspace-cache.decorator';
import { createIdToUniversalIdentifierMap } from 'src/engine/workspace-cache/utils/create-id-to-universal-identifier-map.util';
import { addFlatEntityToFlatEntityMapsThroughMutationOrThrow } from 'src/engine/workspace-manager/workspace-migration/utils/add-flat-entity-to-flat-entity-maps-through-mutation-or-throw.util';
@@ -23,20 +25,20 @@ import { addFlatEntityToFlatEntityMapsThroughMutationOrThrow } from 'src/engine/
@WorkspaceCache('flatPageLayoutWidgetMaps')
export class WorkspaceFlatPageLayoutWidgetMapCacheService extends WorkspaceCacheProvider<FlatPageLayoutWidgetMaps> {
constructor(
@InjectRepository(PageLayoutWidgetEntity)
private readonly pageLayoutWidgetRepository: Repository<PageLayoutWidgetEntity>,
@InjectWorkspaceScopedRepository(PageLayoutWidgetEntity)
private readonly pageLayoutWidgetRepository: WorkspaceScopedRepository<PageLayoutWidgetEntity>,
@InjectRepository(ApplicationEntity)
private readonly applicationRepository: Repository<ApplicationEntity>,
@InjectRepository(PageLayoutTabEntity)
private readonly pageLayoutTabRepository: Repository<PageLayoutTabEntity>,
@InjectWorkspaceScopedRepository(PageLayoutTabEntity)
private readonly pageLayoutTabRepository: WorkspaceScopedRepository<PageLayoutTabEntity>,
@InjectRepository(ObjectMetadataEntity)
private readonly objectMetadataRepository: Repository<ObjectMetadataEntity>,
@InjectRepository(FieldMetadataEntity)
private readonly fieldMetadataRepository: Repository<FieldMetadataEntity>,
@InjectRepository(FrontComponentEntity)
private readonly frontComponentRepository: Repository<FrontComponentEntity>,
@InjectRepository(ViewEntity)
private readonly viewRepository: Repository<ViewEntity>,
@InjectWorkspaceScopedRepository(ViewEntity)
private readonly viewRepository: WorkspaceScopedRepository<ViewEntity>,
) {
super();
}
@@ -53,8 +55,7 @@ export class WorkspaceFlatPageLayoutWidgetMapCacheService extends WorkspaceCache
frontComponents,
views,
] = await Promise.all([
this.pageLayoutWidgetRepository.find({
where: { workspaceId },
this.pageLayoutWidgetRepository.find(workspaceId, {
withDeleted: true,
}),
this.applicationRepository.find({
@@ -62,8 +63,7 @@ export class WorkspaceFlatPageLayoutWidgetMapCacheService extends WorkspaceCache
select: ['id', 'universalIdentifier'],
withDeleted: true,
}),
this.pageLayoutTabRepository.find({
where: { workspaceId },
this.pageLayoutTabRepository.find(workspaceId, {
select: ['id', 'universalIdentifier'],
withDeleted: true,
}),
@@ -82,8 +82,7 @@ export class WorkspaceFlatPageLayoutWidgetMapCacheService extends WorkspaceCache
select: ['id', 'universalIdentifier'],
withDeleted: true,
}),
this.viewRepository.find({
where: { workspaceId },
this.viewRepository.find(workspaceId, {
select: ['id', 'universalIdentifier'],
withDeleted: true,
}),

View File

@@ -6,6 +6,7 @@ import { WorkspaceFlatPageLayoutMapCacheService } from 'src/engine/metadata-modu
import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
import { PageLayoutTabEntity } from 'src/engine/metadata-modules/page-layout-tab/entities/page-layout-tab.entity';
import { PageLayoutEntity } from 'src/engine/metadata-modules/page-layout/entities/page-layout.entity';
import { provideWorkspaceScopedRepository } from 'src/engine/twenty-orm/workspace-scoped-repository/provide-workspace-scoped-repository';
@Module({
imports: [
@@ -16,7 +17,11 @@ import { PageLayoutEntity } from 'src/engine/metadata-modules/page-layout/entiti
ObjectMetadataEntity,
]),
],
providers: [WorkspaceFlatPageLayoutMapCacheService],
providers: [
WorkspaceFlatPageLayoutMapCacheService,
provideWorkspaceScopedRepository(PageLayoutEntity),
provideWorkspaceScopedRepository(PageLayoutTabEntity),
],
exports: [WorkspaceFlatPageLayoutMapCacheService],
})
export class FlatPageLayoutModule {}

View File

@@ -12,6 +12,8 @@ import { transformPageLayoutEntityToFlatPageLayout } from 'src/engine/metadata-m
import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
import { PageLayoutTabEntity } from 'src/engine/metadata-modules/page-layout-tab/entities/page-layout-tab.entity';
import { PageLayoutEntity } from 'src/engine/metadata-modules/page-layout/entities/page-layout.entity';
import { InjectWorkspaceScopedRepository } from 'src/engine/twenty-orm/workspace-scoped-repository/inject-workspace-scoped-repository.decorator';
import { WorkspaceScopedRepository } from 'src/engine/twenty-orm/workspace-scoped-repository/workspace-scoped-repository';
import { WorkspaceCache } from 'src/engine/workspace-cache/decorators/workspace-cache.decorator';
import { createIdToUniversalIdentifierMap } from 'src/engine/workspace-cache/utils/create-id-to-universal-identifier-map.util';
import { regroupEntitiesByRelatedEntityId } from 'src/engine/workspace-cache/utils/regroup-entities-by-related-entity-id';
@@ -21,10 +23,10 @@ import { addFlatEntityToFlatEntityMapsThroughMutationOrThrow } from 'src/engine/
@WorkspaceCache('flatPageLayoutMaps')
export class WorkspaceFlatPageLayoutMapCacheService extends WorkspaceCacheProvider<FlatPageLayoutMaps> {
constructor(
@InjectRepository(PageLayoutEntity)
private readonly pageLayoutRepository: Repository<PageLayoutEntity>,
@InjectRepository(PageLayoutTabEntity)
private readonly pageLayoutTabRepository: Repository<PageLayoutTabEntity>,
@InjectWorkspaceScopedRepository(PageLayoutEntity)
private readonly pageLayoutRepository: WorkspaceScopedRepository<PageLayoutEntity>,
@InjectWorkspaceScopedRepository(PageLayoutTabEntity)
private readonly pageLayoutTabRepository: WorkspaceScopedRepository<PageLayoutTabEntity>,
@InjectRepository(ApplicationEntity)
private readonly applicationRepository: Repository<ApplicationEntity>,
@InjectRepository(ObjectMetadataEntity)
@@ -36,12 +38,10 @@ export class WorkspaceFlatPageLayoutMapCacheService extends WorkspaceCacheProvid
async computeForCache(workspaceId: string): Promise<FlatPageLayoutMaps> {
const [pageLayouts, pageLayoutTabs, applications, objectMetadatas] =
await Promise.all([
this.pageLayoutRepository.find({
where: { workspaceId },
this.pageLayoutRepository.find(workspaceId, {
withDeleted: true,
}),
this.pageLayoutTabRepository.find({
where: { workspaceId },
this.pageLayoutTabRepository.find(workspaceId, {
select: ['id', 'universalIdentifier', 'pageLayoutId'],
withDeleted: true,
}),

View File

@@ -6,6 +6,7 @@ import { WorkspaceManyOrAllFlatEntityMapsCacheModule } from 'src/engine/metadata
import { WorkspaceFlatPermissionFlagMapCacheService } from 'src/engine/metadata-modules/flat-permission-flag/services/workspace-flat-permission-flag-map-cache.service';
import { PermissionFlagEntity } from 'src/engine/metadata-modules/permission-flag/permission-flag.entity';
import { RolePermissionFlagEntity } from 'src/engine/metadata-modules/role-permission-flag/role-permission-flag.entity';
import { provideWorkspaceScopedRepository } from 'src/engine/twenty-orm/workspace-scoped-repository/provide-workspace-scoped-repository';
@Module({
imports: [
@@ -16,7 +17,10 @@ import { RolePermissionFlagEntity } from 'src/engine/metadata-modules/role-permi
]),
WorkspaceManyOrAllFlatEntityMapsCacheModule,
],
providers: [WorkspaceFlatPermissionFlagMapCacheService],
providers: [
WorkspaceFlatPermissionFlagMapCacheService,
provideWorkspaceScopedRepository(PermissionFlagEntity),
],
exports: [WorkspaceFlatPermissionFlagMapCacheService],
})
export class FlatPermissionFlagModule {}

View File

@@ -9,6 +9,8 @@ import { type FlatPermissionFlagMaps } from 'src/engine/metadata-modules/flat-pe
import { fromPermissionFlagEntityToFlatPermissionFlag } from 'src/engine/metadata-modules/flat-permission-flag/utils/from-permission-flag-entity-to-flat-permission-flag.util';
import { PermissionFlagEntity } from 'src/engine/metadata-modules/permission-flag/permission-flag.entity';
import { RolePermissionFlagEntity } from 'src/engine/metadata-modules/role-permission-flag/role-permission-flag.entity';
import { InjectWorkspaceScopedRepository } from 'src/engine/twenty-orm/workspace-scoped-repository/inject-workspace-scoped-repository.decorator';
import { WorkspaceScopedRepository } from 'src/engine/twenty-orm/workspace-scoped-repository/workspace-scoped-repository';
import { WorkspaceCache } from 'src/engine/workspace-cache/decorators/workspace-cache.decorator';
import { WorkspaceCacheProvider } from 'src/engine/workspace-cache/interfaces/workspace-cache-provider.service';
import { createIdToUniversalIdentifierMap } from 'src/engine/workspace-cache/utils/create-id-to-universal-identifier-map.util';
@@ -19,8 +21,8 @@ import { addFlatEntityToFlatEntityMapsThroughMutationOrThrow } from 'src/engine/
@WorkspaceCache('flatPermissionFlagMaps')
export class WorkspaceFlatPermissionFlagMapCacheService extends WorkspaceCacheProvider<FlatPermissionFlagMaps> {
constructor(
@InjectRepository(PermissionFlagEntity)
private readonly permissionFlagRepository: Repository<PermissionFlagEntity>,
@InjectWorkspaceScopedRepository(PermissionFlagEntity)
private readonly permissionFlagRepository: WorkspaceScopedRepository<PermissionFlagEntity>,
@InjectRepository(ApplicationEntity)
private readonly applicationRepository: Repository<ApplicationEntity>,
@InjectRepository(RolePermissionFlagEntity)
@@ -32,8 +34,7 @@ export class WorkspaceFlatPermissionFlagMapCacheService extends WorkspaceCachePr
async computeForCache(workspaceId: string): Promise<FlatPermissionFlagMaps> {
const [permissionFlags, applications, rolePermissionFlags] =
await Promise.all([
this.permissionFlagRepository.find({
where: { workspaceId },
this.permissionFlagRepository.find(workspaceId, {
withDeleted: true,
}),
this.applicationRepository.find({

View File

@@ -10,6 +10,8 @@ import { fromRolePermissionFlagEntityToFlatRolePermissionFlag } from 'src/engine
import { PermissionFlagEntity } from 'src/engine/metadata-modules/permission-flag/permission-flag.entity';
import { RolePermissionFlagEntity } from 'src/engine/metadata-modules/role-permission-flag/role-permission-flag.entity';
import { RoleEntity } from 'src/engine/metadata-modules/role/role.entity';
import { InjectWorkspaceScopedRepository } from 'src/engine/twenty-orm/workspace-scoped-repository/inject-workspace-scoped-repository.decorator';
import { WorkspaceScopedRepository } from 'src/engine/twenty-orm/workspace-scoped-repository/workspace-scoped-repository';
import { WorkspaceCacheProvider } from 'src/engine/workspace-cache/interfaces/workspace-cache-provider.service';
import { WorkspaceCache } from 'src/engine/workspace-cache/decorators/workspace-cache.decorator';
import { createIdToUniversalIdentifierMap } from 'src/engine/workspace-cache/utils/create-id-to-universal-identifier-map.util';
@@ -23,10 +25,10 @@ export class WorkspaceFlatRolePermissionFlagMapCacheService extends WorkspaceCac
private readonly rolePermissionFlagRepository: Repository<RolePermissionFlagEntity>,
@InjectRepository(ApplicationEntity)
private readonly applicationRepository: Repository<ApplicationEntity>,
@InjectRepository(RoleEntity)
private readonly roleRepository: Repository<RoleEntity>,
@InjectRepository(PermissionFlagEntity)
private readonly permissionFlagRepository: Repository<PermissionFlagEntity>,
@InjectWorkspaceScopedRepository(RoleEntity)
private readonly roleRepository: WorkspaceScopedRepository<RoleEntity>,
@InjectWorkspaceScopedRepository(PermissionFlagEntity)
private readonly permissionFlagRepository: WorkspaceScopedRepository<PermissionFlagEntity>,
) {
super();
}
@@ -45,13 +47,11 @@ export class WorkspaceFlatRolePermissionFlagMapCacheService extends WorkspaceCac
select: ['id', 'universalIdentifier'],
withDeleted: true,
}),
this.roleRepository.find({
where: { workspaceId },
this.roleRepository.find(workspaceId, {
select: ['id', 'universalIdentifier'],
withDeleted: true,
}),
this.permissionFlagRepository.find({
where: { workspaceId },
this.permissionFlagRepository.find(workspaceId, {
select: ['id', 'universalIdentifier'],
withDeleted: true,
}),

View File

@@ -11,6 +11,8 @@ import { type FlatRoleTargetMaps } from 'src/engine/metadata-modules/flat-role-t
import { fromRoleTargetEntityToFlatRoleTarget } from 'src/engine/metadata-modules/flat-role-target/utils/from-role-target-entity-to-flat-role-target.util';
import { RoleEntity } from 'src/engine/metadata-modules/role/role.entity';
import { RoleTargetEntity } from 'src/engine/metadata-modules/role-target/role-target.entity';
import { InjectWorkspaceScopedRepository } from 'src/engine/twenty-orm/workspace-scoped-repository/inject-workspace-scoped-repository.decorator';
import { WorkspaceScopedRepository } from 'src/engine/twenty-orm/workspace-scoped-repository/workspace-scoped-repository';
import { WorkspaceCache } from 'src/engine/workspace-cache/decorators/workspace-cache.decorator';
import { createIdToUniversalIdentifierMap } from 'src/engine/workspace-cache/utils/create-id-to-universal-identifier-map.util';
import { addFlatEntityToFlatEntityMapsThroughMutationOrThrow } from 'src/engine/workspace-manager/workspace-migration/utils/add-flat-entity-to-flat-entity-maps-through-mutation-or-throw.util';
@@ -19,20 +21,19 @@ import { addFlatEntityToFlatEntityMapsThroughMutationOrThrow } from 'src/engine/
@WorkspaceCache('flatRoleTargetMaps')
export class WorkspaceFlatRoleTargetMapCacheService extends WorkspaceCacheProvider<FlatRoleTargetMaps> {
constructor(
@InjectRepository(RoleTargetEntity)
private readonly roleTargetRepository: Repository<RoleTargetEntity>,
@InjectWorkspaceScopedRepository(RoleTargetEntity)
private readonly roleTargetRepository: WorkspaceScopedRepository<RoleTargetEntity>,
@InjectRepository(ApplicationEntity)
private readonly applicationRepository: Repository<ApplicationEntity>,
@InjectRepository(RoleEntity)
private readonly roleRepository: Repository<RoleEntity>,
@InjectWorkspaceScopedRepository(RoleEntity)
private readonly roleRepository: WorkspaceScopedRepository<RoleEntity>,
) {
super();
}
async computeForCache(workspaceId: string): Promise<FlatRoleTargetMaps> {
const [roleTargets, applications, roles] = await Promise.all([
this.roleTargetRepository.find({
where: { workspaceId },
this.roleTargetRepository.find(workspaceId, {
withDeleted: true,
}),
this.applicationRepository.find({
@@ -40,8 +41,7 @@ export class WorkspaceFlatRoleTargetMapCacheService extends WorkspaceCacheProvid
select: ['id', 'universalIdentifier'],
withDeleted: true,
}),
this.roleRepository.find({
where: { workspaceId },
this.roleRepository.find(workspaceId, {
select: ['id', 'universalIdentifier'],
withDeleted: true,
}),

View File

@@ -15,6 +15,8 @@ import { RoleEntity } from 'src/engine/metadata-modules/role/role.entity';
import { RowLevelPermissionPredicateGroupEntity } from 'src/engine/metadata-modules/row-level-permission-predicate/entities/row-level-permission-predicate-group.entity';
import { RowLevelPermissionPredicateEntity } from 'src/engine/metadata-modules/row-level-permission-predicate/entities/row-level-permission-predicate.entity';
import { type FlatRowLevelPermissionPredicateGroupMaps } from 'src/engine/metadata-modules/row-level-permission-predicate/types/flat-row-level-permission-predicate-group-maps.type';
import { InjectWorkspaceScopedRepository } from 'src/engine/twenty-orm/workspace-scoped-repository/inject-workspace-scoped-repository.decorator';
import { WorkspaceScopedRepository } from 'src/engine/twenty-orm/workspace-scoped-repository/workspace-scoped-repository';
import { WorkspaceCache } from 'src/engine/workspace-cache/decorators/workspace-cache.decorator';
import { createIdToUniversalIdentifierMap } from 'src/engine/workspace-cache/utils/create-id-to-universal-identifier-map.util';
import { regroupEntitiesByRelatedEntityId } from 'src/engine/workspace-cache/utils/regroup-entities-by-related-entity-id';
@@ -24,16 +26,16 @@ import { addFlatEntityToFlatEntityMapsThroughMutationOrThrow } from 'src/engine/
@WorkspaceCache('flatRowLevelPermissionPredicateGroupMaps')
export class WorkspaceFlatRowLevelPermissionPredicateGroupMapCacheService extends WorkspaceCacheProvider<FlatRowLevelPermissionPredicateGroupMaps> {
constructor(
@InjectRepository(RowLevelPermissionPredicateGroupEntity)
private readonly rowLevelPermissionPredicateGroupRepository: Repository<RowLevelPermissionPredicateGroupEntity>,
@InjectWorkspaceScopedRepository(RowLevelPermissionPredicateGroupEntity)
private readonly rowLevelPermissionPredicateGroupRepository: WorkspaceScopedRepository<RowLevelPermissionPredicateGroupEntity>,
@InjectRepository(ApplicationEntity)
private readonly applicationRepository: Repository<ApplicationEntity>,
@InjectRepository(ObjectMetadataEntity)
private readonly objectMetadataRepository: Repository<ObjectMetadataEntity>,
@InjectRepository(RoleEntity)
private readonly roleRepository: Repository<RoleEntity>,
@InjectRepository(RowLevelPermissionPredicateEntity)
private readonly rowLevelPermissionPredicateRepository: Repository<RowLevelPermissionPredicateEntity>,
@InjectWorkspaceScopedRepository(RoleEntity)
private readonly roleRepository: WorkspaceScopedRepository<RoleEntity>,
@InjectWorkspaceScopedRepository(RowLevelPermissionPredicateEntity)
private readonly rowLevelPermissionPredicateRepository: WorkspaceScopedRepository<RowLevelPermissionPredicateEntity>,
) {
super();
}
@@ -48,8 +50,7 @@ export class WorkspaceFlatRowLevelPermissionPredicateGroupMapCacheService extend
roles,
rowLevelPermissionPredicates,
] = await Promise.all([
this.rowLevelPermissionPredicateGroupRepository.find({
where: { workspaceId },
this.rowLevelPermissionPredicateGroupRepository.find(workspaceId, {
withDeleted: true,
}),
this.applicationRepository.find({
@@ -62,13 +63,11 @@ export class WorkspaceFlatRowLevelPermissionPredicateGroupMapCacheService extend
select: ['id', 'universalIdentifier'],
withDeleted: true,
}),
this.roleRepository.find({
where: { workspaceId },
this.roleRepository.find(workspaceId, {
select: ['id', 'universalIdentifier'],
withDeleted: true,
}),
this.rowLevelPermissionPredicateRepository.find({
where: { workspaceId },
this.rowLevelPermissionPredicateRepository.find(workspaceId, {
select: [
'id',
'universalIdentifier',

View File

@@ -16,6 +16,8 @@ import { RoleEntity } from 'src/engine/metadata-modules/role/role.entity';
import { RowLevelPermissionPredicateGroupEntity } from 'src/engine/metadata-modules/row-level-permission-predicate/entities/row-level-permission-predicate-group.entity';
import { RowLevelPermissionPredicateEntity } from 'src/engine/metadata-modules/row-level-permission-predicate/entities/row-level-permission-predicate.entity';
import { type FlatRowLevelPermissionPredicateMaps } from 'src/engine/metadata-modules/row-level-permission-predicate/types/flat-row-level-permission-predicate-maps.type';
import { InjectWorkspaceScopedRepository } from 'src/engine/twenty-orm/workspace-scoped-repository/inject-workspace-scoped-repository.decorator';
import { WorkspaceScopedRepository } from 'src/engine/twenty-orm/workspace-scoped-repository/workspace-scoped-repository';
import { WorkspaceCache } from 'src/engine/workspace-cache/decorators/workspace-cache.decorator';
import { createIdToUniversalIdentifierMap } from 'src/engine/workspace-cache/utils/create-id-to-universal-identifier-map.util';
import { addFlatEntityToFlatEntityMapsThroughMutationOrThrow } from 'src/engine/workspace-manager/workspace-migration/utils/add-flat-entity-to-flat-entity-maps-through-mutation-or-throw.util';
@@ -24,18 +26,18 @@ import { addFlatEntityToFlatEntityMapsThroughMutationOrThrow } from 'src/engine/
@WorkspaceCache('flatRowLevelPermissionPredicateMaps')
export class WorkspaceFlatRowLevelPermissionPredicateMapCacheService extends WorkspaceCacheProvider<FlatRowLevelPermissionPredicateMaps> {
constructor(
@InjectRepository(RowLevelPermissionPredicateEntity)
private readonly rowLevelPermissionPredicateRepository: Repository<RowLevelPermissionPredicateEntity>,
@InjectWorkspaceScopedRepository(RowLevelPermissionPredicateEntity)
private readonly rowLevelPermissionPredicateRepository: WorkspaceScopedRepository<RowLevelPermissionPredicateEntity>,
@InjectRepository(ApplicationEntity)
private readonly applicationRepository: Repository<ApplicationEntity>,
@InjectRepository(FieldMetadataEntity)
private readonly fieldMetadataRepository: Repository<FieldMetadataEntity>,
@InjectRepository(ObjectMetadataEntity)
private readonly objectMetadataRepository: Repository<ObjectMetadataEntity>,
@InjectRepository(RoleEntity)
private readonly roleRepository: Repository<RoleEntity>,
@InjectRepository(RowLevelPermissionPredicateGroupEntity)
private readonly rowLevelPermissionPredicateGroupRepository: Repository<RowLevelPermissionPredicateGroupEntity>,
@InjectWorkspaceScopedRepository(RoleEntity)
private readonly roleRepository: WorkspaceScopedRepository<RoleEntity>,
@InjectWorkspaceScopedRepository(RowLevelPermissionPredicateGroupEntity)
private readonly rowLevelPermissionPredicateGroupRepository: WorkspaceScopedRepository<RowLevelPermissionPredicateGroupEntity>,
) {
super();
}
@@ -51,8 +53,7 @@ export class WorkspaceFlatRowLevelPermissionPredicateMapCacheService extends Wor
roles,
rowLevelPermissionPredicateGroups,
] = await Promise.all([
this.rowLevelPermissionPredicateRepository.find({
where: { workspaceId },
this.rowLevelPermissionPredicateRepository.find(workspaceId, {
withDeleted: true,
}),
this.applicationRepository.find({
@@ -70,13 +71,11 @@ export class WorkspaceFlatRowLevelPermissionPredicateMapCacheService extends Wor
select: ['id', 'universalIdentifier'],
withDeleted: true,
}),
this.roleRepository.find({
where: { workspaceId },
this.roleRepository.find(workspaceId, {
select: ['id', 'universalIdentifier'],
withDeleted: true,
}),
this.rowLevelPermissionPredicateGroupRepository.find({
where: { workspaceId },
this.rowLevelPermissionPredicateGroupRepository.find(workspaceId, {
select: ['id', 'universalIdentifier'],
withDeleted: true,
}),

View File

@@ -5,13 +5,17 @@ import { ApplicationEntity } from 'src/engine/core-modules/application/applicati
import { WorkspaceManyOrAllFlatEntityMapsCacheModule } from 'src/engine/metadata-modules/flat-entity/services/workspace-many-or-all-flat-entity-maps-cache.module';
import { WorkspaceFlatSkillMapCacheService } from 'src/engine/metadata-modules/flat-skill/services/workspace-flat-skill-map-cache.service';
import { SkillEntity } from 'src/engine/metadata-modules/skill/entities/skill.entity';
import { provideWorkspaceScopedRepository } from 'src/engine/twenty-orm/workspace-scoped-repository/provide-workspace-scoped-repository';
@Module({
imports: [
TypeOrmModule.forFeature([ApplicationEntity, SkillEntity]),
WorkspaceManyOrAllFlatEntityMapsCacheModule,
],
providers: [WorkspaceFlatSkillMapCacheService],
providers: [
WorkspaceFlatSkillMapCacheService,
provideWorkspaceScopedRepository(SkillEntity),
],
exports: [WorkspaceFlatSkillMapCacheService],
})
export class FlatSkillModule {}

View File

@@ -10,6 +10,8 @@ import { createEmptyFlatEntityMaps } from 'src/engine/metadata-modules/flat-enti
import { type FlatSkillMaps } from 'src/engine/metadata-modules/flat-skill/types/flat-skill-maps.type';
import { fromSkillEntityToFlatSkill } from 'src/engine/metadata-modules/flat-skill/utils/from-skill-entity-to-flat-skill.util';
import { SkillEntity } from 'src/engine/metadata-modules/skill/entities/skill.entity';
import { InjectWorkspaceScopedRepository } from 'src/engine/twenty-orm/workspace-scoped-repository/inject-workspace-scoped-repository.decorator';
import { WorkspaceScopedRepository } from 'src/engine/twenty-orm/workspace-scoped-repository/workspace-scoped-repository';
import { WorkspaceCache } from 'src/engine/workspace-cache/decorators/workspace-cache.decorator';
import { createIdToUniversalIdentifierMap } from 'src/engine/workspace-cache/utils/create-id-to-universal-identifier-map.util';
import { addFlatEntityToFlatEntityMapsThroughMutationOrThrow } from 'src/engine/workspace-manager/workspace-migration/utils/add-flat-entity-to-flat-entity-maps-through-mutation-or-throw.util';
@@ -18,8 +20,8 @@ import { addFlatEntityToFlatEntityMapsThroughMutationOrThrow } from 'src/engine/
@WorkspaceCache('flatSkillMaps')
export class WorkspaceFlatSkillMapCacheService extends WorkspaceCacheProvider<FlatSkillMaps> {
constructor(
@InjectRepository(SkillEntity)
private readonly skillRepository: Repository<SkillEntity>,
@InjectWorkspaceScopedRepository(SkillEntity)
private readonly skillRepository: WorkspaceScopedRepository<SkillEntity>,
@InjectRepository(ApplicationEntity)
private readonly applicationRepository: Repository<ApplicationEntity>,
) {
@@ -28,8 +30,7 @@ export class WorkspaceFlatSkillMapCacheService extends WorkspaceCacheProvider<Fl
async computeForCache(workspaceId: string): Promise<FlatSkillMaps> {
const [skills, applications] = await Promise.all([
this.skillRepository.find({
where: { workspaceId },
this.skillRepository.find(workspaceId, {
withDeleted: true,
}),
this.applicationRepository.find({

View File

@@ -12,6 +12,8 @@ import { fromViewFieldGroupEntityToFlatViewFieldGroup } from 'src/engine/metadat
import { ViewFieldGroupEntity } from 'src/engine/metadata-modules/view-field-group/entities/view-field-group.entity';
import { ViewFieldEntity } from 'src/engine/metadata-modules/view-field/entities/view-field.entity';
import { ViewEntity } from 'src/engine/metadata-modules/view/entities/view.entity';
import { InjectWorkspaceScopedRepository } from 'src/engine/twenty-orm/workspace-scoped-repository/inject-workspace-scoped-repository.decorator';
import { WorkspaceScopedRepository } from 'src/engine/twenty-orm/workspace-scoped-repository/workspace-scoped-repository';
import { WorkspaceCache } from 'src/engine/workspace-cache/decorators/workspace-cache.decorator';
import { createIdToUniversalIdentifierMap } from 'src/engine/workspace-cache/utils/create-id-to-universal-identifier-map.util';
import { regroupEntitiesByRelatedEntityId } from 'src/engine/workspace-cache/utils/regroup-entities-by-related-entity-id';
@@ -21,14 +23,14 @@ import { addFlatEntityToFlatEntityMapsThroughMutationOrThrow } from 'src/engine/
@WorkspaceCache('flatViewFieldGroupMaps')
export class WorkspaceFlatViewFieldGroupMapCacheService extends WorkspaceCacheProvider<FlatViewFieldGroupMaps> {
constructor(
@InjectRepository(ViewFieldGroupEntity)
private readonly viewFieldGroupRepository: Repository<ViewFieldGroupEntity>,
@InjectWorkspaceScopedRepository(ViewFieldGroupEntity)
private readonly viewFieldGroupRepository: WorkspaceScopedRepository<ViewFieldGroupEntity>,
@InjectRepository(ApplicationEntity)
private readonly applicationRepository: Repository<ApplicationEntity>,
@InjectRepository(ViewEntity)
private readonly viewRepository: Repository<ViewEntity>,
@InjectRepository(ViewFieldEntity)
private readonly viewFieldRepository: Repository<ViewFieldEntity>,
@InjectWorkspaceScopedRepository(ViewEntity)
private readonly viewRepository: WorkspaceScopedRepository<ViewEntity>,
@InjectWorkspaceScopedRepository(ViewFieldEntity)
private readonly viewFieldRepository: WorkspaceScopedRepository<ViewFieldEntity>,
) {
super();
}
@@ -36,8 +38,7 @@ export class WorkspaceFlatViewFieldGroupMapCacheService extends WorkspaceCachePr
async computeForCache(workspaceId: string): Promise<FlatViewFieldGroupMaps> {
const [viewFieldGroups, applications, views, viewFields] =
await Promise.all([
this.viewFieldGroupRepository.find({
where: { workspaceId },
this.viewFieldGroupRepository.find(workspaceId, {
withDeleted: true,
}),
this.applicationRepository.find({
@@ -45,13 +46,11 @@ export class WorkspaceFlatViewFieldGroupMapCacheService extends WorkspaceCachePr
select: ['id', 'universalIdentifier'],
withDeleted: true,
}),
this.viewRepository.find({
where: { workspaceId },
this.viewRepository.find(workspaceId, {
select: ['id', 'universalIdentifier'],
withDeleted: true,
}),
this.viewFieldRepository.find({
where: { workspaceId },
this.viewFieldRepository.find(workspaceId, {
select: ['id', 'universalIdentifier', 'viewFieldGroupId'],
withDeleted: true,
}),

View File

@@ -13,6 +13,8 @@ import { fromViewFieldEntityToFlatViewField } from 'src/engine/metadata-modules/
import { ViewFieldGroupEntity } from 'src/engine/metadata-modules/view-field-group/entities/view-field-group.entity';
import { ViewFieldEntity } from 'src/engine/metadata-modules/view-field/entities/view-field.entity';
import { ViewEntity } from 'src/engine/metadata-modules/view/entities/view.entity';
import { InjectWorkspaceScopedRepository } from 'src/engine/twenty-orm/workspace-scoped-repository/inject-workspace-scoped-repository.decorator';
import { WorkspaceScopedRepository } from 'src/engine/twenty-orm/workspace-scoped-repository/workspace-scoped-repository';
import { WorkspaceCache } from 'src/engine/workspace-cache/decorators/workspace-cache.decorator';
import { createIdToUniversalIdentifierMap } from 'src/engine/workspace-cache/utils/create-id-to-universal-identifier-map.util';
import { addFlatEntityToFlatEntityMapsThroughMutationOrThrow } from 'src/engine/workspace-manager/workspace-migration/utils/add-flat-entity-to-flat-entity-maps-through-mutation-or-throw.util';
@@ -21,16 +23,16 @@ import { addFlatEntityToFlatEntityMapsThroughMutationOrThrow } from 'src/engine/
@WorkspaceCache('flatViewFieldMaps')
export class WorkspaceFlatViewFieldMapCacheService extends WorkspaceCacheProvider<FlatViewFieldMaps> {
constructor(
@InjectRepository(ViewFieldEntity)
private readonly viewFieldRepository: Repository<ViewFieldEntity>,
@InjectWorkspaceScopedRepository(ViewFieldEntity)
private readonly viewFieldRepository: WorkspaceScopedRepository<ViewFieldEntity>,
@InjectRepository(ApplicationEntity)
private readonly applicationRepository: Repository<ApplicationEntity>,
@InjectRepository(FieldMetadataEntity)
private readonly fieldMetadataRepository: Repository<FieldMetadataEntity>,
@InjectRepository(ViewEntity)
private readonly viewRepository: Repository<ViewEntity>,
@InjectRepository(ViewFieldGroupEntity)
private readonly viewFieldGroupRepository: Repository<ViewFieldGroupEntity>,
@InjectWorkspaceScopedRepository(ViewEntity)
private readonly viewRepository: WorkspaceScopedRepository<ViewEntity>,
@InjectWorkspaceScopedRepository(ViewFieldGroupEntity)
private readonly viewFieldGroupRepository: WorkspaceScopedRepository<ViewFieldGroupEntity>,
) {
super();
}
@@ -38,8 +40,7 @@ export class WorkspaceFlatViewFieldMapCacheService extends WorkspaceCacheProvide
async computeForCache(workspaceId: string): Promise<FlatViewFieldMaps> {
const [viewFields, applications, fieldMetadatas, views, viewFieldGroups] =
await Promise.all([
this.viewFieldRepository.find({
where: { workspaceId },
this.viewFieldRepository.find(workspaceId, {
withDeleted: true,
}),
this.applicationRepository.find({
@@ -52,13 +53,11 @@ export class WorkspaceFlatViewFieldMapCacheService extends WorkspaceCacheProvide
select: ['id', 'universalIdentifier'],
withDeleted: true,
}),
this.viewRepository.find({
where: { workspaceId },
this.viewRepository.find(workspaceId, {
select: ['id', 'universalIdentifier'],
withDeleted: true,
}),
this.viewFieldGroupRepository.find({
where: { workspaceId },
this.viewFieldGroupRepository.find(workspaceId, {
select: ['id', 'universalIdentifier'],
withDeleted: true,
}),

View File

@@ -12,6 +12,8 @@ import { fromViewFilterGroupEntityToFlatViewFilterGroup } from 'src/engine/metad
import { ViewFilterGroupEntity } from 'src/engine/metadata-modules/view-filter-group/entities/view-filter-group.entity';
import { ViewFilterEntity } from 'src/engine/metadata-modules/view-filter/entities/view-filter.entity';
import { ViewEntity } from 'src/engine/metadata-modules/view/entities/view.entity';
import { InjectWorkspaceScopedRepository } from 'src/engine/twenty-orm/workspace-scoped-repository/inject-workspace-scoped-repository.decorator';
import { WorkspaceScopedRepository } from 'src/engine/twenty-orm/workspace-scoped-repository/workspace-scoped-repository';
import { WorkspaceCache } from 'src/engine/workspace-cache/decorators/workspace-cache.decorator';
import { createIdToUniversalIdentifierMap } from 'src/engine/workspace-cache/utils/create-id-to-universal-identifier-map.util';
import { regroupEntitiesByRelatedEntityId } from 'src/engine/workspace-cache/utils/regroup-entities-by-related-entity-id';
@@ -21,14 +23,14 @@ import { addFlatEntityToFlatEntityMapsThroughMutationOrThrow } from 'src/engine/
@WorkspaceCache('flatViewFilterGroupMaps')
export class WorkspaceFlatViewFilterGroupMapCacheService extends WorkspaceCacheProvider<FlatViewFilterGroupMaps> {
constructor(
@InjectRepository(ViewFilterGroupEntity)
private readonly viewFilterGroupRepository: Repository<ViewFilterGroupEntity>,
@InjectWorkspaceScopedRepository(ViewFilterGroupEntity)
private readonly viewFilterGroupRepository: WorkspaceScopedRepository<ViewFilterGroupEntity>,
@InjectRepository(ApplicationEntity)
private readonly applicationRepository: Repository<ApplicationEntity>,
@InjectRepository(ViewFilterEntity)
private readonly viewFilterRepository: Repository<ViewFilterEntity>,
@InjectRepository(ViewEntity)
private readonly viewRepository: Repository<ViewEntity>,
@InjectWorkspaceScopedRepository(ViewFilterEntity)
private readonly viewFilterRepository: WorkspaceScopedRepository<ViewFilterEntity>,
@InjectWorkspaceScopedRepository(ViewEntity)
private readonly viewRepository: WorkspaceScopedRepository<ViewEntity>,
) {
super();
}
@@ -36,8 +38,7 @@ export class WorkspaceFlatViewFilterGroupMapCacheService extends WorkspaceCacheP
async computeForCache(workspaceId: string): Promise<FlatViewFilterGroupMaps> {
const [viewFilterGroups, applications, viewFilters, views] =
await Promise.all([
this.viewFilterGroupRepository.find({
where: { workspaceId },
this.viewFilterGroupRepository.find(workspaceId, {
withDeleted: true,
}),
this.applicationRepository.find({
@@ -45,13 +46,11 @@ export class WorkspaceFlatViewFilterGroupMapCacheService extends WorkspaceCacheP
select: ['id', 'universalIdentifier'],
withDeleted: true,
}),
this.viewFilterRepository.find({
where: { workspaceId },
this.viewFilterRepository.find(workspaceId, {
select: ['id', 'universalIdentifier', 'viewFilterGroupId'],
withDeleted: true,
}),
this.viewRepository.find({
where: { workspaceId },
this.viewRepository.find(workspaceId, {
select: ['id', 'universalIdentifier'],
withDeleted: true,
}),

View File

@@ -13,6 +13,8 @@ import { fromViewFilterEntityToFlatViewFilter } from 'src/engine/metadata-module
import { ViewFilterGroupEntity } from 'src/engine/metadata-modules/view-filter-group/entities/view-filter-group.entity';
import { ViewFilterEntity } from 'src/engine/metadata-modules/view-filter/entities/view-filter.entity';
import { ViewEntity } from 'src/engine/metadata-modules/view/entities/view.entity';
import { InjectWorkspaceScopedRepository } from 'src/engine/twenty-orm/workspace-scoped-repository/inject-workspace-scoped-repository.decorator';
import { WorkspaceScopedRepository } from 'src/engine/twenty-orm/workspace-scoped-repository/workspace-scoped-repository';
import { WorkspaceCache } from 'src/engine/workspace-cache/decorators/workspace-cache.decorator';
import { createIdToUniversalIdentifierMap } from 'src/engine/workspace-cache/utils/create-id-to-universal-identifier-map.util';
import { addFlatEntityToFlatEntityMapsThroughMutationOrThrow } from 'src/engine/workspace-manager/workspace-migration/utils/add-flat-entity-to-flat-entity-maps-through-mutation-or-throw.util';
@@ -21,16 +23,16 @@ import { addFlatEntityToFlatEntityMapsThroughMutationOrThrow } from 'src/engine/
@WorkspaceCache('flatViewFilterMaps')
export class WorkspaceFlatViewFilterMapCacheService extends WorkspaceCacheProvider<FlatViewFilterMaps> {
constructor(
@InjectRepository(ViewFilterEntity)
private readonly viewFilterRepository: Repository<ViewFilterEntity>,
@InjectWorkspaceScopedRepository(ViewFilterEntity)
private readonly viewFilterRepository: WorkspaceScopedRepository<ViewFilterEntity>,
@InjectRepository(ApplicationEntity)
private readonly applicationRepository: Repository<ApplicationEntity>,
@InjectRepository(FieldMetadataEntity)
private readonly fieldMetadataRepository: Repository<FieldMetadataEntity>,
@InjectRepository(ViewFilterGroupEntity)
private readonly viewFilterGroupRepository: Repository<ViewFilterGroupEntity>,
@InjectRepository(ViewEntity)
private readonly viewRepository: Repository<ViewEntity>,
@InjectWorkspaceScopedRepository(ViewFilterGroupEntity)
private readonly viewFilterGroupRepository: WorkspaceScopedRepository<ViewFilterGroupEntity>,
@InjectWorkspaceScopedRepository(ViewEntity)
private readonly viewRepository: WorkspaceScopedRepository<ViewEntity>,
) {
super();
}
@@ -38,8 +40,7 @@ export class WorkspaceFlatViewFilterMapCacheService extends WorkspaceCacheProvid
async computeForCache(workspaceId: string): Promise<FlatViewFilterMaps> {
const [viewFilters, applications, fieldMetadatas, viewFilterGroups, views] =
await Promise.all([
this.viewFilterRepository.find({
where: { workspaceId },
this.viewFilterRepository.find(workspaceId, {
withDeleted: true,
}),
this.applicationRepository.find({
@@ -52,13 +53,11 @@ export class WorkspaceFlatViewFilterMapCacheService extends WorkspaceCacheProvid
select: ['id', 'universalIdentifier'],
withDeleted: true,
}),
this.viewFilterGroupRepository.find({
where: { workspaceId },
this.viewFilterGroupRepository.find(workspaceId, {
select: ['id', 'universalIdentifier'],
withDeleted: true,
}),
this.viewRepository.find({
where: { workspaceId },
this.viewRepository.find(workspaceId, {
select: ['id', 'universalIdentifier'],
withDeleted: true,
}),

View File

@@ -11,6 +11,8 @@ import { FlatViewGroupMaps } from 'src/engine/metadata-modules/flat-view-group/t
import { fromViewGroupEntityToFlatViewGroup } from 'src/engine/metadata-modules/flat-view-group/utils/from-view-group-entity-to-flat-view-group.util';
import { ViewGroupEntity } from 'src/engine/metadata-modules/view-group/entities/view-group.entity';
import { ViewEntity } from 'src/engine/metadata-modules/view/entities/view.entity';
import { InjectWorkspaceScopedRepository } from 'src/engine/twenty-orm/workspace-scoped-repository/inject-workspace-scoped-repository.decorator';
import { WorkspaceScopedRepository } from 'src/engine/twenty-orm/workspace-scoped-repository/workspace-scoped-repository';
import { WorkspaceCache } from 'src/engine/workspace-cache/decorators/workspace-cache.decorator';
import { createIdToUniversalIdentifierMap } from 'src/engine/workspace-cache/utils/create-id-to-universal-identifier-map.util';
import { addFlatEntityToFlatEntityMapsThroughMutationOrThrow } from 'src/engine/workspace-manager/workspace-migration/utils/add-flat-entity-to-flat-entity-maps-through-mutation-or-throw.util';
@@ -19,20 +21,19 @@ import { addFlatEntityToFlatEntityMapsThroughMutationOrThrow } from 'src/engine/
@WorkspaceCache('flatViewGroupMaps')
export class WorkspaceFlatViewGroupMapCacheService extends WorkspaceCacheProvider<FlatViewGroupMaps> {
constructor(
@InjectRepository(ViewGroupEntity)
private readonly viewGroupRepository: Repository<ViewGroupEntity>,
@InjectWorkspaceScopedRepository(ViewGroupEntity)
private readonly viewGroupRepository: WorkspaceScopedRepository<ViewGroupEntity>,
@InjectRepository(ApplicationEntity)
private readonly applicationRepository: Repository<ApplicationEntity>,
@InjectRepository(ViewEntity)
private readonly viewRepository: Repository<ViewEntity>,
@InjectWorkspaceScopedRepository(ViewEntity)
private readonly viewRepository: WorkspaceScopedRepository<ViewEntity>,
) {
super();
}
async computeForCache(workspaceId: string): Promise<FlatViewGroupMaps> {
const [viewGroups, applications, views] = await Promise.all([
this.viewGroupRepository.find({
where: { workspaceId },
this.viewGroupRepository.find(workspaceId, {
withDeleted: true,
}),
this.applicationRepository.find({
@@ -40,8 +41,7 @@ export class WorkspaceFlatViewGroupMapCacheService extends WorkspaceCacheProvide
select: ['id', 'universalIdentifier'],
withDeleted: true,
}),
this.viewRepository.find({
where: { workspaceId },
this.viewRepository.find(workspaceId, {
select: ['id', 'universalIdentifier'],
withDeleted: true,
}),

View File

@@ -5,6 +5,8 @@ import { Repository } from 'typeorm';
import { WorkspaceCacheProvider } from 'src/engine/workspace-cache/interfaces/workspace-cache-provider.service';
import { InjectWorkspaceScopedRepository } from 'src/engine/twenty-orm/workspace-scoped-repository/inject-workspace-scoped-repository.decorator';
import { WorkspaceScopedRepository } from 'src/engine/twenty-orm/workspace-scoped-repository/workspace-scoped-repository';
import { WorkspaceCache } from 'src/engine/workspace-cache/decorators/workspace-cache.decorator';
import { FlatViewSortMaps } from 'src/engine/metadata-modules/flat-view-sort/types/flat-view-sort-maps.type';
import { ViewSortEntity } from 'src/engine/metadata-modules/view-sort/entities/view-sort.entity';
@@ -20,10 +22,10 @@ import { createIdToUniversalIdentifierMap } from 'src/engine/workspace-cache/uti
@WorkspaceCache('flatViewSortMaps')
export class WorkspaceFlatViewSortMapCacheService extends WorkspaceCacheProvider<FlatViewSortMaps> {
constructor(
@InjectRepository(ViewSortEntity)
private readonly viewSortRepository: Repository<ViewSortEntity>,
@InjectRepository(ViewEntity)
private readonly viewRepository: Repository<ViewEntity>,
@InjectWorkspaceScopedRepository(ViewSortEntity)
private readonly viewSortRepository: WorkspaceScopedRepository<ViewSortEntity>,
@InjectWorkspaceScopedRepository(ViewEntity)
private readonly viewRepository: WorkspaceScopedRepository<ViewEntity>,
@InjectRepository(ApplicationEntity)
private readonly applicationRepository: Repository<ApplicationEntity>,
@InjectRepository(FieldMetadataEntity)
@@ -35,8 +37,7 @@ export class WorkspaceFlatViewSortMapCacheService extends WorkspaceCacheProvider
async computeForCache(workspaceId: string): Promise<FlatViewSortMaps> {
const [existingViewSorts, applications, views, fieldMetadatas] =
await Promise.all([
this.viewSortRepository.find({
where: { workspaceId },
this.viewSortRepository.find(workspaceId, {
withDeleted: true,
}),
this.applicationRepository.find({
@@ -44,8 +45,7 @@ export class WorkspaceFlatViewSortMapCacheService extends WorkspaceCacheProvider
select: ['id', 'universalIdentifier'],
withDeleted: true,
}),
this.viewRepository.find({
where: { workspaceId },
this.viewRepository.find(workspaceId, {
select: ['id', 'universalIdentifier'],
withDeleted: true,
}),

View File

@@ -12,6 +12,7 @@ import { ViewFilterEntity } from 'src/engine/metadata-modules/view-filter/entiti
import { ViewGroupEntity } from 'src/engine/metadata-modules/view-group/entities/view-group.entity';
import { ViewEntity } from 'src/engine/metadata-modules/view/entities/view.entity';
import { ViewSortEntity } from 'src/engine/metadata-modules/view-sort/entities/view-sort.entity';
import { provideWorkspaceScopedRepository } from 'src/engine/twenty-orm/workspace-scoped-repository/provide-workspace-scoped-repository';
@Module({
imports: [
@@ -28,7 +29,16 @@ import { ViewSortEntity } from 'src/engine/metadata-modules/view-sort/entities/v
ViewFilterGroupEntity,
]),
],
providers: [WorkspaceFlatViewMapCacheService],
providers: [
WorkspaceFlatViewMapCacheService,
provideWorkspaceScopedRepository(ViewEntity),
provideWorkspaceScopedRepository(ViewFieldEntity),
provideWorkspaceScopedRepository(ViewFieldGroupEntity),
provideWorkspaceScopedRepository(ViewFilterEntity),
provideWorkspaceScopedRepository(ViewFilterGroupEntity),
provideWorkspaceScopedRepository(ViewGroupEntity),
provideWorkspaceScopedRepository(ViewSortEntity),
],
exports: [WorkspaceFlatViewMapCacheService],
})
export class FlatViewModule {}

View File

@@ -18,6 +18,8 @@ import { ViewFilterEntity } from 'src/engine/metadata-modules/view-filter/entiti
import { ViewGroupEntity } from 'src/engine/metadata-modules/view-group/entities/view-group.entity';
import { ViewSortEntity } from 'src/engine/metadata-modules/view-sort/entities/view-sort.entity';
import { ViewEntity } from 'src/engine/metadata-modules/view/entities/view.entity';
import { InjectWorkspaceScopedRepository } from 'src/engine/twenty-orm/workspace-scoped-repository/inject-workspace-scoped-repository.decorator';
import { WorkspaceScopedRepository } from 'src/engine/twenty-orm/workspace-scoped-repository/workspace-scoped-repository';
import { WorkspaceCache } from 'src/engine/workspace-cache/decorators/workspace-cache.decorator';
import { createIdToUniversalIdentifierMap } from 'src/engine/workspace-cache/utils/create-id-to-universal-identifier-map.util';
import { regroupEntitiesByRelatedEntityId } from 'src/engine/workspace-cache/utils/regroup-entities-by-related-entity-id';
@@ -27,26 +29,26 @@ import { addFlatEntityToFlatEntityMapsThroughMutationOrThrow } from 'src/engine/
@WorkspaceCache('flatViewMaps')
export class WorkspaceFlatViewMapCacheService extends WorkspaceCacheProvider<FlatViewMaps> {
constructor(
@InjectRepository(ViewEntity)
private readonly viewRepository: Repository<ViewEntity>,
@InjectWorkspaceScopedRepository(ViewEntity)
private readonly viewRepository: WorkspaceScopedRepository<ViewEntity>,
@InjectRepository(ApplicationEntity)
private readonly applicationRepository: Repository<ApplicationEntity>,
@InjectRepository(ObjectMetadataEntity)
private readonly objectMetadataRepository: Repository<ObjectMetadataEntity>,
@InjectRepository(FieldMetadataEntity)
private readonly fieldMetadataRepository: Repository<FieldMetadataEntity>,
@InjectRepository(ViewFieldEntity)
private readonly viewFieldRepository: Repository<ViewFieldEntity>,
@InjectRepository(ViewFilterEntity)
private readonly viewFilterRepository: Repository<ViewFilterEntity>,
@InjectRepository(ViewGroupEntity)
private readonly viewGroupRepository: Repository<ViewGroupEntity>,
@InjectRepository(ViewFilterGroupEntity)
private readonly viewFilterGroupRepository: Repository<ViewFilterGroupEntity>,
@InjectRepository(ViewSortEntity)
private readonly viewSortRepository: Repository<ViewSortEntity>,
@InjectRepository(ViewFieldGroupEntity)
private readonly viewFieldGroupRepository: Repository<ViewFieldGroupEntity>,
@InjectWorkspaceScopedRepository(ViewFieldEntity)
private readonly viewFieldRepository: WorkspaceScopedRepository<ViewFieldEntity>,
@InjectWorkspaceScopedRepository(ViewFilterEntity)
private readonly viewFilterRepository: WorkspaceScopedRepository<ViewFilterEntity>,
@InjectWorkspaceScopedRepository(ViewGroupEntity)
private readonly viewGroupRepository: WorkspaceScopedRepository<ViewGroupEntity>,
@InjectWorkspaceScopedRepository(ViewFilterGroupEntity)
private readonly viewFilterGroupRepository: WorkspaceScopedRepository<ViewFilterGroupEntity>,
@InjectWorkspaceScopedRepository(ViewSortEntity)
private readonly viewSortRepository: WorkspaceScopedRepository<ViewSortEntity>,
@InjectWorkspaceScopedRepository(ViewFieldGroupEntity)
private readonly viewFieldGroupRepository: WorkspaceScopedRepository<ViewFieldGroupEntity>,
) {
super();
}
@@ -64,8 +66,7 @@ export class WorkspaceFlatViewMapCacheService extends WorkspaceCacheProvider<Fla
viewSorts,
viewFieldGroups,
] = await Promise.all([
this.viewRepository.find({
where: { workspaceId },
this.viewRepository.find(workspaceId, {
withDeleted: true,
}),
this.applicationRepository.find({
@@ -83,33 +84,27 @@ export class WorkspaceFlatViewMapCacheService extends WorkspaceCacheProvider<Fla
select: ['id', 'universalIdentifier'],
withDeleted: true,
}),
this.viewFieldRepository.find({
where: { workspaceId },
this.viewFieldRepository.find(workspaceId, {
select: ['id', 'universalIdentifier', 'viewId'],
withDeleted: true,
}),
this.viewFilterRepository.find({
where: { workspaceId },
this.viewFilterRepository.find(workspaceId, {
select: ['id', 'universalIdentifier', 'viewId'],
withDeleted: true,
}),
this.viewGroupRepository.find({
where: { workspaceId },
this.viewGroupRepository.find(workspaceId, {
select: ['id', 'universalIdentifier', 'viewId'],
withDeleted: true,
}),
this.viewFilterGroupRepository.find({
where: { workspaceId },
this.viewFilterGroupRepository.find(workspaceId, {
select: ['id', 'universalIdentifier', 'viewId'],
withDeleted: true,
}),
this.viewSortRepository.find({
where: { workspaceId },
this.viewSortRepository.find(workspaceId, {
select: ['id', 'universalIdentifier', 'viewId'],
withDeleted: true,
}),
this.viewFieldGroupRepository.find({
where: { workspaceId },
this.viewFieldGroupRepository.find(workspaceId, {
select: ['id', 'universalIdentifier', 'viewId'],
withDeleted: true,
}),

View File

@@ -5,13 +5,17 @@ import { ApplicationEntity } from 'src/engine/core-modules/application/applicati
import { WorkspaceManyOrAllFlatEntityMapsCacheModule } from 'src/engine/metadata-modules/flat-entity/services/workspace-many-or-all-flat-entity-maps-cache.module';
import { WorkspaceFlatWebhookMapCacheService } from 'src/engine/metadata-modules/flat-webhook/services/workspace-flat-webhook-map-cache.service';
import { WebhookEntity } from 'src/engine/metadata-modules/webhook/entities/webhook.entity';
import { provideWorkspaceScopedRepository } from 'src/engine/twenty-orm/workspace-scoped-repository/provide-workspace-scoped-repository';
@Module({
imports: [
TypeOrmModule.forFeature([ApplicationEntity, WebhookEntity]),
WorkspaceManyOrAllFlatEntityMapsCacheModule,
],
providers: [WorkspaceFlatWebhookMapCacheService],
providers: [
WorkspaceFlatWebhookMapCacheService,
provideWorkspaceScopedRepository(WebhookEntity),
],
exports: [WorkspaceFlatWebhookMapCacheService],
})
export class FlatWebhookModule {}

View File

@@ -10,6 +10,8 @@ import { createEmptyFlatEntityMaps } from 'src/engine/metadata-modules/flat-enti
import { type FlatWebhookMaps } from 'src/engine/metadata-modules/flat-webhook/types/flat-webhook-maps.type';
import { fromWebhookEntityToFlatWebhook } from 'src/engine/metadata-modules/flat-webhook/utils/from-webhook-entity-to-flat-webhook.util';
import { WebhookEntity } from 'src/engine/metadata-modules/webhook/entities/webhook.entity';
import { InjectWorkspaceScopedRepository } from 'src/engine/twenty-orm/workspace-scoped-repository/inject-workspace-scoped-repository.decorator';
import { WorkspaceScopedRepository } from 'src/engine/twenty-orm/workspace-scoped-repository/workspace-scoped-repository';
import { WorkspaceCache } from 'src/engine/workspace-cache/decorators/workspace-cache.decorator';
import { createIdToUniversalIdentifierMap } from 'src/engine/workspace-cache/utils/create-id-to-universal-identifier-map.util';
import { addFlatEntityToFlatEntityMapsThroughMutationOrThrow } from 'src/engine/workspace-manager/workspace-migration/utils/add-flat-entity-to-flat-entity-maps-through-mutation-or-throw.util';
@@ -18,8 +20,8 @@ import { addFlatEntityToFlatEntityMapsThroughMutationOrThrow } from 'src/engine/
@WorkspaceCache('flatWebhookMaps')
export class WorkspaceFlatWebhookMapCacheService extends WorkspaceCacheProvider<FlatWebhookMaps> {
constructor(
@InjectRepository(WebhookEntity)
private readonly webhookRepository: Repository<WebhookEntity>,
@InjectWorkspaceScopedRepository(WebhookEntity)
private readonly webhookRepository: WorkspaceScopedRepository<WebhookEntity>,
@InjectRepository(ApplicationEntity)
private readonly applicationRepository: Repository<ApplicationEntity>,
) {
@@ -28,8 +30,8 @@ export class WorkspaceFlatWebhookMapCacheService extends WorkspaceCacheProvider<
async computeForCache(workspaceId: string): Promise<FlatWebhookMaps> {
const [webhooks, applications] = await Promise.all([
this.webhookRepository.find({
where: { workspaceId, deletedAt: IsNull() },
this.webhookRepository.find(workspaceId, {
where: { deletedAt: IsNull() },
}),
this.applicationRepository.find({
where: { workspaceId },

View File

@@ -11,6 +11,7 @@ import { ApplicationEntity } from 'src/engine/core-modules/application/applicati
import { PermissionsService } from 'src/engine/metadata-modules/permissions/permissions.service';
import { RoleEntity } from 'src/engine/metadata-modules/role/role.entity';
import { UserRoleService } from 'src/engine/metadata-modules/user-role/user-role.service';
import { getWorkspaceScopedRepositoryToken } from 'src/engine/twenty-orm/workspace-scoped-repository/get-workspace-scoped-repository-token.util';
import { WorkspaceCacheService } from 'src/engine/workspace-cache/services/workspace-cache.service';
describe('PermissionsService', () => {
@@ -21,7 +22,7 @@ describe('PermissionsService', () => {
providers: [
PermissionsService,
{
provide: getRepositoryToken(RoleEntity),
provide: getWorkspaceScopedRepositoryToken(RoleEntity),
useValue: {},
},
{

View File

@@ -32,6 +32,8 @@ import { WorkspaceCacheModule } from 'src/engine/workspace-cache/workspace-cache
ApiKeyRoleService,
PermissionsService,
provideWorkspaceScopedRepository(ApiKeyEntity),
provideWorkspaceScopedRepository(RoleEntity),
provideWorkspaceScopedRepository(RoleTargetEntity),
],
exports: [PermissionsService, ApiKeyRoleService],
})

View File

@@ -25,6 +25,8 @@ import { type UserWorkspacePermissions } from 'src/engine/metadata-modules/permi
import { RoleEntity } from 'src/engine/metadata-modules/role/role.entity';
import { UserRoleService } from 'src/engine/metadata-modules/user-role/user-role.service';
import { type RolePermissionConfig } from 'src/engine/twenty-orm/types/role-permission-config';
import { InjectWorkspaceScopedRepository } from 'src/engine/twenty-orm/workspace-scoped-repository/inject-workspace-scoped-repository.decorator';
import { WorkspaceScopedRepository } from 'src/engine/twenty-orm/workspace-scoped-repository/workspace-scoped-repository';
import { WorkspaceCacheService } from 'src/engine/workspace-cache/services/workspace-cache.service';
@Injectable()
@@ -33,8 +35,8 @@ export class PermissionsService {
private readonly userRoleService: UserRoleService,
private readonly workspaceCacheService: WorkspaceCacheService,
private readonly apiKeyRoleService: ApiKeyRoleService,
@InjectRepository(RoleEntity)
private readonly roleRepository: Repository<RoleEntity>,
@InjectWorkspaceScopedRepository(RoleEntity)
private readonly roleRepository: WorkspaceScopedRepository<RoleEntity>,
@InjectRepository(ApplicationEntity)
private readonly applicationRepository: Repository<ApplicationEntity>,
) {}
@@ -149,8 +151,8 @@ export class PermissionsService {
workspaceId,
);
const role = await this.roleRepository.findOne({
where: { id: roleId, workspaceId },
const role = await this.roleRepository.findOne(workspaceId, {
where: { id: roleId },
relations: [
'rolePermissionFlags',
'rolePermissionFlags.permissionFlag',
@@ -205,8 +207,8 @@ export class PermissionsService {
const applicationRoleId = application.defaultRoleId;
const role = await this.roleRepository.findOne({
where: { id: applicationRoleId, workspaceId },
const role = await this.roleRepository.findOne(workspaceId, {
where: { id: applicationRoleId },
relations: [
'rolePermissionFlags',
'rolePermissionFlags.permissionFlag',
@@ -289,8 +291,8 @@ export class PermissionsService {
throw new Error('No role IDs provided');
}
const roles = await this.roleRepository.find({
where: { id: In(roleIds), workspaceId },
const roles = await this.roleRepository.find(workspaceId, {
where: { id: In(roleIds) },
relations,
});

View File

@@ -6,6 +6,7 @@ import { WorkspaceManyOrAllFlatEntityMapsCacheModule } from 'src/engine/metadata
import { RoleTargetEntity } from 'src/engine/metadata-modules/role-target/role-target.entity';
import { WorkspaceApiKeyRoleMapCacheService } from 'src/engine/metadata-modules/role-target/services/workspace-api-key-role-map-cache.service';
import { WorkspaceUserWorkspaceRoleMapCacheService } from 'src/engine/metadata-modules/role-target/services/workspace-user-workspace-role-map-cache.service';
import { provideWorkspaceScopedRepository } from 'src/engine/twenty-orm/workspace-scoped-repository/provide-workspace-scoped-repository';
import { WorkspaceMigrationModule } from 'src/engine/workspace-manager/workspace-migration/workspace-migration.module';
import { RoleTargetService } from './services/role-target.service';
@@ -21,6 +22,7 @@ import { RoleTargetService } from './services/role-target.service';
RoleTargetService,
WorkspaceUserWorkspaceRoleMapCacheService,
WorkspaceApiKeyRoleMapCacheService,
provideWorkspaceScopedRepository(RoleTargetEntity),
],
exports: [RoleTargetService],
})

View File

@@ -1,11 +1,12 @@
import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { IsNull, Not, Repository } from 'typeorm';
import { IsNull, Not } from 'typeorm';
import { WorkspaceCacheProvider } from 'src/engine/workspace-cache/interfaces/workspace-cache-provider.service';
import { RoleTargetEntity } from 'src/engine/metadata-modules/role-target/role-target.entity';
import { InjectWorkspaceScopedRepository } from 'src/engine/twenty-orm/workspace-scoped-repository/inject-workspace-scoped-repository.decorator';
import { WorkspaceScopedRepository } from 'src/engine/twenty-orm/workspace-scoped-repository/workspace-scoped-repository';
import { WorkspaceCache } from 'src/engine/workspace-cache/decorators/workspace-cache.decorator';
@Injectable()
@@ -14,16 +15,15 @@ export class WorkspaceApiKeyRoleMapCacheService extends WorkspaceCacheProvider<
Record<string, string>
> {
constructor(
@InjectRepository(RoleTargetEntity)
private readonly roleTargetRepository: Repository<RoleTargetEntity>,
@InjectWorkspaceScopedRepository(RoleTargetEntity)
private readonly roleTargetRepository: WorkspaceScopedRepository<RoleTargetEntity>,
) {
super();
}
async computeForCache(workspaceId: string): Promise<Record<string, string>> {
const roleTargetsMap = await this.roleTargetRepository.find({
const roleTargetsMap = await this.roleTargetRepository.find(workspaceId, {
where: {
workspaceId,
apiKeyId: Not(IsNull()),
},
});

View File

@@ -1,29 +1,29 @@
import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { isDefined } from 'twenty-shared/utils';
import { IsNull, Not, Repository } from 'typeorm';
import { IsNull, Not } from 'typeorm';
import { WorkspaceCacheProvider } from 'src/engine/workspace-cache/interfaces/workspace-cache-provider.service';
import { RoleTargetEntity } from 'src/engine/metadata-modules/role-target/role-target.entity';
import { UserWorkspaceRoleMap } from 'src/engine/metadata-modules/role-target/types/user-workspace-role-map';
import { InjectWorkspaceScopedRepository } from 'src/engine/twenty-orm/workspace-scoped-repository/inject-workspace-scoped-repository.decorator';
import { WorkspaceScopedRepository } from 'src/engine/twenty-orm/workspace-scoped-repository/workspace-scoped-repository';
import { WorkspaceCache } from 'src/engine/workspace-cache/decorators/workspace-cache.decorator';
@Injectable()
@WorkspaceCache('userWorkspaceRoleMap')
export class WorkspaceUserWorkspaceRoleMapCacheService extends WorkspaceCacheProvider<UserWorkspaceRoleMap> {
constructor(
@InjectRepository(RoleTargetEntity)
private readonly roleTargetRepository: Repository<RoleTargetEntity>,
@InjectWorkspaceScopedRepository(RoleTargetEntity)
private readonly roleTargetRepository: WorkspaceScopedRepository<RoleTargetEntity>,
) {
super();
}
async computeForCache(workspaceId: string): Promise<UserWorkspaceRoleMap> {
const roleTargetsMap = await this.roleTargetRepository.find({
const roleTargetsMap = await this.roleTargetRepository.find(workspaceId, {
where: {
workspaceId,
userWorkspaceId: Not(IsNull()),
},
});

View File

@@ -3,10 +3,14 @@ import { TypeOrmModule } from '@nestjs/typeorm';
import { RoleEntity } from 'src/engine/metadata-modules/role/role.entity';
import { RoleValidationService } from 'src/engine/metadata-modules/role-validation/services/role-validation.service';
import { provideWorkspaceScopedRepository } from 'src/engine/twenty-orm/workspace-scoped-repository/provide-workspace-scoped-repository';
@Module({
imports: [TypeOrmModule.forFeature([RoleEntity])],
providers: [RoleValidationService],
providers: [
RoleValidationService,
provideWorkspaceScopedRepository(RoleEntity),
],
exports: [RoleValidationService],
})
export class RoleValidationModule {}

View File

@@ -1,7 +1,4 @@
import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import {
PermissionsException,
@@ -9,22 +6,23 @@ import {
PermissionsExceptionMessage,
} from 'src/engine/metadata-modules/permissions/permissions.exception';
import { RoleEntity } from 'src/engine/metadata-modules/role/role.entity';
import { InjectWorkspaceScopedRepository } from 'src/engine/twenty-orm/workspace-scoped-repository/inject-workspace-scoped-repository.decorator';
import { WorkspaceScopedRepository } from 'src/engine/twenty-orm/workspace-scoped-repository/workspace-scoped-repository';
@Injectable()
export class RoleValidationService {
constructor(
@InjectRepository(RoleEntity)
private readonly roleRepository: Repository<RoleEntity>,
@InjectWorkspaceScopedRepository(RoleEntity)
private readonly roleRepository: WorkspaceScopedRepository<RoleEntity>,
) {}
async validateRoleAssignableToUsersOrThrow(
roleId: string,
workspaceId: string,
): Promise<void> {
const role = await this.roleRepository.findOne({
const role = await this.roleRepository.findOne(workspaceId, {
where: {
id: roleId,
workspaceId,
},
});

View File

@@ -28,6 +28,7 @@ import { RowLevelPermissionPredicateGroupEntity } from 'src/engine/metadata-modu
import { RowLevelPermissionPredicateEntity } from 'src/engine/metadata-modules/row-level-permission-predicate/entities/row-level-permission-predicate.entity';
import { RowLevelPermissionModule } from 'src/engine/metadata-modules/row-level-permission-predicate/row-level-permission.module';
import { UserRoleModule } from 'src/engine/metadata-modules/user-role/user-role.module';
import { provideWorkspaceScopedRepository } from 'src/engine/twenty-orm/workspace-scoped-repository/provide-workspace-scoped-repository';
import { WorkspaceCacheModule } from 'src/engine/workspace-cache/workspace-cache.module';
import { WorkspaceMigrationGraphqlApiExceptionInterceptor } from 'src/engine/workspace-manager/workspace-migration/interceptors/workspace-migration-graphql-api-exception.interceptor';
import { WorkspaceMigrationModule } from 'src/engine/workspace-manager/workspace-migration/workspace-migration.module';
@@ -69,6 +70,12 @@ import { WorkspaceMigrationModule } from 'src/engine/workspace-manager/workspace
WorkspaceFlatRoleTargetMapCacheService,
WorkspaceMigrationGraphqlApiExceptionInterceptor,
WorkspaceRolesPermissionsCacheService,
provideWorkspaceScopedRepository(RoleEntity),
provideWorkspaceScopedRepository(RoleTargetEntity),
provideWorkspaceScopedRepository(ObjectPermissionEntity),
provideWorkspaceScopedRepository(FieldPermissionEntity),
provideWorkspaceScopedRepository(RowLevelPermissionPredicateEntity),
provideWorkspaceScopedRepository(RowLevelPermissionPredicateGroupEntity),
],
exports: [
RoleService,

View File

@@ -36,6 +36,8 @@ import { type UpdateRoleInput } from 'src/engine/metadata-modules/role/dtos/upda
import { RoleEntity } from 'src/engine/metadata-modules/role/role.entity';
import { fromFlatRoleToRoleDto } from 'src/engine/metadata-modules/role/utils/fromFlatRoleToRoleDto.util';
import { UserRoleService } from 'src/engine/metadata-modules/user-role/user-role.service';
import { InjectWorkspaceScopedRepository } from 'src/engine/twenty-orm/workspace-scoped-repository/inject-workspace-scoped-repository.decorator';
import { WorkspaceScopedRepository } from 'src/engine/twenty-orm/workspace-scoped-repository/workspace-scoped-repository';
import { WorkspaceMigrationBuilderException } from 'src/engine/workspace-manager/workspace-migration/exceptions/workspace-migration-builder-exception';
import { WorkspaceMigrationValidateBuildAndRunService } from 'src/engine/workspace-manager/workspace-migration/services/workspace-migration-validate-build-and-run-service';
@@ -46,8 +48,8 @@ export class RoleService {
private readonly flatEntityMapsCacheService: WorkspaceManyOrAllFlatEntityMapsCacheService,
@InjectRepository(WorkspaceEntity)
private readonly workspaceRepository: Repository<WorkspaceEntity>,
@InjectRepository(RoleEntity)
private readonly roleRepository: Repository<RoleEntity>,
@InjectWorkspaceScopedRepository(RoleEntity)
private readonly roleRepository: WorkspaceScopedRepository<RoleEntity>,
private readonly userRoleService: UserRoleService,
private readonly applicationService: ApplicationService,
private readonly apiKeyRoleService: ApiKeyRoleService,
@@ -55,10 +57,7 @@ export class RoleService {
) {}
public async getWorkspaceRoles(workspaceId: string): Promise<RoleEntity[]> {
return this.roleRepository.find({
where: {
workspaceId,
},
return this.roleRepository.find(workspaceId, {
relations: {
roleTargets: true,
rolePermissionFlags: {
@@ -74,10 +73,9 @@ export class RoleService {
id: string,
workspaceId: string,
): Promise<RoleEntity | null> {
return this.roleRepository.findOne({
return this.roleRepository.findOne(workspaceId, {
where: {
id,
workspaceId,
},
relations: {
roleTargets: true,

View File

@@ -16,6 +16,8 @@ import { RoleEntity } from 'src/engine/metadata-modules/role/role.entity';
import { WorkspaceRolesPermissionsCacheService } from 'src/engine/metadata-modules/role/services/workspace-roles-permissions-cache.service';
import { RowLevelPermissionPredicateGroupEntity } from 'src/engine/metadata-modules/row-level-permission-predicate/entities/row-level-permission-predicate-group.entity';
import { RowLevelPermissionPredicateEntity } from 'src/engine/metadata-modules/row-level-permission-predicate/entities/row-level-permission-predicate.entity';
import { getWorkspaceScopedRepositoryToken } from 'src/engine/twenty-orm/workspace-scoped-repository/get-workspace-scoped-repository-token.util';
import { type WorkspaceScopedRepository } from 'src/engine/twenty-orm/workspace-scoped-repository/workspace-scoped-repository';
const WORKSPACE_ID = '20202020-0000-4000-8000-000000000000';
const ROLE_ID = '11111111-1111-4111-8111-111111111111';
@@ -52,12 +54,14 @@ const createBaseRole = (
describe('WorkspaceRolesPermissionsCacheService', () => {
let service: WorkspaceRolesPermissionsCacheService;
let roleRepository: jest.Mocked<Pick<Repository<RoleEntity>, 'find'>>;
let roleRepository: jest.Mocked<
Pick<WorkspaceScopedRepository<RoleEntity>, 'find'>
>;
let objectMetadataRepository: jest.Mocked<
Pick<Repository<ObjectMetadataEntity>, 'find'>
>;
let objectPermissionRepository: jest.Mocked<
Pick<Repository<ObjectPermissionEntity>, 'find'>
Pick<WorkspaceScopedRepository<ObjectPermissionEntity>, 'find'>
>;
let rolePermissionFlagRepository: jest.Mocked<
Pick<Repository<RolePermissionFlagEntity>, 'find'>
@@ -118,11 +122,11 @@ describe('WorkspaceRolesPermissionsCacheService', () => {
useValue: objectMetadataRepository,
},
{
provide: getRepositoryToken(RoleEntity),
provide: getWorkspaceScopedRepositoryToken(RoleEntity),
useValue: roleRepository,
},
{
provide: getRepositoryToken(ObjectPermissionEntity),
provide: getWorkspaceScopedRepositoryToken(ObjectPermissionEntity),
useValue: objectPermissionRepository,
},
{
@@ -130,15 +134,19 @@ describe('WorkspaceRolesPermissionsCacheService', () => {
useValue: rolePermissionFlagRepository,
},
{
provide: getRepositoryToken(FieldPermissionEntity),
provide: getWorkspaceScopedRepositoryToken(FieldPermissionEntity),
useValue: fieldPermissionRepository,
},
{
provide: getRepositoryToken(RowLevelPermissionPredicateEntity),
provide: getWorkspaceScopedRepositoryToken(
RowLevelPermissionPredicateEntity,
),
useValue: rowLevelPermissionPredicateRepository,
},
{
provide: getRepositoryToken(RowLevelPermissionPredicateGroupEntity),
provide: getWorkspaceScopedRepositoryToken(
RowLevelPermissionPredicateGroupEntity,
),
useValue: rowLevelPermissionPredicateGroupRepository,
},
],

View File

@@ -17,6 +17,8 @@ import { RoleTargetEntity } from 'src/engine/metadata-modules/role-target/role-t
import { RoleEntity } from 'src/engine/metadata-modules/role/role.entity';
import { RowLevelPermissionPredicateGroupEntity } from 'src/engine/metadata-modules/row-level-permission-predicate/entities/row-level-permission-predicate-group.entity';
import { RowLevelPermissionPredicateEntity } from 'src/engine/metadata-modules/row-level-permission-predicate/entities/row-level-permission-predicate.entity';
import { InjectWorkspaceScopedRepository } from 'src/engine/twenty-orm/workspace-scoped-repository/inject-workspace-scoped-repository.decorator';
import { WorkspaceScopedRepository } from 'src/engine/twenty-orm/workspace-scoped-repository/workspace-scoped-repository';
import { WorkspaceCache } from 'src/engine/workspace-cache/decorators/workspace-cache.decorator';
import { createIdToUniversalIdentifierMap } from 'src/engine/workspace-cache/utils/create-id-to-universal-identifier-map.util';
import { regroupEntitiesByRelatedEntityId } from 'src/engine/workspace-cache/utils/regroup-entities-by-related-entity-id';
@@ -28,22 +30,22 @@ export class WorkspaceFlatRoleMapCacheService extends WorkspaceCacheProvider<
FlatEntityMaps<FlatRole>
> {
constructor(
@InjectRepository(RoleEntity)
private readonly roleRepository: Repository<RoleEntity>,
@InjectWorkspaceScopedRepository(RoleEntity)
private readonly roleRepository: WorkspaceScopedRepository<RoleEntity>,
@InjectRepository(ApplicationEntity)
private readonly applicationRepository: Repository<ApplicationEntity>,
@InjectRepository(RoleTargetEntity)
private readonly roleTargetRepository: Repository<RoleTargetEntity>,
@InjectRepository(ObjectPermissionEntity)
private readonly objectPermissionRepository: Repository<ObjectPermissionEntity>,
@InjectWorkspaceScopedRepository(RoleTargetEntity)
private readonly roleTargetRepository: WorkspaceScopedRepository<RoleTargetEntity>,
@InjectWorkspaceScopedRepository(ObjectPermissionEntity)
private readonly objectPermissionRepository: WorkspaceScopedRepository<ObjectPermissionEntity>,
@InjectRepository(RolePermissionFlagEntity)
private readonly rolePermissionFlagRepository: Repository<RolePermissionFlagEntity>,
@InjectRepository(FieldPermissionEntity)
private readonly fieldPermissionRepository: Repository<FieldPermissionEntity>,
@InjectRepository(RowLevelPermissionPredicateEntity)
private readonly rowLevelPermissionPredicateRepository: Repository<RowLevelPermissionPredicateEntity>,
@InjectRepository(RowLevelPermissionPredicateGroupEntity)
private readonly rowLevelPermissionPredicateGroupRepository: Repository<RowLevelPermissionPredicateGroupEntity>,
@InjectWorkspaceScopedRepository(FieldPermissionEntity)
private readonly fieldPermissionRepository: WorkspaceScopedRepository<FieldPermissionEntity>,
@InjectWorkspaceScopedRepository(RowLevelPermissionPredicateEntity)
private readonly rowLevelPermissionPredicateRepository: WorkspaceScopedRepository<RowLevelPermissionPredicateEntity>,
@InjectWorkspaceScopedRepository(RowLevelPermissionPredicateGroupEntity)
private readonly rowLevelPermissionPredicateGroupRepository: WorkspaceScopedRepository<RowLevelPermissionPredicateGroupEntity>,
) {
super();
}
@@ -61,8 +63,7 @@ export class WorkspaceFlatRoleMapCacheService extends WorkspaceCacheProvider<
rowLevelPermissionPredicates,
rowLevelPermissionPredicateGroups,
] = await Promise.all([
this.roleRepository.find({
where: { workspaceId },
this.roleRepository.find(workspaceId, {
withDeleted: true,
}),
this.applicationRepository.find({
@@ -70,13 +71,11 @@ export class WorkspaceFlatRoleMapCacheService extends WorkspaceCacheProvider<
select: ['id', 'universalIdentifier'],
withDeleted: true,
}),
this.roleTargetRepository.find({
where: { workspaceId },
this.roleTargetRepository.find(workspaceId, {
select: ['id', 'universalIdentifier', 'roleId'],
withDeleted: true,
}),
this.objectPermissionRepository.find({
where: { workspaceId },
this.objectPermissionRepository.find(workspaceId, {
select: ['id', 'universalIdentifier', 'roleId'],
withDeleted: true,
}),
@@ -85,18 +84,15 @@ export class WorkspaceFlatRoleMapCacheService extends WorkspaceCacheProvider<
select: ['id', 'universalIdentifier', 'roleId'],
withDeleted: true,
}),
this.fieldPermissionRepository.find({
where: { workspaceId },
this.fieldPermissionRepository.find(workspaceId, {
select: ['id', 'universalIdentifier', 'roleId'],
withDeleted: true,
}),
this.rowLevelPermissionPredicateRepository.find({
where: { workspaceId },
this.rowLevelPermissionPredicateRepository.find(workspaceId, {
select: ['id', 'universalIdentifier', 'roleId'],
withDeleted: true,
}),
this.rowLevelPermissionPredicateGroupRepository.find({
where: { workspaceId },
this.rowLevelPermissionPredicateGroupRepository.find(workspaceId, {
select: ['id', 'universalIdentifier', 'roleId'],
withDeleted: true,
}),

View File

@@ -23,6 +23,8 @@ import { RolePermissionFlagEntity } from 'src/engine/metadata-modules/role-permi
import { RoleEntity } from 'src/engine/metadata-modules/role/role.entity';
import { RowLevelPermissionPredicateGroupEntity } from 'src/engine/metadata-modules/row-level-permission-predicate/entities/row-level-permission-predicate-group.entity';
import { RowLevelPermissionPredicateEntity } from 'src/engine/metadata-modules/row-level-permission-predicate/entities/row-level-permission-predicate.entity';
import { InjectWorkspaceScopedRepository } from 'src/engine/twenty-orm/workspace-scoped-repository/inject-workspace-scoped-repository.decorator';
import { WorkspaceScopedRepository } from 'src/engine/twenty-orm/workspace-scoped-repository/workspace-scoped-repository';
import { WorkspaceCache } from 'src/engine/workspace-cache/decorators/workspace-cache.decorator';
import { regroupEntitiesByRelatedEntityId } from 'src/engine/workspace-cache/utils/regroup-entities-by-related-entity-id';
@@ -40,18 +42,18 @@ export class WorkspaceRolesPermissionsCacheService extends WorkspaceCacheProvide
constructor(
@InjectRepository(ObjectMetadataEntity)
private readonly objectMetadataRepository: Repository<ObjectMetadataEntity>,
@InjectRepository(RoleEntity)
private readonly roleRepository: Repository<RoleEntity>,
@InjectRepository(ObjectPermissionEntity)
private readonly objectPermissionRepository: Repository<ObjectPermissionEntity>,
@InjectWorkspaceScopedRepository(RoleEntity)
private readonly roleRepository: WorkspaceScopedRepository<RoleEntity>,
@InjectWorkspaceScopedRepository(ObjectPermissionEntity)
private readonly objectPermissionRepository: WorkspaceScopedRepository<ObjectPermissionEntity>,
@InjectRepository(RolePermissionFlagEntity)
private readonly rolePermissionFlagRepository: Repository<RolePermissionFlagEntity>,
@InjectRepository(FieldPermissionEntity)
private readonly fieldPermissionRepository: Repository<FieldPermissionEntity>,
@InjectRepository(RowLevelPermissionPredicateEntity)
private readonly rowLevelPermissionPredicateRepository: Repository<RowLevelPermissionPredicateEntity>,
@InjectRepository(RowLevelPermissionPredicateGroupEntity)
private readonly rowLevelPermissionPredicateGroupRepository: Repository<RowLevelPermissionPredicateGroupEntity>,
@InjectWorkspaceScopedRepository(FieldPermissionEntity)
private readonly fieldPermissionRepository: WorkspaceScopedRepository<FieldPermissionEntity>,
@InjectWorkspaceScopedRepository(RowLevelPermissionPredicateEntity)
private readonly rowLevelPermissionPredicateRepository: WorkspaceScopedRepository<RowLevelPermissionPredicateEntity>,
@InjectWorkspaceScopedRepository(RowLevelPermissionPredicateGroupEntity)
private readonly rowLevelPermissionPredicateGroupRepository: WorkspaceScopedRepository<RowLevelPermissionPredicateGroupEntity>,
) {
super();
}
@@ -68,24 +70,18 @@ export class WorkspaceRolesPermissionsCacheService extends WorkspaceCacheProvide
rowLevelPermissionPredicateGroups,
workspaceObjectMetadataCollection,
] = await Promise.all([
this.roleRepository.find({
where: { workspaceId },
}),
this.objectPermissionRepository.find({
where: { workspaceId },
}),
this.roleRepository.find(workspaceId),
this.objectPermissionRepository.find(workspaceId),
this.rolePermissionFlagRepository.find({
where: { workspaceId },
relations: ['permissionFlag'],
}),
this.fieldPermissionRepository.find({
where: { workspaceId },
this.fieldPermissionRepository.find(workspaceId),
this.rowLevelPermissionPredicateRepository.find(workspaceId, {
where: { deletedAt: IsNull() },
}),
this.rowLevelPermissionPredicateRepository.find({
where: { workspaceId, deletedAt: IsNull() },
}),
this.rowLevelPermissionPredicateGroupRepository.find({
where: { workspaceId, deletedAt: IsNull() },
this.rowLevelPermissionPredicateGroupRepository.find(workspaceId, {
where: { deletedAt: IsNull() },
}),
this.getWorkspaceObjectMetadataCollection(workspaceId),
]);

View File

@@ -11,6 +11,7 @@ import { RowLevelPermissionPredicateGroupEntity } from 'src/engine/metadata-modu
import { RowLevelPermissionPredicateEntity } from 'src/engine/metadata-modules/row-level-permission-predicate/entities/row-level-permission-predicate.entity';
import { RowLevelPermissionPredicateGroupService } from 'src/engine/metadata-modules/row-level-permission-predicate/services/row-level-permission-predicate-group.service';
import { RowLevelPermissionPredicateService } from 'src/engine/metadata-modules/row-level-permission-predicate/services/row-level-permission-predicate.service';
import { provideWorkspaceScopedRepository } from 'src/engine/twenty-orm/workspace-scoped-repository/provide-workspace-scoped-repository';
import { WorkspaceCacheModule } from 'src/engine/workspace-cache/workspace-cache.module';
import { WorkspaceMigrationModule } from 'src/engine/workspace-manager/workspace-migration/workspace-migration.module';
@@ -30,6 +31,7 @@ import { WorkspaceMigrationModule } from 'src/engine/workspace-manager/workspace
providers: [
RowLevelPermissionPredicateService,
RowLevelPermissionPredicateGroupService,
provideWorkspaceScopedRepository(RowLevelPermissionPredicateGroupEntity),
],
exports: [
RowLevelPermissionPredicateService,

View File

@@ -1,10 +1,8 @@
/* @license Enterprise */
import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { isDefined } from 'twenty-shared/utils';
import { Repository } from 'typeorm';
import { BillingEntitlementKey } from 'src/engine/core-modules/billing/enums/billing-entitlement-key.enum';
import { BillingService } from 'src/engine/core-modules/billing/services/billing.service';
@@ -14,6 +12,8 @@ import { findFlatEntityByIdInFlatEntityMaps } from 'src/engine/metadata-modules/
import { fromFlatRowLevelPermissionPredicateGroupToDto } from 'src/engine/metadata-modules/flat-row-level-permission-predicate/utils/from-flat-row-level-permission-predicate-group-to-dto.util';
import { RowLevelPermissionPredicateGroupDTO } from 'src/engine/metadata-modules/row-level-permission-predicate/dtos/row-level-permission-predicate-group.dto';
import { RowLevelPermissionPredicateGroupEntity } from 'src/engine/metadata-modules/row-level-permission-predicate/entities/row-level-permission-predicate-group.entity';
import { InjectWorkspaceScopedRepository } from 'src/engine/twenty-orm/workspace-scoped-repository/inject-workspace-scoped-repository.decorator';
import { WorkspaceScopedRepository } from 'src/engine/twenty-orm/workspace-scoped-repository/workspace-scoped-repository';
import { WorkspaceCacheService } from 'src/engine/workspace-cache/services/workspace-cache.service';
@Injectable()
@@ -22,8 +22,8 @@ export class RowLevelPermissionPredicateGroupService {
private readonly flatEntityMapsCacheService: WorkspaceManyOrAllFlatEntityMapsCacheService,
private readonly workspaceCacheService: WorkspaceCacheService,
private readonly billingService: BillingService,
@InjectRepository(RowLevelPermissionPredicateGroupEntity)
private readonly rowLevelPermissionPredicateGroupRepository: Repository<RowLevelPermissionPredicateGroupEntity>,
@InjectWorkspaceScopedRepository(RowLevelPermissionPredicateGroupEntity)
private readonly rowLevelPermissionPredicateGroupRepository: WorkspaceScopedRepository<RowLevelPermissionPredicateGroupEntity>,
private readonly enterprisePlanService: EnterprisePlanService,
) {}
@@ -122,9 +122,10 @@ export class RowLevelPermissionPredicateGroupService {
}
public async deleteAllRowLevelPermissionPredicateGroups(workspaceId: string) {
await this.rowLevelPermissionPredicateGroupRepository.delete({
await this.rowLevelPermissionPredicateGroupRepository.delete(
workspaceId,
});
{},
);
await this.workspaceCacheService.invalidateAndRecompute(workspaceId, [
'rolesPermissions',

View File

@@ -6,6 +6,7 @@ import { RoleTargetEntity } from 'src/engine/metadata-modules/role-target/role-t
import { RoleTargetModule } from 'src/engine/metadata-modules/role-target/role-target.module';
import { RoleEntity } from 'src/engine/metadata-modules/role/role.entity';
import { UserRoleService } from 'src/engine/metadata-modules/user-role/user-role.service';
import { provideWorkspaceScopedRepository } from 'src/engine/twenty-orm/workspace-scoped-repository/provide-workspace-scoped-repository';
import { WorkspaceCacheModule } from 'src/engine/workspace-cache/workspace-cache.module';
@Module({
@@ -15,7 +16,10 @@ import { WorkspaceCacheModule } from 'src/engine/workspace-cache/workspace-cache
WorkspaceCacheModule,
RoleTargetModule,
],
providers: [UserRoleService],
providers: [
UserRoleService,
provideWorkspaceScopedRepository(RoleTargetEntity),
],
exports: [UserRoleService],
})
export class UserRoleModule {}

View File

@@ -15,14 +15,16 @@ import { RoleTargetService } from 'src/engine/metadata-modules/role-target/servi
import { RoleEntity } from 'src/engine/metadata-modules/role/role.entity';
import { GlobalWorkspaceOrmManager } from 'src/engine/twenty-orm/global-workspace-datasource/global-workspace-orm.manager';
import { buildSystemAuthContext } from 'src/engine/twenty-orm/utils/build-system-auth-context.util';
import { InjectWorkspaceScopedRepository } from 'src/engine/twenty-orm/workspace-scoped-repository/inject-workspace-scoped-repository.decorator';
import { WorkspaceScopedRepository } from 'src/engine/twenty-orm/workspace-scoped-repository/workspace-scoped-repository';
import { WorkspaceCacheService } from 'src/engine/workspace-cache/services/workspace-cache.service';
import { STANDARD_ROLE } from 'src/engine/workspace-manager/twenty-standard-application/constants/standard-role.constant';
import { WorkspaceMemberWorkspaceEntity } from 'src/modules/workspace-member/standard-objects/workspace-member.workspace-entity';
export class UserRoleService {
constructor(
@InjectRepository(RoleTargetEntity)
private readonly roleTargetRepository: Repository<RoleTargetEntity>,
@InjectWorkspaceScopedRepository(RoleTargetEntity)
private readonly roleTargetRepository: WorkspaceScopedRepository<RoleTargetEntity>,
@InjectRepository(UserWorkspaceEntity)
private readonly userWorkspaceRepository: Repository<UserWorkspaceEntity>,
private readonly globalWorkspaceOrmManager: GlobalWorkspaceOrmManager,
@@ -101,10 +103,9 @@ export class UserRoleService {
return new Map();
}
const allRoleTargets = await this.roleTargetRepository.find({
const allRoleTargets = await this.roleTargetRepository.find(workspaceId, {
where: {
userWorkspaceId: In(userWorkspaceIds),
workspaceId,
},
relations: {
role: {

View File

@@ -1,12 +1,11 @@
import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { t } from '@lingui/core/macro';
import {
isDefined,
isFieldMetadataEligibleForFieldsWidget,
} from 'twenty-shared/utils';
import { IsNull, Repository } from 'typeorm';
import { IsNull } from 'typeorm';
import { v4 } from 'uuid';
import { ApplicationService } from 'src/engine/core-modules/application/application.service';
@@ -36,6 +35,8 @@ import {
ViewFieldGroupExceptionCode,
} from 'src/engine/metadata-modules/view-field-group/exceptions/view-field-group.exception';
import { ViewEntity } from 'src/engine/metadata-modules/view/entities/view.entity';
import { InjectWorkspaceScopedRepository } from 'src/engine/twenty-orm/workspace-scoped-repository/inject-workspace-scoped-repository.decorator';
import { WorkspaceScopedRepository } from 'src/engine/twenty-orm/workspace-scoped-repository/workspace-scoped-repository';
import { WorkspaceMigrationBuilderException } from 'src/engine/workspace-manager/workspace-migration/exceptions/workspace-migration-builder-exception';
import { WorkspaceMigrationValidateBuildAndRunService } from 'src/engine/workspace-manager/workspace-migration/services/workspace-migration-validate-build-and-run-service';
@@ -45,8 +46,8 @@ export class FieldsWidgetUpsertService {
private readonly workspaceMigrationValidateBuildAndRunService: WorkspaceMigrationValidateBuildAndRunService,
private readonly workspaceManyOrAllFlatEntityMapsCacheService: WorkspaceManyOrAllFlatEntityMapsCacheService,
private readonly applicationService: ApplicationService,
@InjectRepository(ViewEntity)
private readonly viewRepository: Repository<ViewEntity>,
@InjectWorkspaceScopedRepository(ViewEntity)
private readonly viewRepository: WorkspaceScopedRepository<ViewEntity>,
) {}
async upsertFieldsWidget({
@@ -181,8 +182,8 @@ export class FieldsWidgetUpsertService {
});
}
const view = await this.viewRepository.findOne({
where: { id: viewId, workspaceId, deletedAt: IsNull() },
const view = await this.viewRepository.findOne(workspaceId, {
where: { id: viewId, deletedAt: IsNull() },
});
if (!isDefined(view)) {

View File

@@ -9,6 +9,7 @@ import { ViewFieldGroupResolver } from 'src/engine/metadata-modules/view-field-g
import { FieldsWidgetUpsertService } from 'src/engine/metadata-modules/view-field-group/services/fields-widget-upsert.service';
import { ViewFieldGroupService } from 'src/engine/metadata-modules/view-field-group/services/view-field-group.service';
import { ViewEntity } from 'src/engine/metadata-modules/view/entities/view.entity';
import { provideWorkspaceScopedRepository } from 'src/engine/twenty-orm/workspace-scoped-repository/provide-workspace-scoped-repository';
import { WorkspaceCacheStorageModule } from 'src/engine/workspace-cache-storage/workspace-cache-storage.module';
import { WorkspaceMigrationModule } from 'src/engine/workspace-manager/workspace-migration/workspace-migration.module';
@@ -25,6 +26,7 @@ import { WorkspaceMigrationModule } from 'src/engine/workspace-manager/workspace
ViewFieldGroupResolver,
ViewFieldGroupService,
FieldsWidgetUpsertService,
provideWorkspaceScopedRepository(ViewEntity),
],
exports: [ViewFieldGroupService],
})

View File

@@ -1,18 +1,18 @@
import { Test, type TestingModule } from '@nestjs/testing';
import { getRepositoryToken } from '@nestjs/typeorm';
import { type Repository } from 'typeorm';
import { ViewFilterGroupLogicalOperator } from 'twenty-shared/types';
import { ApplicationService } from 'src/engine/core-modules/application/application.service';
import { WorkspaceManyOrAllFlatEntityMapsCacheService } from 'src/engine/metadata-modules/flat-entity/services/workspace-many-or-all-flat-entity-maps-cache.service';
import { ViewFilterGroupEntity } from 'src/engine/metadata-modules/view-filter-group/entities/view-filter-group.entity';
import { ViewFilterGroupService } from 'src/engine/metadata-modules/view-filter-group/services/view-filter-group.service';
import { getWorkspaceScopedRepositoryToken } from 'src/engine/twenty-orm/workspace-scoped-repository/get-workspace-scoped-repository-token.util';
import { type WorkspaceScopedRepository } from 'src/engine/twenty-orm/workspace-scoped-repository/workspace-scoped-repository';
import { WorkspaceMigrationValidateBuildAndRunService } from 'src/engine/workspace-manager/workspace-migration/services/workspace-migration-validate-build-and-run-service';
describe('ViewFilterGroupService', () => {
let viewFilterGroupService: ViewFilterGroupService;
let viewFilterGroupRepository: Repository<ViewFilterGroupEntity>;
let viewFilterGroupRepository: WorkspaceScopedRepository<ViewFilterGroupEntity>;
const mockViewFilterGroup = {
id: 'view-filter-group-id',
@@ -30,13 +30,11 @@ describe('ViewFilterGroupService', () => {
providers: [
ViewFilterGroupService,
{
provide: getRepositoryToken(ViewFilterGroupEntity),
provide: getWorkspaceScopedRepositoryToken(ViewFilterGroupEntity),
useValue: {
find: jest.fn(),
findOne: jest.fn(),
create: jest.fn(),
save: jest.fn(),
softDelete: jest.fn(),
delete: jest.fn(),
},
},
@@ -65,9 +63,9 @@ describe('ViewFilterGroupService', () => {
viewFilterGroupService = module.get<ViewFilterGroupService>(
ViewFilterGroupService,
);
viewFilterGroupRepository = module.get<Repository<ViewFilterGroupEntity>>(
getRepositoryToken(ViewFilterGroupEntity),
);
viewFilterGroupRepository = module.get<
WorkspaceScopedRepository<ViewFilterGroupEntity>
>(getWorkspaceScopedRepositoryToken(ViewFilterGroupEntity));
});
it('should be defined', () => {
@@ -86,9 +84,8 @@ describe('ViewFilterGroupService', () => {
const result =
await viewFilterGroupService.findByWorkspaceId(workspaceId);
expect(viewFilterGroupRepository.find).toHaveBeenCalledWith({
expect(viewFilterGroupRepository.find).toHaveBeenCalledWith(workspaceId, {
where: {
workspaceId,
deletedAt: expect.anything(),
},
order: { positionInViewFilterGroup: 'ASC' },
@@ -119,9 +116,8 @@ describe('ViewFilterGroupService', () => {
viewId,
);
expect(viewFilterGroupRepository.find).toHaveBeenCalledWith({
expect(viewFilterGroupRepository.find).toHaveBeenCalledWith(workspaceId, {
where: {
workspaceId,
viewId,
deletedAt: expect.anything(),
},
@@ -149,20 +145,22 @@ describe('ViewFilterGroupService', () => {
const result = await viewFilterGroupService.findById(id, workspaceId);
expect(viewFilterGroupRepository.findOne).toHaveBeenCalledWith({
where: {
id,
workspaceId,
deletedAt: expect.anything(),
expect(viewFilterGroupRepository.findOne).toHaveBeenCalledWith(
workspaceId,
{
where: {
id,
deletedAt: expect.anything(),
},
relations: [
'workspace',
'view',
'viewFilters',
'parentViewFilterGroup',
'childViewFilterGroups',
],
},
relations: [
'workspace',
'view',
'viewFilters',
'parentViewFilterGroup',
'childViewFilterGroups',
],
});
);
expect(result).toEqual(mockViewFilterGroup);
});

View File

@@ -1,7 +1,6 @@
import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { IsNull, type Repository } from 'typeorm';
import { IsNull } from 'typeorm';
import { ApplicationService } from 'src/engine/core-modules/application/application.service';
import { WorkspaceManyOrAllFlatEntityMapsCacheService } from 'src/engine/metadata-modules/flat-entity/services/workspace-many-or-all-flat-entity-maps-cache.service';
@@ -18,14 +17,16 @@ import { type UpdateViewFilterGroupInput } from 'src/engine/metadata-modules/vie
import { type ViewFilterGroupDTO } from 'src/engine/metadata-modules/view-filter-group/dtos/view-filter-group.dto';
import { ViewFilterGroupEntity } from 'src/engine/metadata-modules/view-filter-group/entities/view-filter-group.entity';
import { fromFlatViewFilterGroupToViewFilterGroupDto } from 'src/engine/metadata-modules/view-filter-group/utils/from-flat-view-filter-group-to-view-filter-group-dto.util';
import { InjectWorkspaceScopedRepository } from 'src/engine/twenty-orm/workspace-scoped-repository/inject-workspace-scoped-repository.decorator';
import { WorkspaceScopedRepository } from 'src/engine/twenty-orm/workspace-scoped-repository/workspace-scoped-repository';
import { WorkspaceMigrationBuilderException } from 'src/engine/workspace-manager/workspace-migration/exceptions/workspace-migration-builder-exception';
import { WorkspaceMigrationValidateBuildAndRunService } from 'src/engine/workspace-manager/workspace-migration/services/workspace-migration-validate-build-and-run-service';
@Injectable()
export class ViewFilterGroupService {
constructor(
@InjectRepository(ViewFilterGroupEntity)
private readonly viewFilterGroupRepository: Repository<ViewFilterGroupEntity>,
@InjectWorkspaceScopedRepository(ViewFilterGroupEntity)
private readonly viewFilterGroupRepository: WorkspaceScopedRepository<ViewFilterGroupEntity>,
private readonly workspaceMigrationValidateBuildAndRunService: WorkspaceMigrationValidateBuildAndRunService,
private readonly flatEntityMapsCacheService: WorkspaceManyOrAllFlatEntityMapsCacheService,
private readonly applicationService: ApplicationService,
@@ -320,9 +321,8 @@ export class ViewFilterGroupService {
async findByWorkspaceId(
workspaceId: string,
): Promise<ViewFilterGroupEntity[]> {
return this.viewFilterGroupRepository.find({
return this.viewFilterGroupRepository.find(workspaceId, {
where: {
workspaceId,
deletedAt: IsNull(),
},
order: { positionInViewFilterGroup: 'ASC' },
@@ -340,9 +340,8 @@ export class ViewFilterGroupService {
workspaceId: string,
viewId: string,
): Promise<ViewFilterGroupEntity[]> {
return this.viewFilterGroupRepository.find({
return this.viewFilterGroupRepository.find(workspaceId, {
where: {
workspaceId,
viewId,
deletedAt: IsNull(),
},
@@ -361,20 +360,22 @@ export class ViewFilterGroupService {
id: string,
workspaceId: string,
): Promise<ViewFilterGroupEntity | null> {
const viewFilterGroup = await this.viewFilterGroupRepository.findOne({
where: {
id,
workspaceId,
deletedAt: IsNull(),
const viewFilterGroup = await this.viewFilterGroupRepository.findOne(
workspaceId,
{
where: {
id,
deletedAt: IsNull(),
},
relations: [
'workspace',
'view',
'viewFilters',
'parentViewFilterGroup',
'childViewFilterGroups',
],
},
relations: [
'workspace',
'view',
'viewFilters',
'parentViewFilterGroup',
'childViewFilterGroups',
],
});
);
return viewFilterGroup || null;
}

View File

@@ -10,6 +10,7 @@ import { ViewFilterGroupResolver } from 'src/engine/metadata-modules/view-filter
import { ViewFilterGroupService } from 'src/engine/metadata-modules/view-filter-group/services/view-filter-group.service';
import { ViewPermissionsModule } from 'src/engine/metadata-modules/view-permissions/view-permissions.module';
import { ViewEntity } from 'src/engine/metadata-modules/view/entities/view.entity';
import { provideWorkspaceScopedRepository } from 'src/engine/twenty-orm/workspace-scoped-repository/provide-workspace-scoped-repository';
import { WorkspaceCacheStorageModule } from 'src/engine/workspace-cache-storage/workspace-cache-storage.module';
import { WorkspaceMigrationModule } from 'src/engine/workspace-manager/workspace-migration/workspace-migration.module';
@@ -24,7 +25,11 @@ import { WorkspaceMigrationModule } from 'src/engine/workspace-manager/workspace
ViewPermissionsModule,
],
controllers: [ViewFilterGroupController],
providers: [ViewFilterGroupService, ViewFilterGroupResolver],
providers: [
ViewFilterGroupService,
ViewFilterGroupResolver,
provideWorkspaceScopedRepository(ViewFilterGroupEntity),
],
exports: [ViewFilterGroupService],
})
export class ViewFilterGroupModule {}

View File

@@ -1,7 +1,6 @@
import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { IsNull, Repository } from 'typeorm';
import { IsNull } from 'typeorm';
import { ApplicationService } from 'src/engine/core-modules/application/application.service';
import { WorkspaceManyOrAllFlatEntityMapsCacheService } from 'src/engine/metadata-modules/flat-entity/services/workspace-many-or-all-flat-entity-maps-cache.service';
@@ -18,14 +17,16 @@ import { UpdateViewFilterInput } from 'src/engine/metadata-modules/view-filter/d
import { ViewFilterDTO } from 'src/engine/metadata-modules/view-filter/dtos/view-filter.dto';
import { ViewFilterEntity } from 'src/engine/metadata-modules/view-filter/entities/view-filter.entity';
import { fromFlatViewFilterToViewFilterDto } from 'src/engine/metadata-modules/view-filter/utils/from-flat-view-filter-to-view-filter-dto.util';
import { InjectWorkspaceScopedRepository } from 'src/engine/twenty-orm/workspace-scoped-repository/inject-workspace-scoped-repository.decorator';
import { WorkspaceScopedRepository } from 'src/engine/twenty-orm/workspace-scoped-repository/workspace-scoped-repository';
import { WorkspaceMigrationBuilderException } from 'src/engine/workspace-manager/workspace-migration/exceptions/workspace-migration-builder-exception';
import { WorkspaceMigrationValidateBuildAndRunService } from 'src/engine/workspace-manager/workspace-migration/services/workspace-migration-validate-build-and-run-service';
@Injectable()
export class ViewFilterService {
constructor(
@InjectRepository(ViewFilterEntity)
private readonly viewFilterRepository: Repository<ViewFilterEntity>,
@InjectWorkspaceScopedRepository(ViewFilterEntity)
private readonly viewFilterRepository: WorkspaceScopedRepository<ViewFilterEntity>,
private readonly workspaceMigrationValidateBuildAndRunService: WorkspaceMigrationValidateBuildAndRunService,
private readonly flatEntityMapsCacheService: WorkspaceManyOrAllFlatEntityMapsCacheService,
private readonly applicationService: ApplicationService,
@@ -319,9 +320,8 @@ export class ViewFilterService {
}
async findByWorkspaceId(workspaceId: string): Promise<ViewFilterEntity[]> {
return this.viewFilterRepository.find({
return this.viewFilterRepository.find(workspaceId, {
where: {
workspaceId,
deletedAt: IsNull(),
},
order: { positionInViewFilterGroup: 'ASC' },
@@ -333,9 +333,8 @@ export class ViewFilterService {
workspaceId: string,
viewId: string,
): Promise<ViewFilterEntity[]> {
return this.viewFilterRepository.find({
return this.viewFilterRepository.find(workspaceId, {
where: {
workspaceId,
viewId,
deletedAt: IsNull(),
},
@@ -348,10 +347,9 @@ export class ViewFilterService {
id: string,
workspaceId: string,
): Promise<ViewFilterEntity | null> {
const viewFilter = await this.viewFilterRepository.findOne({
const viewFilter = await this.viewFilterRepository.findOne(workspaceId, {
where: {
id,
workspaceId,
deletedAt: IsNull(),
},
relations: ['workspace', 'view', 'viewFilterGroup'],

View File

@@ -11,6 +11,7 @@ import { ViewFilterService } from 'src/engine/metadata-modules/view-filter/servi
import { ViewFilterToolsFactory } from 'src/engine/metadata-modules/view-filter/tools/view-filter-tools.factory';
import { ViewPermissionsModule } from 'src/engine/metadata-modules/view-permissions/view-permissions.module';
import { ViewEntity } from 'src/engine/metadata-modules/view/entities/view.entity';
import { provideWorkspaceScopedRepository } from 'src/engine/twenty-orm/workspace-scoped-repository/provide-workspace-scoped-repository';
import { WorkspaceCacheStorageModule } from 'src/engine/workspace-cache-storage/workspace-cache-storage.module';
import { WorkspaceMigrationModule } from 'src/engine/workspace-manager/workspace-migration/workspace-migration.module';
@@ -25,7 +26,12 @@ import { WorkspaceMigrationModule } from 'src/engine/workspace-manager/workspace
ViewPermissionsModule,
],
controllers: [ViewFilterController],
providers: [ViewFilterService, ViewFilterResolver, ViewFilterToolsFactory],
providers: [
ViewFilterService,
ViewFilterResolver,
ViewFilterToolsFactory,
provideWorkspaceScopedRepository(ViewFilterEntity),
],
exports: [ViewFilterService, ViewFilterToolsFactory],
})
export class ViewFilterModule {}

View File

@@ -1,8 +1,7 @@
import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { isDefined } from 'twenty-shared/utils';
import { IsNull, Repository } from 'typeorm';
import { IsNull } from 'typeorm';
import { ApplicationService } from 'src/engine/core-modules/application/application.service';
import { WorkspaceManyOrAllFlatEntityMapsCacheService } from 'src/engine/metadata-modules/flat-entity/services/workspace-many-or-all-flat-entity-maps-cache.service';
@@ -25,14 +24,16 @@ import {
ViewGroupExceptionCode,
} from 'src/engine/metadata-modules/view-group/exceptions/view-group.exception';
import { fromFlatViewGroupToViewGroupDto } from 'src/engine/metadata-modules/view-group/utils/from-flat-view-group-to-view-group-dto.util';
import { InjectWorkspaceScopedRepository } from 'src/engine/twenty-orm/workspace-scoped-repository/inject-workspace-scoped-repository.decorator';
import { WorkspaceScopedRepository } from 'src/engine/twenty-orm/workspace-scoped-repository/workspace-scoped-repository';
import { WorkspaceMigrationBuilderException } from 'src/engine/workspace-manager/workspace-migration/exceptions/workspace-migration-builder-exception';
import { WorkspaceMigrationValidateBuildAndRunService } from 'src/engine/workspace-manager/workspace-migration/services/workspace-migration-validate-build-and-run-service';
@Injectable()
export class ViewGroupService {
constructor(
@InjectRepository(ViewGroupEntity)
private readonly viewGroupRepository: Repository<ViewGroupEntity>,
@InjectWorkspaceScopedRepository(ViewGroupEntity)
private readonly viewGroupRepository: WorkspaceScopedRepository<ViewGroupEntity>,
private readonly workspaceMigrationValidateBuildAndRunService: WorkspaceMigrationValidateBuildAndRunService,
private readonly flatEntityMapsCacheService: WorkspaceManyOrAllFlatEntityMapsCacheService,
private readonly applicationService: ApplicationService,
@@ -379,9 +380,8 @@ export class ViewGroupService {
}
async findByWorkspaceId(workspaceId: string): Promise<ViewGroupEntity[]> {
return this.viewGroupRepository.find({
return this.viewGroupRepository.find(workspaceId, {
where: {
workspaceId,
deletedAt: IsNull(),
},
order: { position: 'ASC' },
@@ -393,9 +393,8 @@ export class ViewGroupService {
workspaceId: string,
viewId: string,
): Promise<ViewGroupEntity[]> {
return this.viewGroupRepository.find({
return this.viewGroupRepository.find(workspaceId, {
where: {
workspaceId,
viewId,
deletedAt: IsNull(),
},
@@ -408,10 +407,9 @@ export class ViewGroupService {
id: string,
workspaceId: string,
): Promise<ViewGroupEntity | null> {
const viewGroup = await this.viewGroupRepository.findOne({
const viewGroup = await this.viewGroupRepository.findOne(workspaceId, {
where: {
id,
workspaceId,
deletedAt: IsNull(),
},
relations: ['workspace', 'view'],

View File

@@ -12,6 +12,7 @@ import { ViewGroupResolver } from 'src/engine/metadata-modules/view-group/resolv
import { ViewGroupService } from 'src/engine/metadata-modules/view-group/services/view-group.service';
import { ViewPermissionsModule } from 'src/engine/metadata-modules/view-permissions/view-permissions.module';
import { ViewEntity } from 'src/engine/metadata-modules/view/entities/view.entity';
import { provideWorkspaceScopedRepository } from 'src/engine/twenty-orm/workspace-scoped-repository/provide-workspace-scoped-repository';
import { WorkspaceCacheStorageModule } from 'src/engine/workspace-cache-storage/workspace-cache-storage.module';
import { WorkspaceMigrationModule } from 'src/engine/workspace-manager/workspace-migration/workspace-migration.module';
@@ -28,7 +29,11 @@ import { WorkspaceMigrationModule } from 'src/engine/workspace-manager/workspace
ViewPermissionsModule,
],
controllers: [ViewGroupController],
providers: [ViewGroupService, ViewGroupResolver],
providers: [
ViewGroupService,
ViewGroupResolver,
provideWorkspaceScopedRepository(ViewGroupEntity),
],
exports: [ViewGroupService],
})
export class ViewGroupModule {}

View File

@@ -1,7 +1,4 @@
import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { ViewFieldEntity } from 'src/engine/metadata-modules/view-field/entities/view-field.entity';
import { ViewFilterGroupEntity } from 'src/engine/metadata-modules/view-filter-group/entities/view-filter-group.entity';
@@ -9,20 +6,22 @@ import { ViewFilterEntity } from 'src/engine/metadata-modules/view-filter/entiti
import { ViewGroupEntity } from 'src/engine/metadata-modules/view-group/entities/view-group.entity';
import { type ViewChildEntityKind } from 'src/engine/metadata-modules/view-permissions/types/view-permissions.types';
import { ViewSortEntity } from 'src/engine/metadata-modules/view-sort/entities/view-sort.entity';
import { InjectWorkspaceScopedRepository } from 'src/engine/twenty-orm/workspace-scoped-repository/inject-workspace-scoped-repository.decorator';
import { WorkspaceScopedRepository } from 'src/engine/twenty-orm/workspace-scoped-repository/workspace-scoped-repository';
@Injectable()
export class ViewEntityLookupService {
constructor(
@InjectRepository(ViewFieldEntity)
private readonly viewFieldRepository: Repository<ViewFieldEntity>,
@InjectRepository(ViewFilterEntity)
private readonly viewFilterRepository: Repository<ViewFilterEntity>,
@InjectRepository(ViewFilterGroupEntity)
private readonly viewFilterGroupRepository: Repository<ViewFilterGroupEntity>,
@InjectRepository(ViewGroupEntity)
private readonly viewGroupRepository: Repository<ViewGroupEntity>,
@InjectRepository(ViewSortEntity)
private readonly viewSortRepository: Repository<ViewSortEntity>,
@InjectWorkspaceScopedRepository(ViewFieldEntity)
private readonly viewFieldRepository: WorkspaceScopedRepository<ViewFieldEntity>,
@InjectWorkspaceScopedRepository(ViewFilterEntity)
private readonly viewFilterRepository: WorkspaceScopedRepository<ViewFilterEntity>,
@InjectWorkspaceScopedRepository(ViewFilterGroupEntity)
private readonly viewFilterGroupRepository: WorkspaceScopedRepository<ViewFilterGroupEntity>,
@InjectWorkspaceScopedRepository(ViewGroupEntity)
private readonly viewGroupRepository: WorkspaceScopedRepository<ViewGroupEntity>,
@InjectWorkspaceScopedRepository(ViewSortEntity)
private readonly viewSortRepository: WorkspaceScopedRepository<ViewSortEntity>,
) {}
async findViewIdByEntityIdAndKind(
@@ -32,8 +31,8 @@ export class ViewEntityLookupService {
): Promise<string | null> {
switch (kind) {
case 'viewField': {
const row = await this.viewFieldRepository.findOne({
where: { id: entityId, workspaceId },
const row = await this.viewFieldRepository.findOne(workspaceId, {
where: { id: entityId },
select: ['viewId'],
});
@@ -42,8 +41,8 @@ export class ViewEntityLookupService {
}
case 'viewFilter': {
const row = await this.viewFilterRepository.findOne({
where: { id: entityId, workspaceId },
const row = await this.viewFilterRepository.findOne(workspaceId, {
where: { id: entityId },
select: ['viewId'],
});
@@ -52,8 +51,8 @@ export class ViewEntityLookupService {
}
case 'viewFilterGroup': {
const row = await this.viewFilterGroupRepository.findOne({
where: { id: entityId, workspaceId },
const row = await this.viewFilterGroupRepository.findOne(workspaceId, {
where: { id: entityId },
select: ['viewId'],
});
@@ -62,8 +61,8 @@ export class ViewEntityLookupService {
}
case 'viewGroup': {
const row = await this.viewGroupRepository.findOne({
where: { id: entityId, workspaceId },
const row = await this.viewGroupRepository.findOne(workspaceId, {
where: { id: entityId },
select: ['viewId'],
});
@@ -72,8 +71,8 @@ export class ViewEntityLookupService {
}
case 'viewSort': {
const row = await this.viewSortRepository.findOne({
where: { id: entityId, workspaceId },
const row = await this.viewSortRepository.findOne(workspaceId, {
where: { id: entityId },
select: ['viewId'],
});

View File

@@ -38,6 +38,7 @@ import { ViewEntityLookupService } from 'src/engine/metadata-modules/view-permis
import { ViewSortEntity } from 'src/engine/metadata-modules/view-sort/entities/view-sort.entity';
import { ViewEntity } from 'src/engine/metadata-modules/view/entities/view.entity';
import { ViewService } from 'src/engine/metadata-modules/view/services/view.service';
import { provideWorkspaceScopedRepository } from 'src/engine/twenty-orm/workspace-scoped-repository/provide-workspace-scoped-repository';
import { WorkspaceCacheStorageModule } from 'src/engine/workspace-cache-storage/workspace-cache-storage.module';
import { WorkspaceMigrationModule } from 'src/engine/workspace-manager/workspace-migration/workspace-migration.module';
@@ -86,6 +87,12 @@ import { WorkspaceMigrationModule } from 'src/engine/workspace-manager/workspace
UpdateViewSortPermissionGuard,
DeleteViewSortPermissionGuard,
DestroyViewSortPermissionGuard,
provideWorkspaceScopedRepository(ViewEntity),
provideWorkspaceScopedRepository(ViewFieldEntity),
provideWorkspaceScopedRepository(ViewFilterEntity),
provideWorkspaceScopedRepository(ViewFilterGroupEntity),
provideWorkspaceScopedRepository(ViewGroupEntity),
provideWorkspaceScopedRepository(ViewSortEntity),
],
exports: [
ViewService,

View File

@@ -1,7 +1,6 @@
import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { IsNull, Repository } from 'typeorm';
import { IsNull } from 'typeorm';
import { ApplicationService } from 'src/engine/core-modules/application/application.service';
import { WorkspaceManyOrAllFlatEntityMapsCacheService } from 'src/engine/metadata-modules/flat-entity/services/workspace-many-or-all-flat-entity-maps-cache.service';
@@ -18,14 +17,16 @@ import { UpdateViewSortInput } from 'src/engine/metadata-modules/view-sort/dtos/
import { ViewSortDTO } from 'src/engine/metadata-modules/view-sort/dtos/view-sort.dto';
import { ViewSortEntity } from 'src/engine/metadata-modules/view-sort/entities/view-sort.entity';
import { fromFlatViewSortToViewSortDto } from 'src/engine/metadata-modules/view-sort/utils/from-flat-view-sort-to-view-sort-dto.util';
import { InjectWorkspaceScopedRepository } from 'src/engine/twenty-orm/workspace-scoped-repository/inject-workspace-scoped-repository.decorator';
import { WorkspaceScopedRepository } from 'src/engine/twenty-orm/workspace-scoped-repository/workspace-scoped-repository';
import { WorkspaceMigrationBuilderException } from 'src/engine/workspace-manager/workspace-migration/exceptions/workspace-migration-builder-exception';
import { WorkspaceMigrationValidateBuildAndRunService } from 'src/engine/workspace-manager/workspace-migration/services/workspace-migration-validate-build-and-run-service';
@Injectable()
export class ViewSortService {
constructor(
@InjectRepository(ViewSortEntity)
private readonly viewSortRepository: Repository<ViewSortEntity>,
@InjectWorkspaceScopedRepository(ViewSortEntity)
private readonly viewSortRepository: WorkspaceScopedRepository<ViewSortEntity>,
private readonly workspaceMigrationValidateBuildAndRunService: WorkspaceMigrationValidateBuildAndRunService,
private readonly flatEntityMapsCacheService: WorkspaceManyOrAllFlatEntityMapsCacheService,
private readonly applicationService: ApplicationService,
@@ -301,9 +302,8 @@ export class ViewSortService {
}
async findByWorkspaceId(workspaceId: string): Promise<ViewSortEntity[]> {
return this.viewSortRepository.find({
return this.viewSortRepository.find(workspaceId, {
where: {
workspaceId,
deletedAt: IsNull(),
},
relations: ['workspace', 'view'],
@@ -314,9 +314,8 @@ export class ViewSortService {
workspaceId: string,
viewId: string,
): Promise<ViewSortEntity[]> {
return this.viewSortRepository.find({
return this.viewSortRepository.find(workspaceId, {
where: {
workspaceId,
viewId,
deletedAt: IsNull(),
},
@@ -328,10 +327,9 @@ export class ViewSortService {
id: string,
workspaceId: string,
): Promise<ViewSortEntity | null> {
const viewSort = await this.viewSortRepository.findOne({
const viewSort = await this.viewSortRepository.findOne(workspaceId, {
where: {
id,
workspaceId,
deletedAt: IsNull(),
},
relations: ['workspace', 'view'],

View File

@@ -10,6 +10,7 @@ import { ViewSortResolver } from 'src/engine/metadata-modules/view-sort/resolver
import { ViewSortService } from 'src/engine/metadata-modules/view-sort/services/view-sort.service';
import { ViewSortToolsFactory } from 'src/engine/metadata-modules/view-sort/tools/view-sort-tools.factory';
import { ViewEntity } from 'src/engine/metadata-modules/view/entities/view.entity';
import { provideWorkspaceScopedRepository } from 'src/engine/twenty-orm/workspace-scoped-repository/provide-workspace-scoped-repository';
import { WorkspaceCacheStorageModule } from 'src/engine/workspace-cache-storage/workspace-cache-storage.module';
import { WorkspaceMigrationModule } from 'src/engine/workspace-manager/workspace-migration/workspace-migration.module';
import { WorkspaceManyOrAllFlatEntityMapsCacheModule } from 'src/engine/metadata-modules/flat-entity/services/workspace-many-or-all-flat-entity-maps-cache.module';
@@ -25,7 +26,12 @@ import { WorkspaceManyOrAllFlatEntityMapsCacheModule } from 'src/engine/metadata
ViewPermissionsModule,
],
controllers: [ViewSortController],
providers: [ViewSortService, ViewSortResolver, ViewSortToolsFactory],
providers: [
ViewSortService,
ViewSortResolver,
ViewSortToolsFactory,
provideWorkspaceScopedRepository(ViewSortEntity),
],
exports: [ViewSortService, ViewSortToolsFactory],
})
export class ViewSortModule {}

View File

@@ -1,5 +1,4 @@
import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { t } from '@lingui/core/macro';
import {
@@ -8,7 +7,7 @@ import {
ViewSortDirection,
} from 'twenty-shared/types';
import { isDefined } from 'twenty-shared/utils';
import { IsNull, Repository } from 'typeorm';
import { IsNull } from 'typeorm';
import { v4 } from 'uuid';
import { ApplicationService } from 'src/engine/core-modules/application/application.service';
@@ -43,6 +42,8 @@ import {
ViewException,
ViewExceptionCode,
} from 'src/engine/metadata-modules/view/exceptions/view.exception';
import { InjectWorkspaceScopedRepository } from 'src/engine/twenty-orm/workspace-scoped-repository/inject-workspace-scoped-repository.decorator';
import { WorkspaceScopedRepository } from 'src/engine/twenty-orm/workspace-scoped-repository/workspace-scoped-repository';
import { WorkspaceMigrationBuilderException } from 'src/engine/workspace-manager/workspace-migration/exceptions/workspace-migration-builder-exception';
import { WorkspaceMigrationValidateBuildAndRunService } from 'src/engine/workspace-manager/workspace-migration/services/workspace-migration-validate-build-and-run-service';
@@ -75,8 +76,8 @@ export class ViewWidgetUpsertService {
private readonly workspaceMigrationValidateBuildAndRunService: WorkspaceMigrationValidateBuildAndRunService,
private readonly workspaceManyOrAllFlatEntityMapsCacheService: WorkspaceManyOrAllFlatEntityMapsCacheService,
private readonly applicationService: ApplicationService,
@InjectRepository(ViewEntity)
private readonly viewRepository: Repository<ViewEntity>,
@InjectWorkspaceScopedRepository(ViewEntity)
private readonly viewRepository: WorkspaceScopedRepository<ViewEntity>,
) {}
async upsertViewWidget({
@@ -186,13 +187,15 @@ export class ViewWidgetUpsertService {
!isDefined(input.viewFilters) &&
!isDefined(input.viewSorts)
) {
const view = await this.viewRepository.findOne({
where: {
id: upsertContext.viewId,
workspaceId: upsertContext.workspaceId,
deletedAt: IsNull(),
const view = await this.viewRepository.findOne(
upsertContext.workspaceId,
{
where: {
id: upsertContext.viewId,
deletedAt: IsNull(),
},
},
});
);
if (!isDefined(view)) {
throw new ViewException(
@@ -354,10 +357,9 @@ export class ViewWidgetUpsertService {
);
}
const view = await this.viewRepository.findOne({
const view = await this.viewRepository.findOne(upsertContext.workspaceId, {
where: {
id: upsertContext.viewId,
workspaceId: upsertContext.workspaceId,
deletedAt: IsNull(),
},
});

View File

@@ -1,10 +1,8 @@
import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { APP_LOCALES, SOURCE_LOCALE } from 'twenty-shared/translations';
import { ViewType, ViewVisibility } from 'twenty-shared/types';
import { isDefined } from 'twenty-shared/utils';
import { Repository } from 'typeorm';
import { ApplicationService } from 'src/engine/core-modules/application/application.service';
import { I18nService } from 'src/engine/core-modules/i18n/i18n.service';
@@ -32,14 +30,16 @@ import { UpdateViewInput } from 'src/engine/metadata-modules/view/dtos/inputs/up
import { ViewDTO } from 'src/engine/metadata-modules/view/dtos/view.dto';
import { ViewEntity } from 'src/engine/metadata-modules/view/entities/view.entity';
import { fromFlatViewToViewDto } from 'src/engine/metadata-modules/view/utils/from-flat-view-to-view-dto.util';
import { InjectWorkspaceScopedRepository } from 'src/engine/twenty-orm/workspace-scoped-repository/inject-workspace-scoped-repository.decorator';
import { WorkspaceScopedRepository } from 'src/engine/twenty-orm/workspace-scoped-repository/workspace-scoped-repository';
import { WorkspaceMigrationBuilderException } from 'src/engine/workspace-manager/workspace-migration/exceptions/workspace-migration-builder-exception';
import { WorkspaceMigrationValidateBuildAndRunService } from 'src/engine/workspace-manager/workspace-migration/services/workspace-migration-validate-build-and-run-service';
@Injectable()
export class ViewService {
constructor(
@InjectRepository(ViewEntity)
private readonly viewRepository: Repository<ViewEntity>,
@InjectWorkspaceScopedRepository(ViewEntity)
private readonly viewRepository: WorkspaceScopedRepository<ViewEntity>,
private readonly workspaceMigrationValidateBuildAndRunService: WorkspaceMigrationValidateBuildAndRunService,
private readonly flatEntityMapsCacheService: WorkspaceManyOrAllFlatEntityMapsCacheService,
private readonly applicationService: ApplicationService,
@@ -625,10 +625,9 @@ export class ViewService {
id: string,
workspaceId: string,
): Promise<ViewEntity | null> {
const view = await this.viewRepository.findOne({
const view = await this.viewRepository.findOne(workspaceId, {
where: {
id,
workspaceId,
},
relations: [
'workspace',

View File

@@ -19,6 +19,7 @@ import { ViewResolver } from 'src/engine/metadata-modules/view/resolvers/view.re
import { ViewQueryParamsService } from 'src/engine/metadata-modules/view/services/view-query-params.service';
import { ViewService } from 'src/engine/metadata-modules/view/services/view.service';
import { ViewToolsFactory } from 'src/engine/metadata-modules/view/tools/view-tools.factory';
import { provideWorkspaceScopedRepository } from 'src/engine/twenty-orm/workspace-scoped-repository/provide-workspace-scoped-repository';
import { WorkspaceCacheStorageModule } from 'src/engine/workspace-cache-storage/workspace-cache-storage.module';
import { WorkspaceMigrationModule } from 'src/engine/workspace-manager/workspace-migration/workspace-migration.module';
@@ -46,6 +47,7 @@ import { WorkspaceMigrationModule } from 'src/engine/workspace-manager/workspace
ViewQueryParamsService,
ViewToolsFactory,
ViewWidgetUpsertService,
provideWorkspaceScopedRepository(ViewEntity),
],
exports: [
ViewService,

View File

@@ -13,6 +13,7 @@ import { WebhookGraphqlApiExceptionInterceptor } from 'src/engine/metadata-modul
import { WebhookToolWorkspaceService } from 'src/engine/metadata-modules/webhook/tools/services/webhook-tool.workspace-service';
import { WebhookResolver } from 'src/engine/metadata-modules/webhook/webhook.resolver';
import { WebhookService } from 'src/engine/metadata-modules/webhook/webhook.service';
import { provideWorkspaceScopedRepository } from 'src/engine/twenty-orm/workspace-scoped-repository/provide-workspace-scoped-repository';
import { WorkspaceCacheStorageModule } from 'src/engine/workspace-cache-storage/workspace-cache-storage.module';
import { WorkspaceMigrationGraphqlApiExceptionInterceptor } from 'src/engine/workspace-manager/workspace-migration/interceptors/workspace-migration-graphql-api-exception.interceptor';
import { WorkspaceMigrationModule } from 'src/engine/workspace-manager/workspace-migration/workspace-migration.module';
@@ -35,6 +36,7 @@ import { WorkspaceMigrationModule } from 'src/engine/workspace-manager/workspace
WebhookGraphqlApiExceptionInterceptor,
WorkspaceMigrationGraphqlApiExceptionInterceptor,
WebhookToolWorkspaceService,
provideWorkspaceScopedRepository(WebhookEntity),
],
exports: [WebhookService, WebhookToolWorkspaceService],
})

View File

@@ -13,6 +13,8 @@ import { fromDeleteWebhookInputToFlatWebhookOrThrow } from 'src/engine/metadata-
import { fromFlatWebhookToWebhookDto } from 'src/engine/metadata-modules/flat-webhook/utils/from-flat-webhook-to-webhook-dto.util';
import { fromUpdateWebhookInputToFlatWebhookToUpdateOrThrow } from 'src/engine/metadata-modules/flat-webhook/utils/from-update-webhook-input-to-flat-webhook-to-update-or-throw.util';
import { fromWebhookEntityToFlatWebhook } from 'src/engine/metadata-modules/flat-webhook/utils/from-webhook-entity-to-flat-webhook.util';
import { InjectWorkspaceScopedRepository } from 'src/engine/twenty-orm/workspace-scoped-repository/inject-workspace-scoped-repository.decorator';
import { WorkspaceScopedRepository } from 'src/engine/twenty-orm/workspace-scoped-repository/workspace-scoped-repository';
import { type CreateWebhookInput } from 'src/engine/metadata-modules/webhook/dtos/create-webhook.input';
import { type UpdateWebhookInput } from 'src/engine/metadata-modules/webhook/dtos/update-webhook.input';
import { type WebhookDTO } from 'src/engine/metadata-modules/webhook/dtos/webhook.dto';
@@ -24,8 +26,8 @@ import { WorkspaceMigrationValidateBuildAndRunService } from 'src/engine/workspa
@Injectable()
export class WebhookService {
constructor(
@InjectRepository(WebhookEntity)
private readonly webhookRepository: Repository<WebhookEntity>,
@InjectWorkspaceScopedRepository(WebhookEntity)
private readonly webhookRepository: WorkspaceScopedRepository<WebhookEntity>,
@InjectRepository(ApplicationEntity)
private readonly applicationRepository: Repository<ApplicationEntity>,
private readonly workspaceMigrationValidateBuildAndRunService: WorkspaceMigrationValidateBuildAndRunService,
@@ -45,8 +47,8 @@ export class WebhookService {
async findAll(workspaceId: string): Promise<WebhookDTO[]> {
const [webhooks, applications] = await Promise.all([
this.webhookRepository.find({
where: { workspaceId, deletedAt: IsNull() },
this.webhookRepository.find(workspaceId, {
where: { deletedAt: IsNull() },
order: { createdAt: 'ASC' },
}),
this.applicationRepository.find({
@@ -70,8 +72,8 @@ export class WebhookService {
async findById(id: string, workspaceId: string): Promise<WebhookDTO | null> {
const [webhook, applications] = await Promise.all([
this.webhookRepository.findOne({
where: { id, workspaceId, deletedAt: IsNull() },
this.webhookRepository.findOne(workspaceId, {
where: { id, deletedAt: IsNull() },
}),
this.applicationRepository.find({
where: { workspaceId },

View File

@@ -15,9 +15,16 @@ const createMockRepository = (): jest.Mocked<Repository<FakeEntity>> =>
({
findOne: jest.fn().mockResolvedValue(null),
findOneOrFail: jest.fn(),
findOneBy: jest.fn().mockResolvedValue(null),
find: jest.fn().mockResolvedValue([]),
count: jest.fn().mockResolvedValue(0),
findAndCount: jest.fn().mockResolvedValue([[], 0]),
exists: jest.fn().mockResolvedValue(false),
existsBy: jest.fn().mockResolvedValue(false),
maximum: jest.fn().mockResolvedValue(null),
update: jest.fn(),
increment: jest.fn(),
decrement: jest.fn(),
delete: jest.fn(),
softDelete: jest.fn(),
insert: jest.fn(),
@@ -45,15 +52,22 @@ describe('WorkspaceScopedRepository', () => {
'findOneOrFail',
() => scoped.findOneOrFail(undefined as never, { where: {} }),
],
['findOneBy', () => scoped.findOneBy(undefined as never, {})],
['find', () => scoped.find(undefined as never)],
['count', () => scoped.count(undefined as never)],
['findAndCount', () => scoped.findAndCount(undefined as never)],
['exists', () => scoped.exists(undefined as never)],
['existsBy', () => scoped.existsBy(undefined as never, {})],
['update', () => scoped.update(undefined as never, {}, {})],
['increment', () => scoped.increment(undefined as never, {}, 'count', 1)],
['decrement', () => scoped.decrement(undefined as never, {}, 'count', 1)],
['delete', () => scoped.delete(undefined as never, {})],
['softDelete', () => scoped.softDelete(undefined as never, {})],
['insert', () => scoped.insert(undefined as never, {})],
['upsert', () => scoped.upsert(undefined as never, {}, ['id'])],
['save', () => scoped.save(undefined as never, {})],
['saveMany', () => scoped.saveMany(undefined as never, [{}])],
['maximum', () => scoped.maximum(undefined as never, 'id')],
])('%s throws when workspaceId is undefined', (_name, call) => {
expect(call).toThrow(/workspaceId must be a non-empty string/);
});
@@ -136,6 +150,28 @@ describe('WorkspaceScopedRepository', () => {
});
});
describe('findOneBy', () => {
it('merges workspaceId into where', async () => {
await scoped.findOneBy(WORKSPACE_ID, { id: 'a' });
expect(repository.findOneBy).toHaveBeenCalledWith({
id: 'a',
workspaceId: WORKSPACE_ID,
});
});
it('throws if the caller includes workspaceId in where', () => {
expect(() =>
scoped.findOneBy(WORKSPACE_ID, {
id: 'a',
workspaceId: OTHER_WORKSPACE_ID,
} as never),
).toThrow(/do not include `workspaceId`/);
expect(repository.findOneBy).not.toHaveBeenCalled();
});
});
describe('find', () => {
it('adds workspaceId when no where is provided', async () => {
await scoped.find(WORKSPACE_ID);
@@ -154,6 +190,53 @@ describe('WorkspaceScopedRepository', () => {
});
});
describe('findAndCount', () => {
it('merges workspaceId into where', async () => {
await scoped.findAndCount(WORKSPACE_ID, { where: { status: 'queued' } });
expect(repository.findAndCount).toHaveBeenCalledWith({
where: { status: 'queued', workspaceId: WORKSPACE_ID },
});
});
it('works without options', async () => {
await scoped.findAndCount(WORKSPACE_ID);
expect(repository.findAndCount).toHaveBeenCalledWith({
where: { workspaceId: WORKSPACE_ID },
});
});
});
describe('exists', () => {
it('merges workspaceId into where', async () => {
await scoped.exists(WORKSPACE_ID, { where: { status: 'queued' } });
expect(repository.exists).toHaveBeenCalledWith({
where: { status: 'queued', workspaceId: WORKSPACE_ID },
});
});
it('works without options', async () => {
await scoped.exists(WORKSPACE_ID);
expect(repository.exists).toHaveBeenCalledWith({
where: { workspaceId: WORKSPACE_ID },
});
});
});
describe('existsBy', () => {
it('merges workspaceId into where', async () => {
await scoped.existsBy(WORKSPACE_ID, { id: 'a' });
expect(repository.existsBy).toHaveBeenCalledWith({
id: 'a',
workspaceId: WORKSPACE_ID,
});
});
});
describe('update', () => {
it('merges workspaceId into the criteria, not the patch', async () => {
await scoped.update(WORKSPACE_ID, { id: 'a' }, { status: 'completed' });
@@ -177,6 +260,41 @@ describe('WorkspaceScopedRepository', () => {
});
});
describe('increment and decrement', () => {
it('increment merges workspaceId into criteria', async () => {
await scoped.increment(WORKSPACE_ID, { id: 'a' }, 'count', 1);
expect(repository.increment).toHaveBeenCalledWith(
{ id: 'a', workspaceId: WORKSPACE_ID },
'count',
1,
);
});
it('increment throws if the caller includes workspaceId in the criteria', () => {
expect(() =>
scoped.increment(
WORKSPACE_ID,
{ id: 'a', workspaceId: OTHER_WORKSPACE_ID } as never,
'count',
1,
),
).toThrow(/do not include `workspaceId`/);
expect(repository.increment).not.toHaveBeenCalled();
});
it('decrement merges workspaceId into criteria', async () => {
await scoped.decrement(WORKSPACE_ID, { id: 'a' }, 'count', 1);
expect(repository.decrement).toHaveBeenCalledWith(
{ id: 'a', workspaceId: WORKSPACE_ID },
'count',
1,
);
});
});
describe('delete and softDelete', () => {
it('delete merges workspaceId into criteria', async () => {
await scoped.delete(WORKSPACE_ID, { id: 'a' });
@@ -319,6 +437,25 @@ describe('WorkspaceScopedRepository', () => {
});
});
describe('maximum', () => {
it('calls with scoped criteria when where is provided', async () => {
await scoped.maximum(WORKSPACE_ID, 'id', { status: 'queued' });
expect(repository.maximum).toHaveBeenCalledWith('id', {
status: 'queued',
workspaceId: WORKSPACE_ID,
});
});
it('calls with only workspaceId when no where is given', async () => {
await scoped.maximum(WORKSPACE_ID, 'id');
expect(repository.maximum).toHaveBeenCalledWith('id', {
workspaceId: WORKSPACE_ID,
});
});
});
describe('createQueryBuilder', () => {
it('returns the underlying QueryBuilder unchanged (escape hatch)', () => {
scoped.createQueryBuilder('t');

View File

@@ -39,6 +39,17 @@ export class WorkspaceScopedRepository<T extends WorkspaceScopedEntity> {
});
}
findOneBy(
workspaceId: string,
where: FindOptionsWhere<T>,
): Promise<T | null> {
this.assertWorkspaceId(workspaceId);
return this.repository.findOneBy(
this.mergeWorkspaceIdIntoCriteria(workspaceId, where),
);
}
find(workspaceId: string, options?: FindManyOptions<T>): Promise<T[]> {
this.assertWorkspaceId(workspaceId);
@@ -57,6 +68,51 @@ export class WorkspaceScopedRepository<T extends WorkspaceScopedEntity> {
});
}
findAndCount(
workspaceId: string,
options?: FindManyOptions<T>,
): Promise<[T[], number]> {
this.assertWorkspaceId(workspaceId);
return this.repository.findAndCount({
...options,
where: this.mergeWorkspaceIdIntoWhere(workspaceId, options?.where),
});
}
exists(workspaceId: string, options?: FindManyOptions<T>): Promise<boolean> {
this.assertWorkspaceId(workspaceId);
return this.repository.exists({
...options,
where: this.mergeWorkspaceIdIntoWhere(workspaceId, options?.where),
});
}
existsBy(workspaceId: string, where: FindOptionsWhere<T>): Promise<boolean> {
this.assertWorkspaceId(workspaceId);
return this.repository.existsBy(
this.mergeWorkspaceIdIntoCriteria(workspaceId, where),
);
}
maximum(
workspaceId: string,
columnName: string,
where?: FindOptionsWhere<T>,
): Promise<number | null> {
this.assertWorkspaceId(workspaceId);
// eslint-disable-next-line @typescript-eslint/no-explicit-any
return this.repository.maximum(
columnName as any,
where
? this.mergeWorkspaceIdIntoCriteria(workspaceId, where)
: ({ workspaceId } as FindOptionsWhere<T>),
);
}
update(
workspaceId: string,
criteria: FindOptionsWhere<T>,
@@ -70,6 +126,36 @@ export class WorkspaceScopedRepository<T extends WorkspaceScopedEntity> {
);
}
increment(
workspaceId: string,
criteria: FindOptionsWhere<T>,
propertyPath: string,
value: number | string,
): Promise<UpdateResult> {
this.assertWorkspaceId(workspaceId);
return this.repository.increment(
this.mergeWorkspaceIdIntoCriteria(workspaceId, criteria),
propertyPath,
value,
);
}
decrement(
workspaceId: string,
criteria: FindOptionsWhere<T>,
propertyPath: string,
value: number | string,
): Promise<UpdateResult> {
this.assertWorkspaceId(workspaceId);
return this.repository.decrement(
this.mergeWorkspaceIdIntoCriteria(workspaceId, criteria),
propertyPath,
value,
);
}
delete(
workspaceId: string,
criteria: FindOptionsWhere<T>,
@@ -92,6 +178,14 @@ export class WorkspaceScopedRepository<T extends WorkspaceScopedEntity> {
);
}
// softRemove / recover / remove are intentionally absent.
// TypeORM's entity-based methods use only the primary key in the WHERE
// clause — stamping workspaceId on the entity object does not add an
// AND workspace_id = ? guard to the SQL. A leaked entity id could
// therefore act on a row from a different workspace.
// Use softDelete / delete (criteria-based) instead — they always include
// workspaceId in the WHERE clause.
insert(
workspaceId: string,
entity: QueryDeepPartialEntity<T> | QueryDeepPartialEntity<T>[],

View File

@@ -14,6 +14,8 @@ import { RoleDTO } from 'src/engine/metadata-modules/role/dtos/role.dto';
import { RoleEntity } from 'src/engine/metadata-modules/role/role.entity';
import { RoleService } from 'src/engine/metadata-modules/role/role.service';
import { UserRoleService } from 'src/engine/metadata-modules/user-role/user-role.service';
import { InjectWorkspaceScopedRepository } from 'src/engine/twenty-orm/workspace-scoped-repository/inject-workspace-scoped-repository.decorator';
import { WorkspaceScopedRepository } from 'src/engine/twenty-orm/workspace-scoped-repository/workspace-scoped-repository';
import {
SEED_APPLE_WORKSPACE_ID,
SEED_YCOMBINATOR_WORKSPACE_ID,
@@ -35,8 +37,8 @@ export class DevSeederPermissionsService {
private readonly objectPermissionService: ObjectPermissionService,
@InjectRepository(ObjectMetadataEntity)
private readonly objectMetadataRepository: Repository<ObjectMetadataEntity>,
@InjectRepository(RoleEntity)
private readonly roleRepository: Repository<RoleEntity>,
@InjectWorkspaceScopedRepository(RoleEntity)
private readonly roleRepository: WorkspaceScopedRepository<RoleEntity>,
private readonly fieldPermissionService: FieldPermissionService,
private readonly roleTargetService: RoleTargetService,
@InjectDataSource()
@@ -54,10 +56,9 @@ export class DevSeederPermissionsService {
workspaceCustomFlatApplication: FlatApplication;
light?: boolean;
}) {
const adminRole = await this.roleRepository.findOne({
const adminRole = await this.roleRepository.findOne(workspaceId, {
where: {
universalIdentifier: STANDARD_ROLE.admin.universalIdentifier,
workspaceId,
},
});

View File

@@ -15,9 +15,11 @@ import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadat
import { ObjectMetadataModule } from 'src/engine/metadata-modules/object-metadata/object-metadata.module';
import { ObjectPermissionModule } from 'src/engine/metadata-modules/object-permission/object-permission.module';
import { RoleTargetModule } from 'src/engine/metadata-modules/role-target/role-target.module';
import { RoleEntity } from 'src/engine/metadata-modules/role/role.entity';
import { RoleModule } from 'src/engine/metadata-modules/role/role.module';
import { UserRoleModule } from 'src/engine/metadata-modules/user-role/user-role.module';
import { UpgradeModule } from 'src/engine/core-modules/upgrade/upgrade.module';
import { provideWorkspaceScopedRepository } from 'src/engine/twenty-orm/workspace-scoped-repository/provide-workspace-scoped-repository';
import { WorkspaceCacheStorageModule } from 'src/engine/workspace-cache-storage/workspace-cache-storage.module';
import { WorkspaceCacheModule } from 'src/engine/workspace-cache/workspace-cache.module';
import { WorkspaceDataSourceModule } from 'src/engine/workspace-datasource/workspace-datasource.module';
@@ -62,6 +64,7 @@ import { WorkspaceMigrationModule } from 'src/engine/workspace-manager/workspace
DevSeederPermissionsService,
DevSeederDataService,
TimelineActivitySeederService,
provideWorkspaceScopedRepository(RoleEntity),
],
})
export class DevSeederModule {}

View File

@@ -15,6 +15,7 @@ import { RoleTargetEntity } from 'src/engine/metadata-modules/role-target/role-t
import { RoleEntity } from 'src/engine/metadata-modules/role/role.entity';
import { RoleModule } from 'src/engine/metadata-modules/role/role.module';
import { UserRoleModule } from 'src/engine/metadata-modules/user-role/user-role.module';
import { provideWorkspaceScopedRepository } from 'src/engine/twenty-orm/workspace-scoped-repository/provide-workspace-scoped-repository';
import { WorkspaceDataSourceModule } from 'src/engine/workspace-datasource/workspace-datasource.module';
import { DevSeederModule } from 'src/engine/workspace-manager/dev-seeder/dev-seeder.module';
import { TwentyStandardApplicationModule } from 'src/engine/workspace-manager/twenty-standard-application/twenty-standard-application.module';
@@ -45,6 +46,9 @@ import { WorkspaceManagerService } from './workspace-manager.service';
]),
],
exports: [WorkspaceManagerService],
providers: [WorkspaceManagerService],
providers: [
WorkspaceManagerService,
provideWorkspaceScopedRepository(RoleEntity),
],
})
export class WorkspaceManagerModule {}

View File

@@ -10,6 +10,8 @@ import { WorkspaceEntity } from 'src/engine/core-modules/workspace/workspace.ent
import { RoleEntity } from 'src/engine/metadata-modules/role/role.entity';
import { RoleService } from 'src/engine/metadata-modules/role/role.service';
import { UserRoleService } from 'src/engine/metadata-modules/user-role/user-role.service';
import { InjectWorkspaceScopedRepository } from 'src/engine/twenty-orm/workspace-scoped-repository/inject-workspace-scoped-repository.decorator';
import { WorkspaceScopedRepository } from 'src/engine/twenty-orm/workspace-scoped-repository/workspace-scoped-repository';
import { WorkspaceDataSourceService } from 'src/engine/workspace-datasource/workspace-datasource.service';
import { STANDARD_ROLE } from 'src/engine/workspace-manager/twenty-standard-application/constants/standard-role.constant';
import { TwentyStandardApplicationService } from 'src/engine/workspace-manager/twenty-standard-application/services/twenty-standard-application.service';
@@ -27,8 +29,8 @@ export class WorkspaceManagerService {
private readonly twentyStandardApplicationService: TwentyStandardApplicationService,
@InjectRepository(WorkspaceEntity)
private readonly workspaceRepository: Repository<WorkspaceEntity>,
@InjectRepository(RoleEntity)
private readonly roleRepository: Repository<RoleEntity>,
@InjectWorkspaceScopedRepository(RoleEntity)
private readonly roleRepository: WorkspaceScopedRepository<RoleEntity>,
private readonly applicationService: ApplicationService,
) {}
@@ -97,10 +99,9 @@ export class WorkspaceManagerService {
userId: string;
workspaceCustomFlatApplication: FlatApplication;
}): Promise<void> {
const adminRole = await this.roleRepository.findOne({
const adminRole = await this.roleRepository.findOne(workspaceId, {
where: {
universalIdentifier: STANDARD_ROLE.admin.universalIdentifier,
workspaceId,
},
});

View File

@@ -10,6 +10,7 @@ import { UserWorkspaceEntity } from 'src/engine/core-modules/user-workspace/user
import { CalendarChannelEntity } from 'src/engine/metadata-modules/calendar-channel/entities/calendar-channel.entity';
import { ConnectedAccountEntity } from 'src/engine/metadata-modules/connected-account/entities/connected-account.entity';
import { ObjectMetadataRepositoryModule } from 'src/engine/object-metadata-repository/object-metadata-repository.module';
import { provideWorkspaceScopedRepository } from 'src/engine/twenty-orm/workspace-scoped-repository/provide-workspace-scoped-repository';
import { WorkspaceDataSourceModule } from 'src/engine/workspace-datasource/workspace-datasource.module';
import { BlocklistWorkspaceEntity } from 'src/modules/blocklist/standard-objects/blocklist.workspace-entity';
import { CalendarEventCleanerModule } from 'src/modules/calendar/calendar-event-cleaner/calendar-event-cleaner.module';
@@ -66,6 +67,7 @@ import { RefreshTokensManagerModule } from 'src/modules/connected-account/refres
FeatureFlagModule,
],
providers: [
provideWorkspaceScopedRepository(CalendarChannelEntity),
CalendarChannelSyncStatusService,
CalendarEventsImportService,
CalendarFetchEventsService,

View File

@@ -1,17 +1,17 @@
import { Injectable, Logger } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { ExceptionHandlerService } from 'src/engine/core-modules/exception-handler/exception-handler.service';
import {
type TwentyORMException,
TwentyORMExceptionCode,
} from 'src/engine/twenty-orm/exceptions/twenty-orm.exception';
import { CalendarChannelEntity } from 'src/engine/metadata-modules/calendar-channel/entities/calendar-channel.entity';
import {
ConnectedAccountRefreshAccessTokenException,
ConnectedAccountRefreshAccessTokenExceptionCode,
} from 'src/engine/metadata-modules/connected-account/exceptions/connected-account-refresh-tokens.exception';
import {
type TwentyORMException,
TwentyORMExceptionCode,
} from 'src/engine/twenty-orm/exceptions/twenty-orm.exception';
import { InjectWorkspaceScopedRepository } from 'src/engine/twenty-orm/workspace-scoped-repository/inject-workspace-scoped-repository.decorator';
import { WorkspaceScopedRepository } from 'src/engine/twenty-orm/workspace-scoped-repository/workspace-scoped-repository';
import { CALENDAR_THROTTLE_MAX_ATTEMPTS } from 'src/modules/calendar/calendar-event-import-manager/constants/calendar-throttle-max-attempts';
import {
type CalendarEventImportDriverException,
@@ -22,7 +22,6 @@ import {
CalendarEventImportExceptionCode,
} from 'src/modules/calendar/calendar-event-import-manager/exceptions/calendar-event-import.exception';
import { CalendarChannelSyncStatusService } from 'src/modules/calendar/common/services/calendar-channel-sync-status.service';
import { CalendarChannelEntity } from 'src/engine/metadata-modules/calendar-channel/entities/calendar-channel.entity';
export enum CalendarEventImportSyncStep {
CALENDAR_EVENT_LIST_FETCH = 'CALENDAR_EVENT_LIST_FETCH',
CALENDAR_EVENTS_IMPORT = 'CALENDAR_EVENTS_IMPORT',
@@ -34,8 +33,8 @@ export class CalendarEventImportErrorHandlerService {
CalendarEventImportErrorHandlerService.name,
);
constructor(
@InjectRepository(CalendarChannelEntity)
private readonly calendarChannelRepository: Repository<CalendarChannelEntity>,
@InjectWorkspaceScopedRepository(CalendarChannelEntity)
private readonly calendarChannelRepository: WorkspaceScopedRepository<CalendarChannelEntity>,
private readonly calendarChannelSyncStatusService: CalendarChannelSyncStatusService,
private readonly exceptionHandlerService: ExceptionHandlerService,
) {}
@@ -142,7 +141,8 @@ export class CalendarEventImportErrorHandlerService {
}
await this.calendarChannelRepository.increment(
{ id: calendarChannel.id, workspaceId },
workspaceId,
{ id: calendarChannel.id },
'throttleFailureCount',
1,
);

View File

@@ -55,6 +55,7 @@ import { MessagingProcessFolderActionsService } from 'src/modules/messaging/mess
import { MessagingProcessGroupEmailActionsService } from 'src/modules/messaging/message-import-manager/services/messaging-process-group-email-actions.service';
import { MessagingSaveMessagesAndEnqueueContactCreationService } from 'src/modules/messaging/message-import-manager/services/messaging-save-messages-and-enqueue-contact-creation.service';
import { MessagingWebhooksModule } from 'src/engine/core-modules/messaging-webhooks/messaging-webhooks.module';
import { provideWorkspaceScopedRepository } from 'src/engine/twenty-orm/workspace-scoped-repository/provide-workspace-scoped-repository';
import { MessageParticipantManagerModule } from 'src/modules/messaging/message-participant-manager/message-participant-manager.module';
import { MessagingMonitoringModule } from 'src/modules/messaging/monitoring/messaging-monitoring.module';
@Module({
@@ -88,6 +89,7 @@ import { MessagingMonitoringModule } from 'src/modules/messaging/monitoring/mess
MessagingWebhooksModule,
],
providers: [
provideWorkspaceScopedRepository(MessageChannelEntity),
MessagingMessageListFetchCronCommand,
MessagingMessagesImportCronCommand,
MessagingOngoingStaleCronCommand,

View File

@@ -1,5 +1,4 @@
import { Test, type TestingModule } from '@nestjs/testing';
import { getRepositoryToken } from '@nestjs/typeorm';
import { MessageChannelSyncStatus } from 'twenty-shared/types';
@@ -8,13 +7,14 @@ import {
ConnectedAccountRefreshAccessTokenException,
ConnectedAccountRefreshAccessTokenExceptionCode,
} from 'src/engine/metadata-modules/connected-account/exceptions/connected-account-refresh-tokens.exception';
import { MessageChannelEntity } from 'src/engine/metadata-modules/message-channel/entities/message-channel.entity';
import { getWorkspaceScopedRepositoryToken } from 'src/engine/twenty-orm/workspace-scoped-repository/get-workspace-scoped-repository-token.util';
import { MessageChannelSyncStatusService } from 'src/modules/messaging/common/services/message-channel-sync-status.service';
import {
MessageImportExceptionHandlerService,
MessageImportSyncStep,
} from 'src/modules/messaging/message-import-manager/services/messaging-import-exception-handler.service';
import { MessagingMonitoringService } from 'src/modules/messaging/monitoring/services/messaging-monitoring.service';
import { MessageChannelEntity } from 'src/engine/metadata-modules/message-channel/entities/message-channel.entity';
describe('MessageImportExceptionHandlerService — refresh code dispatch', () => {
let service: MessageImportExceptionHandlerService;
@@ -50,7 +50,7 @@ describe('MessageImportExceptionHandlerService — refresh code dispatch', () =>
providers: [
MessageImportExceptionHandlerService,
{
provide: getRepositoryToken(MessageChannelEntity),
provide: getWorkspaceScopedRepositoryToken(MessageChannelEntity),
useValue: messageChannelRepository,
},
{

View File

@@ -1,19 +1,20 @@
import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { isDefined } from 'twenty-shared/utils';
import { Repository } from 'typeorm';
import { MessageChannelSyncStatus } from 'twenty-shared/types';
import { ExceptionHandlerService } from 'src/engine/core-modules/exception-handler/exception-handler.service';
import {
type TwentyORMException,
TwentyORMExceptionCode,
} from 'src/engine/twenty-orm/exceptions/twenty-orm.exception';
import { MessageChannelEntity } from 'src/engine/metadata-modules/message-channel/entities/message-channel.entity';
import {
ConnectedAccountRefreshAccessTokenException,
ConnectedAccountRefreshAccessTokenExceptionCode,
} from 'src/engine/metadata-modules/connected-account/exceptions/connected-account-refresh-tokens.exception';
import {
type TwentyORMException,
TwentyORMExceptionCode,
} from 'src/engine/twenty-orm/exceptions/twenty-orm.exception';
import { InjectWorkspaceScopedRepository } from 'src/engine/twenty-orm/workspace-scoped-repository/inject-workspace-scoped-repository.decorator';
import { WorkspaceScopedRepository } from 'src/engine/twenty-orm/workspace-scoped-repository/workspace-scoped-repository';
import { MessageChannelSyncStatusService } from 'src/modules/messaging/common/services/message-channel-sync-status.service';
import { MESSAGING_THROTTLE_MAX_ATTEMPTS } from 'src/modules/messaging/message-import-manager/constants/messaging-throttle-max-attempts';
import {
@@ -22,7 +23,6 @@ import {
} from 'src/modules/messaging/message-import-manager/drivers/exceptions/message-import-driver.exception';
import { MessageNetworkExceptionCode } from 'src/modules/messaging/message-import-manager/drivers/exceptions/message-network.exception';
import { MessagingMonitoringService } from 'src/modules/messaging/monitoring/services/messaging-monitoring.service';
import { MessageChannelEntity } from 'src/engine/metadata-modules/message-channel/entities/message-channel.entity';
export enum MessageImportSyncStep {
MESSAGE_LIST_FETCH = 'MESSAGE_LIST_FETCH',
@@ -33,8 +33,8 @@ export enum MessageImportSyncStep {
@Injectable()
export class MessageImportExceptionHandlerService {
constructor(
@InjectRepository(MessageChannelEntity)
private readonly messageChannelRepository: Repository<MessageChannelEntity>,
@InjectWorkspaceScopedRepository(MessageChannelEntity)
private readonly messageChannelRepository: WorkspaceScopedRepository<MessageChannelEntity>,
private readonly messageChannelSyncStatusService: MessageChannelSyncStatusService,
private readonly exceptionHandlerService: ExceptionHandlerService,
private readonly messagingMonitoringService: MessagingMonitoringService,
@@ -183,7 +183,8 @@ export class MessageImportExceptionHandlerService {
}
await this.messageChannelRepository.increment(
{ id: messageChannel.id, workspaceId },
workspaceId,
{ id: messageChannel.id },
'throttleFailureCount',
1,
);
@@ -194,7 +195,8 @@ export class MessageImportExceptionHandlerService {
: undefined;
await this.messageChannelRepository.update(
{ id: messageChannel.id, workspaceId },
workspaceId,
{ id: messageChannel.id },
{
throttleRetryAfter: isDefined(throttleRetryAfter)
? throttleRetryAfter.toISOString()

View File

@@ -12,6 +12,7 @@ import { LogicFunctionFromSourceService } from 'src/engine/metadata-modules/logi
import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
import { RoleTargetEntity } from 'src/engine/metadata-modules/role-target/role-target.entity';
import { GlobalWorkspaceOrmManager } from 'src/engine/twenty-orm/global-workspace-datasource/global-workspace-orm.manager';
import { getWorkspaceScopedRepositoryToken } from 'src/engine/twenty-orm/workspace-scoped-repository/get-workspace-scoped-repository-token.util';
import { WorkspaceCacheService } from 'src/engine/workspace-cache/services/workspace-cache.service';
import { WorkflowCommonWorkspaceService } from 'src/modules/workflow/common/workspace-services/workflow-common.workspace-service';
import { CodeStepBuildService } from 'src/modules/workflow/workflow-builder/workflow-version-step/code-step/services/code-step-build.service';
@@ -143,7 +144,7 @@ describe('WorkflowVersionStepOperationsWorkspaceService', () => {
useValue: agentService,
},
{
provide: getRepositoryToken(RoleTargetEntity),
provide: getWorkspaceScopedRepositoryToken(RoleTargetEntity),
useValue: roleTargetRepository,
},
{

View File

@@ -27,6 +27,8 @@ import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadat
import { RoleTargetEntity } from 'src/engine/metadata-modules/role-target/role-target.entity';
import { GlobalWorkspaceOrmManager } from 'src/engine/twenty-orm/global-workspace-datasource/global-workspace-orm.manager';
import { buildSystemAuthContext } from 'src/engine/twenty-orm/utils/build-system-auth-context.util';
import { InjectWorkspaceScopedRepository } from 'src/engine/twenty-orm/workspace-scoped-repository/inject-workspace-scoped-repository.decorator';
import { WorkspaceScopedRepository } from 'src/engine/twenty-orm/workspace-scoped-repository/workspace-scoped-repository';
import { WorkspaceCacheService } from 'src/engine/workspace-cache/services/workspace-cache.service';
import {
WorkflowVersionStepException,
@@ -70,8 +72,8 @@ export class WorkflowVersionStepOperationsWorkspaceService {
private readonly logicFunctionFromSourceService: LogicFunctionFromSourceService,
private readonly codeStepBuildService: CodeStepBuildService,
private readonly agentService: AgentService,
@InjectRepository(RoleTargetEntity)
private readonly roleTargetRepository: Repository<RoleTargetEntity>,
@InjectWorkspaceScopedRepository(RoleTargetEntity)
private readonly roleTargetRepository: WorkspaceScopedRepository<RoleTargetEntity>,
@InjectRepository(ObjectMetadataEntity)
private readonly objectMetadataRepository: Repository<ObjectMetadataEntity>,
private readonly workflowCommonWorkspaceService: WorkflowCommonWorkspaceService,
@@ -100,12 +102,14 @@ export class WorkflowVersionStepOperationsWorkspaceService {
break;
}
const roleTarget = await this.roleTargetRepository.findOne({
where: {
agentId: step.settings.input.agentId,
workspaceId,
const roleTarget = await this.roleTargetRepository.findOne(
workspaceId,
{
where: {
agentId: step.settings.input.agentId,
},
},
});
);
await this.agentService.deleteManyAgents({
ids: [step.settings.input.agentId],

View File

@@ -9,6 +9,7 @@ import { LogicFunctionModule } from 'src/engine/metadata-modules/logic-function/
import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
import { RoleTargetEntity } from 'src/engine/metadata-modules/role-target/role-target.entity';
import { RoleEntity } from 'src/engine/metadata-modules/role/role.entity';
import { provideWorkspaceScopedRepository } from 'src/engine/twenty-orm/workspace-scoped-repository/provide-workspace-scoped-repository';
import { WorkspaceCacheModule } from 'src/engine/workspace-cache/workspace-cache.module';
import { WorkflowCommonModule } from 'src/modules/workflow/common/workflow-common.module';
import { WorkflowSchemaModule } from 'src/modules/workflow/workflow-builder/workflow-schema/workflow-schema.module';
@@ -43,6 +44,7 @@ import { WorkflowVersionStepWorkspaceService } from 'src/modules/workflow/workfl
WorkflowVersionStepCreationWorkspaceService,
WorkflowVersionStepUpdateWorkspaceService,
WorkflowVersionStepDeletionWorkspaceService,
provideWorkspaceScopedRepository(RoleTargetEntity),
],
exports: [
WorkflowVersionStepWorkspaceService,