feat(app-config): persist relational virtual attrs
This commit is contained in:
@@ -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();
|
||||
}
|
||||
|
@@ -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;
|
||||
|
@@ -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');
|
||||
});
|
||||
});
|
||||
|
Reference in New Issue
Block a user