All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.axway.apim.actions.tasks.ManageClientOrgs Maven / Gradle / Ivy

package com.axway.apim.actions.tasks;

import java.net.URI;
import java.util.ArrayList;
import java.util.List;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.entity.StringEntity;
import org.apache.http.util.EntityUtils;

import com.axway.apim.actions.rest.DELRequest;
import com.axway.apim.actions.rest.POSTRequest;
import com.axway.apim.actions.rest.RestAPICall;
import com.axway.apim.actions.rest.Transaction;
import com.axway.apim.lib.AppException;
import com.axway.apim.lib.CommandParameters;
import com.axway.apim.lib.ErrorCode;
import com.axway.apim.lib.ErrorState;
import com.axway.apim.swagger.APIManagerAdapter;
import com.axway.apim.swagger.api.properties.organization.ApiAccess;
import com.axway.apim.swagger.api.state.AbstractAPI;
import com.axway.apim.swagger.api.state.DesiredAPI;
import com.axway.apim.swagger.api.state.IAPI;
import com.fasterxml.jackson.databind.JsonNode;

public class ManageClientOrgs extends AbstractAPIMTask implements IResponseParser {
	
	private static String MODE					= "MODE";
	private static String MODE_GRANT_ACCESS		= "MODE_GRANT_ACCESS";
	private static String MODE_REMOVE_ACCESS	= "MODE_REMOVE_ACCESS";

	public ManageClientOrgs(IAPI desiredState, IAPI actualState) {
		super(desiredState, actualState);
	}

	public void execute(boolean reCreation) throws AppException {
		if(CommandParameters.getInstance().isIgnoreClientOrgs()) {
			LOG.info("Configured client organizations are ignored, as flag ignoreClientOrgs has been set.");
			return;
		}
		if(desiredState.getState().equals(IAPI.STATE_UNPUBLISHED)) return;
		// The API isn't Re-Created (to take over manually created ClientOrgs) and there are no orgs configured - We can skip the rest
		if(desiredState.getClientOrganizations()==null && !reCreation) return;
		// From here, the assumption is that existing Org-Access has been upgraded already - We only have to take care about additional orgs
		if(((DesiredAPI)desiredState).isRequestForAllOrgs()) {
			LOG.info("Granting permission to all organizations");
			grantClientOrganization(getMissingOrgs(desiredState.getClientOrganizations(), actualState.getClientOrganizations()), actualState.getId(), true);
		} else {
			List missingDesiredOrgs = getMissingOrgs(desiredState.getClientOrganizations(), actualState.getClientOrganizations());
			List removingActualOrgs = getMissingOrgs(actualState.getClientOrganizations(), desiredState.getClientOrganizations());
			if(removingActualOrgs.remove( ((AbstractAPI)desiredState).getOrganization())); // Don't try to remove the Owning-Organization
			if(missingDesiredOrgs.size()==0) {
				if(desiredState.getClientOrganizations()!=null) {
					LOG.info("All desired organizations: "+desiredState.getClientOrganizations()+" have already access. Nothing to do.");
				}
			} else {
				grantClientOrganization(missingDesiredOrgs, actualState.getId(), false);
			}
			if(removingActualOrgs.size()>0) {
				if(CommandParameters.getInstance().getClientOrgsMode().equals(CommandParameters.MODE_REPLACE)) {
					LOG.info("Removing access for orgs: "+removingActualOrgs+" from API: " + actualState.getName());
					removeClientOrganization(removingActualOrgs, actualState.getId());
				} else {
					LOG.info("NOT removing access for existing orgs: "+removingActualOrgs+" from API: " + actualState.getName() + " as clientOrgsMode NOT set to replace.");
				}
			}
		}
	}
	
	
	private void grantClientOrganization(List grantAccessToOrgs, String apiId, boolean allOrgs) throws AppException {
		URI uri;
		HttpEntity entity;
		
		RestAPICall apiCall;
		String formBody;
		Transaction.getInstance().put(MODE, MODE_GRANT_ACCESS);
		if(allOrgs) {
			formBody = "action=all_orgs&apiId="+apiId;
			Transaction.getInstance().put("orgName", "ALL");
		} else {
			formBody = "action=orgs&apiId="+apiId;
			for(String orgName : grantAccessToOrgs) {
				formBody += "&grantOrgId="+APIManagerAdapter.getInstance().getOrgId(orgName);
			}
			Transaction.getInstance().put("orgName", grantAccessToOrgs);
		}
		try {
			uri = new URIBuilder(cmd.getAPIManagerURL()).setPath(RestAPICall.API_VERSION+"/proxies/grantaccess").build();
			
			entity = new StringEntity(formBody);
			
			apiCall = new POSTRequest(entity, uri, this, true);
			apiCall.setContentType("application/x-www-form-urlencoded");
			apiCall.execute();
			// Update the actual state to reflect, which organizations now really have access to the API (this also includes prev. added orgs)
			actualState.getClientOrganizations().addAll(grantAccessToOrgs);
		} catch (Exception e) {
			LOG.error("grantAccessToOrgs: '"+grantAccessToOrgs+"'");
			LOG.error("allOrgs: '"+allOrgs+"'");
			throw new AppException("Can't grant access to organization.", ErrorCode.ACCESS_ORGANIZATION_ERR, e);
		}	
	}
	
