Skip to content

Commit

Permalink
fix: removed migration for configurable enums (#1986)
Browse files Browse the repository at this point in the history
Co-authored-by: Sebastian <sebastian@aam-digital.com>
  • Loading branch information
TheSlimvReal and sleidig committed Aug 25, 2023
1 parent b67daa6 commit 796eea9
Show file tree
Hide file tree
Showing 3 changed files with 3 additions and 147 deletions.
87 changes: 1 addition & 86 deletions src/app/core/config/config.service.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,36 +4,21 @@ import { EntityMapperService } from "../entity/entity-mapper/entity-mapper.servi
import { Config } from "./config";
import { firstValueFrom, Subject } from "rxjs";
import { UpdatedEntity } from "../entity/model/entity-update";
import { ConfigurableEnum } from "../basic-datatypes/configurable-enum/configurable-enum";
import { EntityAbility } from "../permissions/ability/entity-ability";
import { MockedTestingModule } from "../../utils/mocked-testing.module";

describe("ConfigService", () => {
let service: ConfigService;
let entityMapper: jasmine.SpyObj<EntityMapperService>;
const updateSubject = new Subject<UpdatedEntity<Config>>();

beforeEach(waitForAsync(() => {
entityMapper = jasmine.createSpyObj([
"load",
"save",
"receiveUpdates",
"saveAll",
"loadType",
]);
entityMapper = jasmine.createSpyObj(["load", "save", "receiveUpdates"]);
entityMapper.receiveUpdates.and.returnValue(updateSubject);
entityMapper.load.and.rejectWith();
entityMapper.loadType.and.resolveTo([]);
entityMapper.saveAll.and.resolveTo([]);
entityMapper.save.and.resolveTo([]);
TestBed.configureTestingModule({
imports: [MockedTestingModule],
providers: [{ provide: EntityMapperService, useValue: entityMapper }],
});
service = TestBed.inject(ConfigService);
TestBed.inject(EntityAbility).update([
{ subject: "all", action: "manage" },
]);
}));

it("should be created", () => {
Expand Down Expand Up @@ -61,7 +46,6 @@ describe("ConfigService", () => {

const testConfig = new Config();
testConfig.data = { testKey: "testValue" };
console.log("calling next");
updateSubject.next({ type: "new", entity: testConfig });
tick();

Expand Down Expand Up @@ -114,73 +98,4 @@ describe("ConfigService", () => {
const result = service.exportConfig();
expect(result).toEqual(expected);
}));

it("should save enum configs to db it they dont exist yet", async () => {
entityMapper.saveAll.and.resolveTo();
const data = {
"enum:1": [{ id: "some_id", label: "Some Label" }],
"enum:two": [],
"some:other": {},
};
const enum1 = new ConfigurableEnum("1");
enum1.values = data["enum:1"];
const enumTwo = new ConfigurableEnum("two");
enumTwo.values = [];

await initConfig(data);

expect(entityMapper.saveAll).toHaveBeenCalledWith([enum1, enumTwo]);
const config = entityMapper.save.calls.mostRecent().args[0] as Config;
expect(config.data).toEqual({ "some:other": {} });
});

it("should not fail config initialization if changed config cannot be saved", async () => {
entityMapper.saveAll.and.rejectWith();
let configUpdate: Config;
service.configUpdates.subscribe((config) => (configUpdate = config));

await expectAsync(initConfig({ some: "config" })).toBeResolved();

expect(service.getConfig("some")).toBe("config");
expect(configUpdate.data).toEqual({ some: "config" });
});

it("should not save enums that already exist in db", async () => {
entityMapper.loadType.and.resolveTo([new ConfigurableEnum("1")]);
entityMapper.save.and.resolveTo();

await initConfig({ "enum:1": [], "enum:2": [], some: "config" });

expect(entityMapper.saveAll).toHaveBeenCalledWith([
new ConfigurableEnum("2"),
]);
expect(entityMapper.save).toHaveBeenCalledWith(jasmine.any(Config));
expect(service.getConfig("enum:1")).toBeUndefined();
expect(service.getConfig("some")).toBe("config");
});

it("should not save config if nothing has been changed", async () => {
await initConfig({ some: "config", other: "config" });

expect(entityMapper.save).not.toHaveBeenCalled();
expect(entityMapper.saveAll).not.toHaveBeenCalled();
});

it("should not save config if permissions prevent it", async () => {
// user can only read config
TestBed.inject(EntityAbility).update([
{ subject: "Config", action: "read" },
]);

await initConfig({ "enum:1": [], other: "config" });

expect(entityMapper.save).not.toHaveBeenCalled();
});

function initConfig(data) {
const config = new Config();
config.data = data;
entityMapper.load.and.resolveTo(config);
return service.loadConfig();
}
});
60 changes: 2 additions & 58 deletions src/app/core/config/config.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,7 @@ import { Injectable } from "@angular/core";
import { EntityMapperService } from "../entity/entity-mapper/entity-mapper.service";
import { Config } from "./config";
import { Observable, ReplaySubject } from "rxjs";
import { CONFIGURABLE_ENUM_CONFIG_PREFIX } from "../basic-datatypes/configurable-enum/configurable-enum.interface";
import { filter } from "rxjs/operators";
import { LoggingService } from "../logging/logging.service";
import { ConfigurableEnum } from "../basic-datatypes/configurable-enum/configurable-enum";
import { EntityAbility } from "../permissions/ability/entity-ability";

/**
* Access dynamic app configuration retrieved from the database
Expand All @@ -24,11 +20,7 @@ export class ConfigService {
return this._configUpdates.asObservable();
}

constructor(
private entityMapper: EntityMapperService,
private logger: LoggingService,
private ability: EntityAbility,
) {
constructor(private entityMapper: EntityMapperService) {
this.loadConfig();
this.entityMapper
.receiveUpdates(Config)
Expand All @@ -43,9 +35,8 @@ export class ConfigService {
.catch(() => {});
}

private async updateConfigIfChanged(config: Config) {
private updateConfigIfChanged(config: Config) {
if (!this.currentConfig || config._rev !== this.currentConfig?._rev) {
await this.detectLegacyConfig(config);
this.currentConfig = config;
this._configUpdates.next(config);
}
Expand Down Expand Up @@ -73,51 +64,4 @@ export class ConfigService {
}
return matchingConfigs;
}

private async detectLegacyConfig(config: Config): Promise<Config> {
// ugly but easy ... could use https://www.npmjs.com/package/jsonpath-plus in future
const configString = JSON.stringify(config);

if (configString.includes("ImportantNotesComponent")) {
this.logger.warn(
"Legacy Config: ImportantNotesComponent found - you should use 'ImportantNotesDashboard' instead",
);
}

await this.migrateEnumsToEntities(config).catch((err) =>
this.logger.error(`ConfigurableEnum migration error: ${err}`),
);

return config;
}

private async migrateEnumsToEntities(config: Config) {
const enumValues = Object.entries(config.data).filter(([key]) =>
key.startsWith(CONFIGURABLE_ENUM_CONFIG_PREFIX),
);
if (enumValues.length === 0) {
return;
}
const existingEnums = await this.entityMapper
.loadType(ConfigurableEnum)
.then((res) => res.map((e) => e.getId()));

const newEnums: ConfigurableEnum[] = [];
enumValues.forEach(([key, value]) => {
const id = key.replace(CONFIGURABLE_ENUM_CONFIG_PREFIX, "");
if (!existingEnums.includes(id)) {
const newEnum = new ConfigurableEnum(id);
newEnum.values = value as any;
newEnums.push(newEnum);
}
delete config.data[key];
});

if (this.ability.can("create", ConfigurableEnum)) {
await this.entityMapper.saveAll(newEnums);
}
if (this.ability.can("update", config)) {
await this.entityMapper.save(config);
}
}
}
3 changes: 0 additions & 3 deletions src/app/core/config/testing-config-service.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { defaultJsonConfig } from "./config-fix";
import { mockEntityMapper } from "../entity/entity-mapper/mock-entity-mapper-service";
import { LoggingService } from "../logging/logging.service";
import { Config } from "./config";
import { ConfigService } from "./config.service";

Expand All @@ -9,7 +8,5 @@ export function createTestingConfigService(
): ConfigService {
return new ConfigService(
mockEntityMapper([new Config(Config.CONFIG_KEY, configsObject)]),
new LoggingService(),
{ can: () => true } as any,
);
}

0 comments on commit 796eea9

Please sign in to comment.