mirror of
https://github.com/twentyhq/twenty
synced 2026-04-21 21:47:38 +00:00
## Context We recently enabled the option to bypass SSL certificate authority validation when establishing a connection to PostgreSQL. Previously, if this validation failed, the server would revert to unencrypted traffic. Now, it maintains encryption even if the SSL certificate check fails. In the process, we overlooked a few DataSource setups, prompting a review of DataSource creation within our code. ## Current State Our DataSource initialization is distributed as follows: - **Database folder**: Contains 'core', 'metadata', and 'raw' DataSources. The 'core' and 'metadata' DataSources manage migrations and static resolver calls to the database. The 'raw' DataSource is utilized in scripts and commands that require handling both aspects. - **typeorm.service.ts script**: These DataSources facilitate multi-schema connections. ## Vision for Discussion - **SystemSchema (formerly core) DataSource**: Manages system schema migrations and system resolvers/repos. The 'core' schema will be renamed to 'system' as the Core API will include parts of the system and workspace schemas. - **MetadataSchema DataSource**: Handles metadata schema migrations and metadata API resolvers/repos. - **(Dynamic) WorkspaceSchema DataSource**: Will be used in the Twenty ORM to access a specific workspace schema. We currently do not support cross-schema joins, so maintaining these DataSources separately should be feasible. Core API resolvers will select the appropriate DataSource based on the field context. - **To be discussed**: The potential need for an AdminDataSource (akin to 'Raw'), which would be used in commands, setup scripts, and the admin panel to connect to any database schema without loading any model. This DataSource should be reserved for cases where utilizing metadata, system, or workspace entities is impractical. ## In This PR - Ensuring all existing DataSources are compliant with the SSL update. - Introducing RawDataSource to eliminate the need for declaring new DataSource() instances in commands.
175 lines
6.8 KiB
TypeScript
175 lines
6.8 KiB
TypeScript
import { Command, CommandRunner } from 'nest-commander';
|
|
import { EntityManager } from 'typeorm';
|
|
|
|
import { DataSourceService } from 'src/engine/metadata-modules/data-source/data-source.service';
|
|
import { seedCompanies } from 'src/database/typeorm-seeds/workspace/companies';
|
|
import { TypeORMService } from 'src/database/typeorm/typeorm.service';
|
|
import { seedOpportunity } from 'src/database/typeorm-seeds/workspace/opportunities';
|
|
import { seedWorkspaceMember } from 'src/database/typeorm-seeds/workspace/workspace-members';
|
|
import { seedPeople } from 'src/database/typeorm-seeds/workspace/people';
|
|
import { seedCoreSchema } from 'src/database/typeorm-seeds/core';
|
|
import { ObjectMetadataService } from 'src/engine/metadata-modules/object-metadata/object-metadata.service';
|
|
import { WorkspaceDataSourceService } from 'src/engine/workspace-datasource/workspace-datasource.service';
|
|
import { WorkspaceSyncMetadataService } from 'src/engine/workspace-manager/workspace-sync-metadata/workspace-sync-metadata.service';
|
|
import { EnvironmentService } from 'src/engine/integrations/environment/environment.service';
|
|
import {
|
|
SEED_APPLE_WORKSPACE_ID,
|
|
SEED_TWENTY_WORKSPACE_ID,
|
|
} from 'src/database/typeorm-seeds/core/workspaces';
|
|
import { seedConnectedAccount } from 'src/database/typeorm-seeds/workspace/connected-account';
|
|
import { seedMessage } from 'src/database/typeorm-seeds/workspace/messages';
|
|
import { seedMessageChannel } from 'src/database/typeorm-seeds/workspace/message-channels';
|
|
import { seedMessageChannelMessageAssociation } from 'src/database/typeorm-seeds/workspace/message-channel-message-associations';
|
|
import { seedMessageParticipant } from 'src/database/typeorm-seeds/workspace/message-participants';
|
|
import { seedMessageThread } from 'src/database/typeorm-seeds/workspace/message-threads';
|
|
import { viewPrefillData } from 'src/engine/workspace-manager/standard-objects-prefill-data/view';
|
|
import { seedCalendarEvents } from 'src/database/typeorm-seeds/workspace/calendar-events';
|
|
import { seedCalendarChannels } from 'src/database/typeorm-seeds/workspace/calendar-channel';
|
|
import { seedCalendarChannelEventAssociations } from 'src/database/typeorm-seeds/workspace/calendar-channel-event-association';
|
|
import { seedCalendarEventParticipants } from 'src/database/typeorm-seeds/workspace/calendar-event-participants';
|
|
import { rawDataSource } from 'src/database/typeorm/raw/raw.datasource';
|
|
|
|
// TODO: implement dry-run
|
|
@Command({
|
|
name: 'workspace:seed:dev',
|
|
description:
|
|
'Seed workspace with initial data. This command is intended for development only.',
|
|
})
|
|
export class DataSeedWorkspaceCommand extends CommandRunner {
|
|
workspaceIds = [SEED_APPLE_WORKSPACE_ID, SEED_TWENTY_WORKSPACE_ID];
|
|
|
|
constructor(
|
|
private readonly environmentService: EnvironmentService,
|
|
private readonly dataSourceService: DataSourceService,
|
|
private readonly typeORMService: TypeORMService,
|
|
private readonly workspaceSyncMetadataService: WorkspaceSyncMetadataService,
|
|
private readonly workspaceDataSourceService: WorkspaceDataSourceService,
|
|
private readonly objectMetadataService: ObjectMetadataService,
|
|
) {
|
|
super();
|
|
}
|
|
|
|
async run(): Promise<void> {
|
|
try {
|
|
for (const workspaceId of this.workspaceIds) {
|
|
await rawDataSource.initialize();
|
|
|
|
await seedCoreSchema(rawDataSource, workspaceId);
|
|
|
|
await rawDataSource.destroy();
|
|
|
|
const schemaName =
|
|
await this.workspaceDataSourceService.createWorkspaceDBSchema(
|
|
workspaceId,
|
|
);
|
|
|
|
const dataSourceMetadata =
|
|
await this.dataSourceService.createDataSourceMetadata(
|
|
workspaceId,
|
|
schemaName,
|
|
);
|
|
|
|
await this.workspaceSyncMetadataService.synchronize({
|
|
workspaceId: workspaceId,
|
|
dataSourceId: dataSourceMetadata.id,
|
|
});
|
|
}
|
|
} catch (error) {
|
|
console.error(error);
|
|
|
|
return;
|
|
}
|
|
|
|
for (const workspaceId of this.workspaceIds) {
|
|
const dataSourceMetadata =
|
|
await this.dataSourceService.getLastDataSourceMetadataFromWorkspaceIdOrFail(
|
|
workspaceId,
|
|
);
|
|
|
|
const workspaceDataSource =
|
|
await this.typeORMService.connectToDataSource(dataSourceMetadata);
|
|
|
|
if (!workspaceDataSource) {
|
|
throw new Error('Could not connect to workspace data source');
|
|
}
|
|
|
|
try {
|
|
const objectMetadata =
|
|
await this.objectMetadataService.findManyWithinWorkspace(workspaceId);
|
|
const objectMetadataMap = objectMetadata.reduce((acc, object) => {
|
|
acc[object.standardId ?? ''] = {
|
|
id: object.id,
|
|
fields: object.fields.reduce((acc, field) => {
|
|
acc[field.standardId ?? ''] = field.id;
|
|
|
|
return acc;
|
|
}, {}),
|
|
};
|
|
|
|
return acc;
|
|
}, {});
|
|
|
|
await workspaceDataSource.transaction(
|
|
async (entityManager: EntityManager) => {
|
|
await seedCompanies(entityManager, dataSourceMetadata.schema);
|
|
await seedPeople(entityManager, dataSourceMetadata.schema);
|
|
await seedOpportunity(entityManager, dataSourceMetadata.schema);
|
|
await seedWorkspaceMember(
|
|
entityManager,
|
|
dataSourceMetadata.schema,
|
|
workspaceId,
|
|
);
|
|
|
|
if (workspaceId === SEED_APPLE_WORKSPACE_ID) {
|
|
await seedMessageThread(entityManager, dataSourceMetadata.schema);
|
|
await seedConnectedAccount(
|
|
entityManager,
|
|
dataSourceMetadata.schema,
|
|
);
|
|
await seedMessage(entityManager, dataSourceMetadata.schema);
|
|
await seedMessageChannel(
|
|
entityManager,
|
|
dataSourceMetadata.schema,
|
|
);
|
|
await seedMessageChannelMessageAssociation(
|
|
entityManager,
|
|
dataSourceMetadata.schema,
|
|
);
|
|
await seedMessageParticipant(
|
|
entityManager,
|
|
dataSourceMetadata.schema,
|
|
);
|
|
|
|
await seedCalendarEvents(
|
|
entityManager,
|
|
dataSourceMetadata.schema,
|
|
);
|
|
await seedCalendarChannels(
|
|
entityManager,
|
|
dataSourceMetadata.schema,
|
|
);
|
|
await seedCalendarChannelEventAssociations(
|
|
entityManager,
|
|
dataSourceMetadata.schema,
|
|
);
|
|
await seedCalendarEventParticipants(
|
|
entityManager,
|
|
dataSourceMetadata.schema,
|
|
);
|
|
}
|
|
|
|
await viewPrefillData(
|
|
entityManager,
|
|
dataSourceMetadata.schema,
|
|
objectMetadataMap,
|
|
);
|
|
},
|
|
);
|
|
} catch (error) {
|
|
console.error(error);
|
|
}
|
|
|
|
await this.typeORMService.disconnectFromDataSource(dataSourceMetadata.id);
|
|
}
|
|
}
|
|
}
|