/* * Copyright 2012 Nodeable Inc * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.streamreduce.rest.resource.admin; import com.streamreduce.core.model.Account; import com.streamreduce.core.model.Connection; import com.streamreduce.core.model.User; import com.streamreduce.core.service.ConnectionService; import com.streamreduce.core.service.UserService; import com.streamreduce.core.service.exception.AccountNotFoundException; import net.sf.json.JSONObject; import org.bson.types.ObjectId; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import javax.ws.rs.Consumes; import javax.ws.rs.DELETE; import javax.ws.rs.GET; import javax.ws.rs.HEAD; import javax.ws.rs.POST; import javax.ws.rs.PUT; import javax.ws.rs.Path; import javax.ws.rs.PathParam; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import java.util.List; /** * Methods in this class should not be publically available. They are for internal and super-user use only! */ @Component @Path("admin/account") public class AdminAccountResource extends AbstractAdminResource { @Autowired private UserService userService; @Autowired private ConnectionService connectionService; @POST @Consumes(MediaType.APPLICATION_JSON) public Response createAccount(JSONObject json) { if (getJSON(json, "name") == null) { return error("Accounts must have a name", Response.status(Response.Status.BAD_REQUEST)); } Account account = new Account.Builder() .name(getJSON(json, "name")) .description(getJSON(json, "description")) .url(getJSON(json, "url")) .build(); userService.createAccount(account); return Response.status(Response.Status.CREATED).entity(toDTO(account)).build(); } /** * Get the full Account DTO object * * @param accountId - a valid accountId * @return Account DTO * @resource.representation.200 Returned when the account is found * @resource.representation.404 Returned when the id is not found */ @GET @Path("{id}") public Response getAccount(@PathParam("id") ObjectId accountId) { logger.debug("Get accountId " + accountId); Account account; try { account = userService.getAccount(accountId); } catch (AccountNotFoundException e) { return error(e.getMessage(), Response.status(Response.Status.NOT_FOUND)); } return Response.ok(toDTO(account)).build(); } /** * A User alias is unique within an account, so check if it's already in use in the given AccountId * * @param id - the AccountId * @param alias - the alias to test * @return http status code * @resource.representation.200 return if the alias is available * @resource.representation.409 return if the alias is already in use * @resource.representation.500 returned if the accountId is invalid */ @HEAD @Path("{id}/alias/{alias}") public Response checkAliasAvailability(@PathParam("id") String id, @PathParam("alias") String alias) { if (isEmpty(alias)) { return error("alias path param can not be empty.", Response.status(Response.Status.BAD_REQUEST)); } logger.debug("Check alias availability for " + alias); Account account = null; try { userService.getAccount(new ObjectId(id)); } catch (AccountNotFoundException e) { return error("Account not found", Response.status(Response.Status.BAD_REQUEST)); } if (userService.isAliasAvailable(account, alias)) { return Response.ok().build(); } else { return error(Response.Status.CONFLICT); } } /** * Disable a Nodeable account, this sets the boolean flag on the account that will block all User login attempts. * It does NOT delete the account. * * @param id - the AccountId * @return http status code * @resource.representation.204 if the operation was a success * @resource.representation.500 returned if the accountId is invalid */ @PUT @Path("{id}/disable") @Consumes(MediaType.APPLICATION_JSON) public Response disableAccount(@PathParam("id") ObjectId id) { try { Account account = userService.getAccount(id); // TODO: need a better way to lock this... User superUser = userService.getSuperUser(); if (superUser.getAccount().getId().equals(id)) { return error("Cannot disable Nodeable account.", Response.status(Response.Status.BAD_REQUEST)); } account.setConfigValue(Account.ConfigKey.ACCOUNT_LOCKED, true); userService.updateAccount(account); } catch (AccountNotFoundException e) { return error("Account not found.", Response.status(Response.Status.BAD_REQUEST)); } return Response.status(Response.Status.NO_CONTENT).build(); } /** * Enable a Nodeable account, this sets the boolean flag on the account that will enable a disaled account. * It does NOT delete the account. * * @param id - the AccountId * @return http status code * @resource.representation.204 if the operation was a success * @resource.representation.500 returned if the accountId is invalid */ @PUT @Path("{id}/enable") @Consumes(MediaType.APPLICATION_JSON) public Response enableAccount(@PathParam("id") ObjectId id) { try { Account account = userService.getAccount(id); account.setConfigValue(Account.ConfigKey.ACCOUNT_LOCKED, false); userService.updateAccount(account); } catch (AccountNotFoundException e) { return error("Account not found.", Response.status(Response.Status.BAD_REQUEST)); } return Response.status(Response.Status.NO_CONTENT).build(); } /** * Disable inbound gateway use for this account * * @param id - the AccountId * @return http status code * @resource.representation.204 if the operation was a success * @resource.representation.500 returned if the accountId is invalid */ @PUT @Path("{id}/disable/api") @Consumes(MediaType.APPLICATION_JSON) public Response disableInboundAPIForAccount(@PathParam("id") ObjectId id) { try { Account account = userService.getAccount(id); // TODO: need a better way to lock this... User superUser = userService.getSuperUser(); if (superUser.getAccount().getId().equals(id)) { return error("Can not disable Nodeable account.", Response.status(Response.Status.BAD_REQUEST)); } account.setConfigValue(Account.ConfigKey.DISABLE_INBOUND_API, true); userService.updateAccount(account); } catch (AccountNotFoundException e) { return error("Account not found.", Response.status(Response.Status.BAD_REQUEST)); } return Response.status(Response.Status.NO_CONTENT).build(); } /** * Enable inbound gateway use for this account * * @param id - the AccountId * @return http status code * @resource.representation.204 if the operation was a success * @resource.representation.500 returned if the accountId is invalid */ @PUT @Path("{id}/enable/api") @Consumes(MediaType.APPLICATION_JSON) public Response enableInboundAPIForAccount(@PathParam("id") ObjectId id) { try { Account account = userService.getAccount(id); account.setConfigValue(Account.ConfigKey.DISABLE_INBOUND_API, false); userService.updateAccount(account); } catch (AccountNotFoundException e) { return error("Account not found.", Response.status(Response.Status.BAD_REQUEST)); } return Response .status(Response.Status.NO_CONTENT) .build(); } /** * Remove an account from the Nodeable platform and all associated Users. * Messages or resource related payloads are not deleted. * * @param accountId - the accountId to remove * @return a valid http status code * @resource.representation.200 Returned when the account is successfully deleted */ @DELETE @Path("{id}") public Response removeAccount(@PathParam("id") ObjectId accountId) { Account account = null; try { account = userService.getAccount(accountId); } catch (AccountNotFoundException e) { return error("Account not found.", Response.status(Response.Status.BAD_REQUEST)); } /* all this used to happen in an event listener,,,, */ List<Connection> connectionList = connectionService.getAccountConnections(account); for (Connection c : connectionList) { // this should also handle jobs and inventory items connectionService.deleteConnection(c); } // remove users and then finally the account userService.deleteUsersForAccount(account); userService.deleteAccount(accountId); return Response.ok().build(); } }