mirror of
https://github.com/shishantbiswas/bknd.git
synced 2026-03-16 04:27:21 +00:00
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:
@@ -4,8 +4,10 @@ import {
|
|||||||
type BaseRelationConfig,
|
type BaseRelationConfig,
|
||||||
EntityRelation,
|
EntityRelation,
|
||||||
EntityRelationAnchor,
|
EntityRelationAnchor,
|
||||||
|
ManyToManyRelation,
|
||||||
RelationTypes,
|
RelationTypes,
|
||||||
} from "data/relations";
|
} from "data/relations";
|
||||||
|
import * as proto from "data/prototype";
|
||||||
|
|
||||||
class TestEntityRelation extends EntityRelation {
|
class TestEntityRelation extends EntityRelation {
|
||||||
constructor(config?: BaseRelationConfig) {
|
constructor(config?: BaseRelationConfig) {
|
||||||
@@ -75,4 +77,15 @@ describe("[data] EntityRelation", async () => {
|
|||||||
const relation2 = new TestEntityRelation({ required: true });
|
const relation2 = new TestEntityRelation({ required: true });
|
||||||
expect(relation2.required).toBe(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");
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { it, expect, describe } from "bun:test";
|
import { it, expect, describe } from "bun:test";
|
||||||
import { DbModuleManager } from "modules/db/DbModuleManager";
|
import { DbModuleManager } from "modules/db/DbModuleManager";
|
||||||
import { getDummyConnection } from "../helper";
|
import { getDummyConnection } from "../helper";
|
||||||
|
import { TABLE_NAME } from "modules/db/migrations";
|
||||||
|
|
||||||
describe("DbModuleManager", () => {
|
describe("DbModuleManager", () => {
|
||||||
it("should extract secrets", async () => {
|
it("should extract secrets", async () => {
|
||||||
@@ -19,4 +20,57 @@ describe("DbModuleManager", () => {
|
|||||||
expect(m.toJSON(true).auth.jwt.secret).toBe("test");
|
expect(m.toJSON(true).auth.jwt.secret).toBe("test");
|
||||||
await m.save();
|
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" });
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -180,8 +180,15 @@ export class ManyToManyRelation extends EntityRelation<typeof ManyToManyRelation
|
|||||||
|
|
||||||
override getName(): string {
|
override getName(): string {
|
||||||
return [
|
return [
|
||||||
super.getName(),
|
...Array.from(
|
||||||
[this.connectionEntity.name, this.connectionTableMappedName].filter(Boolean),
|
new Set(
|
||||||
|
[
|
||||||
|
this.type().replace(":", ""),
|
||||||
|
this.connectionEntity.name,
|
||||||
|
this.connectionTableMappedName,
|
||||||
|
].filter(Boolean),
|
||||||
|
),
|
||||||
|
),
|
||||||
].join("_");
|
].join("_");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -157,12 +157,12 @@ export class DbModuleManager extends ModuleManager {
|
|||||||
|
|
||||||
this.logger
|
this.logger
|
||||||
.log("took", performance.now() - startTime, "ms", {
|
.log("took", performance.now() - startTime, "ms", {
|
||||||
version: result.version,
|
version: configs?.version,
|
||||||
id: result.id,
|
id: configs?.id,
|
||||||
})
|
})
|
||||||
.clear();
|
.clear();
|
||||||
|
|
||||||
return { configs, secrets };
|
return { configs, secrets } as any;
|
||||||
}
|
}
|
||||||
|
|
||||||
async save() {
|
async save() {
|
||||||
@@ -202,6 +202,7 @@ export class DbModuleManager extends ModuleManager {
|
|||||||
json: configs,
|
json: configs,
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
if (store_secrets) {
|
if (store_secrets) {
|
||||||
updates.push({
|
updates.push({
|
||||||
version: state.configs.version,
|
version: state.configs.version,
|
||||||
@@ -277,6 +278,15 @@ export class DbModuleManager extends ModuleManager {
|
|||||||
created_at: new Date(),
|
created_at: new Date(),
|
||||||
updated_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) {
|
} else if (e instanceof TransformPersistFailedException) {
|
||||||
$console.error("ModuleManager: Cannot save invalid config");
|
$console.error("ModuleManager: Cannot save invalid config");
|
||||||
this.revertModules();
|
this.revertModules();
|
||||||
@@ -484,8 +494,24 @@ export class DbModuleManager extends ModuleManager {
|
|||||||
this.logger.context("initial").log("start");
|
this.logger.context("initial").log("start");
|
||||||
this._version = CURRENT_VERSION;
|
this._version = CURRENT_VERSION;
|
||||||
await this.syncConfigTable();
|
await this.syncConfigTable();
|
||||||
|
|
||||||
const state = await this.buildModules();
|
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();
|
await this.save();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user