Skip to content

Commit 9407572

Browse files
author
Dingane Hlaluku
committed
Allow users to share templates with Accounts or Projects through the
updateTemplate permissions API
1 parent 34030be commit 9407572

File tree

11 files changed

+304
-9
lines changed

11 files changed

+304
-9
lines changed

api/src/main/java/org/apache/cloudstack/api/BaseUpdateTemplateOrIsoPermissionsCmd.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,6 @@ public List<String> getAccountNames() {
8080
if (accountNames != null && projectIds != null) {
8181
throw new InvalidParameterValueException("Accounts and projectIds can't be specified together");
8282
}
83-
8483
return accountNames;
8584
}
8685

api/src/main/java/org/apache/cloudstack/api/command/user/config/ListCapabilitiesCmd.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ public void execute() {
5959
response.setKVMSnapshotEnabled((Boolean)capabilities.get("KVMSnapshotEnabled"));
6060
response.setAllowUserViewDestroyedVM((Boolean)capabilities.get("allowUserViewDestroyedVM"));
6161
response.setAllowUserExpungeRecoverVM((Boolean)capabilities.get("allowUserExpungeRecoverVM"));
62+
response.setAllowUserViewAllDomainAccounts((Boolean)capabilities.get("allowUserViewAllDomainAccounts"));
6263
if (capabilities.containsKey("apiLimitInterval")) {
6364
response.setApiLimitInterval((Integer)capabilities.get("apiLimitInterval"));
6465
}

api/src/main/java/org/apache/cloudstack/api/response/CapabilitiesResponse.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,10 @@ public class CapabilitiesResponse extends BaseResponse {
8484
@Param(description = "true if the user can recover and expunge virtualmachines, false otherwise", since = "4.6.0")
8585
private boolean allowUserExpungeRecoverVM;
8686

87+
@SerializedName("allowuserviewalldomainaccounts")
88+
@Param(description = "true if users can see all accounts within the same domain, false otherwise")
89+
private boolean allowUserViewAllDomainAccounts;
90+
8791
public void setSecurityGroupsEnabled(boolean securityGroupsEnabled) {
8892
this.securityGroupsEnabled = securityGroupsEnabled;
8993
}
@@ -143,4 +147,8 @@ public void setAllowUserViewDestroyedVM(boolean allowUserViewDestroyedVM) {
143147
public void setAllowUserExpungeRecoverVM(boolean allowUserExpungeRecoverVM) {
144148
this.allowUserExpungeRecoverVM = allowUserExpungeRecoverVM;
145149
}
150+
151+
public void setAllowUserViewAllDomainAccounts(boolean allowUserViewAllDomainAccounts) {
152+
this.allowUserViewAllDomainAccounts = allowUserViewAllDomainAccounts;
153+
}
146154
}

server/src/main/java/com/cloud/api/query/QueryManagerImpl.java

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -390,6 +390,9 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
390390
* com.cloud.api.query.QueryService#searchForUsers(org.apache.cloudstack
391391
* .api.command.admin.user.ListUsersCmd)
392392
*/
393+
394+
public static final ConfigKey<Boolean> allowUserViewAllDomainAccounts = new ConfigKey<>("Advanced", Boolean.class,
395+
"allow.user.view.all.domain.accounts", "false", "Determines whether users can view all user accounts within the same domain", true, ConfigKey.Scope.Domain);
393396
@Override
394397
public ListResponse<UserResponse> searchForUsers(ListUsersCmd cmd) throws PermissionDeniedException {
395398
Pair<List<UserAccountJoinVO>, Integer> result = searchForUsersInternal(cmd);
@@ -1963,7 +1966,8 @@ private Pair<List<AccountJoinVO>, Integer> searchForAccountsInternal(ListAccount
19631966
// if no "id" specified...
19641967
if (accountId == null) {
19651968
// listall only has significance if they are an admin
1966-
if (listAll && callerIsAdmin) {
1969+
boolean isDomainListAllAllowed = allowUserViewAllDomainAccounts.valueIn(caller.getDomainId());
1970+
if ((listAll && callerIsAdmin) || isDomainListAllAllowed) {
19671971
// if no domain id specified, use caller's domain
19681972
if (domainId == null) {
19691973
domainId = caller.getDomainId();
@@ -2009,6 +2013,7 @@ private Pair<List<AccountJoinVO>, Integer> searchForAccountsInternal(ListAccount
20092013
sb.and("needsCleanup", sb.entity().isNeedsCleanup(), SearchCriteria.Op.EQ);
20102014
sb.and("typeNEQ", sb.entity().getType(), SearchCriteria.Op.NEQ);
20112015
sb.and("idNEQ", sb.entity().getId(), SearchCriteria.Op.NEQ);
2016+
sb.and("type2NEQ", sb.entity().getType(), SearchCriteria.Op.NEQ);
20122017

20132018
if (domainId != null && isRecursive) {
20142019
sb.and("path", sb.entity().getDomainPath(), SearchCriteria.Op.LIKE);
@@ -2018,9 +2023,15 @@ private Pair<List<AccountJoinVO>, Integer> searchForAccountsInternal(ListAccount
20182023

20192024
// don't return account of type project to the end user
20202025
sc.setParameters("typeNEQ", Account.ACCOUNT_TYPE_PROJECT);
2026+
20212027
// don't return system account...
20222028
sc.setParameters("idNEQ", Account.ACCOUNT_ID_SYSTEM);
20232029

2030+
// do not return account of type domain admin to the end user
2031+
if (!callerIsAdmin) {
2032+
sc.setParameters("type2NEQ", Account.ACCOUNT_TYPE_DOMAIN_ADMIN);
2033+
}
2034+
20242035
if (keyword != null) {
20252036
SearchCriteria<AccountJoinVO> ssc = _accountJoinDao.createSearchCriteria();
20262037
ssc.addOr("accountName", SearchCriteria.Op.LIKE, "%" + keyword + "%");
@@ -3714,6 +3725,6 @@ public String getConfigComponentName() {
37143725

37153726
@Override
37163727
public ConfigKey<?>[] getConfigKeys() {
3717-
return new ConfigKey<?>[] {AllowUserViewDestroyedVM};
3728+
return new ConfigKey<?>[] {AllowUserViewDestroyedVM, allowUserViewAllDomainAccounts};
37183729
}
37193730
}

server/src/main/java/com/cloud/server/ManagementServerImpl.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3455,6 +3455,8 @@ public Map<String, Object> listCapabilities(final ListCapabilitiesCmd cmd) {
34553455
final boolean allowUserViewDestroyedVM = (QueryManagerImpl.AllowUserViewDestroyedVM.valueIn(caller.getId()) | _accountService.isAdmin(caller.getId()));
34563456
final boolean allowUserExpungeRecoverVM = (UserVmManager.AllowUserExpungeRecoverVm.valueIn(caller.getId()) | _accountService.isAdmin(caller.getId()));
34573457

3458+
final boolean allowUserViewAllDomainAccounts = (QueryManagerImpl.allowUserViewAllDomainAccounts.valueIn(caller.getDomainId()));
3459+
34583460
// check if region-wide secondary storage is used
34593461
boolean regionSecondaryEnabled = false;
34603462
final List<ImageStoreVO> imgStores = _imgStoreDao.findRegionImageStores();
@@ -3474,6 +3476,7 @@ public Map<String, Object> listCapabilities(final ListCapabilitiesCmd cmd) {
34743476
capabilities.put("KVMSnapshotEnabled", KVMSnapshotEnabled);
34753477
capabilities.put("allowUserViewDestroyedVM", allowUserViewDestroyedVM);
34763478
capabilities.put("allowUserExpungeRecoverVM", allowUserExpungeRecoverVM);
3479+
capabilities.put("allowUserViewAllDomainAccounts", allowUserViewAllDomainAccounts);
34773480
if (apiLimitEnabled) {
34783481
capabilities.put("apiLimitInterval", apiLimitInterval);
34793482
capabilities.put("apiLimitMax", apiLimitMax);

ui/css/cloudstack3.css

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12745,6 +12745,14 @@ div.ui-dialog div.autoscaler div.field-group div.form-container form div.form-it
1274512745
background-position: -35px -707px;
1274612746
}
1274712747

12748+
.shareTemplate .icon {
12749+
background-position: -165px -122px;
12750+
}
12751+
12752+
.shareTemplate .icon {
12753+
background-position: -165px -704px;
12754+
}
12755+
1274812756
.createVolume .icon {
1274912757
background-position: -70px -124px;
1275012758
}

ui/l10n/en.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ var dictionary = {
9292
"label.about.app":"About CloudStack",
9393
"label.accept.project.invitation":"Accept project invitation",
9494
"label.account":"Account",
95+
"label.accounts":"Accounts",
9596
"label.account.and.security.group":"Account, Security group",
9697
"label.account.details":"Account details",
9798
"label.account.id":"Account ID",
@@ -279,6 +280,7 @@ var dictionary = {
279280
"label.action.run.diagnostics":"Run Diagnostics",
280281
"label.action.secure.host":"Provision Host Security Keys",
281282
"label.action.start.instance":"Start Instance",
283+
"label.action.share.template": "Update Template Permissions",
282284
"label.action.start.instance.processing":"Starting Instance....",
283285
"label.action.start.router":"Start Router",
284286
"label.action.start.router.processing":"Starting Router....",
@@ -1240,6 +1242,7 @@ var dictionary = {
12401242
"label.opendaylight.controller":"OpenDaylight Controller",
12411243
"label.opendaylight.controllerdetail":"OpenDaylight Controller Details",
12421244
"label.opendaylight.controllers":"OpenDaylight Controllers",
1245+
"label.operation": "Operation",
12431246
"label.operator":"Operator",
12441247
"label.optional":"Optional",
12451248
"label.order":"Order",
@@ -1329,6 +1332,7 @@ var dictionary = {
13291332
"label.project":"Project",
13301333
"label.project.dashboard":"Project dashboard",
13311334
"label.project.id":"Project ID",
1335+
"label.project.ids":"Project IDs",
13321336
"label.project.invite":"Invite to project",
13331337
"label.project.name":"Project name",
13341338
"label.project.view":"Project View",

ui/scripts/cloudStack.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,8 @@
151151
g_userProjectsEnabled = json.listcapabilitiesresponse.capability.allowusercreateprojects;
152152

153153
g_cloudstackversion = json.listcapabilitiesresponse.capability.cloudstackversion;
154+
// Allow users to see all accounts within a domain
155+
g_allowUserViewAllDomainAccounts = json.listcapabilitiesresponse.capability.allowuserviewalldomainaccounts;
154156

155157
if (json.listcapabilitiesresponse.capability.apilimitinterval != null && json.listcapabilitiesresponse.capability.apilimitmax != null) {
156158
var intervalLimit = ((json.listcapabilitiesresponse.capability.apilimitinterval * 1000) / json.listcapabilitiesresponse.capability.apilimitmax) * 3; //multiply 3 to be on safe side

ui/scripts/docs.js

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1355,5 +1355,20 @@ cloudStack.docs = {
13551355
helpL2UserData: {
13561356
desc: 'Pass user and meta data to VMs (via ConfigDrive)',
13571357
externalLink: ''
1358-
}
1358+
},
1359+
1360+
// Update Template Permissions Helper
1361+
helpUpdateTemplateOperation: {
1362+
desc: 'Select the permission operator. Add is for sharing with user/project and Reset simply removes all the accounts and projects which template has been shared with.'
1363+
},
1364+
helpUpdateTemplateAccounts: {
1365+
desc: 'Choose one or more accounts to share this template. Ctrl+Click to select multiple accounts to share with. Accounts is mutually exclusive with Projects and only one of the 2 can be specified, do not select any projects when sharing templates with accounts.'
1366+
},
1367+
helpUpdateTemplateProjectIds: {
1368+
desc: 'Choose one or more projects to share this template. Ctrl+Click to select multiple projects to share with. Projects is mutually exclusive with Accounts and only one of the 2 can be specified, do not select any accounts when sharing templates with projects.'
1369+
},
1370+
1371+
helpUpdateTemplateAccountList: {
1372+
desc: 'A comma seperated list of accounts to share the template with. Must be specified with the Add/Remove operation, leave Project ID blank if this is specified.'
1373+
},
13591374
};

ui/scripts/sharedFunctions.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ var g_cloudstackversion = null;
3535
var g_queryAsyncJobResultInterval = 3000;
3636
var g_idpList = null;
3737
var g_appendIdpDomain = false;
38+
var g_allowUserViewAllDomainAccounts= "false";
3839

3940
//keyboard keycode
4041
var keycode_Enter = 13;

0 commit comments

Comments
 (0)