mirror of
https://github.com/n8n-io/n8n.git
synced 2024-12-28 22:19:41 -08:00
feat(core): Add option to filter for empty variables (#12112)
This commit is contained in:
parent
8bb0d3d823
commit
a63f0e878e
|
@ -3,3 +3,4 @@ export { RoleChangeRequestDto } from './user/role-change-request.dto';
|
||||||
export { SettingsUpdateRequestDto } from './user/settings-update-request.dto';
|
export { SettingsUpdateRequestDto } from './user/settings-update-request.dto';
|
||||||
export { UserUpdateRequestDto } from './user/user-update-request.dto';
|
export { UserUpdateRequestDto } from './user/user-update-request.dto';
|
||||||
export { CommunityRegisteredRequestDto } from './license/community-registered-request.dto';
|
export { CommunityRegisteredRequestDto } from './license/community-registered-request.dto';
|
||||||
|
export { VariableListRequestDto } from './variables/variables-list-request.dto';
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
import { z } from 'zod';
|
||||||
|
import { Z } from 'zod-class';
|
||||||
|
|
||||||
|
export class VariableListRequestDto extends Z.class({
|
||||||
|
state: z.literal('empty').optional(),
|
||||||
|
}) {}
|
|
@ -1,4 +1,7 @@
|
||||||
|
import { VariableListRequestDto } from '@n8n/api-types';
|
||||||
|
|
||||||
import { Delete, Get, GlobalScope, Licensed, Patch, Post, RestController } from '@/decorators';
|
import { Delete, Get, GlobalScope, Licensed, Patch, Post, RestController } from '@/decorators';
|
||||||
|
import { Query } from '@/decorators/args';
|
||||||
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 { VariableCountLimitReachedError } from '@/errors/variable-count-limit-reached.error';
|
import { VariableCountLimitReachedError } from '@/errors/variable-count-limit-reached.error';
|
||||||
|
@ -13,8 +16,8 @@ export class VariablesController {
|
||||||
|
|
||||||
@Get('/')
|
@Get('/')
|
||||||
@GlobalScope('variable:list')
|
@GlobalScope('variable:list')
|
||||||
async getVariables() {
|
async getVariables(_req: unknown, _res: unknown, @Query query: VariableListRequestDto) {
|
||||||
return await this.variablesService.getAllCached();
|
return await this.variablesService.getAllCached(query.state);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Post('/')
|
@Post('/')
|
||||||
|
|
|
@ -18,13 +18,22 @@ export class VariablesService {
|
||||||
private readonly eventService: EventService,
|
private readonly eventService: EventService,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
async getAllCached(): Promise<Variables[]> {
|
async getAllCached(state?: 'empty'): Promise<Variables[]> {
|
||||||
const variables = await this.cacheService.get('variables', {
|
let variables = await this.cacheService.get('variables', {
|
||||||
async refreshFn() {
|
async refreshFn() {
|
||||||
return await Container.get(VariablesService).findAll();
|
return await Container.get(VariablesService).findAll();
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
return (variables as Array<Partial<Variables>>).map((v) => this.variablesRepository.create(v));
|
|
||||||
|
if (variables === undefined) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (state === 'empty') {
|
||||||
|
variables = variables.filter((v) => v.value === '');
|
||||||
|
}
|
||||||
|
|
||||||
|
return variables.map((v) => this.variablesRepository.create(v));
|
||||||
}
|
}
|
||||||
|
|
||||||
async getCount(): Promise<number> {
|
async getCount(): Promise<number> {
|
||||||
|
|
|
@ -4,6 +4,7 @@ import type { Variables } from '@/databases/entities/variables';
|
||||||
import { VariablesRepository } from '@/databases/repositories/variables.repository';
|
import { VariablesRepository } from '@/databases/repositories/variables.repository';
|
||||||
import { generateNanoId } from '@/databases/utils/generators';
|
import { generateNanoId } from '@/databases/utils/generators';
|
||||||
import { VariablesService } from '@/environments/variables/variables.service.ee';
|
import { VariablesService } from '@/environments/variables/variables.service.ee';
|
||||||
|
import { CacheService } from '@/services/cache/cache.service';
|
||||||
|
|
||||||
import { createOwner, createUser } from './shared/db/users';
|
import { createOwner, createUser } from './shared/db/users';
|
||||||
import * as testDb from './shared/test-db';
|
import * as testDb from './shared/test-db';
|
||||||
|
@ -65,19 +66,41 @@ beforeEach(async () => {
|
||||||
// ----------------------------------------
|
// ----------------------------------------
|
||||||
describe('GET /variables', () => {
|
describe('GET /variables', () => {
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
await Promise.all([createVariable('test1', 'value1'), createVariable('test2', 'value2')]);
|
await Promise.all([
|
||||||
|
createVariable('test1', 'value1'),
|
||||||
|
createVariable('test2', 'value2'),
|
||||||
|
createVariable('empty', ''),
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should return an empty array if there is nothing in the cache', async () => {
|
||||||
|
const cacheService = Container.get(CacheService);
|
||||||
|
const spy = jest.spyOn(cacheService, 'get').mockResolvedValueOnce(undefined);
|
||||||
|
const response = await authOwnerAgent.get('/variables');
|
||||||
|
expect(spy).toHaveBeenCalledTimes(1);
|
||||||
|
expect(response.statusCode).toBe(200);
|
||||||
|
expect(response.body.data.length).toBe(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('should return all variables for an owner', async () => {
|
test('should return all variables for an owner', async () => {
|
||||||
const response = await authOwnerAgent.get('/variables');
|
const response = await authOwnerAgent.get('/variables');
|
||||||
expect(response.statusCode).toBe(200);
|
expect(response.statusCode).toBe(200);
|
||||||
expect(response.body.data.length).toBe(2);
|
expect(response.body.data.length).toBe(3);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('should return all variables for a member', async () => {
|
test('should return all variables for a member', async () => {
|
||||||
const response = await authMemberAgent.get('/variables');
|
const response = await authMemberAgent.get('/variables');
|
||||||
expect(response.statusCode).toBe(200);
|
expect(response.statusCode).toBe(200);
|
||||||
expect(response.body.data.length).toBe(2);
|
expect(response.body.data.length).toBe(3);
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('state:empty', () => {
|
||||||
|
test('only return empty variables', async () => {
|
||||||
|
const response = await authOwnerAgent.get('/variables').query({ state: 'empty' });
|
||||||
|
expect(response.statusCode).toBe(200);
|
||||||
|
expect(response.body.data.length).toBe(1);
|
||||||
|
expect(response.body.data[0]).toMatchObject({ key: 'empty', value: '', type: 'string' });
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue