<commit_before>/**
* Copyright (c) Microsoft.  All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

'use strict';

var util = require('util');

var policyClientWorkaround = require('./policyClientWorkaround');
var profile = require('../../../util/profile');
var resourceUtils = require('../resource/resourceUtils');
var utils = require('../../../util/utils');

var $ = utils.getLocaleString;

exports.init = function (cli) {
  var log = cli.output;

  var role = cli.category('role');
  var roleAssignment = role.category('assignment')
      .description($('Commands to manage your role assignment'));

  roleAssignment.command('create [principal] [role] [scope] [resource-group] [resource-type] [resource-name]')
    .description($('create a new role assignment'))
    .option('-p --principal <principal>', $('User or group to assign the role to. Accept the UPN, group name, or object id.'))
    .option('-o --role <role>', $('Role to assign the principals with.'))
    .option('-c --scope <scope>', $('Scope of the role assignment.'))
    .option('-g --resource-group <resource-group>', $('Resource group to assign the role to.'))
    .option('-r --resource-type <resource-type>', $('Type of the resource to assign the role to.'))
    .option('-u --resource-name <resource-name>', $('Name of the resource to assign the role to.'))
    .option('--parent <parent>', $('Parent resource of the resource to assign the role to, if there is any.'))
    .option('--subscription <subscription>', $('Subscription id or name of where the role assignment will be created.'))
    .execute(function (principal, role, scope, resourceGroup, resourceType, resourceName, options, _) {
      if (!principal) {
        return cli.missingArgument('principal');
      }
      if (!role) {
        return cli.missingArgument('role');
      }

      var subscription = profile.current.getSubscription(options.subscription);
      var client = policyClientWorkaround.getClient(subscription);

      //A guid object id? (Supporting UPN is coming soon)
      var objectId = getObjectId(principal, subscription, _);
      if (!objectId) {
        throw new Error($('Invalid principal.'));
      }

      //Figure out the scope
      if (!scope) {
        scope = constructScope(subscription, resourceGroup, resourceType, resourceName, options.parent);
      }

      var matchedRoles;
      var progress = cli.interaction.progress($('Getting role definition id'));
      try {
        matchedRoles = client.roleDefinitions.list(_);
        matchedRoles = matchedRoles.roleDefinitions.filter(function (r) {
          return utils.ignoreCaseEquals(r.properties.roleName, role);
        });
      } finally {
        progress.end();
      }

      var roleId;
      if (matchedRoles && matchedRoles.length > 0) {
        roleId = matchedRoles[0].id;
      }
      if (!roleId) {
        throw new Error(util.format($('Role of \'%s\' does not exist'), role));
      }

      var parameter = {
        principalId: objectId,
        roleDefinitionId: roleId,
        scope: scope
      };

      var roleAssignmentNameGuid = utils.uuidGen();
      progress = cli.interaction.progress($('Creating role assignment'));
      try {
        client.roleAssignments.create(scope, roleAssignmentNameGuid, parameter, _);
      } finally {
        progress.end();
      }
    });

  roleAssignment.command('list [principal] [role] [scope] [resource-group] [resource-type] [resource-name]')
    .description($('Get role assignment at a given scope'))
    .option('-p --principal <principal>', $('if not specifed, return role assignments for all the principal.'))
    .option('-o --role <role>', $('Role the principals was assigned to'))
    .option('-c --scope <scope>', $('Scope of the role assignment.'))
    .option('-g --resource-group <resource-group>', $('Resource group to role was assigned to.'))
    .option('-r --resource-type <resource-type>', $('Type of the resource the role was assign to'))
    .option('-u --resource-name <resource-name>', $('The resource the role was assigned to.'))
    .option('--parent <parent>', $('Parent resource of the resource the role was assigned to, if there is any.'))
    .option('--subscription <subscription>', $('Subscription id or name of where the role assignment is from.'))
    .execute(function (principal, role, scope, resourceGroup, resourceType, resourceName, options, _) {
      var subscription = profile.current.getSubscription(options.subscription);
      var client = policyClientWorkaround.getClient(subscription);

      var progress = cli.interaction.progress($('Getting role assignment'));
      var filterResult;
      try {
        filterResult = filterRoleAssignments(subscription, client, principal, role, resourceGroup, resourceType, resourceName, options.parent, scope, _);
      } finally {
        progress.end();
      }

      if (filterResult.assignments.length === 0) {
        log.info($('No matching role assignments were found'));
        return;
      }

      //retrieve user objects from graph and create a mapping between id and principal name
      var graphClient = policyClientWorkaround.getADGraphClient(subscription);  
      var graphQueryResult = graphClient.objects.getObjectsByObjectIds({ ids: filterResult.principalIdList }, _);
      var entities = graphQueryResult.aADObject;
      var principalNames = [];
      for (var i = 0; i < entities.length; i++) {
        principalNames[entities[i].objectId] = entities[i].userPrincipalName || entities[i].displayName;
      }

      //populate principalName, roleName and permissions
      filterResult.assignments.forEach(function (assignment) {
        assignment.properties.principalName = principalNames[assignment.properties.principalId] ? 
                                              principalNames[assignment.properties.principalId] : 
                                              assignment.properties.principalId;
        assignment.properties.roleName = filterResult.roleNames[getRoleGuid(assignment.properties.roleDefinitionId)];
        assignment.properties.permissions = filterResult.rolePermissionList[getRoleGuid(assignment.properties.roleDefinitionId)];
      });

      cli.interaction.formatOutput(filterResult.assignments, function (data) {
        log.table(data, function (row, assignment) {
          row.cell($('PrincipalName'), assignment.properties.principalName);
          row.cell($('Role'), assignment.properties.roleName);
          row.cell($('Scope'), assignment.properties.scope);
          row.cell($('Permissions'), assignment.properties.permissions);
        });<commit_msg>made changes as per the feedback in code review<commit_after>/**
* Copyright (c) Microsoft.  All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

'use strict';

var util = require('util');

var policyClientWorkaround = require('./policyClientWorkaround');
var profile = require('../../../util/profile');
var resourceUtils = require('../resource/resourceUtils');
var utils = require('../../../util/utils');

var $ = utils.getLocaleString;

exports.init = function (cli) {
  var log = cli.output;

  var role = cli.category('role');
  var roleAssignment = role.category('assignment')
      .description($('Commands to manage your role assignment'));

  roleAssignment.command('create [principal] [role] [scope] [resource-group] [resource-type] [resource-name]')
    .description($('create a new role assignment'))
    .option('-p --principal <principal>', $('User or group to assign the role to. Accept the UPN, group name, or object id.'))
    .option('-o --role <role>', $('Role to assign the principals with.'))
    .option('-c --scope <scope>', $('Scope of the role assignment.'))
    .option('-g --resource-group <resource-group>', $('Resource group to assign the role to.'))
    .option('-r --resource-type <resource-type>', $('Type of the resource to assign the role to.'))
    .option('-u --resource-name <resource-name>', $('Name of the resource to assign the role to.'))
    .option('--parent <parent>', $('Parent resource of the resource to assign the role to, if there is any.'))
    .option('--subscription <subscription>', $('Subscription id or name of where the role assignment will be created.'))
    .execute(function (principal, role, scope, resourceGroup, resourceType, resourceName, options, _) {
      if (!principal) {
        return cli.missingArgument('principal');
      }
      if (!role) {
        return cli.missingArgument('role');
      }

      var subscription = profile.current.getSubscription(options.subscription);
      var client = policyClientWorkaround.getClient(subscription);

      //A guid object id? (Supporting UPN is coming soon)
      var objectId = getObjectId(principal, subscription, _);
      if (!objectId) {
        throw new Error($('Invalid principal.'));
      }

      //Figure out the scope
      if (!scope) {
        scope = constructScope(subscription, resourceGroup, resourceType, resourceName, options.parent);
      }

      var matchedRoles;
      var progress = cli.interaction.progress($('Getting role definition id'));
      try {
        matchedRoles = client.roleDefinitions.list(_);
        matchedRoles = matchedRoles.roleDefinitions.filter(function (r) {
          return utils.ignoreCaseEquals(r.properties.roleName, role);
        });
      } finally {
        progress.end();
      }

      var roleId;
      if (matchedRoles && matchedRoles.length > 0) {
        roleId = matchedRoles[0].id;
      }
      if (!roleId) {
        throw new Error(util.format($('Role of \'%s\' does not exist'), role));
      }

      var parameter = {
        principalId: objectId,
        roleDefinitionId: roleId,
        scope: scope
      };

      var roleAssignmentNameGuid = utils.uuidGen();
      progress = cli.interaction.progress($('Creating role assignment'));
      try {
        client.roleAssignments.create(scope, roleAssignmentNameGuid, parameter, _);
      } finally {
        progress.end();
      }
    });

  roleAssignment.command('list [principal] [role] [scope] [resource-group] [resource-type] [resource-name]')
    .description($('Get role assignment at a given scope'))
    .option('-p --principal <principal>', $('if not specifed, return role assignments for all the principal.'))
    .option('-o --role <role>', $('Role the principals was assigned to'))
    .option('-c --scope <scope>', $('Scope of the role assignment.'))
    .option('-g --resource-group <resource-group>', $('Resource group to role was assigned to.'))
    .option('-r --resource-type <resource-type>', $('Type of the resource the role was assign to'))
    .option('-u --resource-name <resource-name>', $('The resource the role was assigned to.'))
    .option('--parent <parent>', $('Parent resource of the resource the role was assigned to, if there is any.'))
    .option('--subscription <subscription>', $('Subscription id or name of where the role assignment is from.'))
    .execute(function (principal, role, scope, resourceGroup, resourceType, resourceName, options, _) {
      var subscription = profile.current.getSubscription(options.subscription);
      var client = policyClientWorkaround.getClient(subscription);

      var progress = cli.interaction.progress($('Getting role assignment'));
      var filterResult;
      try {
        filterResult = filterRoleAssignments(subscription, client, principal, role, resourceGroup, resourceType, resourceName, options.parent, scope, _);
      } finally {
        progress.end();
      }

      if (filterResult.assignments.length === 0) {
        log.info($('No matching role assignments were found'));
        return;
      }

      //retrieve user objects from graph and create a mapping between id and principal name
      var graphClient = policyClientWorkaround.getADGraphClient(subscription);  
      var graphQueryResult = graphClient.objects.getObjectsByObjectIds({ ids: filterResult.principalIdList }, _);
      var entities = graphQueryResult.aADObject;
      var principalNames = [];
      for (var i = 0; i < entities.length; i++) {
        principalNames[entities[i].objectId] = entities[i].userPrincipalName || entities[i].displayName;
      }

      //populate principalName, roleName and permissions so that complete info is provided with --json switch
      filterResult.assignments.forEach(function (assignment) {
        assignment.properties.principalName = principalNames[assignment.properties.principalId] ? 
                                              principalNames[assignment.properties.principalId] : 
                                              assignment.properties.principalId;
        assignment.properties.roleName = filterResult.roleNames[getRoleGuid(assignment.properties.roleDefinitionId)];
        assignment.properties.permissions = filterResult.rolePermissionList[getRoleGuid(assignment.properties.roleDefinitionId)];
      });

      cli.interaction.formatOutput(filterResult.assignments, function (data) {
        log.table(data, function (row, assignment) {
          row.cell($('PrincipalName'), assignment.properties.principalName);
          row.cell($('Role'), assignment.properties.roleName);
          row.cell($('Scope'), assignment.properties.scope);
          row.cell($('Permissions'), assignment.properties.permissions);
        });
{'fraction_non_alphanumeric': 0.13053483020709852, 'fraction_numerical': 0.0011156823094623806, 'mean_word_length': 3.258313539192399, 'pattern_counts': {'":': 0, '<': 37, '<?xml version=': 0, '>': 37, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 8, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4811486', 'n_tokens_mistral': 3753, 'n_tokens_neox': 3750, 'n_words': 1141}