mirror of
https://github.com/Abdulazizzn/n8n-enterprise-unlocked.git
synced 2025-12-17 18:12:04 +00:00
refactor(core): Separate list query entities from request types (#15015)
This commit is contained in:
@@ -21,9 +21,9 @@ import { FolderNotFoundError } from '@/errors/folder-not-found.error';
|
|||||||
import { BadRequestError } from '@/errors/response-errors/bad-request.error';
|
import { BadRequestError } from '@/errors/response-errors/bad-request.error';
|
||||||
import { InternalServerError } from '@/errors/response-errors/internal-server.error';
|
import { InternalServerError } from '@/errors/response-errors/internal-server.error';
|
||||||
import { NotFoundError } from '@/errors/response-errors/not-found.error';
|
import { NotFoundError } from '@/errors/response-errors/not-found.error';
|
||||||
|
import type { ListQuery } from '@/requests';
|
||||||
import { AuthenticatedRequest } from '@/requests';
|
import { AuthenticatedRequest } from '@/requests';
|
||||||
import { FolderService } from '@/services/folder.service';
|
import { FolderService } from '@/services/folder.service';
|
||||||
import type { ListQuery } from '@/types-db';
|
|
||||||
|
|
||||||
@RestController('/projects/:projectId/folders')
|
@RestController('/projects/:projectId/folders')
|
||||||
export class ProjectController {
|
export class ProjectController {
|
||||||
|
|||||||
@@ -27,11 +27,10 @@ import { NotFoundError } from '@/errors/response-errors/not-found.error';
|
|||||||
import { EventService } from '@/events/event.service';
|
import { EventService } from '@/events/event.service';
|
||||||
import { ExternalHooks } from '@/external-hooks';
|
import { ExternalHooks } from '@/external-hooks';
|
||||||
import { listQueryMiddleware } from '@/middlewares';
|
import { listQueryMiddleware } from '@/middlewares';
|
||||||
import { AuthenticatedRequest, UserRequest } from '@/requests';
|
import { ListQuery, AuthenticatedRequest, UserRequest } from '@/requests';
|
||||||
import { FolderService } from '@/services/folder.service';
|
import { FolderService } from '@/services/folder.service';
|
||||||
import { ProjectService } from '@/services/project.service.ee';
|
import { ProjectService } from '@/services/project.service.ee';
|
||||||
import { UserService } from '@/services/user.service';
|
import { UserService } from '@/services/user.service';
|
||||||
import { ListQuery } from '@/types-db';
|
|
||||||
import type { PublicUser } from '@/types-db';
|
import type { PublicUser } from '@/types-db';
|
||||||
import { WorkflowService } from '@/workflows/workflow.service';
|
import { WorkflowService } from '@/workflows/workflow.service';
|
||||||
|
|
||||||
|
|||||||
@@ -33,12 +33,12 @@ import { NotFoundError } from '@/errors/response-errors/not-found.error';
|
|||||||
import { ExternalHooks } from '@/external-hooks';
|
import { ExternalHooks } from '@/external-hooks';
|
||||||
import { validateEntity } from '@/generic-helpers';
|
import { validateEntity } from '@/generic-helpers';
|
||||||
import { userHasScopes } from '@/permissions.ee/check-access';
|
import { userHasScopes } from '@/permissions.ee/check-access';
|
||||||
import type { CredentialRequest } from '@/requests';
|
import type { CredentialRequest, ListQuery } from '@/requests';
|
||||||
import { CredentialsTester } from '@/services/credentials-tester.service';
|
import { CredentialsTester } from '@/services/credentials-tester.service';
|
||||||
import { OwnershipService } from '@/services/ownership.service';
|
import { OwnershipService } from '@/services/ownership.service';
|
||||||
import { ProjectService } from '@/services/project.service.ee';
|
import { ProjectService } from '@/services/project.service.ee';
|
||||||
import { RoleService } from '@/services/role.service';
|
import { RoleService } from '@/services/role.service';
|
||||||
import type { ICredentialsDb, ListQuery, ScopesField } from '@/types-db';
|
import type { ICredentialsDb, ScopesField } from '@/types-db';
|
||||||
|
|
||||||
import { CredentialsFinderService } from './credentials-finder.service';
|
import { CredentialsFinderService } from './credentials-finder.service';
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { Service } from '@n8n/di';
|
|||||||
import { DataSource, In, Repository, Like } from '@n8n/typeorm';
|
import { DataSource, In, Repository, Like } from '@n8n/typeorm';
|
||||||
import type { FindManyOptions } from '@n8n/typeorm';
|
import type { FindManyOptions } from '@n8n/typeorm';
|
||||||
|
|
||||||
import type { ListQuery } from '@/types-db';
|
import type { ListQuery } from '@/requests';
|
||||||
|
|
||||||
import { CredentialsEntity } from '../entities/credentials-entity';
|
import { CredentialsEntity } from '../entities/credentials-entity';
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import type { EntityManager, SelectQueryBuilder } from '@n8n/typeorm';
|
|||||||
import { DataSource, Repository } from '@n8n/typeorm';
|
import { DataSource, Repository } from '@n8n/typeorm';
|
||||||
import { PROJECT_ROOT } from 'n8n-workflow';
|
import { PROJECT_ROOT } from 'n8n-workflow';
|
||||||
|
|
||||||
import type { ListQuery } from '@/types-db';
|
import type { ListQuery } from '@/requests';
|
||||||
|
|
||||||
import type { FolderWithWorkflowAndSubFolderCount } from '../entities/folder';
|
import type { FolderWithWorkflowAndSubFolderCount } from '../entities/folder';
|
||||||
import { Folder } from '../entities/folder';
|
import { Folder } from '../entities/folder';
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import { DataSource, In, Repository } from '@n8n/typeorm';
|
|||||||
|
|
||||||
import { TestDefinition } from '@/databases/entities/test-definition.ee';
|
import { TestDefinition } from '@/databases/entities/test-definition.ee';
|
||||||
import { ForbiddenError } from '@/errors/response-errors/forbidden.error';
|
import { ForbiddenError } from '@/errors/response-errors/forbidden.error';
|
||||||
import type { ListQuery } from '@/types-db';
|
import type { ListQuery } from '@/requests';
|
||||||
|
|
||||||
@Service()
|
@Service()
|
||||||
export class TestDefinitionRepository extends Repository<TestDefinition> {
|
export class TestDefinitionRepository extends Repository<TestDefinition> {
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import { TestRun } from '@/databases/entities/test-run.ee';
|
|||||||
import { NotFoundError } from '@/errors/response-errors/not-found.error';
|
import { NotFoundError } from '@/errors/response-errors/not-found.error';
|
||||||
import type { TestRunErrorCode } from '@/evaluation.ee/test-runner/errors.ee';
|
import type { TestRunErrorCode } from '@/evaluation.ee/test-runner/errors.ee';
|
||||||
import { getTestRunFinalResult } from '@/evaluation.ee/test-runner/utils.ee';
|
import { getTestRunFinalResult } from '@/evaluation.ee/test-runner/utils.ee';
|
||||||
import type { ListQuery } from '@/types-db';
|
import type { ListQuery } from '@/requests';
|
||||||
|
|
||||||
export type TestRunFinalResult = 'success' | 'error' | 'warning';
|
export type TestRunFinalResult = 'success' | 'error' | 'warning';
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import type { GlobalRole } from '@n8n/permissions';
|
|||||||
import type { DeepPartial, EntityManager, FindManyOptions } from '@n8n/typeorm';
|
import type { DeepPartial, EntityManager, FindManyOptions } from '@n8n/typeorm';
|
||||||
import { DataSource, In, IsNull, Not, Repository } from '@n8n/typeorm';
|
import { DataSource, In, IsNull, Not, Repository } from '@n8n/typeorm';
|
||||||
|
|
||||||
import type { ListQuery } from '@/types-db';
|
import type { ListQuery } from '@/requests';
|
||||||
|
|
||||||
import { Project } from '../entities/project';
|
import { Project } from '../entities/project';
|
||||||
import { ProjectRelation } from '../entities/project-relation';
|
import { ProjectRelation } from '../entities/project-relation';
|
||||||
|
|||||||
@@ -13,7 +13,8 @@ import type {
|
|||||||
} from '@n8n/typeorm';
|
} from '@n8n/typeorm';
|
||||||
import { PROJECT_ROOT } from 'n8n-workflow';
|
import { PROJECT_ROOT } from 'n8n-workflow';
|
||||||
|
|
||||||
import type { ListQuery } from '@/types-db';
|
import type { ListQuery } from '@/requests';
|
||||||
|
import type { ListQueryDb } from '@/types-db';
|
||||||
|
|
||||||
import { FolderRepository } from './folder.repository';
|
import { FolderRepository } from './folder.repository';
|
||||||
import type { Folder, FolderWithWorkflowAndSubFolderCount } from '../entities/folder';
|
import type { Folder, FolderWithWorkflowAndSubFolderCount } from '../entities/folder';
|
||||||
@@ -33,8 +34,8 @@ type WorkflowFolderUnionRow = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export type WorkflowFolderUnionFull = (
|
export type WorkflowFolderUnionFull = (
|
||||||
| ListQuery.Workflow.Plain
|
| ListQueryDb.Workflow.Plain
|
||||||
| ListQuery.Workflow.WithSharing
|
| ListQueryDb.Workflow.WithSharing
|
||||||
| FolderWithWorkflowAndSubFolderCount
|
| FolderWithWorkflowAndSubFolderCount
|
||||||
) & {
|
) & {
|
||||||
resource: ResourceType;
|
resource: ResourceType;
|
||||||
@@ -320,7 +321,7 @@ export class WorkflowRepository extends Repository<WorkflowEntity> {
|
|||||||
private enrichDataWithExtras(
|
private enrichDataWithExtras(
|
||||||
baseData: WorkflowFolderUnionRow[],
|
baseData: WorkflowFolderUnionRow[],
|
||||||
extraData: {
|
extraData: {
|
||||||
workflows: ListQuery.Workflow.WithSharing[] | ListQuery.Workflow.Plain[];
|
workflows: ListQueryDb.Workflow.WithSharing[] | ListQueryDb.Workflow.Plain[];
|
||||||
folders: Folder[];
|
folders: Folder[];
|
||||||
},
|
},
|
||||||
): WorkflowFolderUnionFull[] {
|
): WorkflowFolderUnionFull[] {
|
||||||
@@ -343,8 +344,8 @@ export class WorkflowRepository extends Repository<WorkflowEntity> {
|
|||||||
const query = this.getManyQuery(workflowIds, options);
|
const query = this.getManyQuery(workflowIds, options);
|
||||||
|
|
||||||
const workflows = (await query.getMany()) as
|
const workflows = (await query.getMany()) as
|
||||||
| ListQuery.Workflow.Plain[]
|
| ListQueryDb.Workflow.Plain[]
|
||||||
| ListQuery.Workflow.WithSharing[];
|
| ListQueryDb.Workflow.WithSharing[];
|
||||||
|
|
||||||
return workflows;
|
return workflows;
|
||||||
}
|
}
|
||||||
@@ -357,7 +358,7 @@ export class WorkflowRepository extends Repository<WorkflowEntity> {
|
|||||||
const query = this.getManyQuery(sharedWorkflowIds, options);
|
const query = this.getManyQuery(sharedWorkflowIds, options);
|
||||||
|
|
||||||
const [workflows, count] = (await query.getManyAndCount()) as [
|
const [workflows, count] = (await query.getManyAndCount()) as [
|
||||||
ListQuery.Workflow.Plain[] | ListQuery.Workflow.WithSharing[],
|
ListQueryDb.Workflow.Plain[] | ListQueryDb.Workflow.WithSharing[],
|
||||||
number,
|
number,
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|||||||
@@ -6,8 +6,8 @@ import { TestDefinitionRepository } from '@/databases/repositories/test-definiti
|
|||||||
import { BadRequestError } from '@/errors/response-errors/bad-request.error';
|
import { BadRequestError } from '@/errors/response-errors/bad-request.error';
|
||||||
import { NotFoundError } from '@/errors/response-errors/not-found.error';
|
import { NotFoundError } from '@/errors/response-errors/not-found.error';
|
||||||
import { validateEntity } from '@/generic-helpers';
|
import { validateEntity } from '@/generic-helpers';
|
||||||
|
import type { ListQuery } from '@/requests';
|
||||||
import { Telemetry } from '@/telemetry';
|
import { Telemetry } from '@/telemetry';
|
||||||
import type { ListQuery } from '@/types-db';
|
|
||||||
|
|
||||||
type TestDefinitionLike = Omit<
|
type TestDefinitionLike = Omit<
|
||||||
Partial<TestDefinition>,
|
Partial<TestDefinition>,
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
import type { MockedNodeItem } from '@/databases/entities/test-definition.ee';
|
import type { MockedNodeItem } from '@/databases/entities/test-definition.ee';
|
||||||
import type { AuthenticatedRequest } from '@/requests';
|
import type { AuthenticatedRequest, ListQuery } from '@/requests';
|
||||||
import type { ListQuery } from '@/types-db';
|
|
||||||
|
|
||||||
// ----------------------------------
|
// ----------------------------------
|
||||||
// /test-definitions
|
// /test-definitions
|
||||||
|
|||||||
@@ -3,8 +3,9 @@ import type { Response, NextFunction } from 'express';
|
|||||||
import { filterListQueryMiddleware } from '@/middlewares/list-query/filter';
|
import { filterListQueryMiddleware } from '@/middlewares/list-query/filter';
|
||||||
import { paginationListQueryMiddleware } from '@/middlewares/list-query/pagination';
|
import { paginationListQueryMiddleware } from '@/middlewares/list-query/pagination';
|
||||||
import { selectListQueryMiddleware } from '@/middlewares/list-query/select';
|
import { selectListQueryMiddleware } from '@/middlewares/list-query/select';
|
||||||
|
import type { ListQuery } from '@/requests';
|
||||||
import * as ResponseHelper from '@/response-helper';
|
import * as ResponseHelper from '@/response-helper';
|
||||||
import type { ListQuery } from '@/types-db';
|
import type { ListQueryDb } from '@/types-db';
|
||||||
|
|
||||||
import { sortByQueryMiddleware } from '../sort-by';
|
import { sortByQueryMiddleware } from '../sort-by';
|
||||||
|
|
||||||
@@ -177,7 +178,7 @@ describe('List query middleware', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
describe('Query sort by', () => {
|
describe('Query sort by', () => {
|
||||||
const validCases: Array<{ name: string; value: ListQuery.Workflow.SortOrder }> = [
|
const validCases: Array<{ name: string; value: ListQueryDb.Workflow.SortOrder }> = [
|
||||||
{
|
{
|
||||||
name: 'sorting by name asc',
|
name: 'sorting by name asc',
|
||||||
value: 'name:asc',
|
value: 'name:asc',
|
||||||
@@ -236,7 +237,7 @@ describe('List query middleware', () => {
|
|||||||
|
|
||||||
test.each(invalidCases)('should fail validation when $name', async ({ value }) => {
|
test.each(invalidCases)('should fail validation when $name', async ({ value }) => {
|
||||||
mockReq.query = {
|
mockReq.query = {
|
||||||
sortBy: value as ListQuery.Workflow.SortOrder,
|
sortBy: value as ListQueryDb.Workflow.SortOrder,
|
||||||
};
|
};
|
||||||
|
|
||||||
await sortByQueryMiddleware(...args);
|
await sortByQueryMiddleware(...args);
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import type { NextFunction, Response } from 'express';
|
import type { NextFunction, Response } from 'express';
|
||||||
|
|
||||||
|
import type { ListQuery } from '@/requests';
|
||||||
import * as ResponseHelper from '@/response-helper';
|
import * as ResponseHelper from '@/response-helper';
|
||||||
import type { ListQuery } from '@/types-db';
|
|
||||||
import { toError } from '@/utils';
|
import { toError } from '@/utils';
|
||||||
|
|
||||||
import { CredentialsFilter } from './dtos/credentials.filter.dto';
|
import { CredentialsFilter } from './dtos/credentials.filter.dto';
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { type NextFunction, type Response } from 'express';
|
import { type NextFunction, type Response } from 'express';
|
||||||
|
|
||||||
import type { ListQuery } from '@/types-db';
|
import type { ListQuery } from '@/requests';
|
||||||
|
|
||||||
import { filterListQueryMiddleware } from './filter';
|
import { filterListQueryMiddleware } from './filter';
|
||||||
import { paginationListQueryMiddleware } from './pagination';
|
import { paginationListQueryMiddleware } from './pagination';
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import type { RequestHandler } from 'express';
|
import type { RequestHandler } from 'express';
|
||||||
import { UnexpectedError } from 'n8n-workflow';
|
import { UnexpectedError } from 'n8n-workflow';
|
||||||
|
|
||||||
|
import type { ListQuery } from '@/requests';
|
||||||
import * as ResponseHelper from '@/response-helper';
|
import * as ResponseHelper from '@/response-helper';
|
||||||
import type { ListQuery } from '@/types-db';
|
|
||||||
import { toError } from '@/utils';
|
import { toError } from '@/utils';
|
||||||
|
|
||||||
import { Pagination } from './dtos/pagination.dto';
|
import { Pagination } from './dtos/pagination.dto';
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import type { RequestHandler } from 'express';
|
import type { RequestHandler } from 'express';
|
||||||
|
|
||||||
|
import type { ListQuery } from '@/requests';
|
||||||
import * as ResponseHelper from '@/response-helper';
|
import * as ResponseHelper from '@/response-helper';
|
||||||
import type { ListQuery } from '@/types-db';
|
|
||||||
import { toError } from '@/utils';
|
import { toError } from '@/utils';
|
||||||
|
|
||||||
import { CredentialsSelect } from './dtos/credentials.select.dto';
|
import { CredentialsSelect } from './dtos/credentials.select.dto';
|
||||||
|
|||||||
@@ -3,8 +3,8 @@ import { validateSync } from 'class-validator';
|
|||||||
import type { RequestHandler } from 'express';
|
import type { RequestHandler } from 'express';
|
||||||
import { UnexpectedError } from 'n8n-workflow';
|
import { UnexpectedError } from 'n8n-workflow';
|
||||||
|
|
||||||
|
import type { ListQuery } from '@/requests';
|
||||||
import * as ResponseHelper from '@/response-helper';
|
import * as ResponseHelper from '@/response-helper';
|
||||||
import type { ListQuery } from '@/types-db';
|
|
||||||
import { toError } from '@/utils';
|
import { toError } from '@/utils';
|
||||||
|
|
||||||
import { WorkflowSorting } from './dtos/workflow.sort-by.dto';
|
import { WorkflowSorting } from './dtos/workflow.sort-by.dto';
|
||||||
|
|||||||
@@ -11,7 +11,8 @@ import type {
|
|||||||
import type { Project } from '@/databases/entities/project';
|
import type { Project } from '@/databases/entities/project';
|
||||||
import type { User } from '@/databases/entities/user';
|
import type { User } from '@/databases/entities/user';
|
||||||
import type { WorkflowHistory } from '@/databases/entities/workflow-history';
|
import type { WorkflowHistory } from '@/databases/entities/workflow-history';
|
||||||
import type { ListQuery } from '@/types-db';
|
|
||||||
|
import type { ListQueryDb } from './types-db';
|
||||||
|
|
||||||
export type APIRequest<
|
export type APIRequest<
|
||||||
RouteParams = {},
|
RouteParams = {},
|
||||||
@@ -42,13 +43,35 @@ export type AuthenticatedRequest<
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export namespace ListQuery {
|
||||||
|
export type Request = AuthenticatedRequest<{}, {}, {}, Params> & {
|
||||||
|
listQueryOptions?: Options;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type Params = {
|
||||||
|
filter?: string;
|
||||||
|
skip?: string;
|
||||||
|
take?: string;
|
||||||
|
select?: string;
|
||||||
|
sortBy?: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type Options = {
|
||||||
|
filter?: Record<string, unknown>;
|
||||||
|
select?: Record<string, true>;
|
||||||
|
skip?: number;
|
||||||
|
take?: number;
|
||||||
|
sortBy?: string;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
// ----------------------------------
|
// ----------------------------------
|
||||||
// list query
|
// list query
|
||||||
// ----------------------------------
|
// ----------------------------------
|
||||||
|
|
||||||
export function hasSharing(
|
export function hasSharing(
|
||||||
workflows: ListQuery.Workflow.Plain[] | ListQuery.Workflow.WithSharing[],
|
workflows: ListQueryDb.Workflow.Plain[] | ListQueryDb.Workflow.WithSharing[],
|
||||||
): workflows is ListQuery.Workflow.WithSharing[] {
|
): workflows is ListQueryDb.Workflow.WithSharing[] {
|
||||||
return workflows.some((w) => 'shared' in w);
|
return workflows.some((w) => 'shared' in w);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,10 @@ import { Service } from '@n8n/di';
|
|||||||
import type { AnnotationTagEntity } from '@/databases/entities/annotation-tag-entity.ee';
|
import type { AnnotationTagEntity } from '@/databases/entities/annotation-tag-entity.ee';
|
||||||
import { AnnotationTagRepository } from '@/databases/repositories/annotation-tag.repository.ee';
|
import { AnnotationTagRepository } from '@/databases/repositories/annotation-tag.repository.ee';
|
||||||
import { validateEntity } from '@/generic-helpers';
|
import { validateEntity } from '@/generic-helpers';
|
||||||
import type { IAnnotationTagDb, IAnnotationTagWithCountDb } from '@/types-db';
|
|
||||||
|
type IAnnotationTagDb = Pick<AnnotationTagEntity, 'id' | 'name' | 'createdAt' | 'updatedAt'>;
|
||||||
|
|
||||||
|
type IAnnotationTagWithCountDb = IAnnotationTagDb & { usageCount: number };
|
||||||
|
|
||||||
type GetAllResult<T> = T extends { withUsageCount: true }
|
type GetAllResult<T> = T extends { withUsageCount: true }
|
||||||
? IAnnotationTagWithCountDb[]
|
? IAnnotationTagWithCountDb[]
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import { FolderTagMappingRepository } from '@/databases/repositories/folder-tag-
|
|||||||
import { FolderRepository } from '@/databases/repositories/folder.repository';
|
import { FolderRepository } from '@/databases/repositories/folder.repository';
|
||||||
import { WorkflowRepository } from '@/databases/repositories/workflow.repository';
|
import { WorkflowRepository } from '@/databases/repositories/workflow.repository';
|
||||||
import { FolderNotFoundError } from '@/errors/folder-not-found.error';
|
import { FolderNotFoundError } from '@/errors/folder-not-found.error';
|
||||||
import type { ListQuery } from '@/types-db';
|
import type { ListQuery } from '@/requests';
|
||||||
|
|
||||||
export interface SimpleFolderNode {
|
export interface SimpleFolderNode {
|
||||||
id: string;
|
id: string;
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import { ProjectRepository } from '@/databases/repositories/project.repository';
|
|||||||
import { SharedWorkflowRepository } from '@/databases/repositories/shared-workflow.repository';
|
import { SharedWorkflowRepository } from '@/databases/repositories/shared-workflow.repository';
|
||||||
import { UserRepository } from '@/databases/repositories/user.repository';
|
import { UserRepository } from '@/databases/repositories/user.repository';
|
||||||
import { CacheService } from '@/services/cache/cache.service';
|
import { CacheService } from '@/services/cache/cache.service';
|
||||||
import type { ListQuery } from '@/types-db';
|
import type { ListQueryDb } from '@/types-db';
|
||||||
|
|
||||||
@Service()
|
@Service()
|
||||||
export class OwnershipService {
|
export class OwnershipService {
|
||||||
@@ -57,18 +57,20 @@ export class OwnershipService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
addOwnedByAndSharedWith(
|
addOwnedByAndSharedWith(
|
||||||
rawWorkflow: ListQuery.Workflow.WithSharing,
|
rawWorkflow: ListQueryDb.Workflow.WithSharing,
|
||||||
): ListQuery.Workflow.WithOwnedByAndSharedWith;
|
): ListQueryDb.Workflow.WithOwnedByAndSharedWith;
|
||||||
addOwnedByAndSharedWith(
|
addOwnedByAndSharedWith(
|
||||||
rawCredential: ListQuery.Credentials.WithSharing,
|
rawCredential: ListQueryDb.Credentials.WithSharing,
|
||||||
): ListQuery.Credentials.WithOwnedByAndSharedWith;
|
): ListQueryDb.Credentials.WithOwnedByAndSharedWith;
|
||||||
addOwnedByAndSharedWith(
|
addOwnedByAndSharedWith(
|
||||||
rawEntity: ListQuery.Workflow.WithSharing | ListQuery.Credentials.WithSharing,
|
rawEntity: ListQueryDb.Workflow.WithSharing | ListQueryDb.Credentials.WithSharing,
|
||||||
): ListQuery.Workflow.WithOwnedByAndSharedWith | ListQuery.Credentials.WithOwnedByAndSharedWith {
|
):
|
||||||
|
| ListQueryDb.Workflow.WithOwnedByAndSharedWith
|
||||||
|
| ListQueryDb.Credentials.WithOwnedByAndSharedWith {
|
||||||
const shared = rawEntity.shared;
|
const shared = rawEntity.shared;
|
||||||
const entity = rawEntity as
|
const entity = rawEntity as
|
||||||
| ListQuery.Workflow.WithOwnedByAndSharedWith
|
| ListQueryDb.Workflow.WithOwnedByAndSharedWith
|
||||||
| ListQuery.Credentials.WithOwnedByAndSharedWith;
|
| ListQueryDb.Credentials.WithOwnedByAndSharedWith;
|
||||||
|
|
||||||
Object.assign(entity, {
|
Object.assign(entity, {
|
||||||
homeProject: null,
|
homeProject: null,
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ import {
|
|||||||
WORKFLOW_SHARING_EDITOR_SCOPES,
|
WORKFLOW_SHARING_EDITOR_SCOPES,
|
||||||
WORKFLOW_SHARING_OWNER_SCOPES,
|
WORKFLOW_SHARING_OWNER_SCOPES,
|
||||||
} from '@/permissions.ee/resource-roles';
|
} from '@/permissions.ee/resource-roles';
|
||||||
import type { ListQuery, ScopesField } from '@/types-db';
|
import type { ListQueryDb, ScopesField } from '@/types-db';
|
||||||
|
|
||||||
export type RoleNamespace = 'global' | 'project' | 'credential' | 'workflow';
|
export type RoleNamespace = 'global' | 'project' | 'credential' | 'workflow';
|
||||||
|
|
||||||
@@ -159,10 +159,10 @@ export class RoleService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
addScopes(
|
addScopes(
|
||||||
rawWorkflow: ListQuery.Workflow.WithSharing | ListQuery.Workflow.WithOwnedByAndSharedWith,
|
rawWorkflow: ListQueryDb.Workflow.WithSharing | ListQueryDb.Workflow.WithOwnedByAndSharedWith,
|
||||||
user: User,
|
user: User,
|
||||||
userProjectRelations: ProjectRelation[],
|
userProjectRelations: ProjectRelation[],
|
||||||
): ListQuery.Workflow.WithScopes;
|
): ListQueryDb.Workflow.WithScopes;
|
||||||
addScopes(
|
addScopes(
|
||||||
rawCredential: CredentialsEntity,
|
rawCredential: CredentialsEntity,
|
||||||
user: User,
|
user: User,
|
||||||
@@ -170,29 +170,29 @@ export class RoleService {
|
|||||||
): CredentialsEntity & ScopesField;
|
): CredentialsEntity & ScopesField;
|
||||||
addScopes(
|
addScopes(
|
||||||
rawCredential:
|
rawCredential:
|
||||||
| ListQuery.Credentials.WithSharing
|
| ListQueryDb.Credentials.WithSharing
|
||||||
| ListQuery.Credentials.WithOwnedByAndSharedWith,
|
| ListQueryDb.Credentials.WithOwnedByAndSharedWith,
|
||||||
user: User,
|
user: User,
|
||||||
userProjectRelations: ProjectRelation[],
|
userProjectRelations: ProjectRelation[],
|
||||||
): ListQuery.Credentials.WithScopes;
|
): ListQueryDb.Credentials.WithScopes;
|
||||||
addScopes(
|
addScopes(
|
||||||
rawEntity:
|
rawEntity:
|
||||||
| CredentialsEntity
|
| CredentialsEntity
|
||||||
| ListQuery.Workflow.WithSharing
|
| ListQueryDb.Workflow.WithSharing
|
||||||
| ListQuery.Credentials.WithOwnedByAndSharedWith
|
| ListQueryDb.Credentials.WithOwnedByAndSharedWith
|
||||||
| ListQuery.Credentials.WithSharing
|
| ListQueryDb.Credentials.WithSharing
|
||||||
| ListQuery.Workflow.WithOwnedByAndSharedWith,
|
| ListQueryDb.Workflow.WithOwnedByAndSharedWith,
|
||||||
user: User,
|
user: User,
|
||||||
userProjectRelations: ProjectRelation[],
|
userProjectRelations: ProjectRelation[],
|
||||||
):
|
):
|
||||||
| (CredentialsEntity & ScopesField)
|
| (CredentialsEntity & ScopesField)
|
||||||
| ListQuery.Workflow.WithScopes
|
| ListQueryDb.Workflow.WithScopes
|
||||||
| ListQuery.Credentials.WithScopes {
|
| ListQueryDb.Credentials.WithScopes {
|
||||||
const shared = rawEntity.shared;
|
const shared = rawEntity.shared;
|
||||||
const entity = rawEntity as
|
const entity = rawEntity as
|
||||||
| (CredentialsEntity & ScopesField)
|
| (CredentialsEntity & ScopesField)
|
||||||
| ListQuery.Workflow.WithScopes
|
| ListQueryDb.Workflow.WithScopes
|
||||||
| ListQuery.Credentials.WithScopes;
|
| ListQueryDb.Credentials.WithScopes;
|
||||||
|
|
||||||
Object.assign(entity, {
|
Object.assign(entity, {
|
||||||
scopes: [],
|
scopes: [],
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
import type { GlobalRole, Scope } from '@n8n/permissions';
|
import type { GlobalRole, Scope } from '@n8n/permissions';
|
||||||
import type express from 'express';
|
|
||||||
import type {
|
import type {
|
||||||
ICredentialsEncrypted,
|
ICredentialsEncrypted,
|
||||||
IRunExecutionData,
|
IRunExecutionData,
|
||||||
@@ -13,7 +12,6 @@ import type {
|
|||||||
IUser,
|
IUser,
|
||||||
} from 'n8n-workflow';
|
} from 'n8n-workflow';
|
||||||
|
|
||||||
import type { AnnotationTagEntity } from '@/databases/entities/annotation-tag-entity.ee';
|
|
||||||
import type { AuthProviderType } from '@/databases/entities/auth-identity';
|
import type { AuthProviderType } from '@/databases/entities/auth-identity';
|
||||||
import type { CredentialsEntity } from '@/databases/entities/credentials-entity';
|
import type { CredentialsEntity } from '@/databases/entities/credentials-entity';
|
||||||
import type { Folder } from '@/databases/entities/folder';
|
import type { Folder } from '@/databases/entities/folder';
|
||||||
@@ -71,10 +69,6 @@ export type ITagDb = Pick<TagEntity, 'id' | 'name' | 'createdAt' | 'updatedAt'>;
|
|||||||
|
|
||||||
export type ITagWithCountDb = ITagDb & UsageCount;
|
export type ITagWithCountDb = ITagDb & UsageCount;
|
||||||
|
|
||||||
export type IAnnotationTagDb = Pick<AnnotationTagEntity, 'id' | 'name' | 'createdAt' | 'updatedAt'>;
|
|
||||||
|
|
||||||
export type IAnnotationTagWithCountDb = IAnnotationTagDb & UsageCount;
|
|
||||||
|
|
||||||
// Almost identical to editor-ui.Interfaces.ts
|
// Almost identical to editor-ui.Interfaces.ts
|
||||||
export interface IWorkflowDb extends IWorkflowBase {
|
export interface IWorkflowDb extends IWorkflowBase {
|
||||||
triggerCount: number;
|
triggerCount: number;
|
||||||
@@ -211,49 +205,7 @@ export namespace ExecutionSummaries {
|
|||||||
export type ExecutionSummaryWithScopes = ExecutionSummary & { scopes: Scope[] };
|
export type ExecutionSummaryWithScopes = ExecutionSummary & { scopes: Scope[] };
|
||||||
}
|
}
|
||||||
|
|
||||||
export type APIRequest<
|
export namespace ListQueryDb {
|
||||||
RouteParams = {},
|
|
||||||
ResponseBody = {},
|
|
||||||
RequestBody = {},
|
|
||||||
RequestQuery = {},
|
|
||||||
> = express.Request<RouteParams, ResponseBody, RequestBody, RequestQuery> & {
|
|
||||||
browserId?: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
export type AuthenticatedRequest<
|
|
||||||
RouteParams = {},
|
|
||||||
ResponseBody = {},
|
|
||||||
RequestBody = {},
|
|
||||||
RequestQuery = {},
|
|
||||||
> = Omit<APIRequest<RouteParams, ResponseBody, RequestBody, RequestQuery>, 'user' | 'cookies'> & {
|
|
||||||
user: User;
|
|
||||||
cookies: Record<string, string | undefined>;
|
|
||||||
headers: express.Request['headers'] & {
|
|
||||||
'push-ref': string;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
export namespace ListQuery {
|
|
||||||
export type Request = AuthenticatedRequest<{}, {}, {}, Params> & {
|
|
||||||
listQueryOptions?: Options;
|
|
||||||
};
|
|
||||||
|
|
||||||
export type Params = {
|
|
||||||
filter?: string;
|
|
||||||
skip?: string;
|
|
||||||
take?: string;
|
|
||||||
select?: string;
|
|
||||||
sortBy?: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
export type Options = {
|
|
||||||
filter?: Record<string, unknown>;
|
|
||||||
select?: Record<string, true>;
|
|
||||||
skip?: number;
|
|
||||||
take?: number;
|
|
||||||
sortBy?: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Slim workflow returned from a list query operation.
|
* Slim workflow returned from a list query operation.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -8,8 +8,7 @@ import type {
|
|||||||
IWorkflowBase,
|
IWorkflowBase,
|
||||||
} from 'n8n-workflow';
|
} from 'n8n-workflow';
|
||||||
|
|
||||||
import type { AuthenticatedRequest } from '@/requests';
|
import type { AuthenticatedRequest, ListQuery } from '@/requests';
|
||||||
import type { ListQuery } from '@/types-db';
|
|
||||||
|
|
||||||
export declare namespace WorkflowRequest {
|
export declare namespace WorkflowRequest {
|
||||||
type CreateUpdatePayload = Partial<{
|
type CreateUpdatePayload = Partial<{
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ import { NotFoundError } from '@/errors/response-errors/not-found.error';
|
|||||||
import { EventService } from '@/events/event.service';
|
import { EventService } from '@/events/event.service';
|
||||||
import { ExternalHooks } from '@/external-hooks';
|
import { ExternalHooks } from '@/external-hooks';
|
||||||
import { validateEntity } from '@/generic-helpers';
|
import { validateEntity } from '@/generic-helpers';
|
||||||
|
import type { ListQuery } from '@/requests';
|
||||||
import { hasSharing } from '@/requests';
|
import { hasSharing } from '@/requests';
|
||||||
import { FolderService } from '@/services/folder.service';
|
import { FolderService } from '@/services/folder.service';
|
||||||
import { OrchestrationService } from '@/services/orchestration.service';
|
import { OrchestrationService } from '@/services/orchestration.service';
|
||||||
@@ -34,7 +35,7 @@ import { OwnershipService } from '@/services/ownership.service';
|
|||||||
import { ProjectService } from '@/services/project.service.ee';
|
import { ProjectService } from '@/services/project.service.ee';
|
||||||
import { RoleService } from '@/services/role.service';
|
import { RoleService } from '@/services/role.service';
|
||||||
import { TagService } from '@/services/tag.service';
|
import { TagService } from '@/services/tag.service';
|
||||||
import type { ListQuery } from '@/types-db';
|
import type { ListQueryDb } from '@/types-db';
|
||||||
import * as WorkflowHelpers from '@/workflow-helpers';
|
import * as WorkflowHelpers from '@/workflow-helpers';
|
||||||
|
|
||||||
import { WorkflowFinderService } from './workflow-finder.service';
|
import { WorkflowFinderService } from './workflow-finder.service';
|
||||||
@@ -138,7 +139,7 @@ export class WorkflowService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private async processSharedWorkflows(
|
private async processSharedWorkflows(
|
||||||
workflows: ListQuery.Workflow.WithSharing[],
|
workflows: ListQueryDb.Workflow.WithSharing[],
|
||||||
options?: ListQuery.Options,
|
options?: ListQuery.Options,
|
||||||
) {
|
) {
|
||||||
const projectId = options?.filter?.projectId;
|
const projectId = options?.filter?.projectId;
|
||||||
@@ -152,7 +153,7 @@ export class WorkflowService {
|
|||||||
return workflows.map((workflow) => this.ownershipService.addOwnedByAndSharedWith(workflow));
|
return workflows.map((workflow) => this.ownershipService.addOwnedByAndSharedWith(workflow));
|
||||||
}
|
}
|
||||||
|
|
||||||
private async addSharedRelation(workflows: ListQuery.Workflow.WithSharing[]): Promise<void> {
|
private async addSharedRelation(workflows: ListQueryDb.Workflow.WithSharing[]): Promise<void> {
|
||||||
const workflowIds = workflows.map((workflow) => workflow.id);
|
const workflowIds = workflows.map((workflow) => workflow.id);
|
||||||
const relations = await this.sharedWorkflowRepository.getAllRelationsForWorkflows(workflowIds);
|
const relations = await this.sharedWorkflowRepository.getAllRelationsForWorkflows(workflowIds);
|
||||||
|
|
||||||
@@ -162,7 +163,7 @@ export class WorkflowService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private async addUserScopes(
|
private async addUserScopes(
|
||||||
workflows: ListQuery.Workflow.Plain[] | ListQuery.Workflow.WithSharing[],
|
workflows: ListQueryDb.Workflow.Plain[] | ListQueryDb.Workflow.WithSharing[],
|
||||||
user: User,
|
user: User,
|
||||||
) {
|
) {
|
||||||
const projectRelations = await this.projectService.getProjectRelationsForUser(user);
|
const projectRelations = await this.projectService.getProjectRelationsForUser(user);
|
||||||
@@ -173,7 +174,7 @@ export class WorkflowService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private cleanupSharedField(
|
private cleanupSharedField(
|
||||||
workflows: ListQuery.Workflow.Plain[] | ListQuery.Workflow.WithSharing[],
|
workflows: ListQueryDb.Workflow.Plain[] | ListQueryDb.Workflow.WithSharing[],
|
||||||
): void {
|
): void {
|
||||||
/*
|
/*
|
||||||
This is to emulate the old behavior of removing the shared field as
|
This is to emulate the old behavior of removing the shared field as
|
||||||
@@ -187,7 +188,7 @@ export class WorkflowService {
|
|||||||
|
|
||||||
private mergeProcessedWorkflows(
|
private mergeProcessedWorkflows(
|
||||||
workflowsAndFolders: WorkflowFolderUnionFull[],
|
workflowsAndFolders: WorkflowFolderUnionFull[],
|
||||||
processedWorkflows: ListQuery.Workflow.Plain[] | ListQuery.Workflow.WithSharing[],
|
processedWorkflows: ListQueryDb.Workflow.Plain[] | ListQueryDb.Workflow.WithSharing[],
|
||||||
) {
|
) {
|
||||||
const workflowMap = new Map(processedWorkflows.map((workflow) => [workflow.id, workflow]));
|
const workflowMap = new Map(processedWorkflows.map((workflow) => [workflow.id, workflow]));
|
||||||
|
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import type { User } from '@/databases/entities/user';
|
|||||||
import { ProjectRepository } from '@/databases/repositories/project.repository';
|
import { ProjectRepository } from '@/databases/repositories/project.repository';
|
||||||
import { SharedCredentialsRepository } from '@/databases/repositories/shared-credentials.repository';
|
import { SharedCredentialsRepository } from '@/databases/repositories/shared-credentials.repository';
|
||||||
import { ProjectService } from '@/services/project.service.ee';
|
import { ProjectService } from '@/services/project.service.ee';
|
||||||
import type { ListQuery } from '@/types-db';
|
import type { ListQueryDb } from '@/types-db';
|
||||||
import { UserManagementMailer } from '@/user-management/email';
|
import { UserManagementMailer } from '@/user-management/email';
|
||||||
import { createWorkflow, shareWorkflowWithUsers } from '@test-integration/db/workflows';
|
import { createWorkflow, shareWorkflowWithUsers } from '@test-integration/db/workflows';
|
||||||
|
|
||||||
@@ -134,13 +134,14 @@ describe('GET /credentials', () => {
|
|||||||
|
|
||||||
expect(response.statusCode).toBe(200);
|
expect(response.statusCode).toBe(200);
|
||||||
expect(response.body.data).toHaveLength(2); // owner retrieved owner cred and member cred
|
expect(response.body.data).toHaveLength(2); // owner retrieved owner cred and member cred
|
||||||
const ownerCredential: ListQuery.Credentials.WithOwnedByAndSharedWith = response.body.data.find(
|
const ownerCredential: ListQueryDb.Credentials.WithOwnedByAndSharedWith =
|
||||||
(e: ListQuery.Credentials.WithOwnedByAndSharedWith) =>
|
|
||||||
e.homeProject?.id === ownerPersonalProject.id,
|
|
||||||
);
|
|
||||||
const memberCredential: ListQuery.Credentials.WithOwnedByAndSharedWith =
|
|
||||||
response.body.data.find(
|
response.body.data.find(
|
||||||
(e: ListQuery.Credentials.WithOwnedByAndSharedWith) =>
|
(e: ListQueryDb.Credentials.WithOwnedByAndSharedWith) =>
|
||||||
|
e.homeProject?.id === ownerPersonalProject.id,
|
||||||
|
);
|
||||||
|
const memberCredential: ListQueryDb.Credentials.WithOwnedByAndSharedWith =
|
||||||
|
response.body.data.find(
|
||||||
|
(e: ListQueryDb.Credentials.WithOwnedByAndSharedWith) =>
|
||||||
e.homeProject?.id === member1PersonalProject.id,
|
e.homeProject?.id === member1PersonalProject.id,
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -205,7 +206,7 @@ describe('GET /credentials', () => {
|
|||||||
expect(response.statusCode).toBe(200);
|
expect(response.statusCode).toBe(200);
|
||||||
expect(response.body.data).toHaveLength(1); // member retrieved only member cred
|
expect(response.body.data).toHaveLength(1); // member retrieved only member cred
|
||||||
|
|
||||||
const [member1Credential]: [ListQuery.Credentials.WithOwnedByAndSharedWith] =
|
const [member1Credential]: [ListQueryDb.Credentials.WithOwnedByAndSharedWith] =
|
||||||
response.body.data;
|
response.body.data;
|
||||||
|
|
||||||
validateMainCredentialData(member1Credential);
|
validateMainCredentialData(member1Credential);
|
||||||
@@ -536,7 +537,8 @@ describe('GET /credentials/:id', () => {
|
|||||||
|
|
||||||
expect(firstResponse.statusCode).toBe(200);
|
expect(firstResponse.statusCode).toBe(200);
|
||||||
|
|
||||||
const firstCredential: ListQuery.Credentials.WithOwnedByAndSharedWith = firstResponse.body.data;
|
const firstCredential: ListQueryDb.Credentials.WithOwnedByAndSharedWith =
|
||||||
|
firstResponse.body.data;
|
||||||
validateMainCredentialData(firstCredential);
|
validateMainCredentialData(firstCredential);
|
||||||
expect(firstCredential.data).toBeUndefined();
|
expect(firstCredential.data).toBeUndefined();
|
||||||
|
|
||||||
@@ -593,7 +595,7 @@ describe('GET /credentials/:id', () => {
|
|||||||
|
|
||||||
const response1 = await authOwnerAgent.get(`/credentials/${savedCredential.id}`).expect(200);
|
const response1 = await authOwnerAgent.get(`/credentials/${savedCredential.id}`).expect(200);
|
||||||
|
|
||||||
const credential: ListQuery.Credentials.WithOwnedByAndSharedWith = response1.body.data;
|
const credential: ListQueryDb.Credentials.WithOwnedByAndSharedWith = response1.body.data;
|
||||||
|
|
||||||
validateMainCredentialData(credential);
|
validateMainCredentialData(credential);
|
||||||
expect(credential.data).toBeUndefined();
|
expect(credential.data).toBeUndefined();
|
||||||
@@ -617,7 +619,7 @@ describe('GET /credentials/:id', () => {
|
|||||||
.query({ includeData: true })
|
.query({ includeData: true })
|
||||||
.expect(200);
|
.expect(200);
|
||||||
|
|
||||||
const credential2: ListQuery.Credentials.WithOwnedByAndSharedWith = response2.body.data;
|
const credential2: ListQueryDb.Credentials.WithOwnedByAndSharedWith = response2.body.data;
|
||||||
|
|
||||||
validateMainCredentialData(credential);
|
validateMainCredentialData(credential);
|
||||||
expect(credential2.data).toBeDefined(); // Instance owners should be capable of editing all credentials
|
expect(credential2.data).toBeDefined(); // Instance owners should be capable of editing all credentials
|
||||||
@@ -645,7 +647,8 @@ describe('GET /credentials/:id', () => {
|
|||||||
.get(`/credentials/${savedCredential.id}`)
|
.get(`/credentials/${savedCredential.id}`)
|
||||||
.expect(200);
|
.expect(200);
|
||||||
|
|
||||||
const firstCredential: ListQuery.Credentials.WithOwnedByAndSharedWith = firstResponse.body.data;
|
const firstCredential: ListQueryDb.Credentials.WithOwnedByAndSharedWith =
|
||||||
|
firstResponse.body.data;
|
||||||
validateMainCredentialData(firstCredential);
|
validateMainCredentialData(firstCredential);
|
||||||
expect(firstCredential.data).toBeUndefined();
|
expect(firstCredential.data).toBeUndefined();
|
||||||
expect(firstCredential).toMatchObject({
|
expect(firstCredential).toMatchObject({
|
||||||
@@ -676,7 +679,7 @@ describe('GET /credentials/:id', () => {
|
|||||||
.query({ includeData: true })
|
.query({ includeData: true })
|
||||||
.expect(200);
|
.expect(200);
|
||||||
|
|
||||||
const secondCredential: ListQuery.Credentials.WithOwnedByAndSharedWith =
|
const secondCredential: ListQueryDb.Credentials.WithOwnedByAndSharedWith =
|
||||||
secondResponse.body.data;
|
secondResponse.body.data;
|
||||||
validateMainCredentialData(secondCredential);
|
validateMainCredentialData(secondCredential);
|
||||||
expect(secondCredential.data).toBeDefined();
|
expect(secondCredential.data).toBeDefined();
|
||||||
@@ -1359,7 +1362,7 @@ describe('PUT /:credentialId/transfer', () => {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
function validateMainCredentialData(credential: ListQuery.Credentials.WithOwnedByAndSharedWith) {
|
function validateMainCredentialData(credential: ListQueryDb.Credentials.WithOwnedByAndSharedWith) {
|
||||||
expect(typeof credential.name).toBe('string');
|
expect(typeof credential.name).toBe('string');
|
||||||
expect(typeof credential.type).toBe('string');
|
expect(typeof credential.type).toBe('string');
|
||||||
expect(credential.homeProject).toBeDefined();
|
expect(credential.homeProject).toBeDefined();
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ import { CredentialsRepository } from '@/databases/repositories/credentials.repo
|
|||||||
import { ProjectRepository } from '@/databases/repositories/project.repository';
|
import { ProjectRepository } from '@/databases/repositories/project.repository';
|
||||||
import { SharedCredentialsRepository } from '@/databases/repositories/shared-credentials.repository';
|
import { SharedCredentialsRepository } from '@/databases/repositories/shared-credentials.repository';
|
||||||
import { CredentialsTester } from '@/services/credentials-tester.service';
|
import { CredentialsTester } from '@/services/credentials-tester.service';
|
||||||
import type { ListQuery } from '@/types-db';
|
import type { ListQueryDb } from '@/types-db';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
decryptCredentialData,
|
decryptCredentialData,
|
||||||
@@ -74,7 +74,7 @@ beforeEach(async () => {
|
|||||||
sharedCredentialsRepository = Container.get(SharedCredentialsRepository);
|
sharedCredentialsRepository = Container.get(SharedCredentialsRepository);
|
||||||
});
|
});
|
||||||
|
|
||||||
type GetAllResponse = { body: { data: ListQuery.Credentials.WithOwnedByAndSharedWith[] } };
|
type GetAllResponse = { body: { data: ListQueryDb.Credentials.WithOwnedByAndSharedWith[] } };
|
||||||
|
|
||||||
// ----------------------------------------
|
// ----------------------------------------
|
||||||
// GET /credentials - fetch all credentials
|
// GET /credentials - fetch all credentials
|
||||||
@@ -92,7 +92,7 @@ describe('GET /credentials', () => {
|
|||||||
expect(response.body.data.length).toBe(2); // owner retrieved owner cred and member cred
|
expect(response.body.data.length).toBe(2); // owner retrieved owner cred and member cred
|
||||||
|
|
||||||
const savedCredentialsIds = [savedOwnerCredentialId, savedMemberCredentialId];
|
const savedCredentialsIds = [savedOwnerCredentialId, savedMemberCredentialId];
|
||||||
response.body.data.forEach((credential: ListQuery.Credentials.WithOwnedByAndSharedWith) => {
|
response.body.data.forEach((credential: ListQueryDb.Credentials.WithOwnedByAndSharedWith) => {
|
||||||
validateMainCredentialData(credential);
|
validateMainCredentialData(credential);
|
||||||
expect('data' in credential).toBe(false);
|
expect('data' in credential).toBe(false);
|
||||||
expect(savedCredentialsIds).toContain(credential.id);
|
expect(savedCredentialsIds).toContain(credential.id);
|
||||||
@@ -1502,7 +1502,7 @@ const INVALID_PAYLOADS = [
|
|||||||
undefined,
|
undefined,
|
||||||
];
|
];
|
||||||
|
|
||||||
function validateMainCredentialData(credential: ListQuery.Credentials.WithOwnedByAndSharedWith) {
|
function validateMainCredentialData(credential: ListQueryDb.Credentials.WithOwnedByAndSharedWith) {
|
||||||
const { name, type, sharedWithProjects, homeProject, isManaged } = credential;
|
const { name, type, sharedWithProjects, homeProject, isManaged } = credential;
|
||||||
|
|
||||||
expect(typeof name).toBe('string');
|
expect(typeof name).toBe('string');
|
||||||
@@ -1522,7 +1522,9 @@ function validateMainCredentialData(credential: ListQuery.Credentials.WithOwnedB
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function validateCredentialWithNoData(credential: ListQuery.Credentials.WithOwnedByAndSharedWith) {
|
function validateCredentialWithNoData(
|
||||||
|
credential: ListQueryDb.Credentials.WithOwnedByAndSharedWith,
|
||||||
|
) {
|
||||||
validateMainCredentialData(credential);
|
validateMainCredentialData(credential);
|
||||||
|
|
||||||
expect('data' in credential).toBe(false);
|
expect('data' in credential).toBe(false);
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ import type { WorkflowFolderUnionFull } from '@/databases/repositories/workflow.
|
|||||||
import { WorkflowRepository } from '@/databases/repositories/workflow.repository';
|
import { WorkflowRepository } from '@/databases/repositories/workflow.repository';
|
||||||
import { License } from '@/license';
|
import { License } from '@/license';
|
||||||
import { ProjectService } from '@/services/project.service.ee';
|
import { ProjectService } from '@/services/project.service.ee';
|
||||||
import type { ListQuery } from '@/types-db';
|
import type { ListQueryDb } from '@/types-db';
|
||||||
import { EnterpriseWorkflowService } from '@/workflows/workflow.service.ee';
|
import { EnterpriseWorkflowService } from '@/workflows/workflow.service.ee';
|
||||||
import { createFolder } from '@test-integration/db/folders';
|
import { createFolder } from '@test-integration/db/folders';
|
||||||
|
|
||||||
@@ -641,7 +641,7 @@ describe('GET /workflows', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const found = response.body.data.find(
|
const found = response.body.data.find(
|
||||||
(w: ListQuery.Workflow.WithOwnership) => w.name === 'First',
|
(w: ListQueryDb.Workflow.WithOwnership) => w.name === 'First',
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(found.nodes).toBeUndefined();
|
expect(found.nodes).toBeUndefined();
|
||||||
@@ -1458,7 +1458,7 @@ describe('GET /workflows?includeFolders=true', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const found = response.body.data.find(
|
const found = response.body.data.find(
|
||||||
(w: ListQuery.Workflow.WithOwnership) => w.name === 'First',
|
(w: ListQueryDb.Workflow.WithOwnership) => w.name === 'First',
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(found.nodes).toBeUndefined();
|
expect(found.nodes).toBeUndefined();
|
||||||
|
|||||||
Reference in New Issue
Block a user