	private void removeClientOrganization(List removingActualOrgs, String apiId) throws AppException {
		URI uri;
		Transaction.getInstance().put(MODE, MODE_REMOVE_ACCESS);
		RestAPICall apiCall;
		for(String orgName : removingActualOrgs) {
			String orgId = APIManagerAdapter.getInstance().getOrgId(orgName);
			Transaction.getInstance().put("orgName", orgName);
			List orgsApis = APIManagerAdapter.getOrgsApiAccess(orgId, false);
			for(ApiAccess apiAccess : orgsApis) {
				if(apiAccess.getApiId().equals(apiId)) {
					try {
						uri = new URIBuilder(cmd.getAPIManagerURL()).setPath(RestAPICall.API_VERSION+"/organizations/"+orgId+"/apis/"+apiAccess.getId()).build();
						
						
						apiCall = new DELRequest(uri, this, true);
						apiCall.execute();
						// Update the actual state to reflect, which organizations now really have access to the API (this also includes prev. added orgs)
						actualState.getClientOrganizations().removeAll(removingActualOrgs);
					} catch (Exception e) {
						LOG.error("Can't delete API-Access for organization. ");
						throw new AppException("Can't delete API-Access for organization.", ErrorCode.ACCESS_ORGANIZATION_ERR, e);
					}	
				}
			}
		}
	}
	
	@Override
	public JsonNode parseResponse(HttpResponse httpResponse) throws AppException {
		Transaction context = Transaction.getInstance();
		try {
			if(httpResponse.getStatusLine().getStatusCode()==HttpStatus.SC_NO_CONTENT) {
				if(context.get(MODE).equals(MODE_GRANT_ACCESS)) {
					LOG.debug("Granted permission to organization: '"+context.get("orgName")+"'");
				} else {			
					LOG.debug("Removed permission from organization: '"+context.get("orgName")+"'");
				}
			} else {
				LOG.error("Received status code: " + httpResponse.getStatusLine().getStatusCode());
				try {
					LOG.error("Received response: " + EntityUtils.toString(httpResponse.getEntity()));
				} catch (Exception e) {
					LOG.error(e.getMessage(), e);
				}
				throw new AppException("Failure granting/deleting permission to/from organization: '"+context.get("orgName")+"'. Mode: '"+context.get(MODE)+"'", 
						ErrorCode.ACCESS_ORGANIZATION_ERR);
			}
		} finally {
			try {
				((CloseableHttpResponse)httpResponse).close();
			} catch (Exception ignore) { }
		}
		return null;
	}
	
	private static List getMissingOrgs(List orgs, List referenceOrgs) throws AppException {
		List missingOrgs = new ArrayList();
		if(orgs==null || referenceOrgs ==null) return missingOrgs;
		for(String orgName : orgs) {
			if(referenceOrgs.contains(orgName)) {
				continue;
			}
			if(APIManagerAdapter.getInstance().getOrgId(orgName)==null) {
				LOG.warn("Configured organizations: " + APIManagerAdapter.getInstance().getAllOrgs());
				ErrorState.getInstance().setError("Unknown Org-Name: '" + orgName + "'", ErrorCode.UNKNOWN_ORGANIZATION, false);
				throw new AppException("Unknown Org-Name: '" + orgName + "'", ErrorCode.UNKNOWN_ORGANIZATION);
			}
			missingOrgs.add(orgName);
		}
		return missingOrgs;
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy