github.com/thomasobenaus/nomad@v0.11.1/ui/app/abilities/job.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, or, not } from '@ember/object/computed';
     5  
     6  export default Ability.extend({
     7    system: service(),
     8    token: service(),
     9  
    10    canRun: or('bypassAuthorization', 'selfTokenIsManagement', 'policiesSupportRunning'),
    11  
    12    bypassAuthorization: not('token.aclEnabled'),
    13    selfTokenIsManagement: equal('token.selfToken.type', 'management'),
    14  
    15    activeNamespace: computed('system.activeNamespace.name', function() {
    16      return this.get('system.activeNamespace.name') || 'default';
    17    }),
    18  
    19    rulesForActiveNamespace: computed('activeNamespace', 'token.selfTokenPolicies.[]', function() {
    20      let activeNamespace = this.activeNamespace;
    21  
    22      return (this.get('token.selfTokenPolicies') || []).toArray().reduce((rules, policy) => {
    23        let policyNamespaces = get(policy, 'rulesJSON.Namespaces') || [];
    24  
    25        let matchingNamespace = this._findMatchingNamespace(policyNamespaces, activeNamespace);
    26  
    27        if (matchingNamespace) {
    28          rules.push(policyNamespaces.find(namespace => namespace.Name === matchingNamespace));
    29        }
    30  
    31        return rules;
    32      }, []);
    33    }),
    34  
    35    policiesSupportRunning: computed('rulesForActiveNamespace.@each.capabilities', function() {
    36      return this.rulesForActiveNamespace.some(rules => {
    37        let capabilities = get(rules, 'Capabilities') || [];
    38        return capabilities.includes('submit-job');
    39      });
    40    }),
    41  
    42    // Chooses the closest namespace as described at the bottom here:
    43    // https://www.nomadproject.io/guides/security/acl.html#namespace-rules
    44    _findMatchingNamespace(policyNamespaces, activeNamespace) {
    45      let namespaceNames = policyNamespaces.mapBy('Name');
    46  
    47      if (namespaceNames.includes(activeNamespace)) {
    48        return activeNamespace;
    49      }
    50  
    51      let globNamespaceNames = namespaceNames.filter(namespaceName => namespaceName.includes('*'));
    52  
    53      let matchingNamespaceName = globNamespaceNames.reduce(
    54        (mostMatching, namespaceName) => {
    55          // Convert * wildcards to .* for regex matching
    56          let namespaceNameRegExp = new RegExp(namespaceName.replace(/\*/g, '.*'));
    57          let characterDifference = activeNamespace.length - namespaceName.length;
    58  
    59          if (
    60            characterDifference < mostMatching.mostMatchingCharacterDifference &&
    61            activeNamespace.match(namespaceNameRegExp)
    62          ) {
    63            return {
    64              mostMatchingNamespaceName: namespaceName,
    65              mostMatchingCharacterDifference: characterDifference,
    66            };
    67          } else {
    68            return mostMatching;
    69          }
    70        },
    71        { mostMatchingNamespaceName: null, mostMatchingCharacterDifference: Number.MAX_SAFE_INTEGER }
    72      ).mostMatchingNamespaceName;
    73  
    74      if (matchingNamespaceName) {
    75        return matchingNamespaceName;
    76      } else if (namespaceNames.includes('default')) {
    77        return 'default';
    78      }
    79    },
    80  });