Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions api/src/main/java/com/cloud/user/AccountService.java
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
import com.cloud.offering.NetworkOffering;
import com.cloud.offering.ServiceOffering;
import org.apache.cloudstack.auth.UserTwoFactorAuthenticator;
import org.apache.cloudstack.backup.BackupOffering;

public interface AccountService {

Expand Down Expand Up @@ -115,6 +116,8 @@ User createUser(String userName, String password, String firstName, String lastN

void checkAccess(Account account, VpcOffering vof, DataCenter zone) throws PermissionDeniedException;

void checkAccess(Account account, BackupOffering bof) throws PermissionDeniedException;

void checkAccess(User user, ControlledEntity entity);

void checkAccess(Account account, AccessType accessType, boolean sameOwner, String apiName, ControlledEntity... entities) throws PermissionDeniedException;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@
import com.cloud.user.User;
import com.cloud.utils.component.Adapter;

import org.apache.cloudstack.backup.BackupOffering;

/**
* SecurityChecker checks the ownership and access control to objects within
*/
Expand Down Expand Up @@ -145,4 +147,6 @@ boolean checkAccess(Account caller, AccessType accessType, String action, Contro
boolean checkAccess(Account account, NetworkOffering nof, DataCenter zone) throws PermissionDeniedException;

boolean checkAccess(Account account, VpcOffering vof, DataCenter zone) throws PermissionDeniedException;

boolean checkAccess(Account account, BackupOffering bof) throws PermissionDeniedException;
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
import org.apache.cloudstack.backup.BackupOffering;
import org.apache.cloudstack.context.CallContext;

public abstract class BaseBackupListCmd extends BaseListCmd {
public abstract class BaseBackupListCmd extends BaseListAccountResourcesCmd {

protected void setupResponseBackupOfferingsList(final List<BackupOffering> offerings, final Integer count) {
final ListResponse<BackupOfferingResponse> response = new ListResponse<>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import org.apache.cloudstack.api.Parameter;
import org.apache.cloudstack.api.ServerApiException;
import org.apache.cloudstack.api.response.BackupOfferingResponse;
import org.apache.cloudstack.api.response.DomainResponse;
import org.apache.cloudstack.api.response.ZoneResponse;
import org.apache.cloudstack.backup.BackupManager;
import org.apache.cloudstack.backup.BackupOffering;
Expand All @@ -40,6 +41,11 @@
import com.cloud.exception.ResourceAllocationException;
import com.cloud.exception.ResourceUnavailableException;
import com.cloud.utils.exception.CloudRuntimeException;
import org.apache.commons.collections.CollectionUtils;

import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;

@APICommand(name = "importBackupOffering",
description = "Imports a backup offering using a backup provider",
Expand Down Expand Up @@ -76,6 +82,13 @@ public class ImportBackupOfferingCmd extends BaseAsyncCmd {
description = "Whether users are allowed to create adhoc backups and backup schedules", required = true)
private Boolean userDrivenBackups;

@Parameter(name = ApiConstants.DOMAIN_ID,
type = CommandType.LIST,
collectionType = CommandType.UUID,
entityType = DomainResponse.class,
description = "the ID of the containing domain(s), null for public offerings")
private List<Long> domainIds;

/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
/////////////////////////////////////////////////////
Expand All @@ -100,6 +113,15 @@ public Boolean getUserDrivenBackups() {
return userDrivenBackups == null ? false : userDrivenBackups;
}

public List<Long> getDomainIds() {
if (CollectionUtils.isNotEmpty(domainIds)) {
Set<Long> set = new LinkedHashSet<>(domainIds);
domainIds.clear();
domainIds.addAll(set);
}
return domainIds;
}

/////////////////////////////////////////////////////
/////////////// API Implementation///////////////////
/////////////////////////////////////////////////////
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,19 +25,24 @@
import org.apache.cloudstack.api.BaseCmd;
import org.apache.cloudstack.api.Parameter;
import org.apache.cloudstack.api.ServerApiException;
import org.apache.cloudstack.api.command.offering.DomainAndZoneIdResolver;
import org.apache.cloudstack.api.response.BackupOfferingResponse;
import org.apache.cloudstack.backup.BackupManager;
import org.apache.cloudstack.backup.BackupOffering;
import org.apache.cloudstack.utils.reflectiontostringbuilderutils.ReflectionToStringBuilderUtils;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;

import com.cloud.exception.InvalidParameterValueException;
import com.cloud.user.Account;
import com.cloud.utils.exception.CloudRuntimeException;

import java.util.List;
import java.util.function.LongFunction;

@APICommand(name = "updateBackupOffering", description = "Updates a backup offering.", responseObject = BackupOfferingResponse.class,
requestHasSensitiveInfo = false, responseHasSensitiveInfo = false, since = "4.16.0")
public class UpdateBackupOfferingCmd extends BaseCmd {
public class UpdateBackupOfferingCmd extends BaseCmd implements DomainAndZoneIdResolver {

@Inject
private BackupManager backupManager;
Expand All @@ -57,6 +62,13 @@ public class UpdateBackupOfferingCmd extends BaseCmd {
@Parameter(name = ApiConstants.ALLOW_USER_DRIVEN_BACKUPS, type = CommandType.BOOLEAN, description = "Whether to allow user driven backups or not")
private Boolean allowUserDrivenBackups;

@Parameter(name = ApiConstants.DOMAIN_ID,
type = CommandType.STRING,
description = "the ID of the containing domain(s) as comma separated string, public for public offerings",
since = "4.23.0",
length = 4096)
private String domainIds;

/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
/////////////////////////////////////////////////////
Expand All @@ -82,7 +94,7 @@ public Boolean getAllowUserDrivenBackups() {
@Override
public void execute() {
try {
if (StringUtils.isAllEmpty(getName(), getDescription()) && getAllowUserDrivenBackups() == null) {
if (StringUtils.isAllEmpty(getName(), getDescription()) && getAllowUserDrivenBackups() == null && CollectionUtils.isEmpty(getDomainIds())) {
throw new InvalidParameterValueException(String.format("Can't update Backup Offering [id: %s] because there are no parameters to be updated, at least one of the",
"following should be informed: name, description or allowUserDrivenBackups.", id));
}
Expand All @@ -103,6 +115,18 @@ public void execute() {
}
}

public List<Long> getDomainIds() {
// backupManager may be null in unit tests where the command is spied without injection.
// Avoid creating a method reference to a null receiver which causes NPE. When backupManager
// is null, pass null as the defaultDomainsProvider so resolveDomainIds will simply return
// an empty list or parse the explicit domainIds string.
LongFunction<List<Long>> defaultDomainsProvider = null;
if (backupManager != null) {
defaultDomainsProvider = backupManager::getBackupOfferingDomains;
}
return resolveDomainIds(domainIds, id, defaultDomainsProvider, "backup offering");
}

@Override
public long getEntityOwnerId() {
return Account.ACCOUNT_ID_SYSTEM;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
// under the License.
package org.apache.cloudstack.api.command.admin.network;

import java.util.ArrayList;
import java.util.List;

import org.apache.cloudstack.api.APICommand;
Expand All @@ -26,18 +25,16 @@
import org.apache.cloudstack.api.BaseCmd;
import org.apache.cloudstack.api.Parameter;
import org.apache.cloudstack.api.ServerApiException;
import org.apache.cloudstack.api.command.offering.DomainAndZoneIdResolver;
import org.apache.cloudstack.api.response.NetworkOfferingResponse;
import org.apache.commons.lang3.StringUtils;

import com.cloud.dc.DataCenter;
import com.cloud.domain.Domain;
import com.cloud.exception.InvalidParameterValueException;

import com.cloud.offering.NetworkOffering;
import com.cloud.user.Account;

@APICommand(name = "updateNetworkOffering", description = "Updates a network offering.", responseObject = NetworkOfferingResponse.class,
requestHasSensitiveInfo = false, responseHasSensitiveInfo = false)
public class UpdateNetworkOfferingCmd extends BaseCmd {
public class UpdateNetworkOfferingCmd extends BaseCmd implements DomainAndZoneIdResolver {

/////////////////////////////////////////////////////
//////////////// API parameters /////////////////////
Expand Down Expand Up @@ -129,63 +126,11 @@ public String getTags() {
}

public List<Long> getDomainIds() {
List<Long> validDomainIds = new ArrayList<>();
if (StringUtils.isNotEmpty(domainIds)) {
if (domainIds.contains(",")) {
String[] domains = domainIds.split(",");
for (String domain : domains) {
Domain validDomain = _entityMgr.findByUuid(Domain.class, domain.trim());
if (validDomain != null) {
validDomainIds.add(validDomain.getId());
} else {
throw new InvalidParameterValueException("Failed to create network offering because invalid domain has been specified.");
}
}
} else {
domainIds = domainIds.trim();
if (!domainIds.matches("public")) {
Domain validDomain = _entityMgr.findByUuid(Domain.class, domainIds.trim());
if (validDomain != null) {
validDomainIds.add(validDomain.getId());
} else {
throw new InvalidParameterValueException("Failed to create network offering because invalid domain has been specified.");
}
}
}
} else {
validDomainIds.addAll(_configService.getNetworkOfferingDomains(id));
}
return validDomainIds;
return resolveDomainIds(domainIds, id, _configService::getNetworkOfferingDomains, "network offering");
}

public List<Long> getZoneIds() {
List<Long> validZoneIds = new ArrayList<>();
if (StringUtils.isNotEmpty(zoneIds)) {
if (zoneIds.contains(",")) {
String[] zones = zoneIds.split(",");
for (String zone : zones) {
DataCenter validZone = _entityMgr.findByUuid(DataCenter.class, zone.trim());
if (validZone != null) {
validZoneIds.add(validZone.getId());
} else {
throw new InvalidParameterValueException("Failed to create network offering because invalid zone has been specified.");
}
}
} else {
zoneIds = zoneIds.trim();
if (!zoneIds.matches("all")) {
DataCenter validZone = _entityMgr.findByUuid(DataCenter.class, zoneIds.trim());
if (validZone != null) {
validZoneIds.add(validZone.getId());
} else {
throw new InvalidParameterValueException("Failed to create network offering because invalid zone has been specified.");
}
}
}
} else {
validZoneIds.addAll(_configService.getNetworkOfferingZones(id));
}
return validZoneIds;
return resolveZoneIds(zoneIds, id, _configService::getNetworkOfferingZones, "network offering");
}

/////////////////////////////////////////////////////
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
// under the License.
package org.apache.cloudstack.api.command.admin.offering;

import java.util.ArrayList;
import java.util.List;

import com.cloud.offering.DiskOffering.State;
Expand All @@ -27,19 +26,18 @@
import org.apache.cloudstack.api.BaseCmd;
import org.apache.cloudstack.api.Parameter;
import org.apache.cloudstack.api.ServerApiException;
import org.apache.cloudstack.api.command.offering.DomainAndZoneIdResolver;
import org.apache.cloudstack.api.response.DiskOfferingResponse;
import org.apache.commons.lang3.EnumUtils;
import org.apache.commons.lang3.StringUtils;

import com.cloud.dc.DataCenter;
import com.cloud.domain.Domain;
import com.cloud.exception.InvalidParameterValueException;
import com.cloud.offering.DiskOffering;
import com.cloud.user.Account;

@APICommand(name = "updateDiskOffering", description = "Updates a disk offering.", responseObject = DiskOfferingResponse.class,
requestHasSensitiveInfo = false, responseHasSensitiveInfo = false)
public class UpdateDiskOfferingCmd extends BaseCmd {
public class UpdateDiskOfferingCmd extends BaseCmd implements DomainAndZoneIdResolver {

/////////////////////////////////////////////////////
//////////////// API parameters /////////////////////
Expand Down Expand Up @@ -151,63 +149,11 @@ public Boolean getDisplayOffering() {
}

public List<Long> getDomainIds() {
List<Long> validDomainIds = new ArrayList<>();
if (StringUtils.isNotEmpty(domainIds)) {
if (domainIds.contains(",")) {
String[] domains = domainIds.split(",");
for (String domain : domains) {
Domain validDomain = _entityMgr.findByUuid(Domain.class, domain.trim());
if (validDomain != null) {
validDomainIds.add(validDomain.getId());
} else {
throw new InvalidParameterValueException("Failed to create disk offering because invalid domain has been specified.");
}
}
} else {
domainIds = domainIds.trim();
if (!domainIds.matches("public")) {
Domain validDomain = _entityMgr.findByUuid(Domain.class, domainIds.trim());
if (validDomain != null) {
validDomainIds.add(validDomain.getId());
} else {
throw new InvalidParameterValueException("Failed to create disk offering because invalid domain has been specified.");
}
}
}
} else {
validDomainIds.addAll(_configService.getDiskOfferingDomains(id));
}
return validDomainIds;
return resolveDomainIds(domainIds, id, _configService::getDiskOfferingDomains, "disk offering");
}

public List<Long> getZoneIds() {
List<Long> validZoneIds = new ArrayList<>();
if (StringUtils.isNotEmpty(zoneIds)) {
if (zoneIds.contains(",")) {
String[] zones = zoneIds.split(",");
for (String zone : zones) {
DataCenter validZone = _entityMgr.findByUuid(DataCenter.class, zone.trim());
if (validZone != null) {
validZoneIds.add(validZone.getId());
} else {
throw new InvalidParameterValueException("Failed to create disk offering because invalid zone has been specified.");
}
}
} else {
zoneIds = zoneIds.trim();
if (!zoneIds.matches("all")) {
DataCenter validZone = _entityMgr.findByUuid(DataCenter.class, zoneIds.trim());
if (validZone != null) {
validZoneIds.add(validZone.getId());
} else {
throw new InvalidParameterValueException("Failed to create disk offering because invalid zone has been specified.");
}
}
}
} else {
validZoneIds.addAll(_configService.getDiskOfferingZones(id));
}
return validZoneIds;
return resolveZoneIds(zoneIds, id, _configService::getDiskOfferingZones, "disk offering");
}

public String getTags() {
Expand Down
Loading
Loading