package net.whydah.admin.user; import com.fasterxml.jackson.core.JsonGenerationException; import com.fasterxml.jackson.databind.JsonMappingException; import com.fasterxml.jackson.databind.ObjectMapper; import net.whydah.admin.application.Application; import net.whydah.admin.user.uib.*; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import javax.ws.rs.*; import javax.ws.rs.core.*; import java.io.IOException; import java.util.ArrayList; import java.util.List; /** * @author <a href="bard.lind@gmail.com">Bard Lind</a> */ @Path("/{applicationtokenid}/{userTokenId}/user") @Controller public class UserResource { private static final Logger log = LoggerFactory.getLogger(UserResource.class); UserService userService; ObjectMapper mapper = new ObjectMapper(); @Context private Request request; @Autowired public UserResource(UserService userService) { this.userService = userService; } /** * Create a new user from xml. * * * Password is left out deliberately. A password belong to user credential as in user login. We will support multiple ways for logging in, * where uid/passord is one. Another login is via FB and Windows AD tokens. * * @param userXmlOrJson xml representing a User * @return Application */ @POST @Path("/") @Consumes({MediaType.APPLICATION_JSON,MediaType.APPLICATION_XML}) @Produces({MediaType.APPLICATION_JSON,MediaType.APPLICATION_XML}) public Response createUser(@PathParam("applicationtokenid") String applicationTokenId, @PathParam("userTokenId") String userTokenId, String userXmlOrJson, @Context Request request) { log.trace("createUser is called with userXmlOrJson={}", userXmlOrJson); MediaType responseMediaType = findPreferredResponseMediaType(); UserIdentity createdUser; String userResponse; UserAggregate userAggregate = null; try { if (isXmlContent(userXmlOrJson) || responseMediaType == MediaType.APPLICATION_XML_TYPE) { createdUser = userService.createUserFromXml(applicationTokenId, userTokenId, userXmlOrJson); } else { createdUser = userService.createUser(applicationTokenId, userTokenId, userXmlOrJson); } if (createdUser != null) { userAggregate = new UserAggregate(createdUser, new ArrayList<UserPropertyAndRole>()); if (responseMediaType.isCompatible(MediaType.APPLICATION_JSON_TYPE)){ userResponse = mapper.writeValueAsString(userAggregate); } else { userResponse = buildUserXml(userAggregate); } return Response.ok(userResponse).build(); } else { return Response.status(Response.Status.NO_CONTENT).build(); } } catch (IllegalArgumentException iae) { log.error("createUser: Invalid xml={}", userXmlOrJson, iae); return Response.status(Response.Status.BAD_REQUEST).build(); } catch (IllegalStateException ise) { log.info(ise.getMessage()); return Response.status(Response.Status.CONFLICT).build(); } catch (ConflictExeption ce) { log.info(ce.getMessage()); /* ResponseBuilderImpl builder = new ResponseBuilderImpl(); builder.status(Response.Status.CONFLICT); builder.entity("An existing user record conflicts with your input. Future versions will notify which parameter is in conflict. Unique parmeters are: username and email. "); Response response = builder.build(); */ return Response.status(Response.Status.CONFLICT).entity(ce.getMessage()).build(); } catch (JsonMappingException e) { log.error("", e); return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build(); } catch (JsonGenerationException e) { log.error("Could not map created user to Json. User: {}", userAggregate.toString(), e); return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build(); } catch (IOException e) { log.error("Could not map created user to Json. User: {}", userAggregate.toString(), e); return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build(); } catch (RuntimeException e) { log.error("Unkonwn error.", e); return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build(); } } private boolean isXmlContent(String userXml) { boolean isXml = false; if (userXml != null) { isXml = userXml.trim().startsWith("<"); } return isXml; } @Deprecated //TODO merge with normal endpoint @POST @Path("/xml") public Response createUserFromXml(@PathParam("applicationtokenid") String applicationTokenId, @PathParam("userTokenId") String userTokenId, String userXml, @Context Request request) { return createUser(applicationTokenId,userTokenId,userXml,request); } @GET @Path("/{uid}") @Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML}) public Response getUserIdentity(@PathParam("applicationtokenid") String applicationTokenId, @PathParam("userTokenId") String userTokenId, @PathParam("uid") String uid, @Context Request req) { MediaType mediaType = findPreferredResponseMediaType(); //MediaType responseMediaType = findPreferedResponseType(req); log.trace("getUserIdentity is called with uid={}. Preferred mediatype from client {}", uid, mediaType); String userResponse; UserIdentity userIdentity = null; try { userIdentity = userService.getUserIdentity(applicationTokenId, userTokenId, uid); if (mediaType == MediaType.APPLICATION_XML_TYPE) { //userResponse = buildUserXml(userIdentity); userResponse = userIdentity.toXML(); } else { //userResponse = mapper.writeValueAsString(userIdentity); userResponse = userIdentity.toJson(); } return Response.ok(userResponse).build(); } catch (IllegalArgumentException iae) { log.error("getUserIdentity: Invalid xml={}", uid, iae); return Response.status(Response.Status.BAD_REQUEST).build(); } catch (IllegalStateException ise) { log.error(ise.getMessage()); return Response.status(Response.Status.CONFLICT).build(); } /* catch (JsonMappingException e) { log.warn("Could not create json from {}", userIdentity.toString()); return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build(); } catch (JsonGenerationException e) { log.warn("Could not create json from {}", userIdentity.toString()); return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build(); } catch (IOException e) { log.warn("Could not responseobject from {}", userIdentity.toString()); return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build(); } */ catch (RuntimeException e) { log.error("", e); return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build(); } } //TODO https://github.com/Cantara/Whydah-UserAdminService/issues/25 /* @PUT @Path("/{uid}") @Consumes(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON) public Response updateUserIdentity(@PathParam("applicationtokenid") String applicationTokenId, @PathParam("userTokenId") String userTokenId, @PathParam("uid") String uid, String userXmlOrJson) { log.trace("updateUserIdentity: uid={}, userXmlOrJson={}", uid, userXmlOrJson); userService.updateUserIdentity(applicationTokenId, userTokenId, userXmlOrJson); } */ @DELETE @Path("/{uid}") public Response deleteUser(@PathParam("applicationtokenid") String applicationTokenId, @PathParam("userTokenId") String userTokenId, @PathParam("uid") String uid) { log.trace("deleteUser, uid={}, roleid={}", uid); try { userService.deleteUser(applicationTokenId, userTokenId,uid); return Response.status(Response.Status.NO_CONTENT).build(); } catch (RuntimeException e) { log.error("deleteUser-RuntimeException. uid {}", uid, e); return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build(); } } @POST @Path("/changePassword/{username}") @Consumes(MediaType.APPLICATION_FORM_URLENCODED) @Produces(MediaType.APPLICATION_XML) public Response changePassword(@PathParam("applicationtokenid") String applicationTokenId, @PathParam("userTokenId") String userTokenId, @PathParam("username") String userName, String password) { log.trace("changePassword is called with username={}", userName); boolean isPasswordUpdated = false; try { isPasswordUpdated = userService.changePassword(applicationTokenId, userTokenId, userName, password); } catch (RuntimeException e) { log.error("", e); return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build(); } String passwdOk = "<passwordUpdated><username>" + userName +"</username><status>" + isPasswordUpdated+"</status></passwordUpdated>"; return Response.ok(passwdOk).build(); } @GET @Path("/{uid}/roles") @Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML}) public Response getRoles(@PathParam("applicationtokenid") String applicationTokenId, @PathParam("userTokenId") String userTokenId, @PathParam("uid") String uid) { log.trace("getRoles, uid={}", uid); MediaType responseMediaType = findPreferredResponseMediaType(); try { String body = null; if (responseMediaType == MediaType.APPLICATION_XML_TYPE) { body = userService.getRolesAsXml(applicationTokenId, userTokenId, uid); } else if (responseMediaType == MediaType.APPLICATION_JSON_TYPE) { body = userService.getRolesAsJson(applicationTokenId, userTokenId, uid); } log.trace("getRoles for uid={}, response: {}", uid, body); return Response.ok(body).build(); } catch (Exception e) { log.error("getRoles failed. uid={}", uid, e); return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build(); } } private MediaType findPreferredResponseMediaType() { List<Variant> availableVariants = Variant.mediaTypes(MediaType.APPLICATION_JSON_TYPE, MediaType.APPLICATION_XML_TYPE).add().build(); Variant bestMatch = request.selectVariant(availableVariants); return bestMatch.getMediaType(); } /* * @param roleXmlOrJson for json * {"uid":"test.me@example.com"," * applicationId":"12", * "applicationRoleName":"developer", * "applicationRoleValue":"30", * "applicationName":"UserAdminService", * "organizationName":"Verification"} */ @POST @Path("/{uid}/role") @Consumes({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML}) @Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML}) public Response addRole(@PathParam("applicationtokenid") String applicationTokenId, @PathParam("userTokenId") String userTokenId, @PathParam("uid") String uid, String roleXmlOrJson) { log.trace("addRole is called with uid={}, roleXmlOrJson={}", uid, roleXmlOrJson); MediaType responseMediaType = findPreferredResponseMediaType(); try { RoleRepresentationRequest roleRequest; if (responseMediaType == MediaType.APPLICATION_XML_TYPE) { roleRequest = RoleRepresentationRequest.fromXml(roleXmlOrJson); RoleRepresentation roleRepresentation = userService.addUserRole(applicationTokenId, userTokenId, uid, roleRequest); return Response.ok(roleRepresentation.toXML()).build(); } else if (responseMediaType == MediaType.APPLICATION_JSON_TYPE) { roleRequest = RoleRepresentationRequest.fromJson(roleXmlOrJson); RoleRepresentation roleRepresentation = userService.addUserRole(applicationTokenId, userTokenId, uid, roleRequest); return Response.ok(roleRepresentation.toJson()).build(); } else { log.error("addRole failed. Invalid roleXmlOrJson={}, uid={}", roleXmlOrJson, uid); return Response.status(Response.Status.BAD_REQUEST).build(); } } catch (IllegalArgumentException iae) { log.error("addRole: Invalid xml={}, uid={}", roleXmlOrJson,uid, iae); return Response.status(Response.Status.BAD_REQUEST).build(); } catch (IllegalStateException ise) { log.error("addRole: IllegalStateException roleXmlOrJson={}, uid={}", roleXmlOrJson, uid, ise); return Response.status(Response.Status.CONFLICT).build(); } catch (RuntimeException e) { log.error("addRole: RuntimeException roleXmlOrJson={}, uid={}", roleXmlOrJson, uid, e); return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build(); } } /* * * @param applicationTokenId * @param userTokenId * @param uid * @param roleJson expect to be on the forme like this * {"uid":"test.me@example.com"," * applicationId":"12", * "applicationRoleName":"developer", * "applicationRoleValue":"30", * "applicationName":"UserAdminService", * "organizationName":"Verification"} * @return */ /* @POST @Path("/{uid}/role/") @Consumes(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON) public Response addRoleJson(@PathParam("applicationtokenid") String applicationTokenId, @PathParam("userTokenId") String userTokenId, @PathParam("uid") String uid, String roleJson) { log.trace("addRoleJson is called with uid={}, roleJson {}", uid, roleJson); try { RoleRepresentationRequest roleRequest = RoleRepresentationRequest.fromJson(roleJson); RoleRepresentation roleRepresentation = userService.addUserRole(applicationTokenId, userTokenId, uid, roleRequest); return Response.ok(roleRepresentation.toJson()).build(); } catch (IllegalArgumentException iae) { log.error("addRoleJson: Invalid json={}, uid {}", roleJson,uid, iae); return Response.status(Response.Status.BAD_REQUEST).build(); } catch (IllegalStateException ise) { log.error("addRoleJson: IllegalStateException json={}, uid {}", roleJson,uid, ise); return Response.status(Response.Status.CONFLICT).build(); } catch (RuntimeException e) { log.error("addRoleJson: RuntimeException json={}, uid {}", roleJson,uid, e); return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build(); } } */ /* @POST @Path("/{uid}/rolexml") @Consumes(MediaType.APPLICATION_XML) @Produces(MediaType.APPLICATION_XML) public Response addRoleXml(@PathParam("applicationtokenid") String applicationTokenId, @PathParam("userTokenId") String userTokenId, @PathParam("uid") String uid, String roleXml) { log.trace("addRole is called with uid={}, roleXml {}", uid, roleXml); try { RoleRepresentationRequest roleRequest = RoleRepresentationRequest.fromXml(roleXml); RoleRepresentation roleRepresentation = userService.addUserRole(applicationTokenId, userTokenId, uid, roleRequest); return Response.ok(roleRepresentation.toXML()).build(); } catch (IllegalArgumentException iae) { log.error("addRoleXml: Invalid xml={}, uid {}", roleXml,uid, iae); return Response.status(Response.Status.BAD_REQUEST).build(); } catch (IllegalStateException ise) { log.error("addRoleXml: IllegalStateException xml={}, uid {}", roleXml,uid, ise); return Response.status(Response.Status.CONFLICT).build(); } catch (RuntimeException e) { log.error("addRoleXml: RuntimeException xml={}, uid {}", roleXml,uid, e); return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build(); } } */ @DELETE @Path("/{uid}/role/{roleid}") public Response deleteRole(@PathParam("applicationtokenid") String applicationTokenId, @PathParam("userTokenId") String userTokenId, @PathParam("uid") String uid, @PathParam("roleid") String roleid) { log.trace("deleteRole, uid={}, roleid={}", uid, roleid); try { userService.deleteUserRole(applicationTokenId, userTokenId,uid, roleid); return Response.status(Response.Status.NO_CONTENT).build(); } catch (RuntimeException e) { log.error("deleteRole-RuntimeException. roleId {}", roleid, e); return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build(); } } @GET @Path("/ping/pong") @Produces(MediaType.TEXT_HTML) public Response ping() { return Response.ok("pong").build(); } protected String buildApplicationJson(Application application) { String applicationCreatedJson = null; try { applicationCreatedJson = mapper.writeValueAsString(application); } catch (IOException e) { log.warn("Could not convert application to Json {}", application.toString()); } return applicationCreatedJson; } protected String buildUserXml(UserAggregate userAggregate) { String userXml = null; if (userAggregate != null) { userXml = userAggregate.toXML(); } return userXml; } }