This is an automated email from the ASF dual-hosted git repository.

bhaisaab pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/cloudstack.git


The following commit(s) were added to refs/heads/master by this push:
     new 3f330a2  CLOUDSTACK-10044: Update role permission (#2236)
3f330a2 is described below

commit 3f330a219916083fa6c91ee7b83ee6caaa70b9c1
Author: Nicolas Vazquez <nicovazque...@gmail.com>
AuthorDate: Fri Aug 11 07:24:50 2017 -0300

    CLOUDSTACK-10044: Update role permission (#2236)
    
    This feature allows changing permission for existing role permissions, as 
those were static and could not be changed once created. It also provides the 
ability to change these permissions in the UI using a drop down menu for each 
permission rule, in which admin can select ‘Allow’ or ‘Deny’ permission.
    
    Changes in the API:
    
    This feature modifies behaviour of updateRolePermission API method:
    
    New optional parameters ‘ruleid’ and ‘permission’ are introduced, they are 
mutual exclusive to ‘ruleorder’ parameter. This defines two use cases:
    Update role permission: ‘ruleid’ and ‘permission’ parameters needed
    Update rules order: ‘ruleorder’ parameter needed
    Parameter ‘ruleorder’ is now optional
    updateRolePermission providing ‘ruleorder’ parameter should be sent via POST
---
 api/src/org/apache/cloudstack/acl/RoleService.java |  4 +-
 .../org/apache/cloudstack/api/ApiConstants.java    |  1 +
 .../command/admin/acl/UpdateRolePermissionCmd.java | 56 ++++++++++++++++++----
 .../cloudstack/acl/dao/RolePermissionsDao.java     | 10 ++++
 .../cloudstack/acl/dao/RolePermissionsDaoImpl.java | 14 ++++++
 .../org/apache/cloudstack/acl/RoleManagerImpl.java |  6 +++
 test/integration/smoke/test_dynamicroles.py        | 40 ++++++++++++++++
 ui/l10n/ar.js                                      |  1 +
 ui/l10n/ca.js                                      |  1 +
 ui/l10n/de_DE.js                                   |  1 +
 ui/l10n/en.js                                      |  1 +
 ui/l10n/es.js                                      |  1 +
 ui/l10n/fr_FR.js                                   |  1 +
 ui/l10n/hu.js                                      |  1 +
 ui/l10n/it_IT.js                                   |  1 +
 ui/l10n/ja_JP.js                                   |  1 +
 ui/l10n/ko_KR.js                                   |  1 +
 ui/l10n/nb_NO.js                                   |  1 +
 ui/l10n/nl_NL.js                                   |  1 +
 ui/l10n/pl.js                                      |  1 +
 ui/l10n/pt_BR.js                                   |  1 +
 ui/l10n/ru_RU.js                                   |  1 +
 ui/l10n/zh_CN.js                                   |  1 +
 ui/scripts/roles.js                                | 23 +++++++++
 ui/scripts/ui/widgets/multiEdit.js                 | 35 ++++++++++++--
 25 files changed, 192 insertions(+), 13 deletions(-)

diff --git a/api/src/org/apache/cloudstack/acl/RoleService.java 
b/api/src/org/apache/cloudstack/acl/RoleService.java
index 59eef51..98d170b 100644
--- a/api/src/org/apache/cloudstack/acl/RoleService.java
+++ b/api/src/org/apache/cloudstack/acl/RoleService.java
@@ -17,6 +17,7 @@
 
 package org.apache.cloudstack.acl;
 
+import org.apache.cloudstack.acl.RolePermission.Permission;
 import org.apache.cloudstack.framework.config.ConfigKey;
 
 import java.util.List;
@@ -36,13 +37,14 @@ public interface RoleService {
     RolePermission findRolePermission(final Long id);
     RolePermission findRolePermissionByUuid(final String uuid);
 
-    RolePermission createRolePermission(final Role role, final Rule rule, 
final RolePermission.Permission permission, final String description);
+    RolePermission createRolePermission(final Role role, final Rule rule, 
final Permission permission, final String description);
     /**
      * updateRolePermission updates the order/position of an role permission
      * @param role The role whose permissions needs to be re-ordered
      * @param newOrder The new list of ordered role permissions
      */
     boolean updateRolePermission(final Role role, final List<RolePermission> 
newOrder);
+    boolean updateRolePermission(final Role role, final RolePermission 
rolePermission, final Permission permission);
     boolean deleteRolePermission(final RolePermission rolePermission);
 
     List<Role> listRoles();
diff --git a/api/src/org/apache/cloudstack/api/ApiConstants.java 
b/api/src/org/apache/cloudstack/api/ApiConstants.java
index 10470b5..6421fb3 100644
--- a/api/src/org/apache/cloudstack/api/ApiConstants.java
+++ b/api/src/org/apache/cloudstack/api/ApiConstants.java
@@ -373,6 +373,7 @@ public class ApiConstants {
     public static final String ROLE_NAME = "rolename";
     public static final String PERMISSION = "permission";
     public static final String RULE = "rule";
+    public static final String RULE_ID = "ruleid";
     public static final String RULE_ORDER = "ruleorder";
     public static final String USER = "user";
     public static final String ACTIVE_ONLY = "activeonly";
diff --git 
a/api/src/org/apache/cloudstack/api/command/admin/acl/UpdateRolePermissionCmd.java
 
b/api/src/org/apache/cloudstack/api/command/admin/acl/UpdateRolePermissionCmd.java
index 055265c..045464e 100644
--- 
a/api/src/org/apache/cloudstack/api/command/admin/acl/UpdateRolePermissionCmd.java
+++ 
b/api/src/org/apache/cloudstack/api/command/admin/acl/UpdateRolePermissionCmd.java
@@ -20,6 +20,7 @@ package org.apache.cloudstack.api.command.admin.acl;
 import com.cloud.user.Account;
 import org.apache.cloudstack.acl.Role;
 import org.apache.cloudstack.acl.RolePermission;
+import org.apache.cloudstack.acl.RolePermission.Permission;
 import org.apache.cloudstack.acl.RoleType;
 import org.apache.cloudstack.api.APICommand;
 import org.apache.cloudstack.api.ApiArgValidator;
@@ -51,10 +52,18 @@ public class UpdateRolePermissionCmd extends BaseCmd {
             description = "ID of the role", validations = 
{ApiArgValidator.PositiveNumber})
     private Long roleId;
 
-    @Parameter(name = ApiConstants.RULE_ORDER, type = CommandType.LIST, 
collectionType = CommandType.UUID, required = true, entityType = 
RolePermissionResponse.class,
+    @Parameter(name = ApiConstants.RULE_ORDER, type = CommandType.LIST, 
collectionType = CommandType.UUID, entityType = RolePermissionResponse.class,
             description = "The parent role permission uuid, use 0 to move this 
rule at the top of the list")
     private List<Long> rulePermissionOrder;
 
+    @Parameter(name = ApiConstants.RULE_ID, type = CommandType.UUID, 
entityType = RolePermissionResponse.class,
+            description = "Role permission rule id", since="4.11")
+    private Long ruleId;
+
+    @Parameter(name = ApiConstants.PERMISSION, type = CommandType.STRING,
+            description = "Rule permission, can be: allow or deny", 
since="4.11")
+    private String rulePermission;
+
     /////////////////////////////////////////////////////
     /////////////////// Accessors ///////////////////////
     /////////////////////////////////////////////////////
@@ -67,6 +76,21 @@ public class UpdateRolePermissionCmd extends BaseCmd {
         return rulePermissionOrder;
     }
 
+    public Long getRuleId() {
+        return ruleId;
+    }
+
+    public Permission getRulePermission() {
+        if (this.rulePermission == null) {
+            return null;
+        }
+        if (!this.rulePermission.equalsIgnoreCase(Permission.ALLOW.toString()) 
&&
+                
!this.rulePermission.equalsIgnoreCase(Permission.DENY.toString())) {
+            throw new ServerApiException(ApiErrorCode.PARAM_ERROR, "Values for 
permission parameter should be: allow or deny");
+        }
+        return rulePermission.equalsIgnoreCase(Permission.ALLOW.toString()) ? 
Permission.ALLOW : Permission.DENY;
+    }
+
     /////////////////////////////////////////////////////
     /////////////// API Implementation///////////////////
     /////////////////////////////////////////////////////
@@ -84,19 +108,35 @@ public class UpdateRolePermissionCmd extends BaseCmd {
     @Override
     public void execute() {
         final Role role = roleService.findRole(getRoleId());
+        boolean result = false;
         if (role == null) {
             throw new ServerApiException(ApiErrorCode.PARAM_ERROR, "Invalid 
role id provided");
         }
-        CallContext.current().setEventDetails("Reordering permissions for role 
id: " + role.getId());
-        final List<RolePermission> rolePermissionsOrder = new ArrayList<>();
-        for (Long rolePermissionId : getRulePermissionOrder()) {
-            final RolePermission rolePermission = 
roleService.findRolePermission(rolePermissionId);
+        if (getRulePermissionOrder() != null) {
+            if (getRuleId() != null || getRulePermission() != null) {
+                throw new ServerApiException(ApiErrorCode.PARAM_ERROR, 
"Parameters permission and ruleid must be mutually exclusive with ruleorder");
+            }
+            CallContext.current().setEventDetails("Reordering permissions for 
role id: " + role.getId());
+            final List<RolePermission> rolePermissionsOrder = new 
ArrayList<>();
+            for (Long rolePermissionId : getRulePermissionOrder()) {
+                final RolePermission rolePermission = 
roleService.findRolePermission(rolePermissionId);
+                if (rolePermission == null) {
+                    throw new ServerApiException(ApiErrorCode.PARAM_ERROR, 
"Provided role permission(s) do not exist");
+                }
+                rolePermissionsOrder.add(rolePermission);
+            }
+            result = roleService.updateRolePermission(role, 
rolePermissionsOrder);
+        } else if (getRuleId() != null && getRulePermission() != null) {
+            if (getRulePermissionOrder() != null) {
+                throw new ServerApiException(ApiErrorCode.PARAM_ERROR, 
"Parameters permission and ruleid must be mutually exclusive with ruleorder");
+            }
+            RolePermission rolePermission = 
roleService.findRolePermission(getRuleId());
             if (rolePermission == null) {
-                throw new ServerApiException(ApiErrorCode.PARAM_ERROR, 
"Provided role permission(s) do not exist");
+                throw new ServerApiException(ApiErrorCode.PARAM_ERROR, 
"Invalid rule id provided");
             }
-            rolePermissionsOrder.add(rolePermission);
+            CallContext.current().setEventDetails("Updating permission for 
rule id: " + getRuleId() + " to: " + getRulePermission().toString());
+            result = roleService.updateRolePermission(role, rolePermission, 
getRulePermission());
         }
-        boolean result = roleService.updateRolePermission(role, 
rolePermissionsOrder);
         SuccessResponse response = new SuccessResponse(getCommandName());
         response.setSuccess(result);
         setResponseObject(response);
diff --git 
a/engine/schema/src/org/apache/cloudstack/acl/dao/RolePermissionsDao.java 
b/engine/schema/src/org/apache/cloudstack/acl/dao/RolePermissionsDao.java
index 3754491..c9aeba1 100644
--- a/engine/schema/src/org/apache/cloudstack/acl/dao/RolePermissionsDao.java
+++ b/engine/schema/src/org/apache/cloudstack/acl/dao/RolePermissionsDao.java
@@ -20,6 +20,7 @@ package org.apache.cloudstack.acl.dao;
 import com.cloud.utils.db.GenericDao;
 import org.apache.cloudstack.acl.Role;
 import org.apache.cloudstack.acl.RolePermission;
+import org.apache.cloudstack.acl.RolePermission.Permission;
 import org.apache.cloudstack.acl.RolePermissionVO;
 
 import java.util.List;
@@ -41,6 +42,15 @@ public interface RolePermissionsDao extends 
GenericDao<RolePermissionVO, Long> {
     boolean update(final Role role, final List<RolePermission> newOrder);
 
     /**
+     * Updates existing role permission
+     * @param role role of which rule belongs
+     * @param rolePermission role permission
+     * @param permission permission
+     * @return true on success, false if not
+     */
+    boolean update(final Role role, final RolePermission rolePermission, final 
Permission permission);
+
+    /**
      * Returns ordered linked-list of role permission for a given role
      * @param roleId the ID of the role
      * @return returns list of role permissions
diff --git 
a/engine/schema/src/org/apache/cloudstack/acl/dao/RolePermissionsDaoImpl.java 
b/engine/schema/src/org/apache/cloudstack/acl/dao/RolePermissionsDaoImpl.java
index 8f6fa83..32faf4e 100644
--- 
a/engine/schema/src/org/apache/cloudstack/acl/dao/RolePermissionsDaoImpl.java
+++ 
b/engine/schema/src/org/apache/cloudstack/acl/dao/RolePermissionsDaoImpl.java
@@ -29,6 +29,7 @@ import com.cloud.utils.db.UpdateBuilder;
 import com.cloud.utils.exception.CloudRuntimeException;
 import org.apache.cloudstack.acl.Role;
 import org.apache.cloudstack.acl.RolePermission;
+import org.apache.cloudstack.acl.RolePermission.Permission;
 import org.apache.cloudstack.acl.RolePermissionVO;
 import org.apache.log4j.Logger;
 import org.springframework.stereotype.Component;
@@ -150,6 +151,19 @@ public class RolePermissionsDaoImpl extends 
GenericDaoBase<RolePermissionVO, Lon
     }
 
     @Override
+    public boolean update(Role role, RolePermission rolePermission, Permission 
permission) {
+        if (role == null || rolePermission == null || permission == null) {
+            return false;
+        }
+        RolePermissionVO rolePermissionVO = findById(rolePermission.getId());
+        if (rolePermissionVO == null || role.getId() != 
rolePermission.getRoleId() || rolePermissionVO.getId() != 
rolePermission.getId()) {
+            return false;
+        }
+        rolePermissionVO.setPermission(permission);
+        return update(rolePermission.getId(), rolePermissionVO);
+    }
+
+    @Override
     public List<RolePermissionVO> findAllByRoleIdSorted(final Long roleId) {
         final SearchCriteria<RolePermissionVO> sc = 
RolePermissionsSearch.create();
         if (roleId != null && roleId > 0L) {
diff --git a/server/src/org/apache/cloudstack/acl/RoleManagerImpl.java 
b/server/src/org/apache/cloudstack/acl/RoleManagerImpl.java
index 27cb3d0..6cf8f97 100644
--- a/server/src/org/apache/cloudstack/acl/RoleManagerImpl.java
+++ b/server/src/org/apache/cloudstack/acl/RoleManagerImpl.java
@@ -205,6 +205,12 @@ public class RoleManagerImpl extends ManagerBase 
implements RoleService, Configu
     }
 
     @Override
+    public boolean updateRolePermission(Role role, RolePermission 
rolePermission, RolePermission.Permission permission) {
+        checkCallerAccess();
+        return role != null && rolePermissionsDao.update(role, rolePermission, 
permission);
+    }
+
+    @Override
     @ActionEvent(eventType = EventTypes.EVENT_ROLE_PERMISSION_DELETE, 
eventDescription = "deleting Role Permission")
     public boolean deleteRolePermission(final RolePermission rolePermission) {
         checkCallerAccess();
diff --git a/test/integration/smoke/test_dynamicroles.py 
b/test/integration/smoke/test_dynamicroles.py
index 9961437..5d105f6 100644
--- a/test/integration/smoke/test_dynamicroles.py
+++ b/test/integration/smoke/test_dynamicroles.py
@@ -394,6 +394,46 @@ class TestDynamicRoles(cloudstackTestCase):
             rule.update(self.apiclient, ruleorder=",".join(map(lambda x: x.id, 
permissions)))
             validate_permissions_list(permissions)
 
+    @attr(tags=['advanced', 'simulator', 'basic', 'sg'], 
required_hardware=False)
+    def test_rolepermission_lifecycle_update_permission(self):
+        """
+            Tests update of Allow to Deny permission of a rule
+        """
+        permissions = [self.rolepermission]
+
+        rule = permissions.pop(0)
+        rule.update(self.apiclient, ruleid=rule.id, permission='deny')
+
+        list_rolepermissions = RolePermission.list(self.apiclient, 
roleid=self.role.id)
+        self.assertEqual(
+            list_rolepermissions[0].permission,
+            'deny',
+            msg="List of role permissions do not match created list of 
permissions"
+        )
+
+        rule.update(self.apiclient, ruleid=rule.id, permission='allow')
+
+        list_rolepermissions = RolePermission.list(self.apiclient, 
roleid=self.role.id)
+        self.assertEqual(
+            list_rolepermissions[0].permission,
+            'allow',
+            msg="List of role permissions do not match created list of 
permissions"
+        )
+
+    @attr(tags=['advanced', 'simulator', 'basic', 'sg'], 
required_hardware=False)
+    def test_rolepermission_lifecycle_update_permission_negative(self):
+        """
+            Tests negative test for setting incorrect value as permission
+        """
+        permissions = [self.rolepermission]
+
+        rule = permissions.pop(0)
+        try:
+            rule.update(self.apiclient, ruleid=rule.id, 
permission='some_other_value')
+        except Exception:
+            pass
+        else:
+            self.fail("Negative test: Setting permission to 'some_other_value' 
should not be successful, failing")
 
     @attr(tags=['advanced', 'simulator', 'basic', 'sg'], 
required_hardware=False)
     def test_rolepermission_lifecycle_concurrent_updates(self):
diff --git a/ui/l10n/ar.js b/ui/l10n/ar.js
index 599db00..538fd4b 100644
--- a/ui/l10n/ar.js
+++ b/ui/l10n/ar.js
@@ -2176,6 +2176,7 @@ var dictionary = {
     "message.restart.vpc": "يرجى تأكيد رغبتك في إعادة تشغيل الـVPN",
     "message.restart.vpc.remark": "Please confirm that you want to restart the 
VPC <p><small><i>Remark: making a non-redundant VPC redundant will force a 
clean up. The networks will not be available for a couple of 
minutes</i>.</small></p>",
     "message.restoreVM": "Do you want to restore the VM ?",
+    "message.role.update.fail": "Failed updating rule permission",
     "message.role.ordering.fail": "Reordering of rule permissions aborted as 
the list has changed while you were making changes. Please try again.",
     "message.security.group.usage": "(Use <strong>Ctrl-click</strong> to 
select all applicable security groups)",
     "message.select.a.zone": "A zone typically corresponds to a single 
datacenter. Multiple zones help make the cloud more reliable by providing 
physical isolation and redundancy.",
diff --git a/ui/l10n/ca.js b/ui/l10n/ca.js
index a2f8fd4..d97a948 100644
--- a/ui/l10n/ca.js
+++ b/ui/l10n/ca.js
@@ -2176,6 +2176,7 @@ var dictionary = {
     "message.restart.vpc": "Please confirm that you want to restart the VPC",
     "message.restart.vpc.remark": "Please confirm that you want to restart the 
VPC <p><small><i>Remark: making a non-redundant VPC redundant will force a 
clean up. The networks will not be available for a couple of 
minutes</i>.</small></p>",
     "message.restoreVM": "Do you want to restore the VM ?",
+    "message.role.update.fail": "Failed updating rule permission",
     "message.role.ordering.fail": "Reordering of rule permissions aborted as 
the list has changed while you were making changes. Please try again.",
     "message.security.group.usage": "(Use <strong>Ctrl-click</strong> to 
select all applicable security groups)",
     "message.select.a.zone": "A zone typically corresponds to a single 
datacenter. Multiple zones help make the cloud more reliable by providing 
physical isolation and redundancy.",
diff --git a/ui/l10n/de_DE.js b/ui/l10n/de_DE.js
index 0df5861..f3d93bf 100644
--- a/ui/l10n/de_DE.js
+++ b/ui/l10n/de_DE.js
@@ -2176,6 +2176,7 @@ var dictionary = {
     "message.restart.vpc": "Bitte bestätigen Sie, dass Sie den VPC neu starten 
möchten",
     "message.restart.vpc.remark": "Bitte bestätigen Sie, dass Sie die VPC neu 
starten möchten <p>small><i>Hinweis: Ein nicht-redundante VPC redundant zu 
machen wird eine Bereinigung erzwingen. Die Netzwerke werden dadurch einige 
Minuten nicht verfügbar sein</i>.</small></p>",
     "message.restoreVM": "Möchten Sie die VM wiederherstellen?",
+    "message.role.update.fail": "Failed updating rule permission",
     "message.role.ordering.fail": "Die Neuordnung der Regelberechtigungen 
wurde abgebrochen, es sind Änderungen eingetreten während Sie an der Liste 
Arbeiten durchgeführt haben. Bitte versuchen Sie es erneut.",
     "message.security.group.usage": "(Verwenden Sie 
<strong>Ctrl-click</strong> um alle passenden Sicherheits Gruppen auszuwählen)",
     "message.select.a.zone": "Eine Zone steht typischerweise für ein einzelnes 
Rechenzentrum. Mehrere Zonen helfen dabei, die Cloud zuverlässiger zu machen 
durch physikalische Isolation und Redundanz.",
diff --git a/ui/l10n/en.js b/ui/l10n/en.js
index 3503296..8cfa419 100644
--- a/ui/l10n/en.js
+++ b/ui/l10n/en.js
@@ -2207,6 +2207,7 @@ var dictionary = {"ICMP.code":"ICMP Code",
 "message.restart.vpc":"Please confirm that you want to restart the VPC",
 "message.restart.vpc.remark":"Please confirm that you want to restart the VPC 
<p><small><i>Remark: making a non-redundant VPC redundant will force a clean 
up. The networks will not be available for a couple of 
minutes</i>.</small></p>",
 "message.restoreVM":"Do you want to restore the VM ?",
+"message.role.update.fail": "Failed updating rule permission",
 "message.role.ordering.fail":"Reordering of rule permissions aborted as the 
list has changed while you were making changes. Please try again.",
 "message.security.group.usage":"(Use <strong>Ctrl-click</strong> to select all 
applicable security groups)",
 "message.select.a.zone":"A zone typically corresponds to a single datacenter. 
Multiple zones help make the cloud more reliable by providing physical 
isolation and redundancy.",
diff --git a/ui/l10n/es.js b/ui/l10n/es.js
index eee421f..38ec9c0 100644
--- a/ui/l10n/es.js
+++ b/ui/l10n/es.js
@@ -2176,6 +2176,7 @@ var dictionary = {
     "message.restart.vpc": "Por favor confirme que usted quiere reiniciar el 
VPC",
     "message.restart.vpc.remark": "Por favor confirme que desea reiniciar el 
VPC <p><small><i>Atención: creando un VPC sin redundancia forzara la limpieza. 
Todas las redes dejaran de estar disponibles por unos minutos</i>.</small></p>",
     "message.restoreVM": "¿Desea recuperar la MV?",
+    "message.role.update.fail": "Failed updating rule permission",
     "message.role.ordering.fail": "Reordenación de permisos de reglas abortada 
ya que la lista ha cambiado mientras realizaba los cambios. Por favor, intente 
de nuevo. ",
     "message.security.group.usage": "(Use <strong> Ctrl-click </strong> para 
seleccionar todos los grupos de seguridad pertinentes)",
     "message.select.a.zone": "Una zona normalmente se corresponde con un solo 
datacenter. Múltiples zonas pueden ayudar a aumentar la disponibilidad del 
cloud al proveer aislamiento físico y redundancia.",
diff --git a/ui/l10n/fr_FR.js b/ui/l10n/fr_FR.js
index 8a03fb0..0bb6a0d 100644
--- a/ui/l10n/fr_FR.js
+++ b/ui/l10n/fr_FR.js
@@ -2176,6 +2176,7 @@ var dictionary = {
     "message.restart.vpc": "Confirmer le redémarrage du VPC",
     "message.restart.vpc.remark": "Veuillez confirmer que vous voulez 
redémarrer le VPC <p><small><i>Note : transformer un VPC non-redondant en VPC 
redondant va forcer un nettoyage du routeur. Le réseau associé ne sera pas 
disponible durant quelques minutes</i>.</small></p>",
     "message.restoreVM": "Voulez-vous restaurer la VM ?",
+    "message.role.update.fail": "Failed updating rule permission",
     "message.role.ordering.fail": "La réorganisation des règles 
d'autorisations a été abandonnée car la liste a changé pendant que vous 
apportez des modifications. Veuillez réessayer.",
     "message.security.group.usage": "(Utilisez <strong>Ctrl-clic</strong> pour 
sélectionner les groupes de sécurité visés)",
     "message.select.a.zone": "Une zone correspond typiquement à un seul centre 
de données. Des zones multiples peuvent permettre de rendre votre cloud plus 
fiable en apportant une isolation physique et de la redondance.",
diff --git a/ui/l10n/hu.js b/ui/l10n/hu.js
index 726cab8..3da6941 100644
--- a/ui/l10n/hu.js
+++ b/ui/l10n/hu.js
@@ -2176,6 +2176,7 @@ var dictionary = {
     "message.restart.vpc": "Erősítsd meg, hogy újra akarod indítani a VPC-t!",
     "message.restart.vpc.remark": "Erősítsd meg, hogy újra akarod indítani a 
VPC-t! <p><small><i>Megjegyzés: egy nem redundáns VPC redundánssá tétele 
takarítást tesz szükségessé. A hálózatok nem lesznek elérhetőek egy pár 
percig.</i>.</small></p>",
     "message.restoreVM": "Helyre akarod állítani a VM-et?",
+    "message.role.update.fail": "Failed updating rule permission",
     "message.role.ordering.fail": "Reordering of rule permissions aborted as 
the list has changed while you were making changes. Please try again.",
     "message.security.group.usage": "(A <strong>Ctrl-kattintás</strong> 
használatával tudod az összes alkalmazható biztonsági csoportot kiválasztani)",
     "message.select.a.zone": "Egy zóna tipikusan egy adatközpontnak felel meg. 
Több zóna segíthet a felhőt megbízhatóbbá tenni fizikai izolációval és 
redundanciával.",
diff --git a/ui/l10n/it_IT.js b/ui/l10n/it_IT.js
index 71875a3..247b8e0 100644
--- a/ui/l10n/it_IT.js
+++ b/ui/l10n/it_IT.js
@@ -2176,6 +2176,7 @@ var dictionary = {
     "message.restart.vpc": "Si prega di confermare di voler riavviare VPC",
     "message.restart.vpc.remark": "Please confirm that you want to restart the 
VPC <p><small><i>Remark: making a non-redundant VPC redundant will force a 
clean up. The networks will not be available for a couple of 
minutes</i>.</small></p>",
     "message.restoreVM": "Do you want to restore the VM ?",
+    "message.role.update.fail": "Failed updating rule permission",
     "message.role.ordering.fail": "Reordering of rule permissions aborted as 
the list has changed while you were making changes. Please try again.",
     "message.security.group.usage": "(Use <strong>Ctrl-click</strong> to 
select all applicable security groups)",
     "message.select.a.zone": "Una zona corrisponde tipicamente ad un singolo 
datacenter. Zone multiple consentono di aumentare l'affidabilità creando 
isolamento fisico e ridondanza.",
diff --git a/ui/l10n/ja_JP.js b/ui/l10n/ja_JP.js
index 5a55e87..a5da1a3 100644
--- a/ui/l10n/ja_JP.js
+++ b/ui/l10n/ja_JP.js
@@ -2180,6 +2180,7 @@ var dictionary = {
     "message.restart.vpc": "VPC を再起動してもよろしいですか?",
     "message.restart.vpc.remark": "VPC を再起動してもよろしいですか? <p><small><i>注意: 非冗長 
VPC の冗長化は強制的にクリーンアップされます.  また、ネットワークは数分間利用出来なくなります</i>.</small></p>",
     "message.restoreVM": "VM を復元してもよろしいですか?",
+    "message.role.update.fail": "Failed updating rule permission",
     "message.role.ordering.fail": "Reordering of rule permissions aborted as 
the list has changed while you were making changes. Please try again.",
     "message.security.group.usage": "(該当するセキュリティ グループをすべて選択するには、<strong>Ctrl 
キーを押しながらクリック</strong>してください)",
     "message.select.a.zone": 
"ゾーンは通常、単一のデータセンターに相当します。複数のゾーンを設定し、物理的に分離して冗長性を持たせることにより、クラウドの信頼性を高めます。",
diff --git a/ui/l10n/ko_KR.js b/ui/l10n/ko_KR.js
index ca22238..f592a7c 100644
--- a/ui/l10n/ko_KR.js
+++ b/ui/l10n/ko_KR.js
@@ -2176,6 +2176,7 @@ var dictionary = {
     "message.restart.vpc": "VPC를 재시작하시겠습니까?",
     "message.restart.vpc.remark": "Please confirm that you want to restart the 
VPC <p><small><i>Remark: making a non-redundant VPC redundant will force a 
clean up. The networks will not be available for a couple of 
minutes</i>.</small></p>",
     "message.restoreVM": "Do you want to restore the VM ?",
+    "message.role.update.fail": "Failed updating rule permission",
     "message.role.ordering.fail": "Reordering of rule permissions aborted as 
the list has changed while you were making changes. Please try again.",
     "message.security.group.usage": "(해당하는 보안 그룹을 모두 선택하려면 <strong>Ctrl 키를 
누르면서 클릭</strong>해 주십시오)",
     "message.select.a.zone": "Zone은 원래 단일 데이터 센터에 해당합니다. 복수 Zone을 설정하고 물리적으로 
분리하는 방법으로 클라우드의 신뢰성을 높일 수 있습니다.",
diff --git a/ui/l10n/nb_NO.js b/ui/l10n/nb_NO.js
index 801ce7f..1ef4145 100644
--- a/ui/l10n/nb_NO.js
+++ b/ui/l10n/nb_NO.js
@@ -2176,6 +2176,7 @@ var dictionary = {
     "message.restart.vpc": "Vennligst bekreft at du ønsker å restarte VPC",
     "message.restart.vpc.remark": "Vennligst bekreft du at du vil restarte VPC 
<p><small><i>Merk: Å gjøre en ikke reduntant VPC redundant vil tvinge en 
opprydning. Nettverkene vil ikke være tilgjengelig i noen 
minutter</i>.</small></p>",
     "message.restoreVM": "Vil du gjenopprette denne VMen?",
+    "message.role.update.fail": "Failed updating rule permission",
     "message.role.ordering.fail": "Reordering of rule permissions aborted as 
the list has changed while you were making changes. Please try again.",
     "message.security.group.usage": "(Bruk <strong>Ctrl-klikk</strong> for å 
velge alle aktuelle sikkerhetsgrupper)",
     "message.select.a.zone": "En sone er typisk sett på som et datasenter. 
Multiple soner gir  CloudStack bedre pålitelighet gjennom isolasjon og 
redundans.",
diff --git a/ui/l10n/nl_NL.js b/ui/l10n/nl_NL.js
index 10456e8..58465f3 100644
--- a/ui/l10n/nl_NL.js
+++ b/ui/l10n/nl_NL.js
@@ -2176,6 +2176,7 @@ var dictionary = {
     "message.restart.vpc": "Bevestig dat u deze VPC wilt herstarten",
     "message.restart.vpc.remark": "Bevestig altublieft dat U de VPC wilt 
herstarten <p><small><i>Opmerking: Een niet-redundante VPC redundant maken zal 
opschonen forceren. De netwerken zullen enige tijd niet beschikbaar 
zijn</i>.</small></p>",
     "message.restoreVM": "Wilt u de VM herstellen?",
+    "message.role.update.fail": "Failed updating rule permission",
     "message.role.ordering.fail": "Reordering of rule permissions aborted as 
the list has changed while you were making changes. Please try again.",
     "message.security.group.usage": "(Gebruik <strong>Ctrl-klik</strong> om 
meerdere security groups te selecteren)",
     "message.select.a.zone": "Een zone correspondeert meestal met een enkel 
datacenter. Meerdere zones maken de cloud betrouwbaarder door fysiek isolatie 
en redunatie te verzorgen.",
diff --git a/ui/l10n/pl.js b/ui/l10n/pl.js
index 80bc1f3..1ba89b2 100644
--- a/ui/l10n/pl.js
+++ b/ui/l10n/pl.js
@@ -2176,6 +2176,7 @@ var dictionary = {
     "message.restart.vpc": "Please confirm that you want to restart the VPC",
     "message.restart.vpc.remark": "Please confirm that you want to restart the 
VPC <p><small><i>Remark: making a non-redundant VPC redundant will force a 
clean up. The networks will not be available for a couple of 
minutes</i>.</small></p>",
     "message.restoreVM": "Do you want to restore the VM ?",
+    "message.role.update.fail": "Failed updating rule permission",
     "message.role.ordering.fail": "Reordering of rule permissions aborted as 
the list has changed while you were making changes. Please try again.",
     "message.security.group.usage": "(Use <strong>Ctrl-click</strong> to 
select all applicable security groups)",
     "message.select.a.zone": "A zone typically corresponds to a single 
datacenter. Multiple zones help make the cloud more reliable by providing 
physical isolation and redundancy.",
diff --git a/ui/l10n/pt_BR.js b/ui/l10n/pt_BR.js
index bc34f15..77bfe53 100644
--- a/ui/l10n/pt_BR.js
+++ b/ui/l10n/pt_BR.js
@@ -2176,6 +2176,7 @@ var dictionary = {
     "message.restart.vpc": "Favor confirmar que você deseja reiniciar a VPC",
     "message.restart.vpc.remark": "Por favor, confirme a reinicialização do 
VPC <p><small><i>Observação: fazendo um VPC redundante não redundante irá 
forçar uma limpeza. As redes não estarão disponíveis por alguns 
minutos</i>.</small></p>",
     "message.restoreVM": "Quer restaurar a VM?",
+    "message.role.update.fail": "Failed updating rule permission",
     "message.role.ordering.fail": "Reordering of rule permissions aborted as 
the list has changed while you were making changes. Please try again.",
     "message.security.group.usage": "(Use <strong>Ctrl-clique</strong> para 
selecionar todos os Security Groups)",
     "message.select.a.zone": "A zone tipicamente corresponde a um único 
datacenter. Múltiplas zonas auxiliam a cloud a ser mais confiável provendo 
isolamento físico e redundância.",
diff --git a/ui/l10n/ru_RU.js b/ui/l10n/ru_RU.js
index f9fd5db..aaa40b8 100644
--- a/ui/l10n/ru_RU.js
+++ b/ui/l10n/ru_RU.js
@@ -2176,6 +2176,7 @@ var dictionary = {
     "message.restart.vpc": "Подтвердите, что вы действительно хотите 
перезапустить VPC",
     "message.restart.vpc.remark": "Please confirm that you want to restart the 
VPC <p><small><i>Remark: making a non-redundant VPC redundant will force a 
clean up. The networks will not be available for a couple of 
minutes</i>.</small></p>",
     "message.restoreVM": "Do you want to restore the VM ?",
+    "message.role.update.fail": "Failed updating rule permission",
     "message.role.ordering.fail": "Reordering of rule permissions aborted as 
the list has changed while you were making changes. Please try again.",
     "message.security.group.usage": "(Используйте <strong>Ctrl-click</strong> 
для выбора всех применимых security groups)",
     "message.select.a.zone": "Зона обычно соответствует единичному центру 
обработки данных. Несколько зон помогают создавать более надежные облака, 
обеспечивая физическую изоляцию и избыточность.",
diff --git a/ui/l10n/zh_CN.js b/ui/l10n/zh_CN.js
index 54646b0..2131c98 100644
--- a/ui/l10n/zh_CN.js
+++ b/ui/l10n/zh_CN.js
@@ -2180,6 +2180,7 @@ var dictionary = {
     "message.restart.vpc": "请确认您确实要重新启动 VPC",
     "message.restart.vpc.remark": "请确定您要重启VPC  <p><small><i> 警告: 
重启非冗余的VPC将会导致网络中断,直至VPC重启完成</i>.</small></p>",
     "message.restoreVM": "是否要还原此 VM?",
+    "message.role.update.fail": "Failed updating rule permission",
     "message.role.ordering.fail": "Reordering of rule permissions aborted as 
the list has changed while you were making changes. Please try again.",
     "message.security.group.usage": "(<strong>按住 Ctrl 
键并单击鼠标</strong>可选择所有适用的安全组)",
     "message.select.a.zone": "一个资源域通常与一个数据中心相对应。多个资源域可以提供物理隔离和冗余,有助于使云更加可靠。",
diff --git a/ui/scripts/roles.js b/ui/scripts/roles.js
index eae088f..01700df 100644
--- a/ui/scripts/roles.js
+++ b/ui/scripts/roles.js
@@ -171,6 +171,28 @@
                                 context: context,
                                 noSelect: true,
                                 noHeaderActionsColumn: true,
+                                selectPermission: {
+                                    action: function(args){
+                                        $.ajax({
+                                            url: 
createURL("updateRolePermission"),
+                                            data: {
+                                                roleid: args.roleid,
+                                                ruleid: args.ruleid,
+                                                permission: args.permission
+                                            },
+                                            dataType: "json",
+                                            async: true,
+                                            success: function(json) {
+                                                
$(window).trigger('cloudStack.fullRefresh');
+                                            },
+                                            error: function(json) {
+                                                cloudStack.dialog.notice({
+                                                    message: 
'message.role.update.fail'
+                                                });
+                                            }
+                                        });
+                                    }
+                                },
                                 reorder: {
                                     moveDrag: {
                                         action: function(args) {
@@ -193,6 +215,7 @@
                                             });
 
                                             $.ajax({
+                                               type: 'POST',
                                                 url: 
createURL('updateRolePermission'),
                                                 data: {
                                                     roleid: rule.roleid,
diff --git a/ui/scripts/ui/widgets/multiEdit.js 
b/ui/scripts/ui/widgets/multiEdit.js
index 3e88b92..48d597e 100755
--- a/ui/scripts/ui/widgets/multiEdit.js
+++ b/ui/scripts/ui/widgets/multiEdit.js
@@ -31,6 +31,7 @@
             var $item = $('<div>').addClass('data-item');
             var multiRule = data;
             var reorder = options.reorder;
+            var selectPermission = options.selectPermission;
 
             $item.append($('<table>').append($('<tbody>')));
             $tr = $('<tr>').appendTo($item.find('tbody'));
@@ -189,10 +190,34 @@
                                 return $(this).val() == data[fieldName];
                             });
 
-                        var matchingValue = $matchingOption.size() ?
-                            $matchingOption.html() : data[fieldName];
+                        if (selectPermission) {
+                            // Wrap div to get its html code
+                            selectedOptionHtml = 
$matchingOption.clone().wrap('<div>').parent().html();
+                            // Get html code from not matching option
+                            $matchingSelect.find('option').each(
+                                function() {
+                                    if ($(this).val() != data[fieldName]){
+                                        selectedOptionHtml += 
$(this).clone().wrap('<div>').parent().html();
+                                    }
+                                }
+                            );
+                            $select = $('<select>');
+                            $select.html(selectedOptionHtml);
+                            $select.change(function(event) {
+                                selectPermission.action({
+                                    roleid: data['roleid'],
+                                    ruleid: data['id'],
+                                    permission: $(this).val()
+                                });
+                            });
+                            $td.append($select);
+                        }
+                        else {
+                            var matchingValue = $matchingOption.size() ?
+                                $matchingOption.html() : data[fieldName];
 
-                        $td.append($('<span>').html(_s(matchingValue)));
+                            $td.append($('<span>').html(_s(matchingValue)));
+                        }
                     } else if (field.addButton && !options.noSelect) {
                         if (options.multipleAdd) {
                             $addButton.click(function() {
@@ -862,6 +887,7 @@
         var actionPreFilter = args.actionPreFilter;
         var readOnlyCheck = args.readOnlyCheck;
         var reorder = args.reorder;
+        var selectPermission = args.selectPermission;
 
         var $thead = $('<tr>').appendTo(
             $('<thead>').appendTo($inputTable)
@@ -1197,7 +1223,8 @@
                                     preFilter: actionPreFilter,
                                     listView: listView,
                                     tags: tags,
-                                    reorder: reorder
+                                    reorder: reorder,
+                                    selectPermission: selectPermission
                                 }
                             ).appendTo($dataBody);
                         });

-- 
To stop receiving notification emails like this one, please contact
['"commits@cloudstack.apache.org" <commits@cloudstack.apache.org>'].

Reply via email to