github.com/Ilhicas/nomad@v1.0.4-0.20210304152020-e86851182bc3/ui/app/abilities/abstract.js (about) 1 import { Ability } from 'ember-can'; 2 import { inject as service } from '@ember/service'; 3 import { computed, get } from '@ember/object'; 4 import { equal, not } from '@ember/object/computed'; 5 import classic from 'ember-classic-decorator'; 6 7 @classic 8 export default class Abstract extends Ability { 9 @service system; 10 @service token; 11 12 @not('token.aclEnabled') bypassAuthorization; 13 @equal('token.selfToken.type', 'management') selfTokenIsManagement; 14 15 @computed('system.activeNamespace.name') 16 get activeNamespace() { 17 return this.get('system.activeNamespace.name') || 'default'; 18 } 19 20 @computed('activeNamespace', 'token.selfTokenPolicies.[]') 21 get rulesForActiveNamespace() { 22 let activeNamespace = this.activeNamespace; 23 24 return (this.get('token.selfTokenPolicies') || []).toArray().reduce((rules, policy) => { 25 let policyNamespaces = get(policy, 'rulesJSON.Namespaces') || []; 26 27 let matchingNamespace = this._findMatchingNamespace(policyNamespaces, activeNamespace); 28 29 if (matchingNamespace) { 30 rules.push(policyNamespaces.find(namespace => namespace.Name === matchingNamespace)); 31 } 32 33 return rules; 34 }, []); 35 } 36 37 @computed('token.selfTokenPolicies.[]') 38 get capabilitiesForAllNamespaces() { 39 return (this.get('token.selfTokenPolicies') || []) 40 .toArray() 41 .reduce((allCapabilities, policy) => { 42 (get(policy, 'rulesJSON.Namespaces') || []).forEach(({ Capabilities }) => { 43 allCapabilities = allCapabilities.concat(Capabilities); 44 }); 45 return allCapabilities; 46 }, []); 47 } 48 49 activeNamespaceIncludesCapability(capability) { 50 return this.rulesForActiveNamespace.some(rules => { 51 let capabilities = get(rules, 'Capabilities') || []; 52 return capabilities.includes(capability); 53 }); 54 } 55 56 @computed('system.features.[]') 57 get features() { 58 return this.system.features; 59 } 60 61 featureIsPresent(featureName) { 62 return this.features.includes(featureName); 63 } 64 65 // Chooses the closest namespace as described at the bottom here: 66 // https://learn.hashicorp.com/tutorials/nomad/access-control-policies?in=nomad/access-control#namespace-rules 67 _findMatchingNamespace(policyNamespaces, activeNamespace) { 68 let namespaceNames = policyNamespaces.mapBy('Name'); 69 70 if (namespaceNames.includes(activeNamespace)) { 71 return activeNamespace; 72 } 73 74 let globNamespaceNames = namespaceNames.filter(namespaceName => namespaceName.includes('*')); 75 76 let matchingNamespaceName = globNamespaceNames.reduce( 77 (mostMatching, namespaceName) => { 78 // Convert * wildcards to .* for regex matching 79 let namespaceNameRegExp = new RegExp(namespaceName.replace(/\*/g, '.*')); 80 let characterDifference = activeNamespace.length - namespaceName.length; 81 82 if ( 83 characterDifference < mostMatching.mostMatchingCharacterDifference && 84 activeNamespace.match(namespaceNameRegExp) 85 ) { 86 return { 87 mostMatchingNamespaceName: namespaceName, 88 mostMatchingCharacterDifference: characterDifference, 89 }; 90 } else { 91 return mostMatching; 92 } 93 }, 94 { mostMatchingNamespaceName: null, mostMatchingCharacterDifference: Number.MAX_SAFE_INTEGER } 95 ).mostMatchingNamespaceName; 96 97 if (matchingNamespaceName) { 98 return matchingNamespaceName; 99 } else if (namespaceNames.includes('default')) { 100 return 'default'; 101 } 102 } 103 }