refactor: Use string ids on Credentials, Workflows, Tags, and Executions DB entities (#5041)

This commit is contained in:
कारतोफ्फेलस्क्रिप्ट™
2023-01-02 17:42:32 +01:00
committed by GitHub
parent 8bee04cd2a
commit ee28213538
83 changed files with 468 additions and 645 deletions

View File

@@ -1,14 +1,16 @@
import type { ICredentialNodeAccess } from 'n8n-workflow';
import { Column, Entity, Index, OneToMany, PrimaryGeneratedColumn } from 'typeorm';
import { Column, Entity, Generated, Index, OneToMany, PrimaryColumn } from 'typeorm';
import { IsArray, IsObject, IsString, Length } from 'class-validator';
import type { SharedCredentials } from './SharedCredentials';
import { AbstractEntity, jsonColumnType } from './AbstractEntity';
import type { ICredentialsDb } from '@/Interfaces';
import { idStringifier } from '../utils/transformers';
@Entity()
export class CredentialsEntity extends AbstractEntity implements ICredentialsDb {
@PrimaryGeneratedColumn()
id: number;
@Generated()
@PrimaryColumn({ transformer: idStringifier })
id: string;
@Column({ length: 128 })
@IsString({ message: 'Credential `name` must be of type string.' })

View File

@@ -1,7 +1,8 @@
import type { WorkflowExecuteMode } from 'n8n-workflow';
import { Column, Entity, Index, PrimaryGeneratedColumn } from 'typeorm';
import { Column, Entity, Generated, Index, PrimaryColumn } from 'typeorm';
import { datetimeColumnType, jsonColumnType } from './AbstractEntity';
import type { IExecutionFlattedDb, IWorkflowDb } from '@/Interfaces';
import { idStringifier } from '../utils/transformers';
@Entity()
@Index(['workflowId', 'id'])
@@ -10,8 +11,9 @@ import type { IExecutionFlattedDb, IWorkflowDb } from '@/Interfaces';
@Index(['workflowId', 'finished', 'id'])
@Index(['workflowId', 'waitTill', 'id'])
export class ExecutionEntity implements IExecutionFlattedDb {
@PrimaryGeneratedColumn()
id: number;
@Generated()
@PrimaryColumn({ transformer: idStringifier })
id: string;
@Column('text')
data: string;
@@ -38,7 +40,7 @@ export class ExecutionEntity implements IExecutionFlattedDb {
@Column(jsonColumnType)
workflowData: IWorkflowDb;
@Column({ nullable: true })
@Column({ nullable: true, transformer: idStringifier })
workflowId: string;
@Column({ type: datetimeColumnType, nullable: true })

View File

@@ -3,6 +3,7 @@ import type { CredentialsEntity } from './CredentialsEntity';
import type { User } from './User';
import type { Role } from './Role';
import { AbstractEntity } from './AbstractEntity';
import { idStringifier } from '../utils/transformers';
@Entity()
export class SharedCredentials extends AbstractEntity {
@@ -22,7 +23,7 @@ export class SharedCredentials extends AbstractEntity {
})
credentials: CredentialsEntity;
@PrimaryColumn()
@PrimaryColumn({ transformer: idStringifier })
@RelationId((sharedCredential: SharedCredentials) => sharedCredential.credentials)
credentialsId: number;
credentialsId: string;
}

View File

@@ -3,6 +3,7 @@ import type { WorkflowEntity } from './WorkflowEntity';
import type { User } from './User';
import type { Role } from './Role';
import { AbstractEntity } from './AbstractEntity';
import { idStringifier } from '../utils/transformers';
@Entity()
export class SharedWorkflow extends AbstractEntity {
@@ -22,7 +23,7 @@ export class SharedWorkflow extends AbstractEntity {
})
workflow: WorkflowEntity;
@PrimaryColumn()
@PrimaryColumn({ transformer: idStringifier })
@RelationId((sharedWorkflow: SharedWorkflow) => sharedWorkflow.workflow)
workflowId: number;
workflowId: string;
}

View File

@@ -1,18 +1,15 @@
import { Column, Entity, Generated, Index, ManyToMany, PrimaryColumn } from 'typeorm';
import { IsString, Length } from 'class-validator';
import type { ITagDb } from '@/Interfaces';
import { idStringifier } from '../utils/transformers';
import type { WorkflowEntity } from './WorkflowEntity';
import { AbstractEntity } from './AbstractEntity';
@Entity()
export class TagEntity extends AbstractEntity implements ITagDb {
export class TagEntity extends AbstractEntity {
@Generated()
@PrimaryColumn({
transformer: idStringifier,
})
id: number;
@PrimaryColumn({ transformer: idStringifier })
id: string;
@Column({ length: 24 })
@Index({ unique: true })

View File

@@ -1,12 +1,12 @@
import { Column, Entity, Index, PrimaryColumn } from 'typeorm';
import { IWebhookDb } from '@/Interfaces';
import { idStringifier } from '../utils/transformers';
@Entity()
@Index(['webhookId', 'method', 'pathLength'])
export class WebhookEntity implements IWebhookDb {
@Column()
workflowId: number;
export class WebhookEntity {
@Column({ transformer: idStringifier })
workflowId: string;
@PrimaryColumn()
webhookPath: string;
@@ -18,8 +18,8 @@ export class WebhookEntity implements IWebhookDb {
node: string;
@Column({ nullable: true })
webhookId: string;
webhookId?: string;
@Column({ nullable: true })
pathLength: number;
pathLength?: number;
}

View File

@@ -12,26 +12,28 @@ import type {
import {
Column,
Entity,
Generated,
Index,
JoinColumn,
JoinTable,
ManyToMany,
OneToMany,
PrimaryGeneratedColumn,
PrimaryColumn,
} from 'typeorm';
import config from '@/config';
import type { TagEntity } from './TagEntity';
import type { SharedWorkflow } from './SharedWorkflow';
import type { WorkflowStatistics } from './WorkflowStatistics';
import { objectRetriever, sqlite } from '../utils/transformers';
import { idStringifier, objectRetriever, sqlite } from '../utils/transformers';
import { AbstractEntity, jsonColumnType } from './AbstractEntity';
import type { IWorkflowDb } from '@/Interfaces';
@Entity()
export class WorkflowEntity extends AbstractEntity implements IWorkflowDb {
@PrimaryGeneratedColumn()
id: number;
@Generated()
@PrimaryColumn({ transformer: idStringifier })
id: string;
// TODO: Add XSS check
@Index({ unique: true })

View File

@@ -1,4 +1,5 @@
import { Column, Entity, RelationId, ManyToOne, PrimaryColumn } from 'typeorm';
import { idStringifier } from '../utils/transformers';
import { datetimeColumnType } from './AbstractEntity';
import type { WorkflowEntity } from './WorkflowEntity';
@@ -26,7 +27,7 @@ export class WorkflowStatistics {
})
workflow: WorkflowEntity;
@PrimaryColumn({ transformer: idStringifier })
@RelationId((workflowStatistics: WorkflowStatistics) => workflowStatistics.workflow)
@PrimaryColumn()
workflowId: number;
workflowId: string;
}

View File

@@ -36,7 +36,7 @@ export class UpdateWorkflowCredentials1630451444017 implements MigrationInterfac
// @ts-ignore
(credentials) => credentials.name === name && credentials.type === type,
);
node.credentials[type] = { id: matchingCredentials?.id.toString() || null, name };
node.credentials[type] = { id: matchingCredentials?.id || null, name };
credentialsUpdated = true;
}
}
@@ -79,7 +79,7 @@ export class UpdateWorkflowCredentials1630451444017 implements MigrationInterfac
// @ts-ignore
(credentials) => credentials.name === name && credentials.type === type,
);
node.credentials[type] = { id: matchingCredentials?.id.toString() || null, name };
node.credentials[type] = { id: matchingCredentials?.id || null, name };
credentialsUpdated = true;
}
}
@@ -123,7 +123,7 @@ export class UpdateWorkflowCredentials1630451444017 implements MigrationInterfac
// @ts-ignore
(credentials) => credentials.name === name && credentials.type === type,
);
node.credentials[type] = { id: matchingCredentials?.id.toString() || null, name };
node.credentials[type] = { id: matchingCredentials?.id || null, name };
credentialsUpdated = true;
}
}

