fix: secret handling and relation naming logic

Implemented improved handling for secrets in `DbModuleManager`, allowing secret merging and building before saving. Enhanced `ManyToManyRelation` naming to produce valid identifiers and ensured better testing coverage for both changes.
This commit is contained in:
dswbx
2025-09-18 09:47:47 +02:00
parent 9aae6e78d6
commit 8c4a8d91a2
4 changed files with 106 additions and 6 deletions

View File

@@ -4,8 +4,10 @@ import {
type BaseRelationConfig,
EntityRelation,
EntityRelationAnchor,
ManyToManyRelation,
RelationTypes,
} from "data/relations";
import * as proto from "data/prototype";
class TestEntityRelation extends EntityRelation {
constructor(config?: BaseRelationConfig) {
@@ -75,4 +77,15 @@ describe("[data] EntityRelation", async () => {
const relation2 = new TestEntityRelation({ required: true });
expect(relation2.required).toBe(true);
});
it("correctly produces the relation name", async () => {
const relation = new ManyToManyRelation(new Entity("apps"), new Entity("organizations"));
expect(relation.getName()).not.toContain(",");
expect(relation.getName()).toBe("mn_apps_organizations");
const relation2 = new ManyToManyRelation(new Entity("apps"), new Entity("organizations"), {
connectionTableMappedName: "appOrganizations",
});
expect(relation2.getName()).toBe("mn_apps_organizations_appOrganizations");
});
});

View File

@@ -1,6 +1,7 @@
import { it, expect, describe } from "bun:test";
import { DbModuleManager } from "modules/db/DbModuleManager";
import { getDummyConnection } from "../helper";
import { TABLE_NAME } from "modules/db/migrations";
describe("DbModuleManager", () => {
it("should extract secrets", async () => {
@@ -19,4 +20,57 @@ describe("DbModuleManager", () => {
expect(m.toJSON(true).auth.jwt.secret).toBe("test");
await m.save();
});
it("should work with initial secrets", async () => {
const { dummyConnection } = getDummyConnection(false);
const db = dummyConnection.kysely;
const m = new DbModuleManager(dummyConnection, {
initial: {
auth: {
enabled: true,
jwt: {
secret: "",
},
},
},
secrets: {
"auth.jwt.secret": "test",
},
});
await m.build();
expect(m.toJSON(true).auth.jwt.secret).toBe("test");
const getSecrets = () =>
db
.selectFrom(TABLE_NAME)
.selectAll()
.where("type", "=", "secrets")
.executeTakeFirst()
.then((r) => r?.json);
expect(await getSecrets()).toEqual({ "auth.jwt.secret": "test" });
// also after rebuild
await m.build();
await m.save();
expect(await getSecrets()).toEqual({ "auth.jwt.secret": "test" });
// and ignore if already present
const m2 = new DbModuleManager(dummyConnection, {
initial: {
auth: {
enabled: true,
jwt: {
secret: "",
},
},
},
secrets: {
"auth.jwt.secret": "something completely different",
},
});
await m2.build();
await m2.save();
expect(await getSecrets()).toEqual({ "auth.jwt.secret": "test" });
});
});

View File

@@ -180,8 +180,15 @@ export class ManyToManyRelation extends EntityRelation<typeof ManyToManyRelation
override getName(): string {
return [
super.getName(),
[this.connectionEntity.name, this.connectionTableMappedName].filter(Boolean),
...Array.from(
new Set(
[
this.type().replace(":", ""),
this.connectionEntity.name,
this.connectionTableMappedName,
].filter(Boolean),
),
),
].join("_");
}
}

View File

@@ -157,12 +157,12 @@ export class DbModuleManager extends ModuleManager {
this.logger
.log("took", performance.now() - startTime, "ms", {
version: result.version,
id: result.id,
version: configs?.version,
id: configs?.id,
})
.clear();
return { configs, secrets };
return { configs, secrets } as any;
}
async save() {
@@ -202,6 +202,7 @@ export class DbModuleManager extends ModuleManager {
json: configs,
},
];
if (store_secrets) {
updates.push({
version: state.configs.version,
@@ -277,6 +278,15 @@ export class DbModuleManager extends ModuleManager {
created_at: new Date(),
updated_at: new Date(),
});
if (store_secrets) {
await this.mutator().insertOne({
type: "secrets",
version,
json: secrets,
created_at: new Date(),
updated_at: new Date(),
});
}
} else if (e instanceof TransformPersistFailedException) {
$console.error("ModuleManager: Cannot save invalid config");
this.revertModules();
@@ -484,8 +494,24 @@ export class DbModuleManager extends ModuleManager {
this.logger.context("initial").log("start");
this._version = CURRENT_VERSION;
await this.syncConfigTable();
const state = await this.buildModules();
if (!state.saved) {
// in case there are secrets provided, we need to extract the keys and merge them with the configs. Then another build is required.
if (this.options?.secrets) {
const { configs, extractedKeys } = this.extractSecrets();
for (const key of extractedKeys) {
if (key in this.options.secrets) {
setPath(configs, key, this.options.secrets[key]);
}
}
await this.setConfigs(configs);
await this.buildModules();
}
// generally only save if not already done
// unless secrets are provided, then we need to save again
if (!state.saved || this.options?.secrets) {
await this.save();
}