<commit_before>/**
 * @license
 * Copyright 2020 The FOAM Authors. All Rights Reserved.
 * http://www.apache.org/licenses/LICENSE-2.0
 */
foam.CLASS({
  package: 'foam.u2.crunch',
  name: 'CrunchController',
  documentation: `
    Defines behaviour for invocation of CRUNCH-related views.
  `,

  implements: [
    'foam.mlang.Expressions'
  ],

  imports: [
    'capabilityDAO',
    'crunchService',
    'ctrl',
    'prerequisiteCapabilityJunctionDAO',
    'stack',
    'subject',
    'userCapabilityJunctionDAO'
  ],

  requires: [
    'foam.log.LogLevel',
    'foam.nanos.crunch.AgentCapabilityJunction',
    'foam.nanos.crunch.Capability',
    'foam.nanos.crunch.CapabilityCapabilityJunction',
    'foam.nanos.crunch.CapabilityJunctionStatus',
    'foam.nanos.crunch.ui.CapabilityWizardlet',
    'foam.nanos.crunch.UserCapabilityJunction',
    'foam.u2.borders.MarginBorder',
    'foam.u2.crunch.CapabilityInterceptView',
    'foam.u2.detail.AbstractSectionedDetailView',
    'foam.u2.dialog.Popup'
  ],

  messages: [
    { name: 'CANNOT_OPEN_GRANTED', message: 'This capability has already been granted to you.' },
    { name: 'CANNOT_OPEN_PENDING', message: 'This capability is awaiting approval, updates are not permitted at this time.' },
    { name: 'CANNOT_OPEN_ACTION_PENDING', message: 'This capability is awaiting review, updates are not permitted at this time.' }
  ],

  properties: [
    {
      name: 'activeIntercepts',
      class: 'Array',
      documentation: `
        Since permissions may be checked during asynchronous calls,
        it is possible that the same intercept view will be requested
        twice in a short period of time. Keeping a map of active
        intercept views is done to prevent two intercept views being
        open for the same permission (as this would be confusing for
        the user if they happen to choose the "cancel" option).

        This also allows a single intercept view to activate the
        message retry for multiple permissioned calls made
        asynchronously.
      `
    }
  ],

  methods: [
    function getCapsAndWizardlets(capabilityId) {
      return this.crunchService.getGrantPath(this.__subContext__, capabilityId).then((capabilities) => {
        return Promise.all([
          Promise.resolve(capabilities),
          Promise.all(capabilities
            .filter(cap => !! cap.of )
            .map(cap => {
                var associatedEntity = cap.associatedEntity === foam.nanos.crunch.AssociatedEntity.USER ? this.subject.user : this.subject.realUser;
                var wizardlet = this.CapabilityWizardlet.create({ capability: cap });
                return this.updateUCJ(wizardlet, associatedEntity);
              })
            )
          ]).then((capAndSections) => {
            return {
              caps: capAndSections[0],
              wizCaps: capAndSections[1]
                .filter((wizardSection) =>
                  wizardSection.ucj === null ||
                  (
                    wizardSection.ucj.status != this.CapabilityJunctionStatus.GRANTED &&
                    wizardSection.ucj.status != this.CapabilityJunctionStatus.PENDING
                  ))
            };
          });
      });
    },

    function generateSections(generatedWizardlets) {
      return generatedWizardlets.map(wizardlet =>
        this.AbstractSectionedDetailView.create({
          of: wizardlet.of
        }).sections);
    },

    function generateAndDisplayWizard(capabilitiesSections) {
      // called in CapabilityRequirementView
      return ctrl.add(this.Popup.create({ closeable: false }).tag({
        class: 'foam.u2.wizard.StepWizardletView',
        data: foam.u2.wizard.StepWizardletController.create({
          wizardlets: capabilitiesSections.wizCaps
        }),
        onClose: (x) => {
          this.finalOnClose(x, capabilitiesSections.caps);
        }
      }));
    },

    async function startWizardFlow(capabilityId, toLaunchOrNot) {
      return this.getCapsAndWizardlets(capabilityId)
        .then((capabilitiesSections) => {
          // generate and popUp summary view (CapabilityRequirmentView) before wizard
          return this.onStartShowPopRequirements(capabilityId, capabilitiesSections, toLaunchOrNot);
        });
    },

    function finalOnClose(x, capabilities) {
      return new Promise((wizardResolve) => {
        x.closeDialog();
        // Save no-data capabilities (i.e. not displayed in wizard)
        Promise.all(capabilities.filter(cap => ! cap.of).map(
          cap => this.userCapabilityJunctionDAO.put(this.UserCapabilityJunction.create({
            sourceId: this.subject.user.id,
            targetId: cap.id
          })).then(() => {
            console.log('SAVED (no-data cap)', cap.id);
          })
        )).then(() => {
          wizardResolve();
        });
      });
    },

    async function launchWizard(capability) {
      if ( typeof capability == 'string' ) capability = await this.capabilityDAO.find(capability);<commit_msg>fix no-data cap not added multiple times<commit_after>/**
 * @license
 * Copyright 2020 The FOAM Authors. All Rights Reserved.
 * http://www.apache.org/licenses/LICENSE-2.0
 */
foam.CLASS({
  package: 'foam.u2.crunch',
  name: 'CrunchController',
  documentation: `
    Defines behaviour for invocation of CRUNCH-related views.
  `,

  implements: [
    'foam.mlang.Expressions'
  ],

  imports: [
    'capabilityDAO',
    'crunchService',
    'ctrl',
    'prerequisiteCapabilityJunctionDAO',
    'stack',
    'subject',
    'userCapabilityJunctionDAO'
  ],

  requires: [
    'foam.log.LogLevel',
    'foam.nanos.crunch.AgentCapabilityJunction',
    'foam.nanos.crunch.Capability',
    'foam.nanos.crunch.CapabilityCapabilityJunction',
    'foam.nanos.crunch.CapabilityJunctionStatus',
    'foam.nanos.crunch.ui.CapabilityWizardlet',
    'foam.nanos.crunch.UserCapabilityJunction',
    'foam.u2.borders.MarginBorder',
    'foam.u2.crunch.CapabilityInterceptView',
    'foam.u2.detail.AbstractSectionedDetailView',
    'foam.u2.dialog.Popup'
  ],

  messages: [
    { name: 'CANNOT_OPEN_GRANTED', message: 'This capability has already been granted to you.' },
    { name: 'CANNOT_OPEN_PENDING', message: 'This capability is awaiting approval, updates are not permitted at this time.' },
    { name: 'CANNOT_OPEN_ACTION_PENDING', message: 'This capability is awaiting review, updates are not permitted at this time.' }
  ],

  properties: [
    {
      name: 'activeIntercepts',
      class: 'Array',
      documentation: `
        Since permissions may be checked during asynchronous calls,
        it is possible that the same intercept view will be requested
        twice in a short period of time. Keeping a map of active
        intercept views is done to prevent two intercept views being
        open for the same permission (as this would be confusing for
        the user if they happen to choose the "cancel" option).

        This also allows a single intercept view to activate the
        message retry for multiple permissioned calls made
        asynchronously.
      `
    }
  ],

  methods: [
    function getCapsAndWizardlets(capabilityId) {
      return this.crunchService.getGrantPath(this.__subContext__, capabilityId).then((capabilities) => {
        return Promise.all([
          Promise.resolve(capabilities),
          Promise.all(capabilities
            .filter(cap => !! cap.of )
            .map(cap => {
                var associatedEntity = cap.associatedEntity === foam.nanos.crunch.AssociatedEntity.USER ? this.subject.user : this.subject.realUser;
                var wizardlet = this.CapabilityWizardlet.create({ capability: cap });
                return this.updateUCJ(wizardlet, associatedEntity);
              })
            )
          ]).then((capAndSections) => {
            return {
              caps: capAndSections[0],
              wizCaps: capAndSections[1]
                .filter((wizardSection) =>
                  wizardSection.ucj === null ||
                  (
                    wizardSection.ucj.status != this.CapabilityJunctionStatus.GRANTED &&
                    wizardSection.ucj.status != this.CapabilityJunctionStatus.PENDING
                  ))
            };
          });
      });
    },

    function generateSections(generatedWizardlets) {
      return generatedWizardlets.map(wizardlet =>
        this.AbstractSectionedDetailView.create({
          of: wizardlet.of
        }).sections);
    },

    function generateAndDisplayWizard(capabilitiesSections) {
      // called in CapabilityRequirementView
      return ctrl.add(this.Popup.create({ closeable: false }).tag({
        class: 'foam.u2.wizard.StepWizardletView',
        data: foam.u2.wizard.StepWizardletController.create({
          wizardlets: capabilitiesSections.wizCaps
        }),
        onClose: (x) => {
          this.finalOnClose(x, capabilitiesSections.caps);
        }
      }));
    },

    async function startWizardFlow(capabilityId, toLaunchOrNot) {
      return this.getCapsAndWizardlets(capabilityId)
        .then((capabilitiesSections) => {
          // generate and popUp summary view (CapabilityRequirmentView) before wizard
          return this.onStartShowPopRequirements(capabilityId, capabilitiesSections, toLaunchOrNot);
        });
    },

    function finalOnClose(x, capabilities) {
      return new Promise((wizardResolve) => {
        x.closeDialog();
        // Save no-data capabilities (i.e. not displayed in wizard)
        Promise.all(capabilities.filter(cap => ! cap.of).map(
          cap => {
            var associatedEntity = cap.associatedEntity === foam.nanos.crunch.AssociatedEntity.USER ? this.subject.user : this.subject.realUser;
            this.userCapabilityJunctionDAO.find(
              this.AND(
                this.OR(
                  this.AND(
                    this.NOT(this.INSTANCE_OF(this.AgentCapabilityJunction)),
                    this.EQ(this.UserCapabilityJunction.SOURCE_ID, associatedEntity.id)
                  ),
                  this.AND(
                    this.INSTANCE_OF(this.AgentCapabilityJunction),
                    this.EQ(this.UserCapabilityJunction.SOURCE_ID, associatedEntity.id),
                    this.EQ(this.AgentCapabilityJunction.EFFECTIVE_USER, this.subject.user.id)
                  )
                ),
                this.EQ(this.UserCapabilityJunction.TARGET_ID, cap.id))
            ).then((ucj) => {
              if ( ucj == null ) {
                ucj = this.UserCapabilityJunction.create({
                  sourceId: associatedEntity.id,
                  targetId: cap.id
                });
              }
              this.userCapabilityJunctionDAO.put(ucj).then(() => console.log('SAVED (no-data cap)', cap.id));
            });
          }
        )).then(() => {
          wizardResolve();
        });
      });
    },

    async function launchWizard(capability) {
      if ( typeof capability == 'string' ) capability = await this.capabilityDAO.find(capability);
{'fraction_non_alphanumeric': 0.10736613210111444, 'fraction_numerical': 0.002718129926610492, 'mean_word_length': 2.352976913730255, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 30, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3938655', 'n_tokens_mistral': 3187, 'n_tokens_neox': 3112, 'n_words': 633}