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>'].