diff --git a/api/src/com/cloud/api/ApiConstants.java b/api/src/com/cloud/api/ApiConstants.java index df140410a3f..22136f8107a 100755 --- a/api/src/com/cloud/api/ApiConstants.java +++ b/api/src/com/cloud/api/ApiConstants.java @@ -268,5 +268,6 @@ public class ApiConstants { public static final String USER = "user"; public static final String ACTIVE_ONLY = "activeonly"; public static final String TOKEN = "token"; + public static final String ACCEPT = "accept"; } diff --git a/api/src/com/cloud/api/commands/DeleteProjectInvitationCmd.java b/api/src/com/cloud/api/commands/DeleteProjectInvitationCmd.java new file mode 100644 index 00000000000..ca909ae57c2 --- /dev/null +++ b/api/src/com/cloud/api/commands/DeleteProjectInvitationCmd.java @@ -0,0 +1,87 @@ +/** + * Copyright (C) 2010 Cloud.com, Inc. All rights reserved. + * + * This software is licensed under the GNU General Public License v3 or later. + * + * It is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ +package com.cloud.api.commands; + +import org.apache.log4j.Logger; + +import com.cloud.api.ApiConstants; +import com.cloud.api.BaseAsyncCmd; +import com.cloud.api.BaseCmd; +import com.cloud.api.Implementation; +import com.cloud.api.Parameter; +import com.cloud.api.ServerApiException; +import com.cloud.api.response.SuccessResponse; +import com.cloud.event.EventTypes; +import com.cloud.user.Account; +import com.cloud.user.UserContext; + +@Implementation(description="Accepts or declines project invitation", responseObject=SuccessResponse.class) +public class DeleteProjectInvitationCmd extends BaseAsyncCmd { + public static final Logger s_logger = Logger.getLogger(DeleteProjectInvitationCmd.class.getName()); + private static final String s_name = "deleteprojectinvitationresponse"; + + ///////////////////////////////////////////////////// + //////////////// API parameters ///////////////////// + ///////////////////////////////////////////////////// + @Parameter(name=ApiConstants.ID, required=true, type=CommandType.LONG, description="id of the invitation") + private Long id; + + ///////////////////////////////////////////////////// + /////////////////// Accessors /////////////////////// + ///////////////////////////////////////////////////// + public Long getId() { + return id; + } + + @Override + public String getCommandName() { + return s_name; + } + + ///////////////////////////////////////////////////// + /////////////// API Implementation/////////////////// + ///////////////////////////////////////////////////// + @Override + public long getEntityOwnerId() { + //TODO - return project entity ownerId + return Account.ACCOUNT_ID_SYSTEM; // no account info given, parent this command to SYSTEM so ERROR events are tracked + } + + + @Override + public void execute(){ + UserContext.current().setEventDetails("Project invitation id " + id); + boolean result = _projectService.deleteProjectInvitation(id); + if (result) { + SuccessResponse response = new SuccessResponse(getCommandName()); + this.setResponseObject(response); + } else { + throw new ServerApiException(BaseCmd.INTERNAL_ERROR, "Failed to delete the project invitation"); + } + } + + @Override + public String getEventType() { + return EventTypes.EVENT_PROJECT_INVITATION_REMOVE; + } + + @Override + public String getEventDescription() { + return "Project invitatino id " + id + " is being removed"; + } +} diff --git a/api/src/com/cloud/api/commands/ListProjectInvitationsCmd.java b/api/src/com/cloud/api/commands/ListProjectInvitationsCmd.java index e5599e74a2a..cb08c8a7d28 100644 --- a/api/src/com/cloud/api/commands/ListProjectInvitationsCmd.java +++ b/api/src/com/cloud/api/commands/ListProjectInvitationsCmd.java @@ -52,6 +52,9 @@ public class ListProjectInvitationsCmd extends BaseListCmd { @Parameter(name=ApiConstants.STATE, type=CommandType.STRING, description="list invitations by state") private String state; + + @Parameter(name=ApiConstants.ID, type=CommandType.LONG, description="list invitations by id") + private Long id; ///////////////////////////////////////////////////// /////////////////// Accessors /////////////////////// ///////////////////////////////////////////////////// @@ -75,6 +78,10 @@ public class ListProjectInvitationsCmd extends BaseListCmd { return state; } + public Long getId() { + return id; + } + @Override public String getCommandName() { return s_name; @@ -86,7 +93,7 @@ public class ListProjectInvitationsCmd extends BaseListCmd { @Override public void execute(){ - List invites = _projectService.listProjectInvitations(projectId, accountName, domainId, state, activeOnly, this.getStartIndex(), this.getPageSizeVal()); + List invites = _projectService.listProjectInvitations(id, projectId, accountName, domainId, state, activeOnly, this.getStartIndex(), this.getPageSizeVal()); ListResponse response = new ListResponse(); List projectInvitationResponses = new ArrayList(); for (ProjectInvitation invite : invites) { diff --git a/api/src/com/cloud/api/commands/JoinProjectCmd.java b/api/src/com/cloud/api/commands/UpdateProjectInvitationCmd.java similarity index 75% rename from api/src/com/cloud/api/commands/JoinProjectCmd.java rename to api/src/com/cloud/api/commands/UpdateProjectInvitationCmd.java index 033cc7ce050..2ca4a854975 100644 --- a/api/src/com/cloud/api/commands/JoinProjectCmd.java +++ b/api/src/com/cloud/api/commands/UpdateProjectInvitationCmd.java @@ -30,10 +30,11 @@ import com.cloud.event.EventTypes; import com.cloud.user.Account; import com.cloud.user.UserContext; -@Implementation(description="Makes account to join the project", responseObject=SuccessResponse.class) -public class JoinProjectCmd extends BaseAsyncCmd { - public static final Logger s_logger = Logger.getLogger(JoinProjectCmd.class.getName()); - private static final String s_name = "joinprojectresponse"; +@Implementation(description="Accepts or declines project invitation", responseObject=SuccessResponse.class) +public class UpdateProjectInvitationCmd extends BaseAsyncCmd { + public static final Logger s_logger = Logger.getLogger(UpdateProjectInvitationCmd.class.getName()); + private static final String s_name = "updateprojectinvitationresponse"; + ///////////////////////////////////////////////////// //////////////// API parameters ///////////////////// @@ -41,11 +42,14 @@ public class JoinProjectCmd extends BaseAsyncCmd { @Parameter(name=ApiConstants.PROJECT_ID, required=true, type=CommandType.LONG, description="id of the project to join") private Long projectId; - @Parameter(name=ApiConstants.ACCOUNT, type=CommandType.STRING, required=true, description="account that is joining the project") + @Parameter(name=ApiConstants.ACCOUNT, type=CommandType.STRING, description="account that is joining the project") private String accountName; @Parameter(name=ApiConstants.TOKEN, type=CommandType.STRING, description="list invitations for specified account; this parameter has to be specified with domainId") private String token; + + @Parameter(name=ApiConstants.ACCEPT, type=CommandType.BOOLEAN, description="if true, accept the invitation, decline if false. True by default") + private Boolean accept; ///////////////////////////////////////////////////// /////////////////// Accessors /////////////////////// @@ -67,10 +71,17 @@ public class JoinProjectCmd extends BaseAsyncCmd { return token; } + public Boolean getAccept() { + if (accept == null) { + return true; + } + return accept; + } + + ///////////////////////////////////////////////////// /////////////// API Implementation/////////////////// ///////////////////////////////////////////////////// - @Override public long getEntityOwnerId() { //TODO - return project entity ownerId @@ -80,8 +91,8 @@ public class JoinProjectCmd extends BaseAsyncCmd { @Override public void execute(){ - UserContext.current().setEventDetails("Project id: "+ projectId + "; accountName " + accountName); - boolean result = _projectService.joinProject(projectId, accountName, token); + UserContext.current().setEventDetails("Project id: "+ projectId + "; accountName " + accountName + "; accept " + getAccept()); + boolean result = _projectService.updateInvitation(projectId, accountName, token, getAccept()); if (result) { SuccessResponse response = new SuccessResponse(getCommandName()); this.setResponseObject(response); @@ -92,11 +103,11 @@ public class JoinProjectCmd extends BaseAsyncCmd { @Override public String getEventType() { - return EventTypes.EVENT_PROJECT_JOIN; + return EventTypes.EVENT_PROJECT_INVITATION_UPDATE; } @Override public String getEventDescription() { - return "Account " + accountName + " joining the project: " + projectId; + return "Updating project invitation for projectId " + projectId; } } diff --git a/api/src/com/cloud/api/response/ProjectInvitationResponse.java b/api/src/com/cloud/api/response/ProjectInvitationResponse.java index 017a1e611d0..fb9182df5d2 100644 --- a/api/src/com/cloud/api/response/ProjectInvitationResponse.java +++ b/api/src/com/cloud/api/response/ProjectInvitationResponse.java @@ -6,6 +6,9 @@ import com.google.gson.annotations.SerializedName; @SuppressWarnings("unused") public class ProjectInvitationResponse extends BaseResponse implements ControlledEntityResponse{ + @SerializedName(ApiConstants.ID) @Param(description="the id of the invitation") + private Long id; + @SerializedName(ApiConstants.PROJECT_ID) @Param(description="the id of the project") private Long projectId; @@ -26,6 +29,10 @@ public class ProjectInvitationResponse extends BaseResponse implements Controlle @SerializedName(ApiConstants.STATE) @Param(description="the invitation state") private String invitationState; + + public void setId(Long id) { + this.id = id; + } public void setProjectId(Long projectId) { this.projectId = projectId; diff --git a/api/src/com/cloud/event/EventTypes.java b/api/src/com/cloud/event/EventTypes.java index 3b3389edf9a..103316a6031 100755 --- a/api/src/com/cloud/event/EventTypes.java +++ b/api/src/com/cloud/event/EventTypes.java @@ -212,6 +212,7 @@ public class EventTypes { public static final String EVENT_PROJECT_ACTIVATE = "PROJECT.ACTIVATE"; public static final String EVENT_PROJECT_SUSPEND = "PROJECT.SUSPEND"; public static final String EVENT_PROJECT_ACCOUNT_ADD = "PROJECT.ACCOUNT.ADD"; - public static final String EVENT_PROJECT_JOIN = "PROJECT.JOIN"; + public static final String EVENT_PROJECT_INVITATION_UPDATE = "PROJECT.INVITATION.UPDATE"; + public static final String EVENT_PROJECT_INVITATION_REMOVE = "PROJECT.INVITATION.REMOVE"; public static final String EVENT_PROJECT_ACCOUNT_REMOVE = "PROJECT.ACCOUNT.REMOVE"; } diff --git a/api/src/com/cloud/projects/ProjectInvitation.java b/api/src/com/cloud/projects/ProjectInvitation.java index 954891deeab..608a3840559 100644 --- a/api/src/com/cloud/projects/ProjectInvitation.java +++ b/api/src/com/cloud/projects/ProjectInvitation.java @@ -3,7 +3,7 @@ package com.cloud.projects; import java.util.Date; public interface ProjectInvitation { - public enum State {Pending, Completed, Expired} + public enum State {Pending, Completed, Expired, Declined} long getId(); diff --git a/api/src/com/cloud/projects/ProjectService.java b/api/src/com/cloud/projects/ProjectService.java index fa2148dd0af..7593f65f13b 100644 --- a/api/src/com/cloud/projects/ProjectService.java +++ b/api/src/com/cloud/projects/ProjectService.java @@ -58,13 +58,15 @@ public interface ProjectService { List listProjectAccounts(long projectId, String accountName, String role, Long startIndex, Long pageSizeVal); - List listProjectInvitations(Long projectId, String accountName, Long domainId, String state, boolean activeOnly, Long startIndex, Long pageSizeVal); + List listProjectInvitations(Long id, Long projectId, String accountName, Long domainId, String state, boolean activeOnly, Long startIndex, Long pageSizeVal); - boolean joinProject(long projectId, String accountName, String token); + boolean updateInvitation(long projectId, String accountName, String token, boolean accept); Project activateProject(long projectId); Project suspendProject(long projectId) throws ConcurrentOperationException, ResourceUnavailableException; Project enableProject(long projectId); + + boolean deleteProjectInvitation(long invitationId); } diff --git a/client/tomcatconf/commands.properties.in b/client/tomcatconf/commands.properties.in index 9409cd780f9..86d1bd0eda0 100755 --- a/client/tomcatconf/commands.properties.in +++ b/client/tomcatconf/commands.properties.in @@ -278,7 +278,8 @@ addAccountToProject=com.cloud.api.commands.AddAccountToProjectCmd;15 deleteAccountFromProject=com.cloud.api.commands.DeleteAccountFromProjectCmd;15 listProjectAccounts=com.cloud.api.commands.ListProjectAccountsCmd;15 listProjectInvitations=com.cloud.api.commands.ListProjectInvitationsCmd;15 -joinProject=com.cloud.api.commands.JoinProjectCmd;15 +updateProjectInvitation=com.cloud.api.commands.UpdateProjectInvitationCmd;15 +deleteProjectInvitation=com.cloud.api.commands.DeleteProjectInvitationCmd;15 #### createFirewallRule=com.cloud.api.commands.CreateFirewallRuleCmd;15 diff --git a/server/src/com/cloud/api/ApiResponseHelper.java b/server/src/com/cloud/api/ApiResponseHelper.java index df47ee53889..365192f3d28 100755 --- a/server/src/com/cloud/api/ApiResponseHelper.java +++ b/server/src/com/cloud/api/ApiResponseHelper.java @@ -2540,6 +2540,7 @@ public class ApiResponseHelper implements ResponseGenerator { @Override public ProjectInvitationResponse createProjectInvitationResponse(ProjectInvitation invite) { ProjectInvitationResponse response = new ProjectInvitationResponse(); + response.setId(invite.getId()); response.setProjectId(invite.getProjectId()); response.setProjectName(ApiDBUtils.findProjectById(invite.getProjectId()).getName()); response.setInvitationState(invite.getState().toString()); diff --git a/server/src/com/cloud/baremetal/BareMetalVmManagerImpl.java b/server/src/com/cloud/baremetal/BareMetalVmManagerImpl.java index 97d5f52f539..ea6fd84e677 100755 --- a/server/src/com/cloud/baremetal/BareMetalVmManagerImpl.java +++ b/server/src/com/cloud/baremetal/BareMetalVmManagerImpl.java @@ -244,8 +244,8 @@ public class BareMetalVmManagerImpl extends UserVmManagerImpl implements BareMet if (domain == null) { throw new CloudRuntimeException("Unable to find the domain " + dc.getDomainId() + " for the zone: " + dc); } - _accountMgr.checkAccess(caller, domain, null); - _accountMgr.checkAccess(owner, domain, null); + _accountMgr.checkAccess(caller, domain); + _accountMgr.checkAccess(owner, domain); } // check if account/domain is with in resource limits to create a new vm diff --git a/server/src/com/cloud/network/NetworkManagerImpl.java b/server/src/com/cloud/network/NetworkManagerImpl.java index c59581288aa..f9dd0fbaba8 100755 --- a/server/src/com/cloud/network/NetworkManagerImpl.java +++ b/server/src/com/cloud/network/NetworkManagerImpl.java @@ -1559,7 +1559,7 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag if (domain == null) { throw new InvalidParameterValueException("Unable to find domain by id " + cmd.getDomainId()); } - _accountMgr.checkAccess(caller, domain, null); + _accountMgr.checkAccess(caller, domain); isDomainSpecific = true; } } @@ -1856,7 +1856,7 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag throw new InvalidParameterValueException("Domain id=" + domainId + " doesn't exist in the system"); } - _accountMgr.checkAccess(caller, domain, null); + _accountMgr.checkAccess(caller, domain); if (accountName != null) { Account owner = _accountMgr.getActiveAccountByName(accountName, domainId); if (owner == null) { diff --git a/server/src/com/cloud/network/security/SecurityGroupManagerImpl.java b/server/src/com/cloud/network/security/SecurityGroupManagerImpl.java index b9570e4bcd7..4a66c5fd139 100755 --- a/server/src/com/cloud/network/security/SecurityGroupManagerImpl.java +++ b/server/src/com/cloud/network/security/SecurityGroupManagerImpl.java @@ -1042,7 +1042,7 @@ public class SecurityGroupManagerImpl implements SecurityGroupManager, SecurityG if (domain == null) { throw new InvalidParameterValueException("Unable to find domain by id " + domainId); } - _accountMgr.checkAccess(caller, domain, null); + _accountMgr.checkAccess(caller, domain); if (accountName != null) { Account account = _accountMgr.getActiveAccountByName(accountName, domainId); if (account == null) { diff --git a/server/src/com/cloud/projects/ProjectManagerImpl.java b/server/src/com/cloud/projects/ProjectManagerImpl.java index b20ebd95a97..0267075721d 100644 --- a/server/src/com/cloud/projects/ProjectManagerImpl.java +++ b/server/src/com/cloud/projects/ProjectManagerImpl.java @@ -216,7 +216,7 @@ public class ProjectManagerImpl implements ProjectManager, Manager{ throw new InvalidParameterValueException("Unable to find project by id " + projectId); } - _accountMgr.checkAccess(caller, _domainDao.findById(project.getDomainId()), AccessType.ModifyProject); + _accountMgr.checkAccess(caller,AccessType.ModifyProject, _accountMgr.getAccount(project.getProjectAccountId())); //at this point enabling project doesn't require anything, so just update the state project.setState(State.Active); @@ -239,7 +239,7 @@ public class ProjectManagerImpl implements ProjectManager, Manager{ throw new InvalidParameterValueException("Unable to find project by id " + projectId); } - _accountMgr.checkAccess(caller, _domainDao.findById(project.getDomainId()), AccessType.ModifyProject); + _accountMgr.checkAccess(caller,AccessType.ModifyProject, _accountMgr.getAccount(project.getProjectAccountId())); //mark project as inactive first, so you can't add resources to it Transaction txn = Transaction.currentTxn(); @@ -335,7 +335,7 @@ public class ProjectManagerImpl implements ProjectManager, Manager{ throw new InvalidParameterValueException("Domain id=" + domainId + " doesn't exist in the system"); } - _accountMgr.checkAccess(caller, domain, null); + _accountMgr.checkAccess(caller, domain); if (accountName != null) { Account owner = _accountMgr.getActiveAccountByName(accountName, domainId); @@ -438,7 +438,7 @@ public class ProjectManagerImpl implements ProjectManager, Manager{ return true; } else if (caller.getType() == Account.ACCOUNT_TYPE_DOMAIN_ADMIN) { Account owner = _accountMgr.getAccount(accountId); - _accountMgr.checkAccess(caller, _domainDao.findById(owner.getDomainId()), null); + _accountMgr.checkAccess(caller, _domainDao.findById(owner.getDomainId())); return true; } @@ -451,7 +451,7 @@ public class ProjectManagerImpl implements ProjectManager, Manager{ return true; } else if (caller.getType() == Account.ACCOUNT_TYPE_DOMAIN_ADMIN) { Account owner = _accountMgr.getAccount(accountId); - _accountMgr.checkAccess(caller, _domainDao.findById(owner.getDomainId()), null); + _accountMgr.checkAccess(caller, _domainDao.findById(owner.getDomainId())); return true; } return _projectAccountDao.canModifyProjectAccount(caller.getId(), accountId); @@ -470,7 +470,7 @@ public class ProjectManagerImpl implements ProjectManager, Manager{ } //verify permissions - _accountMgr.checkAccess(caller, _domainDao.findById(project.getDomainId()), AccessType.ModifyProject); + _accountMgr.checkAccess(caller,AccessType.ModifyProject, _accountMgr.getAccount(project.getProjectAccountId())); Transaction txn = Transaction.currentTxn(); txn.start(); @@ -532,8 +532,8 @@ public class ProjectManagerImpl implements ProjectManager, Manager{ throw new InvalidParameterValueException("Unable to find account name=" + accountName + " in domain id=" + project.getDomainId()); } - //verify permissions - _accountMgr.checkAccess(caller, _domainDao.findById(project.getDomainId()), AccessType.ModifyProject); + //verify permissions - only project owner can assign + _accountMgr.checkAccess(caller, AccessType.ModifyProject, _accountMgr.getAccount(project.getProjectAccountId())); //Check if the account already added to the project ProjectAccount projectAccount = _projectAccountDao.findByProjectIdAccountId(projectId, account.getId()); @@ -601,7 +601,7 @@ public class ProjectManagerImpl implements ProjectManager, Manager{ } //verify permissions - _accountMgr.checkAccess(caller, _domainDao.findById(project.getDomainId()), AccessType.ModifyProject); + _accountMgr.checkAccess(caller,AccessType.ModifyProject, _accountMgr.getAccount(project.getProjectAccountId())); //Check if the account exists in the project ProjectAccount projectAccount = _projectAccountDao.findByProjectIdAccountId(projectId, account.getId()); @@ -630,7 +630,7 @@ public class ProjectManagerImpl implements ProjectManager, Manager{ } //verify permissions - _accountMgr.checkAccess(caller, _domainDao.findById(project.getDomainId()), null); + _accountMgr.checkAccess(caller, _domainDao.findById(project.getDomainId())); Filter searchFilter = new Filter(ProjectAccountVO.class, "id", false, startIndex, pageSizeVal); SearchBuilder sb = _projectAccountDao.createSearchBuilder(); @@ -706,7 +706,7 @@ public class ProjectManagerImpl implements ProjectManager, Manager{ } @Override - public List listProjectInvitations(Long projectId, String accountName, Long domainId, String state, boolean activeOnly, Long startIndex, Long pageSizeVal) { + public List listProjectInvitations(Long id, Long projectId, String accountName, Long domainId, String state, boolean activeOnly, Long startIndex, Long pageSizeVal) { Account caller = UserContext.current().getCaller(); Long accountId = null; String domainPath = null; @@ -725,7 +725,7 @@ public class ProjectManagerImpl implements ProjectManager, Manager{ if (domain == null) { throw new InvalidParameterValueException("Domain id=" + domainId + " doesn't exist"); } - _accountMgr.checkAccess(caller, domain, null); + _accountMgr.checkAccess(caller, domain); if (accountName != null) { Account account = _accountDao.findActiveAccount(accountName, domainId); @@ -746,6 +746,7 @@ public class ProjectManagerImpl implements ProjectManager, Manager{ sb.and("projectId", sb.entity().getProjectId(), SearchCriteria.Op.EQ); sb.and("state", sb.entity().getState(), SearchCriteria.Op.EQ); sb.and("created", sb.entity().getCreated(), SearchCriteria.Op.GT); + sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ); if (domainPath != null) { // do a domain LIKE match for the admin case if isRecursive is true @@ -772,6 +773,10 @@ public class ProjectManagerImpl implements ProjectManager, Manager{ sc.setParameters("state", state); } + if (id != null) { + sc.setParameters("id", id); + } + if (activeOnly) { sc.setParameters("state", ProjectInvitation.State.Pending); sc.setParameters("created", new Date((System.currentTimeMillis() >> 10) - _invitationTimeOut)); @@ -781,12 +786,17 @@ public class ProjectManagerImpl implements ProjectManager, Manager{ } @Override @DB - @ActionEvent(eventType = EventTypes.EVENT_PROJECT_JOIN, eventDescription = "account joining from project", async=true) - public boolean joinProject(long projectId, String accountName, String token) { + @ActionEvent(eventType = EventTypes.EVENT_PROJECT_INVITATION_UPDATE, eventDescription = "updating project invitation", async=true) + public boolean updateInvitation(long projectId, String accountName, String token, boolean accept) { Account caller = UserContext.current().getCaller(); Long accountId = null; boolean result = true; + //if accountname and token are null, default accountname to caller's account name + if (accountName == null && token == null) { + accountName = caller.getAccountName(); + } + //check that the project exists Project project = getProject(projectId); @@ -802,7 +812,8 @@ public class ProjectManagerImpl implements ProjectManager, Manager{ } //verify permissions - _accountMgr.checkAccess(caller, _domainDao.findById(project.getDomainId()), AccessType.ModifyProject); + _accountMgr.checkAccess(caller, null, account); + accountId = account.getId(); } else { accountId = caller.getId(); @@ -817,18 +828,21 @@ public class ProjectManagerImpl implements ProjectManager, Manager{ } if (invite != null) { - if (!_projectInvitationDao.isActive(invite.getId(), _invitationTimeOut)) { + if (!_projectInvitationDao.isActive(invite.getId(), _invitationTimeOut) && accept) { expireInvitation(invite); throw new InvalidParameterValueException("Invitation is expired for account id=" + accountName + " to the project id=" + projectId); } else { Transaction txn = Transaction.currentTxn(); txn.start(); - //complete invitation - s_logger.debug("Marking invitation " + invite + " with state " + ProjectInvitation.State.Completed); - invite.setState(ProjectInvitation.State.Completed); + + ProjectInvitation.State newState = accept ? ProjectInvitation.State.Completed : ProjectInvitation.State.Declined; + + //update invitation + s_logger.debug("Marking invitation " + invite + " with state " + newState); + invite.setState(newState); result = _projectInvitationDao.update(invite.getId(), invite); - if (result) { + if (result && accept) { //check if account already exists for the project (was added before invitation got accepted) ProjectAccount projectAccount = _projectAccountDao.findByProjectIdAccountId(projectId, accountId); if (projectAccount != null) { @@ -837,13 +851,13 @@ public class ProjectManagerImpl implements ProjectManager, Manager{ assignAccountToProject(project, accountId, ProjectAccount.Role.Regular); } } else { - s_logger.warn("Failed to update project invitation " + invite + " with state " + ProjectInvitation.State.Completed); + s_logger.warn("Failed to update project invitation " + invite + " with state " + newState); } txn.commit(); } } else { - throw new InvalidParameterValueException("Unable to find invitation for account id=" + accountName + " to the project id=" + projectId); + throw new InvalidParameterValueException("Unable to find invitation for account name=" + accountName + " to the project id=" + projectId); } return result; @@ -867,7 +881,7 @@ public class ProjectManagerImpl implements ProjectManager, Manager{ } //verify permissions - _accountMgr.checkAccess(caller, _domainDao.findById(project.getDomainId()), AccessType.ModifyProject); + _accountMgr.checkAccess(caller,AccessType.ModifyProject, _accountMgr.getAccount(project.getProjectAccountId())); //allow project activation only when it's in Suspended state Project.State currentState = project.getState(); @@ -899,7 +913,7 @@ public class ProjectManagerImpl implements ProjectManager, Manager{ throw new InvalidParameterValueException("Unable to find project by id " + projectId); } - _accountMgr.checkAccess(caller, _domainDao.findById(project.getDomainId()), AccessType.ModifyProject); + _accountMgr.checkAccess(caller,AccessType.ModifyProject, _accountMgr.getAccount(project.getProjectAccountId())); if (suspendProject(project)) { s_logger.debug("Successfully suspended project id=" + projectId); @@ -1021,4 +1035,30 @@ public class ProjectManagerImpl implements ProjectManager, Manager{ } } } + + + @Override @DB + @ActionEvent(eventType = EventTypes.EVENT_PROJECT_INVITATION_REMOVE, eventDescription = "removing project invitation", async=true) + public boolean deleteProjectInvitation(long id) { + Account caller = UserContext.current().getCaller(); + + ProjectInvitation invitation = _projectInvitationDao.findById(id); + if (invitation == null) { + throw new InvalidParameterValueException("Unable to find project invitation by id " + id); + } + + //check that the project exists + Project project = getProject(invitation.getProjectId()); + + //check permissions - only project owner can remove the invitations + _accountMgr.checkAccess(caller, AccessType.ModifyProject, _accountMgr.getAccount(project.getProjectAccountId())); + + if (_projectInvitationDao.remove(id)) { + s_logger.debug("Project Invitation id=" + id + " is removed"); + return true; + } else { + s_logger.debug("Failed to remove project invitation id=" + id); + return false; + } + } } diff --git a/server/src/com/cloud/projects/dao/ProjectInvitationDao.java b/server/src/com/cloud/projects/dao/ProjectInvitationDao.java index aa8eccd0cdd..a3796277fda 100644 --- a/server/src/com/cloud/projects/dao/ProjectInvitationDao.java +++ b/server/src/com/cloud/projects/dao/ProjectInvitationDao.java @@ -29,5 +29,6 @@ public interface ProjectInvitationDao extends GenericDao sc = AllFieldsSearch.create(); + sc.setParameters("id", id); + sc.setParameters("state", State.Pending); + + return findOneBy(sc); + } + @Override public void cleanupInvitations(long projectId) { SearchCriteria sc = AllFieldsSearch.create(); diff --git a/server/src/com/cloud/resourcelimit/ResourceLimitManagerImpl.java b/server/src/com/cloud/resourcelimit/ResourceLimitManagerImpl.java index 4814297ae77..bbc5854466f 100644 --- a/server/src/com/cloud/resourcelimit/ResourceLimitManagerImpl.java +++ b/server/src/com/cloud/resourcelimit/ResourceLimitManagerImpl.java @@ -323,7 +323,7 @@ public class ResourceLimitManagerImpl implements ResourceLimitService, Manager{ return limits; } - _accountMgr.checkAccess(caller, domain, null); + _accountMgr.checkAccess(caller, domain); if (accountId != null) { //Verify account information and permissions @@ -356,7 +356,7 @@ public class ResourceLimitManagerImpl implements ResourceLimitService, Manager{ _accountMgr.checkAccess(caller, null, _accountDao.findById(vo.getAccountId())); limits.add(vo); } else if (vo.getDomainId() != null) { - _accountMgr.checkAccess(caller, _domainDao.findById(vo.getDomainId()), null); + _accountMgr.checkAccess(caller, _domainDao.findById(vo.getDomainId())); limits.add(vo); } @@ -493,7 +493,7 @@ public class ResourceLimitManagerImpl implements ResourceLimitService, Manager{ } else if (domainId != null) { Domain domain = _entityMgr.findById(Domain.class, domainId); - _accountMgr.checkAccess(caller, domain, null); + _accountMgr.checkAccess(caller, domain); if ((caller.getDomainId() == domainId.longValue()) && caller.getType() == Account.ACCOUNT_TYPE_DOMAIN_ADMIN || caller.getType() == Account.ACCOUNT_TYPE_RESOURCE_DOMAIN_ADMIN) { // if the admin is trying to update their own domain, disallow... @@ -550,7 +550,7 @@ public class ResourceLimitManagerImpl implements ResourceLimitService, Manager{ if (domain == null) { throw new InvalidParameterValueException("Please specify a valid domain ID."); } - _accountMgr.checkAccess(callerAccount, domain, null); + _accountMgr.checkAccess(callerAccount, domain); if (resourceType != null) { resourceTypes.add(resourceType); diff --git a/server/src/com/cloud/server/ManagementServerImpl.java b/server/src/com/cloud/server/ManagementServerImpl.java index c17eecc0708..6c9f84e208d 100755 --- a/server/src/com/cloud/server/ManagementServerImpl.java +++ b/server/src/com/cloud/server/ManagementServerImpl.java @@ -601,7 +601,7 @@ public class ManagementServerImpl implements ManagementServer { throw new InvalidParameterValueException("Unable to find domain by id=" + domainId); } - _accountMgr.checkAccess(caller, domain, null); + _accountMgr.checkAccess(caller, domain); } else { // default domainId to the admin's domain domainId = caller.getDomainId(); @@ -1431,7 +1431,7 @@ public class ManagementServerImpl implements ManagementServer { if (domain == null) { throw new InvalidParameterValueException("Domain id=" + domainId + " doesn't exist"); } - _accountMgr.checkAccess(caller, domain, null); + _accountMgr.checkAccess(caller, domain); if (accountName != null) { Account account = _accountDao.findActiveAccount(accountName, domainId); @@ -2007,7 +2007,7 @@ public class ManagementServerImpl implements ManagementServer { if (domain == null) { throw new InvalidParameterValueException("Unable to find domain by id " + domainId); } - _accountMgr.checkAccess(caller, domain, null); + _accountMgr.checkAccess(caller, domain); if (accountName != null) { Account userAccount = _accountDao.findActiveAccount(accountName, domainId); @@ -2371,7 +2371,7 @@ public class ManagementServerImpl implements ManagementServer { // check permissions Account caller = UserContext.current().getCaller(); - _accountMgr.checkAccess(caller, domain, null); + _accountMgr.checkAccess(caller, domain); //domain name is unique in the cloud if (domainName != null) { @@ -2691,7 +2691,7 @@ public class ManagementServerImpl implements ManagementServer { throw new InvalidParameterValueException("Unable to find domain by id " + domainId); } - _accountMgr.checkAccess(caller, domain, null); + _accountMgr.checkAccess(caller, domain); if (acctName != null) { Account userAccount = _accountDao.findActiveAccount(acctName, domainId); diff --git a/server/src/com/cloud/user/AccountManager.java b/server/src/com/cloud/user/AccountManager.java index c3e39653830..29cd874819d 100755 --- a/server/src/com/cloud/user/AccountManager.java +++ b/server/src/com/cloud/user/AccountManager.java @@ -42,7 +42,7 @@ public interface AccountManager extends AccountService { boolean deleteAccount(AccountVO account, long callerUserId, Account caller); - void checkAccess(Account account, Domain domain, AccessType accessType) throws PermissionDeniedException; + void checkAccess(Account account, Domain domain) throws PermissionDeniedException; void checkAccess(Account account, AccessType accessType, ControlledEntity... entities) throws PermissionDeniedException; diff --git a/server/src/com/cloud/user/AccountManagerImpl.java b/server/src/com/cloud/user/AccountManagerImpl.java index ec5f93f880f..0abbfde5c3a 100755 --- a/server/src/com/cloud/user/AccountManagerImpl.java +++ b/server/src/com/cloud/user/AccountManagerImpl.java @@ -266,7 +266,7 @@ public class AccountManagerImpl implements AccountManager, AccountService, Manag } @Override - public void checkAccess(Account caller, Domain domain, AccessType accessType) throws PermissionDeniedException { + public void checkAccess(Account caller, Domain domain) throws PermissionDeniedException { for (SecurityChecker checker : _securityCheckers) { if (checker.checkAccess(caller, domain)) { if (s_logger.isDebugEnabled()) { @@ -619,7 +619,7 @@ public class AccountManagerImpl implements AccountManager, AccountService, Manag } //Check permissions - checkAccess(UserContext.current().getCaller(), domain, null); + checkAccess(UserContext.current().getCaller(), domain); if (!_userAccountDao.validateUsernameInDomain(userName, domainId)) { @@ -670,7 +670,7 @@ public class AccountManagerImpl implements AccountManager, AccountService, Manag throw new CloudRuntimeException("The user cannot be created as domain " + domain.getName() + " is being deleted"); } - checkAccess(UserContext.current().getCaller(), domain, null); + checkAccess(UserContext.current().getCaller(), domain); Account account = _accountDao.findActiveAccount(accountName, domainId); if (account == null || account.getType() == Account.ACCOUNT_TYPE_PROJECT) { @@ -1045,7 +1045,7 @@ public class AccountManagerImpl implements AccountManager, AccountService, Manag } // Check if user performing the action is allowed to modify this account - checkAccess(UserContext.current().getCaller(), _domainMgr.getDomain(account.getDomainId()), null); + checkAccess(UserContext.current().getCaller(), _domainMgr.getDomain(account.getDomainId())); // check if the given account name is unique in this domain for updating Account duplicateAcccount = _accountDao.findAccount(newAccountName, domainId); @@ -1252,7 +1252,7 @@ public class AccountManagerImpl implements AccountManager, AccountService, Manag if (owner == null) { throw new InvalidParameterValueException("Unable to find account " + accountName + " in domain " + domainId); } - checkAccess(caller, domain, null); + checkAccess(caller, domain); return owner; } else if (!isAdmin(caller.getType()) && accountName != null && domainId != null) { @@ -1320,7 +1320,7 @@ public class AccountManagerImpl implements AccountManager, AccountService, Manag throw new InvalidParameterValueException("Unable to find the domain by id=" + domainId); } - checkAccess(caller, domain, null); + checkAccess(caller, domain); if (accountName != null) { Account owner = getActiveAccountByName(accountName, domainId); diff --git a/server/src/com/cloud/user/DomainManagerImpl.java b/server/src/com/cloud/user/DomainManagerImpl.java index 28dabf03189..85a6b396973 100644 --- a/server/src/com/cloud/user/DomainManagerImpl.java +++ b/server/src/com/cloud/user/DomainManagerImpl.java @@ -135,7 +135,7 @@ public class DomainManagerImpl implements DomainManager, DomainService, Manager{ throw new CloudRuntimeException("The domain cannot be created as the parent domain " + parentDomain.getName() + " is being deleted"); } - _accountMgr.checkAccess(caller, parentDomain, null); + _accountMgr.checkAccess(caller, parentDomain); return createDomain(name, parentId, caller.getId(), networkDomain); @@ -208,7 +208,7 @@ public class DomainManagerImpl implements DomainManager, DomainService, Manager{ throw new PermissionDeniedException("Can't delete ROOT domain"); } - _accountMgr.checkAccess(caller, domain, null); + _accountMgr.checkAccess(caller, domain); return deleteDomain(domain, cleanup); } diff --git a/server/src/com/cloud/vm/UserVmManagerImpl.java b/server/src/com/cloud/vm/UserVmManagerImpl.java index f4634cd1d57..ecc4cd95d9c 100755 --- a/server/src/com/cloud/vm/UserVmManagerImpl.java +++ b/server/src/com/cloud/vm/UserVmManagerImpl.java @@ -2299,9 +2299,9 @@ public class UserVmManagerImpl implements UserVmManager, UserVmService, Manager throw new CloudRuntimeException("Unable to find the domain " + zone.getDomainId() + " for the zone: " + zone); } // check that caller can operate with domain - _accountMgr.checkAccess(caller, domain, null); + _accountMgr.checkAccess(caller, domain); // check that vm owner can create vm in the domain - _accountMgr.checkAccess(owner, domain, null); + _accountMgr.checkAccess(owner, domain); } // check if account/domain is with in resource limits to create a new vm @@ -2906,7 +2906,7 @@ public class UserVmManagerImpl implements UserVmManager, UserVmService, Manager if (domain == null) { throw new InvalidParameterValueException("Domain id=" + domainId + " doesn't exist"); } - _accountMgr.checkAccess(caller, domain, null); + _accountMgr.checkAccess(caller, domain); } boolean isAdmin = false; @@ -3331,7 +3331,7 @@ public class UserVmManagerImpl implements UserVmManager, UserVmService, Manager // VV 5: check that vm owner can create vm in the domain DomainVO domain = _domainDao.findById(oldAccount.getDomainId()); - _accountMgr.checkAccess(newAccount, domain, null); + _accountMgr.checkAccess(newAccount, domain); DataCenterVO zone = _dcDao.findById(vm.getDataCenterIdToDeployIn()); VMInstanceVO vmoi = _itMgr.findByIdAndType(vm.getType(), vm.getId()); diff --git a/server/test/com/cloud/user/MockAccountManagerImpl.java b/server/test/com/cloud/user/MockAccountManagerImpl.java index 1c4afeeb3d3..2ae47709776 100644 --- a/server/test/com/cloud/user/MockAccountManagerImpl.java +++ b/server/test/com/cloud/user/MockAccountManagerImpl.java @@ -179,7 +179,7 @@ public class MockAccountManagerImpl implements Manager, AccountManager { } @Override - public void checkAccess(Account account, Domain domain, AccessType accessType) throws PermissionDeniedException { + public void checkAccess(Account account, Domain domain) throws PermissionDeniedException { // TODO Auto-generated method stub }