diff --git a/src/accessControlService.ts b/src/accessControlService.ts index a084c85..386fda6 100644 --- a/src/accessControlService.ts +++ b/src/accessControlService.ts @@ -2,7 +2,7 @@ import _ from 'lodash-es'; import { Server } from '@restorecommerce/chassis-srv'; import { Events } from '@restorecommerce/kafka-client'; import { CommandInterface } from '@restorecommerce/chassis-srv'; -import { ResourceManager } from './resourceManager.js'; +import { ResourceManager, PolicySetService } from './resourceManager.js'; import { RedisClientType } from 'redis'; import { AccessController } from './core/accessController.js'; import { loadPoliciesFromDoc } from './core/utils.js'; @@ -35,22 +35,7 @@ export class AccessControlService implements AccessControlServiceImplementation } async loadPolicies(): Promise { this.logger.info('Loading policies'); - - const policiesCfg = this.cfg.get('policies'); - const loadType = policiesCfg?.type; - switch (loadType) { - case 'local': - const path: string = policiesCfg?.path; - this.accessController = await loadPoliciesFromDoc(this.accessController, path); - this.logger.silly('Policies from local files loaded'); - break; - case 'database': - const policySetService = this.resourceManager.getResourceService('policy_set'); - const policySets: Map = await policySetService.load() || new Map(); - this.accessController.policySets = policySets; - this.logger.silly('Policies from database loaded'); - break; - } + this.accessController.loadPolicies(this.resourceManager); } clearPolicies(): void { diff --git a/src/core/accessController.ts b/src/core/accessController.ts index 3442277..c86e6f5 100644 --- a/src/core/accessController.ts +++ b/src/core/accessController.ts @@ -20,7 +20,8 @@ import { Logger } from 'winston'; import { createClient, RedisClientType } from 'redis'; import { Topic } from '@restorecommerce/kafka-client'; import { verifyACLList } from './verifyACL.js'; -import { conditionMatches } from './utils.js'; +import { conditionMatches, loadPoliciesFromDoc } from './utils.js'; +import { PolicySetService, ResourceManager } from '../resourceManager.js'; export class AccessController { policySets: Map; @@ -75,6 +76,24 @@ export class AccessController { this.userService = userService; } + async loadPolicies(resourceManager: ResourceManager): Promise { + const policiesCfg = this.cfg.get('policies'); + const loadType = policiesCfg?.type; + switch (loadType) { + case 'local': + const path: string = policiesCfg?.path; + await loadPoliciesFromDoc(this, path); + this.logger.silly('Policies from local files loaded'); + break; + case 'database': + const policySetService: PolicySetService = resourceManager.getResourceService('policy_set'); + const policySets: Map = await policySetService.load() || new Map(); + this.policySets = policySets; + this.logger.silly('Policies from database loaded'); + break; + } + } + clearPolicies(): void { this.policySets.clear(); } diff --git a/src/resourceManager.ts b/src/resourceManager.ts index dc30650..8c27e5d 100644 --- a/src/resourceManager.ts +++ b/src/resourceManager.ts @@ -108,6 +108,22 @@ export class RuleService extends ServiceBase impleme return this.getRules(); } + // async reloadRules(result: DeepPartial): Promise { + // const policySets = _.cloneDeep(_accessController.policySets); + // if (result?.items?.length > 0) { + // for (let item of result.items) { + // const rule: Rule = marshallResource(item?.payload, 'rule'); + // for (let [, policySet] of policySets) { + // for (let [, policy] of (policySet).combinables) { + // if (!_.isNil(policy) && policy.combinables.has(rule.id)) { + // _accessController.updateRule(policySet.id, policy.id, rule); + // } + // } + // } + // } + // } + // } + async getRules(ruleIDs?: string[]): Promise> { const filters = ruleIDs ? makeFilter(ruleIDs) : {}; const result = await super.read(ReadRequest.fromPartial({ filters }), {}); @@ -141,20 +157,8 @@ export class RuleService extends ServiceBase impleme async superUpsert(request: RuleList, ctx: any): Promise> { const result = await super.upsert(request, ctx); - const policySets = _.cloneDeep(_accessController.policySets); - - if (result?.items?.length > 0) { - for (let item of result.items) { - const rule: Rule = marshallResource(item?.payload, 'rule'); - for (let [, policySet] of policySets) { - for (let [, policy] of (policySet).combinables) { - if (!_.isNil(policy) && policy.combinables.has(rule.id)) { - _accessController.updateRule(policySet.id, policy.id, rule); - } - } - } - } - } + // const policySets: Map = await policySetService.load() || new Map(); + // this.policySets = policySets; return result; } @@ -185,20 +189,7 @@ export class RuleService extends ServiceBase impleme return { operation_status: acsResponse.operation_status }; } const result = await super.create(request, ctx); - const policySets = _.cloneDeep(_accessController.policySets); - - if (result?.items?.length > 0) { - for (let item of result.items) { - const rule: Rule = marshallResource(item?.payload, 'rule'); - for (let [, policySet] of policySets) { - for (let [, policy] of (policySet).combinables) { - if (!_.isNil(policy) && policy.combinables.has(rule.id)) { - _accessController.updateRule(policySet.id, policy.id, rule); - } - } - } - } - } + await this.reloadRules(result); return result; } @@ -257,6 +248,7 @@ export class RuleService extends ServiceBase impleme return { operation_status: acsResponse.operation_status }; } const result = await super.update(request, ctx); + await this.reloadRules(result); return result; } @@ -285,7 +277,7 @@ export class RuleService extends ServiceBase impleme if (acsResponse.decision != Response_Decision.PERMIT) { return { operation_status: acsResponse.operation_status }; } - const result = await super.upsert(request, ctx); + const result = await this.superUpsert(request, ctx); return result; } @@ -390,32 +382,35 @@ export class PolicyService extends ServiceBase i return this.getPolicies(); } + // async reloadPolicies(result: DeepPartial): Promise { + // const policySets = _.cloneDeep(_accessController.policySets); + // if (result?.items?.length > 0) { + // for (let item of result.items) { + // for (let [, policySet] of policySets) { + // if (policySet.combinables.has(item.payload?.id)) { + // const policy: PolicyWithCombinables = marshallResource(item.payload, 'policy'); + + // if (_.has(item.payload, 'rules') && !_.isEmpty(item.payload.rules)) { + // policy.combinables = await ruleService.getRules(item.payload.rules); + + // if (policy.combinables.size != item?.payload?.rules?.length) { + // for (let id of item.payload.rules) { + // if (!policy.combinables.has(id)) { + // policy.combinables.set(id, null); + // } + // } + // } + // } + // _accessController.updatePolicy(policySet.id, policy); + // } + // } + // } + // } + // } + async superUpsert(request: PolicyList, ctx: any): Promise> { const result = await super.upsert(request, ctx); - const policySets = _.cloneDeep(_accessController.policySets); - - if (result?.items?.length > 0) { - for (let item of result.items) { - for (let [, policySet] of policySets) { - if (policySet.combinables.has(item.payload?.id)) { - const policy: PolicyWithCombinables = marshallResource(item.payload, 'policy'); - - if (_.has(item.payload, 'rules') && !_.isEmpty(item.payload.rules)) { - policy.combinables = await ruleService.getRules(item.payload.rules); - - if (policy.combinables.size != item?.payload?.rules?.length) { - for (let id of item.payload.rules) { - if (!policy.combinables.has(id)) { - policy.combinables.set(id, null); - } - } - } - } - _accessController.updatePolicy(policySet.id, policy); - } - } - } - } + await _accessController.loadPolicies(); return result; } @@ -445,30 +440,7 @@ export class PolicyService extends ServiceBase i return { operation_status: acsResponse.operation_status }; } const result = await super.create(request, ctx); - const policySets = _.cloneDeep(_accessController.policySets); - - if (result?.items?.length > 0) { - for (let item of result.items) { - for (let [, policySet] of policySets) { - if (policySet.combinables.has(item.payload?.id)) { - const policy: PolicyWithCombinables = marshallResource(item.payload, 'policy'); - - if (_.has(item.payload, 'rules') && !_.isEmpty(item.payload.rules)) { - policy.combinables = await ruleService.getRules(item.payload.rules); - - if (policy.combinables.size != item?.payload?.rules?.length) { - for (let id of item.payload.rules) { - if (!policy.combinables.has(id)) { - policy.combinables.set(id, null); - } - } - } - } - _accessController.updatePolicy(policySet.id, policy); - } - } - } - } + await this.reloadPolicies(result); return result; } @@ -541,6 +513,7 @@ export class PolicyService extends ServiceBase i return { operation_status: acsResponse.operation_status }; } const result = await super.update(request, ctx); + await this.reloadPolicies(result); return result; } @@ -569,7 +542,7 @@ export class PolicyService extends ServiceBase i if (acsResponse.decision != Response_Decision.PERMIT) { return { operation_status: acsResponse.operation_status }; } - const result = await super.upsert(request, ctx); + const result = await this.superUpsert(request, ctx); return result; } @@ -985,7 +958,7 @@ export class PolicySetService extends ServiceBase => { - if (acsEvents.indexOf(eventName) > -1) { - await accessControlService.loadPolicies(); - } else if (eventName === hierarchicalScopesResponse) { + if (eventName === hierarchicalScopesResponse) { // Add subject_id to waiting list const hierarchical_scopes = msg?.hierarchical_scopes ? msg.hierarchical_scopes : []; const tokenDate = msg?.token;