feat(app-config): persist relational virtual attrs

This commit is contained in:
Ali BARIN
2024-10-07 09:11:55 +00:00
committed by Faruk AYDIN
parent ecb04b4ba9
commit f5d796ea77
4 changed files with 94 additions and 21 deletions

View File

@@ -2,6 +2,7 @@ import AES from 'crypto-js/aes.js';
import enc from 'crypto-js/enc-utf8.js';
import appConfig from '../config/app.js';
import Base from './base.js';
import AppConfig from './app-config.js';
class AppAuthClient extends Base {
static tableName = 'app_auth_clients';
@@ -21,6 +22,17 @@ class AppAuthClient extends Base {
},
};
static relationMappings = () => ({
appConfig: {
relation: Base.HasOneRelation,
modelClass: AppConfig,
join: {
from: 'app_auth_clients.app_key',
to: 'app_configs.key',
},
},
});
encryptData() {
if (!this.eligibleForEncryption()) return;
@@ -48,6 +60,12 @@ class AppAuthClient extends Base {
return this.authDefaults ? true : false;
}
async triggerAppConfigUpdate() {
const appConfig = await this.$relatedQuery('appConfig').select('*');
await appConfig.$query().patch({});
}
// TODO: Make another abstraction like beforeSave instead of using
// beforeInsert and beforeUpdate separately for the same operation.
async $beforeInsert(queryContext) {
@@ -55,11 +73,23 @@ class AppAuthClient extends Base {
this.encryptData();
}
async $afterInsert(queryContext) {
await super.$afterInsert(queryContext);
await this.triggerAppConfigUpdate();
}
async $beforeUpdate(opt, queryContext) {
await super.$beforeUpdate(opt, queryContext);
this.encryptData();
}
async $afterUpdate(queryContext) {
await super.$afterUpdate(queryContext);
await this.triggerAppConfigUpdate();
}
async $afterFind() {
this.decryptData();
}

View File

@@ -12,6 +12,7 @@ class AppConfig extends Base {
properties: {
id: { type: 'string', format: 'uuid' },
key: { type: 'string' },
canConnect: { type: 'boolean', default: false },
allowCustomConnection: { type: 'boolean', default: false },
shared: { type: 'boolean', default: false },
disabled: { type: 'boolean', default: false },
@@ -32,30 +33,39 @@ class AppConfig extends Base {
});
static get virtualAttributes() {
return ['canConnect', 'canCustomConnect'];
return ['canCustomConnect'];
}
get canCustomConnect() {
return !this.disabled && this.allowCustomConnection;
}
get canConnect() {
const hasSomeActiveAppAuthClients = !!this.appAuthClients?.some(
(appAuthClient) => appAuthClient.active
);
const shared = this.shared;
const active = this.disabled === false;
const conditions = [hasSomeActiveAppAuthClients, shared, active];
return conditions.every(Boolean);
}
async getApp() {
if (!this.key) return null;
return await App.findOneByKey(this.key);
}
async updateCanConnectValue() {
const appAuthClients = await this.$relatedQuery('appAuthClients');
const hasSomeActiveAppAuthClients = !!appAuthClients?.some(
(appAuthClient) => appAuthClient.active
);
const shared = this.shared;
const active = this.disabled === false;
const conditions = [hasSomeActiveAppAuthClients, shared, active];
this.canConnect = conditions.every(Boolean);
return this;
}
async $beforeUpdate(opt, queryContext) {
await super.$beforeUpdate(opt, queryContext);
await opt.old.updateCanConnectValue();
}
}
export default AppConfig;

View File

@@ -36,14 +36,6 @@ describe('AppConfig model', () => {
expect(AppConfig.virtualAttributes).toMatchSnapshot();
});
it('getApp should return associated application', async () => {
const appConfig = await createAppConfig({ key: 'deepl' });
const app = await appConfig.getApp();
expect(app.key).toBe('deepl');
});
describe('canCustomConnect', () => {
it('should return true when app is enabled and allows custom connection', async () => {
const appConfig = await createAppConfig({
@@ -112,4 +104,12 @@ describe('AppConfig model', () => {
expect(appConfig.canConnect).toBe(false);
});
});
it('getApp should return associated application', async () => {
const appConfig = await createAppConfig({ key: 'deepl' });
const app = await appConfig.getApp();
expect(app.key).toBe('deepl');
});
});