Fix: Get rid of subgroups in admin/env-variables (#10105)
closes https://github.com/twentyhq/core-team-issues/issues/379 --------- Co-authored-by: Félix Malfait <felix@twenty.com>
This commit is contained in:
@ -7,13 +7,12 @@ import {
|
||||
AuthExceptionCode,
|
||||
} from 'src/engine/core-modules/auth/auth.exception';
|
||||
import { LoginTokenService } from 'src/engine/core-modules/auth/token/services/login-token.service';
|
||||
import { EnvironmentVariablesGroup } from 'src/engine/core-modules/environment/enums/environment-variables-group.enum';
|
||||
import { DomainManagerService } from 'src/engine/core-modules/domain-manager/services/domain-manager.service';
|
||||
import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service';
|
||||
import { FeatureFlagKey } from 'src/engine/core-modules/feature-flag/enums/feature-flag-key.enum';
|
||||
import { FeatureFlag } from 'src/engine/core-modules/feature-flag/feature-flag.entity';
|
||||
import { User } from 'src/engine/core-modules/user/user.entity';
|
||||
import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity';
|
||||
import { DomainManagerService } from 'src/engine/core-modules/domain-manager/services/domain-manager.service';
|
||||
|
||||
const UserFindOneMock = jest.fn();
|
||||
const WorkspaceFindOneMock = jest.fn();
|
||||
@ -34,31 +33,23 @@ jest.mock(
|
||||
);
|
||||
|
||||
jest.mock(
|
||||
'src/engine/core-modules/environment/constants/environment-variables-group-metadata',
|
||||
'../../environment/constants/environment-variables-group-metadata',
|
||||
() => ({
|
||||
ENVIRONMENT_VARIABLES_GROUP_METADATA: {
|
||||
GROUP_1: {
|
||||
SERVER_CONFIG: {
|
||||
position: 100,
|
||||
description: '',
|
||||
description: 'Server config description',
|
||||
isHiddenOnLoad: false,
|
||||
},
|
||||
GROUP_2: {
|
||||
RATE_LIMITING: {
|
||||
position: 200,
|
||||
description: '',
|
||||
description: 'Rate limiting description',
|
||||
isHiddenOnLoad: false,
|
||||
},
|
||||
VISIBLE_GROUP: {
|
||||
OTHER: {
|
||||
position: 300,
|
||||
description: '',
|
||||
},
|
||||
},
|
||||
}),
|
||||
);
|
||||
|
||||
jest.mock(
|
||||
'src/engine/core-modules/environment/constants/environment-variables-sub-group-metadata',
|
||||
() => ({
|
||||
ENVIRONMENT_VARIABLES_SUB_GROUP_METADATA: {
|
||||
SUBGROUP_1: {
|
||||
description: '',
|
||||
description: 'Other description',
|
||||
isHiddenOnLoad: true,
|
||||
},
|
||||
},
|
||||
}),
|
||||
@ -269,29 +260,35 @@ describe('AdminPanelService', () => {
|
||||
});
|
||||
|
||||
describe('getEnvironmentVariablesGrouped', () => {
|
||||
it('should correctly group environment variables', () => {
|
||||
it('should correctly group and sort environment variables', () => {
|
||||
EnvironmentServiceGetAllMock.mockReturnValue({
|
||||
VAR_1: {
|
||||
value: 'value1',
|
||||
SERVER_URL: {
|
||||
value: 'http://localhost',
|
||||
metadata: {
|
||||
group: 'GROUP_1',
|
||||
description: 'Description 1',
|
||||
group: 'SERVER_CONFIG',
|
||||
description: 'Server URL',
|
||||
},
|
||||
},
|
||||
VAR_2: {
|
||||
value: 'value2',
|
||||
RATE_LIMIT_TTL: {
|
||||
value: '60',
|
||||
metadata: {
|
||||
group: 'GROUP_1',
|
||||
subGroup: 'SUBGROUP_1',
|
||||
description: 'Description 2',
|
||||
group: 'RATE_LIMITING',
|
||||
description: 'Rate limit TTL',
|
||||
},
|
||||
},
|
||||
API_KEY: {
|
||||
value: 'secret-key',
|
||||
metadata: {
|
||||
group: 'SERVER_CONFIG',
|
||||
description: 'API Key',
|
||||
sensitive: true,
|
||||
},
|
||||
},
|
||||
VAR_3: {
|
||||
value: 'value3',
|
||||
OTHER_VAR: {
|
||||
value: 'other',
|
||||
metadata: {
|
||||
group: 'GROUP_2',
|
||||
description: 'Description 3',
|
||||
group: 'OTHER',
|
||||
description: 'Other var',
|
||||
},
|
||||
},
|
||||
});
|
||||
@ -301,74 +298,56 @@ describe('AdminPanelService', () => {
|
||||
expect(result).toEqual({
|
||||
groups: [
|
||||
{
|
||||
name: 'GROUP_1',
|
||||
description: '',
|
||||
name: 'SERVER_CONFIG',
|
||||
description: 'Server config description',
|
||||
isHiddenOnLoad: false,
|
||||
variables: [
|
||||
{
|
||||
name: 'VAR_1',
|
||||
value: 'value1',
|
||||
description: 'Description 1',
|
||||
sensitive: false,
|
||||
name: 'API_KEY',
|
||||
value: 'secret-key',
|
||||
description: 'API Key',
|
||||
sensitive: true,
|
||||
},
|
||||
],
|
||||
subgroups: [
|
||||
{
|
||||
name: 'SUBGROUP_1',
|
||||
description: '',
|
||||
variables: [
|
||||
{
|
||||
name: 'VAR_2',
|
||||
value: 'value2',
|
||||
description: 'Description 2',
|
||||
sensitive: true,
|
||||
},
|
||||
],
|
||||
name: 'SERVER_URL',
|
||||
value: 'http://localhost',
|
||||
description: 'Server URL',
|
||||
sensitive: false,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'GROUP_2',
|
||||
description: '',
|
||||
name: 'RATE_LIMITING',
|
||||
description: 'Rate limiting description',
|
||||
isHiddenOnLoad: false,
|
||||
variables: [
|
||||
{
|
||||
name: 'VAR_3',
|
||||
value: 'value3',
|
||||
description: 'Description 3',
|
||||
name: 'RATE_LIMIT_TTL',
|
||||
value: '60',
|
||||
description: 'Rate limit TTL',
|
||||
sensitive: false,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'OTHER',
|
||||
description: 'Other description',
|
||||
isHiddenOnLoad: true,
|
||||
variables: [
|
||||
{
|
||||
name: 'OTHER_VAR',
|
||||
value: 'other',
|
||||
description: 'Other var',
|
||||
sensitive: false,
|
||||
},
|
||||
],
|
||||
subgroups: [],
|
||||
},
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
it('should sort groups by position and variables alphabetically', () => {
|
||||
EnvironmentServiceGetAllMock.mockReturnValue({
|
||||
Z_VAR: {
|
||||
value: 'valueZ',
|
||||
metadata: {
|
||||
group: 'GROUP_1',
|
||||
description: 'Description Z',
|
||||
},
|
||||
},
|
||||
A_VAR: {
|
||||
value: 'valueA',
|
||||
metadata: {
|
||||
group: 'GROUP_1',
|
||||
description: 'Description A',
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const result = service.getEnvironmentVariablesGrouped();
|
||||
|
||||
const group = result.groups.find(
|
||||
(g) => g.name === ('GROUP_1' as EnvironmentVariablesGroup),
|
||||
);
|
||||
|
||||
expect(group?.variables[0].name).toBe('A_VAR');
|
||||
expect(group?.variables[1].name).toBe('Z_VAR');
|
||||
expect(result.groups[0].name).toBe('SERVER_CONFIG');
|
||||
expect(result.groups[1].name).toBe('RATE_LIMITING');
|
||||
expect(result.groups[2].name).toBe('OTHER');
|
||||
});
|
||||
|
||||
it('should handle empty environment variables', () => {
|
||||
@ -380,5 +359,25 @@ describe('AdminPanelService', () => {
|
||||
groups: [],
|
||||
});
|
||||
});
|
||||
|
||||
it('should handle variables with undefined metadata fields', () => {
|
||||
EnvironmentServiceGetAllMock.mockReturnValue({
|
||||
TEST_VAR: {
|
||||
value: 'test',
|
||||
metadata: {
|
||||
group: 'SERVER_CONFIG',
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const result = service.getEnvironmentVariablesGrouped();
|
||||
|
||||
expect(result.groups[0].variables[0]).toEqual({
|
||||
name: 'TEST_VAR',
|
||||
value: 'test',
|
||||
description: undefined,
|
||||
sensitive: false,
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@ -12,10 +12,9 @@ import {
|
||||
AuthExceptionCode,
|
||||
} from 'src/engine/core-modules/auth/auth.exception';
|
||||
import { LoginTokenService } from 'src/engine/core-modules/auth/token/services/login-token.service';
|
||||
import { DomainManagerService } from 'src/engine/core-modules/domain-manager/services/domain-manager.service';
|
||||
import { ENVIRONMENT_VARIABLES_GROUP_METADATA } from 'src/engine/core-modules/environment/constants/environment-variables-group-metadata';
|
||||
import { ENVIRONMENT_VARIABLES_SUB_GROUP_METADATA } from 'src/engine/core-modules/environment/constants/environment-variables-sub-group-metadata';
|
||||
import { EnvironmentVariablesGroup } from 'src/engine/core-modules/environment/enums/environment-variables-group.enum';
|
||||
import { EnvironmentVariablesSubGroup } from 'src/engine/core-modules/environment/enums/environment-variables-sub-group.enum';
|
||||
import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service';
|
||||
import { FeatureFlagKey } from 'src/engine/core-modules/feature-flag/enums/feature-flag-key.enum';
|
||||
import { FeatureFlag } from 'src/engine/core-modules/feature-flag/feature-flag.entity';
|
||||
@ -28,7 +27,6 @@ import { User } from 'src/engine/core-modules/user/user.entity';
|
||||
import { userValidator } from 'src/engine/core-modules/user/user.validate';
|
||||
import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity';
|
||||
import { workspaceValidator } from 'src/engine/core-modules/workspace/workspace.validate';
|
||||
import { DomainManagerService } from 'src/engine/core-modules/domain-manager/services/domain-manager.service';
|
||||
|
||||
@Injectable()
|
||||
export class AdminPanelService {
|
||||
@ -175,14 +173,11 @@ export class AdminPanelService {
|
||||
const rawEnvVars = this.environmentService.getAll();
|
||||
const groupedData = new Map<
|
||||
EnvironmentVariablesGroup,
|
||||
{
|
||||
variables: EnvironmentVariable[];
|
||||
subgroups: Map<EnvironmentVariablesSubGroup, EnvironmentVariable[]>;
|
||||
}
|
||||
EnvironmentVariable[]
|
||||
>();
|
||||
|
||||
for (const [varName, { value, metadata }] of Object.entries(rawEnvVars)) {
|
||||
const { group, subGroup, description } = metadata;
|
||||
const { group, description } = metadata;
|
||||
|
||||
const envVar: EnvironmentVariable = {
|
||||
name: varName,
|
||||
@ -191,27 +186,11 @@ export class AdminPanelService {
|
||||
sensitive: metadata.sensitive ?? false,
|
||||
};
|
||||
|
||||
let currentGroup = groupedData.get(group);
|
||||
|
||||
if (!currentGroup) {
|
||||
currentGroup = {
|
||||
variables: [],
|
||||
subgroups: new Map(),
|
||||
};
|
||||
groupedData.set(group, currentGroup);
|
||||
if (!groupedData.has(group)) {
|
||||
groupedData.set(group, []);
|
||||
}
|
||||
|
||||
if (subGroup) {
|
||||
let subgroupVars = currentGroup.subgroups.get(subGroup);
|
||||
|
||||
if (!subgroupVars) {
|
||||
subgroupVars = [];
|
||||
currentGroup.subgroups.set(subGroup, subgroupVars);
|
||||
}
|
||||
subgroupVars.push(envVar);
|
||||
} else {
|
||||
currentGroup.variables.push(envVar);
|
||||
}
|
||||
groupedData.get(group)?.push(envVar);
|
||||
}
|
||||
|
||||
const groups: EnvironmentVariablesGroupData[] = Array.from(
|
||||
@ -223,20 +202,12 @@ export class AdminPanelService {
|
||||
|
||||
return positionA - positionB;
|
||||
})
|
||||
.map(([name, data]) => ({
|
||||
.map(([name, variables]) => ({
|
||||
name,
|
||||
description: ENVIRONMENT_VARIABLES_GROUP_METADATA[name].description,
|
||||
isHiddenOnLoad:
|
||||
ENVIRONMENT_VARIABLES_GROUP_METADATA[name].isHiddenOnLoad,
|
||||
variables: data.variables.sort((a, b) => a.name.localeCompare(b.name)),
|
||||
subgroups: Array.from(data.subgroups.entries())
|
||||
.sort((a, b) => a[0].localeCompare(b[0]))
|
||||
.map(([name, variables]) => ({
|
||||
name,
|
||||
description:
|
||||
ENVIRONMENT_VARIABLES_SUB_GROUP_METADATA[name].description,
|
||||
variables,
|
||||
})),
|
||||
variables: variables.sort((a, b) => a.name.localeCompare(b.name)),
|
||||
}));
|
||||
|
||||
return { groups };
|
||||
|
||||
@ -3,7 +3,6 @@ import { Field, ObjectType, registerEnumType } from '@nestjs/graphql';
|
||||
import { EnvironmentVariablesGroup } from 'src/engine/core-modules/environment/enums/environment-variables-group.enum';
|
||||
|
||||
import { EnvironmentVariable } from './environment-variable.dto';
|
||||
import { EnvironmentVariablesSubgroupData } from './environment-variables-subgroup.dto';
|
||||
|
||||
registerEnumType(EnvironmentVariablesGroup, {
|
||||
name: 'EnvironmentVariablesGroup',
|
||||
@ -14,9 +13,6 @@ export class EnvironmentVariablesGroupData {
|
||||
@Field(() => [EnvironmentVariable])
|
||||
variables: EnvironmentVariable[];
|
||||
|
||||
@Field(() => [EnvironmentVariablesSubgroupData])
|
||||
subgroups: EnvironmentVariablesSubgroupData[];
|
||||
|
||||
@Field(() => EnvironmentVariablesGroup)
|
||||
name: EnvironmentVariablesGroup;
|
||||
|
||||
|
||||
@ -1,21 +0,0 @@
|
||||
import { Field, ObjectType, registerEnumType } from '@nestjs/graphql';
|
||||
|
||||
import { EnvironmentVariablesSubGroup } from 'src/engine/core-modules/environment/enums/environment-variables-sub-group.enum';
|
||||
|
||||
import { EnvironmentVariable } from './environment-variable.dto';
|
||||
|
||||
registerEnumType(EnvironmentVariablesSubGroup, {
|
||||
name: 'EnvironmentVariablesSubGroup',
|
||||
});
|
||||
|
||||
@ObjectType()
|
||||
export class EnvironmentVariablesSubgroupData {
|
||||
@Field(() => [EnvironmentVariable])
|
||||
variables: EnvironmentVariable[];
|
||||
|
||||
@Field(() => EnvironmentVariablesSubGroup)
|
||||
name: EnvironmentVariablesSubGroup;
|
||||
|
||||
@Field(() => String, { defaultValue: '' })
|
||||
description: string;
|
||||
}
|
||||
Reference in New Issue
Block a user