View File

@@ -42,7 +42,7 @@ export class UpdateWorkflowCredentials1630419189837 implements MigrationInterfac
// @ts-ignore
(credentials) => credentials.name === name && credentials.type === type,
);
node.credentials[type] = { id: matchingCredentials?.id.toString() || null, name };
node.credentials[type] = { id: matchingCredentials?.id || null, name };
credentialsUpdated = true;
}
}
@@ -85,7 +85,7 @@ export class UpdateWorkflowCredentials1630419189837 implements MigrationInterfac
// @ts-ignore
(credentials) => credentials.name === name && credentials.type === type,
);
node.credentials[type] = { id: matchingCredentials?.id.toString() || null, name };
node.credentials[type] = { id: matchingCredentials?.id || null, name };
credentialsUpdated = true;
}
}
@@ -131,7 +131,7 @@ export class UpdateWorkflowCredentials1630419189837 implements MigrationInterfac
// @ts-ignore
(credentials) => credentials.name === name && credentials.type === type,
);
node.credentials[type] = { id: matchingCredentials?.id.toString() || null, name };
node.credentials[type] = { id: matchingCredentials?.id || null, name };
credentialsUpdated = true;
}
}

View File

@@ -39,7 +39,7 @@ export class UpdateWorkflowCredentials1630330987096 implements MigrationInterfac
// @ts-ignore
(credentials) => credentials.name === name && credentials.type === type,
);
node.credentials[type] = { id: matchingCredentials?.id.toString() || null, name };
node.credentials[type] = { id: matchingCredentials?.id || null, name };
credentialsUpdated = true;
}
}
@@ -82,7 +82,7 @@ export class UpdateWorkflowCredentials1630330987096 implements MigrationInterfac
// @ts-ignore
(credentials) => credentials.name === name && credentials.type === type,
);
node.credentials[type] = { id: matchingCredentials?.id.toString() || null, name };
node.credentials[type] = { id: matchingCredentials?.id || null, name };
credentialsUpdated = true;
}
}
@@ -126,7 +126,7 @@ export class UpdateWorkflowCredentials1630330987096 implements MigrationInterfac
// @ts-ignore
(credentials) => credentials.name === name && credentials.type === type,
);
node.credentials[type] = { id: matchingCredentials?.id.toString() || null, name };
node.credentials[type] = { id: matchingCredentials?.id || null, name };
credentialsUpdated = true;
}
}

View File

@@ -1,10 +1,13 @@
import { jsonParse } from 'n8n-workflow';
import { ValueTransformer } from 'typeorm';
import type { ValueTransformer, FindOperator } from 'typeorm';
import config from '@/config';
export const idStringifier = {
from: (value: number): string | number => (typeof value === 'number' ? value.toString() : value),
to: (value: string): number | string => (typeof value === 'string' ? Number(value) : value),
from: (value?: number): string | undefined => value?.toString(),
to: (
value: string | FindOperator<unknown> | undefined,
): number | FindOperator<unknown> | undefined =>
typeof value === 'string' ? Number(value) : value,
};
export const lowerCaser = {