/* * Copyright (C) 2007-2014 Crafter Software Corporation. * * This program 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 * (at your option) 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 <http://www.gnu.org/licenses/>. */ package org.craftercms.profile.controllers.rest; import java.io.IOException; import java.io.InputStream; import java.util.Collection; import java.util.List; import java.util.Map; import java.util.Set; import javax.servlet.http.HttpServletResponse; import org.apache.commons.io.IOUtils; import org.apache.commons.lang3.StringUtils; import org.craftercms.profile.api.Profile; import org.craftercms.profile.api.SortOrder; import org.craftercms.profile.api.VerificationToken; import org.craftercms.profile.api.exceptions.ProfileException; import org.craftercms.profile.api.services.ProfileAttachment; import org.craftercms.profile.api.services.ProfileService; import org.craftercms.profile.exceptions.NoSuchProfileException; import org.craftercms.profile.exceptions.ParamDeserializationException; import org.springframework.beans.factory.annotation.Required; import org.springframework.http.HttpStatus; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.ResponseStatus; import org.springframework.web.multipart.MultipartFile; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.ObjectMapper; import com.wordnik.swagger.annotations.Api; import com.wordnik.swagger.annotations.ApiImplicitParam; import com.wordnik.swagger.annotations.ApiOperation; import com.wordnik.swagger.annotations.ApiParam; import static org.craftercms.profile.api.ProfileConstants.*; /** * REST controller for the profile service. * * @author avasquez */ @Controller @RequestMapping(BASE_URL_PROFILE) @Api(value = "profile", basePath = BASE_URL_PROFILE, description = "Profile operations") public class ProfileController { private static final TypeReference<Map<String, Object>> ATTRIBUTES_TYPE_REFERENCE = new TypeReference<Map<String, Object>>() {}; protected ProfileService profileService; protected ObjectMapper objectMapper; @Required public void setProfileService(ProfileService profileService) { this.profileService = profileService; } @Required public void setObjectMapper(ObjectMapper objectMapper) { this.objectMapper = objectMapper; } @ApiOperation("Creates a new profile for a specific tenant name") @ApiImplicitParam(name = "accessTokenId", required = true, dataType = "string", paramType = "query", value = "The ID of the application access token") @RequestMapping(value = URL_PROFILE_CREATE, method = RequestMethod.POST) @ResponseBody public Profile createProfile( @ApiParam("The name of the tenant to add the profile to") @RequestParam(PARAM_TENANT_NAME) String tenantName, @ApiParam("The profile's username") @RequestParam(PARAM_USERNAME) String username, @ApiParam("The profile's password") @RequestParam(value = PARAM_PASSWORD, required = false) String password, @ApiParam("The profile's email") @RequestParam(PARAM_EMAIL) String email, @ApiParam("If the profile should be enabled or not") @RequestParam(PARAM_ENABLED) boolean enabled, @ApiParam("The profile's roles") @RequestParam(value = PARAM_ROLE, required = false) Set<String> roles, @ApiParam("The additional attributes to add to the profile (specify a JSON string)") @RequestParam(value = PARAM_ATTRIBUTES, required = false) String serializedAttributes, @ApiParam("The URL (sans token) the user needs to go in case it needs to verify the created profile " + "" + "(verification depends on tenant)") @RequestParam(value = PARAM_VERIFICATION_URL, required = false) String verificationUrl) throws ProfileException { Map<String, Object> attributes = deserializeAttributes(serializedAttributes); return profileService.createProfile(tenantName, username, password, email, enabled, roles, attributes, verificationUrl); } @ApiOperation("Updates the profile's info") @ApiImplicitParam(name = "accessTokenId", required = true, dataType = "string", paramType = "query", value = "The ID of the application access token") @RequestMapping(value = URL_PROFILE_UPDATE, method = RequestMethod.POST) @ResponseBody public Profile updateProfile(@ApiParam("The profile's ID") @PathVariable(PATH_VAR_ID) String profileId, @ApiParam("The new username for the profile") @RequestParam(value = PARAM_USERNAME, required = false) String username, @ApiParam("The new password for the profile") @RequestParam(value = PARAM_PASSWORD, required = false) String password, @ApiParam("The new email for the profile") @RequestParam(value = PARAM_EMAIL, required = false) String email, @ApiParam("If the profile should be enabled or not") @RequestParam(value = PARAM_ENABLED, required = false) Boolean enabled, @ApiParam("The new roles for the profile") @RequestParam(value = PARAM_ROLE, required = false) Set<String> roles, @ApiParam("The attributes to update (specify a JSON string)") @RequestParam(value = PARAM_ATTRIBUTES, required = false) String serializedAttributes, @ApiParam("The name of the attributes to return (don't specify to return all)") @RequestParam(value = PARAM_ATTRIBUTE_TO_RETURN, required = false) String[] attributesToReturn) throws ProfileException { Map<String, Object> attributes = deserializeAttributes(serializedAttributes); return profileService.updateProfile(profileId, username, password, email, enabled, roles, attributes, attributesToReturn); } @ApiOperation("Enables a profile") @ApiImplicitParam(name = "accessTokenId", required = true, dataType = "string", paramType = "query", value = "The ID of the application access token") @RequestMapping(value = URL_PROFILE_ENABLE, method = RequestMethod.POST) @ResponseBody public Profile enableProfile(@ApiParam("The profile's ID") @PathVariable(PATH_VAR_ID) String profileId, @ApiParam("The name of the attributes to return (don't specify to return all)") @RequestParam(value = PARAM_ATTRIBUTE_TO_RETURN, required = false) String[] attributesToReturn) throws ProfileException { return profileService.enableProfile(profileId, attributesToReturn); } @ApiOperation("Disables a profile") @ApiImplicitParam(name = "accessTokenId", required = true, dataType = "string", paramType = "query", value = "The ID of the application access token") @RequestMapping(value = URL_PROFILE_DISABLE, method = RequestMethod.POST) @ResponseBody public Profile disableProfile(@ApiParam("The profile's ID") @PathVariable(PATH_VAR_ID) String profileId, @ApiParam("The name of the attributes to return (don't specify to return all)") @RequestParam(value = PARAM_ATTRIBUTE_TO_RETURN, required = false) String[] attributesToReturn) throws ProfileException { return profileService.disableProfile(profileId, attributesToReturn); } @ApiOperation("Assigns roles to a profile") @ApiImplicitParam(name = "accessTokenId", required = true, dataType = "string", paramType = "query", value = "The ID of the application access token") @RequestMapping(value = URL_PROFILE_ADD_ROLES, method = RequestMethod.POST) @ResponseBody public Profile addRoles(@ApiParam("The profile's ID") @PathVariable(PATH_VAR_ID) String profileId, @ApiParam("The roles to assign") @RequestParam(PARAM_ROLE) Collection<String> roles, @ApiParam("The name of the attributes to return (don't specify to return all)") @RequestParam(value = PARAM_ATTRIBUTE_TO_RETURN, required = false) String[] attributesToReturn) throws ProfileException { return profileService.addRoles(profileId, roles, attributesToReturn); } @ApiOperation("Removes assigned roles from a profile") @ApiImplicitParam(name = "accessTokenId", required = true, dataType = "string", paramType = "query", value = "The ID of the application access token") @RequestMapping(value = URL_PROFILE_REMOVE_ROLES, method = RequestMethod.POST) @ResponseBody public Profile removeRoles(@ApiParam("The profile's ID") @PathVariable(PATH_VAR_ID) String profileId, @ApiParam("The roles to remove") @RequestParam(PARAM_ROLE) Collection<String> roles, @ApiParam("The name of the attributes to return (don't specify to return all)") @RequestParam(value = PARAM_ATTRIBUTE_TO_RETURN, required = false) String[] attributesToReturn) throws ProfileException { return profileService.removeRoles(profileId, roles, attributesToReturn); } @ApiOperation("Sets the profile as verified if the verification token is valid") @ApiImplicitParam(name = "accessTokenId", required = true, dataType = "string", paramType = "query", value = "The ID of the application access token") @RequestMapping(value = URL_PROFILE_VERIFY, method = RequestMethod.POST) @ResponseBody public Profile verifyProfile( @ApiParam("The verification token ID") @RequestParam(PARAM_VERIFICATION_TOKEN_ID) String verificationTokenId, @ApiParam("The name of the attributes to return (don't specify to return all)") @RequestParam(value = PARAM_ATTRIBUTE_TO_RETURN, required = false) String[] attributesToReturn) throws ProfileException { return profileService.verifyProfile(verificationTokenId, attributesToReturn); } @ApiOperation("Returns the attributes of a profile") @ApiImplicitParam(name = "accessTokenId", required = true, dataType = "string", paramType = "query", value = "The ID of the application access token") @RequestMapping(value = URL_PROFILE_GET_ATTRIBUTES, method = RequestMethod.GET) @ResponseBody public Map<String, Object> getAttributes(@ApiParam("The profile's ID") @PathVariable(PATH_VAR_ID) String profileId, @ApiParam("The name of the attributes to return (don't specify to " + "return all)") @RequestParam(value = PARAM_ATTRIBUTE_TO_RETURN, required = false) String[] attributesToReturn) throws ProfileException { return profileService.getAttributes(profileId, attributesToReturn); } @ApiOperation(value = "Updates the attributes of a profile", notes = "The specified attributes will be merged " + "with existing attributes") @ApiImplicitParam(name = "accessTokenId", required = true, dataType = "string", paramType = "query", value = "The ID of the application access token") @RequestMapping(value = URL_PROFILE_UPDATE_ATTRIBUTES, method = RequestMethod.POST) @ResponseBody public Profile updateAttributes(@ApiParam("The profile's ID") @PathVariable(PATH_VAR_ID) String profileId, @ApiParam("The new attributes") @RequestBody Map<String, Object> attributes, @ApiParam("The name of the attributes to return (don't specify to return all)") @RequestParam(value = PARAM_ATTRIBUTE_TO_RETURN, required = false) String[] attributesToReturn) throws ProfileException { return profileService.updateAttributes(profileId, attributes, attributesToReturn); } @ApiOperation("Removes a list of attributes of a profile") @ApiImplicitParam(name = "accessTokenId", required = true, dataType = "string", paramType = "query", value = "The ID of the application access token") @RequestMapping(value = URL_PROFILE_REMOVE_ATTRIBUTES, method = RequestMethod.POST) @ResponseBody public Profile removeAttributes(@ApiParam("The profile's ID") @PathVariable(PATH_VAR_ID) String profileId, @ApiParam("The name of the attributes to remove") @RequestParam(PARAM_ATTRIBUTE_NAME) Collection<String> attributeNames, @ApiParam("The name of the attributes to return (don't specify to return all)") @RequestParam(value = PARAM_ATTRIBUTE_TO_RETURN, required = false) String[] attributesToReturn) throws ProfileException { return profileService.removeAttributes(profileId, attributeNames, attributesToReturn); } @ApiOperation("Deletes a profile") @ApiImplicitParam(name = "accessTokenId", required = true, dataType = "string", paramType = "query", value = "The ID of the application access token") @RequestMapping(value = URL_PROFILE_DELETE_PROFILE, method = RequestMethod.POST) @ResponseStatus(HttpStatus.OK) public void deleteProfile( @ApiParam("The profile's ID") @PathVariable(PATH_VAR_ID) String profileId) throws ProfileException { profileService.deleteProfile(profileId); } @ApiOperation("Returns the single profile that matches the specified query") @ApiImplicitParam(name = "accessTokenId", required = true, dataType = "string", paramType = "query", value = "The ID of the application access token") @RequestMapping(value = URL_PROFILE_GET_ONE_BY_QUERY, method = RequestMethod.GET) @ResponseBody public Profile getProfileByQuery(@ApiParam("The tenant's name") @RequestParam(PARAM_TENANT_NAME) String tenantName, @ApiParam("The Mongo query used to search for the profiles. Must not contain " + "the $where operator, the tenant's name (already specified) or any " + "non-readable attribute by the application") @RequestParam(PARAM_QUERY) String query, @ApiParam("The name of the attributes to return (don't specify to return all)") @RequestParam(value = PARAM_ATTRIBUTE_TO_RETURN, required = false) String[] attributesToReturn) throws ProfileException { return profileService.getProfileByQuery(tenantName, query, attributesToReturn); } @ApiOperation("Returns the profile for the specified ID") @ApiImplicitParam(name = "accessTokenId", required = true, dataType = "string", paramType = "query", value = "The ID of the application access token") @RequestMapping(value = URL_PROFILE_GET, method = RequestMethod.GET) @ResponseBody public Profile getProfile(@ApiParam("The profile's ID") @PathVariable(PATH_VAR_ID) String profileId, @ApiParam("The name of the attributes to return (don't specify to return all)") @RequestParam(value = PARAM_ATTRIBUTE_TO_RETURN, required = false) String[] attributesToReturn) throws ProfileException { return profileService.getProfile(profileId, attributesToReturn); } @ApiOperation("Returns the user for the specified tenant and username") @ApiImplicitParam(name = "accessTokenId", required = true, dataType = "string", paramType = "query", value = "The ID of the application access token") @RequestMapping(value = URL_PROFILE_GET_BY_USERNAME, method = RequestMethod.GET) @ResponseBody public Profile getProfileByUsername( @ApiParam("The tenant's name") @RequestParam(PARAM_TENANT_NAME) String tenantName, @ApiParam("The profile's username") @RequestParam(PARAM_USERNAME) String username, @ApiParam("The name of the attributes to return (don't specify to return all)") @RequestParam(value = PARAM_ATTRIBUTE_TO_RETURN, required = false) String[] attributesToReturn) throws ProfileException { return profileService.getProfileByUsername(tenantName, username, attributesToReturn); } @ApiOperation("Returns the profile for the specified ticket") @ApiImplicitParam(name = "accessTokenId", required = true, dataType = "string", paramType = "query", value = "The ID of the application access token") @RequestMapping(value = URL_PROFILE_GET_BY_TICKET, method = RequestMethod.GET) @ResponseBody public Profile getProfileByTicket( @ApiParam("The ID ticket of the authenticated profile") @RequestParam(PARAM_TICKET_ID) String ticketId, @ApiParam("The name of the attributes to return (don't specify to return all)") @RequestParam(value = PARAM_ATTRIBUTE_TO_RETURN, required = false) String[] attributesToReturn) throws ProfileException { return profileService.getProfileByTicket(ticketId, attributesToReturn); } @ApiOperation("Returns the number of profiles of the specified tenant") @ApiImplicitParam(name = "accessTokenId", required = true, dataType = "string", paramType = "query", value = "The ID of the application access token") @RequestMapping(value = URL_PROFILE_GET_COUNT, method = RequestMethod.GET) @ResponseBody public long getProfileCount( @ApiParam("The tenant's name") @RequestParam(PARAM_TENANT_NAME) String tenantName) throws ProfileException { return profileService.getProfileCount(tenantName); } @ApiOperation("Returns the number of profiles that match the query for the specified tenant") @ApiImplicitParam(name = "accessTokenId", required = true, dataType = "string", paramType = "query", value = "The ID of the application access token") @RequestMapping(value = URL_TENANT_COUNT_BY_QUERY, method = RequestMethod.GET) @ResponseBody public long getProfileCount(@ApiParam("The tenant's name") @RequestParam(PARAM_TENANT_NAME) String tenantName, @ApiParam("The Mongo query used to search for the profiles. Must not contain " + "the $where operator, the tenant's name (already specified) or any " + "non-readable attribute by the application") @RequestParam(PARAM_QUERY) String query) throws ProfileException { return profileService.getProfileCountByQuery(tenantName, query); } @ApiOperation("Returns the profiles that match the specified query") @ApiImplicitParam(name = "accessTokenId", required = true, dataType = "string", paramType = "query", value = "The ID of the application access token") @RequestMapping(value = URL_PROFILE_GET_BY_QUERY, method = RequestMethod.GET) @ResponseBody public List<Profile> getProfilesByQuery( @ApiParam("The tenant's name") @RequestParam(PARAM_TENANT_NAME) String tenantName, @ApiParam("The Mongo query used to search for the profiles. Must not " + "contain the $where operator, the tenant's name (already specified) " + "or any non-readable attribute by the application") @RequestParam(PARAM_QUERY) String query, @ApiParam("Profile attribute to sort the list by") @RequestParam(value = PARAM_SORT_BY, required = false) String sortBy, @ApiParam("The sort order (either ASC or DESC)") @RequestParam(value = PARAM_SORT_ORDER, required = false) SortOrder sortOrder, @ApiParam("From the entire list of results, the position where the " + "actual results should start (useful " + "for pagination)") @RequestParam(value = PARAM_START, required = false) Integer start, @ApiParam("The number of profiles to return") @RequestParam(value = PARAM_COUNT, required = false) Integer count, @ApiParam("The name of the attributes to return (don't specify to " + "return all)") @RequestParam(value = PARAM_ATTRIBUTE_TO_RETURN, required = false) String[] attributesToReturn) throws ProfileException { return profileService.getProfilesByQuery(tenantName, query, sortBy, sortOrder, start, count, attributesToReturn); } @ApiOperation("Returns a list of profiles for the specified list of IDs") @ApiImplicitParam(name = "accessTokenId", required = true, dataType = "string", paramType = "query", value = "The ID of the application access token") @RequestMapping(value = URL_PROFILE_GET_BY_IDS, method = RequestMethod.GET) @ResponseBody public Iterable<Profile> getProfileByIds( @ApiParam("The IDs of the profiles to look for") @RequestParam(PATH_VAR_ID) List<String> profileIds, @ApiParam("Profile attribute to sort the list by") @RequestParam(value = PARAM_SORT_BY, required = false) String sortBy, @ApiParam("The sort order (either ASC or DESC)") @RequestParam(value = PARAM_SORT_ORDER, required = false) SortOrder sortOrder, @ApiParam("The name of the attributes to return (don't specify to " + "return all)") @RequestParam(value = PARAM_ATTRIBUTE_TO_RETURN, required = false) String[] attributesToReturn) throws ProfileException { return profileService.getProfilesByIds(profileIds, sortBy, sortOrder, attributesToReturn); } @ApiOperation("Returns a range of profiles for the specified tenant") @ApiImplicitParam(name = "accessTokenId", required = true, dataType = "string", paramType = "query", value = "The ID of the application access token") @RequestMapping(value = URL_PROFILE_GET_RANGE, method = RequestMethod.GET) @ResponseBody public Iterable<Profile> getProfileRange( @ApiParam("The tenant's name") @RequestParam(PARAM_TENANT_NAME) String tenantName, @ApiParam("Profile attribute to sort the list by") @RequestParam(value = PARAM_SORT_BY, required = false) String sortBy, @ApiParam("The sort order (either ASC or DESC)") @RequestParam(value = PARAM_SORT_ORDER, required = false) SortOrder sortOrder, @ApiParam("From the entire list of results, the position where the actual results should start (useful " + "for pagination)") @RequestParam(value = PARAM_START, required = false) Integer start, @ApiParam("The number of profiles to return") @RequestParam(value = PARAM_COUNT, required = false) Integer count, @ApiParam("The name of the attributes to return (don't specify to " + "return all)") @RequestParam(value = PARAM_ATTRIBUTE_TO_RETURN, required = false) String[] attributesToReturn) throws ProfileException { return profileService.getProfileRange(tenantName, sortBy, sortOrder, start, count, attributesToReturn); } @ApiOperation("Returns a list of profiles for a specific role and tenant") @ApiImplicitParam(name = "accessTokenId", required = true, dataType = "string", paramType = "query", value = "The ID of the application access token") @RequestMapping(value = URL_PROFILE_GET_BY_ROLE, method = RequestMethod.GET) @ResponseBody public Iterable<Profile> getProfilesByRole( @ApiParam("The tenant's name") @RequestParam(PARAM_TENANT_NAME) String tenantName, @ApiParam("The role's name") @RequestParam(PARAM_ROLE) String role, @ApiParam("Profile attribute to sort the list by") @RequestParam(value = PARAM_SORT_BY, required = false) String sortBy, @ApiParam("The sort order (either ASC or DESC)") @RequestParam(value = PARAM_SORT_ORDER, required = false) SortOrder sortOrder, @ApiParam("The name of the attributes to return (don't specify to " + "return all)") @RequestParam(value = PARAM_ATTRIBUTE_TO_RETURN, required = false) String[] attributesToReturn) throws ProfileException { return profileService.getProfilesByRole(tenantName, role, sortBy, sortOrder, attributesToReturn); } @ApiOperation("Returns the list of profiles that have the given attribute, with any value") @ApiImplicitParam(name = "accessTokenId", required = true, dataType = "string", paramType = "query", value = "The ID of the application access token") @RequestMapping(value = URL_PROFILE_GET_BY_EXISTING_ATTRIB, method = RequestMethod.GET) @ResponseBody public Iterable<Profile> getProfilesByExistingAttribute( @ApiParam("The tenant's name") @RequestParam(PARAM_TENANT_NAME) String tenantName, @ApiParam("The name of the attribute profiles must have") @RequestParam(PARAM_ATTRIBUTE_NAME) String attributeName, @ApiParam("Profile attribute to sort the list by") @RequestParam(value = PARAM_SORT_BY, required = false) String sortBy, @ApiParam("The sort order (either ASC or DESC)") @RequestParam(value = PARAM_SORT_ORDER, required = false) SortOrder sortOrder, @ApiParam("The name of the attributes to return (don't " + "specify to return all)") @RequestParam(value = PARAM_ATTRIBUTE_TO_RETURN, required = false) String[] attributesToReturn) throws ProfileException { return profileService.getProfilesByExistingAttribute(tenantName, attributeName, sortBy, sortOrder, attributesToReturn); } @ApiOperation("Returns the list of profiles that have the given attribute with the given value") @ApiImplicitParam(name = "accessTokenId", required = true, dataType = "string", paramType = "query", value = "The ID of the application access token") @RequestMapping(value = URL_PROFILE_GET_BY_ATTRIB_VALUE, method = RequestMethod.GET) @ResponseBody public Iterable<Profile> getProfilesByAttributeValue( @ApiParam("The tenant's name") @RequestParam(PARAM_TENANT_NAME) String tenantName, @ApiParam("The name of the attribute profiles must have") @RequestParam(PARAM_ATTRIBUTE_NAME) String attributeName, @ApiParam("The value of the attribute profiles must have") @RequestParam(PARAM_ATTRIBUTE_VALUE) String attributeValue, @ApiParam("Profile attribute to sort the list by") @RequestParam(value = PARAM_SORT_BY, required = false) String sortBy, @ApiParam("The sort order (either ASC or DESC)") @RequestParam(value = PARAM_SORT_ORDER, required = false) SortOrder sortOrder, @ApiParam("The name of the attributes to return (don't " + "specify to return all)") @RequestParam(value = PARAM_ATTRIBUTE_TO_RETURN, required = false) String[] attributesToReturn) throws ProfileException { return profileService.getProfilesByAttributeValue(tenantName, attributeName, attributeValue, sortBy, sortOrder, attributesToReturn); } @ApiOperation("Sends an email to the profile's user to indicate that the password needs to be reset") @ApiImplicitParam(name = "accessTokenId", required = true, dataType = "string", paramType = "query", value = "The ID of the application access token") @RequestMapping(value = URL_PROFILE_RESET_PASSWORD, method = RequestMethod.POST) @ResponseBody public Profile resetPassword(@ApiParam("The profile's ID") @PathVariable(PATH_VAR_ID) String profileId, @ApiParam("The base URL to use to build the final URL the profile will use to " + "reset their password.") @RequestParam(PARAM_RESET_PASSWORD_URL) String resetPasswordUrl, @ApiParam("The name of the attributes to return (don't specify to return all)") @RequestParam(value = PARAM_ATTRIBUTE_TO_RETURN, required = false) String[] attributesToReturn) throws ProfileException { return profileService.resetPassword(profileId, resetPasswordUrl, attributesToReturn); } @ApiOperation("Resets a profile's password") @ApiImplicitParam(name = "accessTokenId", required = true, dataType = "string", paramType = "query", value = "The ID of the application access token") @RequestMapping(value = URL_PROFILE_CHANGE_PASSWORD, method = RequestMethod.POST) @ResponseBody public Profile changePassword( @ApiParam("The reset token ID") @RequestParam(PARAM_RESET_TOKEN_ID) String resetTokenId, @ApiParam("The new password") @RequestParam(PARAM_NEW_PASSWORD) String newPassword, @ApiParam("The name of the attributes to return (don't specify to return all)") @RequestParam(value = PARAM_ATTRIBUTE_TO_RETURN, required = false) String[] attributesToReturn) throws ProfileException { return profileService.changePassword(resetTokenId, newPassword, attributesToReturn); } @ApiOperation(value = "Creates a token that can be sent to the user in an email as a link", notes = "After the user clicks the link, the token then can be passed to verifyProfile or " + "changePassword to verify that the user agrees") @ApiImplicitParam(name = "accessTokenId", required = true, dataType = "string", paramType = "query", value = "The ID of the application access token") @RequestMapping(value = URL_PROFILE_CREATE_VERIFICATION_TOKEN, method = RequestMethod.POST) @ResponseBody public VerificationToken createVerificationToken( @ApiParam("The profile ID of the user that needs to be contacted") @PathVariable(PATH_VAR_ID) String profileId) throws ProfileException { return profileService.createVerificationToken(profileId); } @ApiOperation(value = "Returns the verification token that corresponds to the given ID") @ApiImplicitParam(name = "accessTokenId", required = true, dataType = "string", paramType = "query", value = "The ID of the application access token") @RequestMapping(value = URL_PROFILE_GET_VERIFICATION_TOKEN, method = RequestMethod.GET) @ResponseBody public VerificationToken getVerificationToken( @ApiParam("The token ID") @PathVariable(PATH_VAR_ID) String tokenId) throws ProfileException { return profileService.getVerificationToken(tokenId); } @ApiOperation(value = "Deletes a verification token when it's not needed anymore", notes = "Not necessary to call if verifyProfile or changePassword, since they already delete the " + "token") @ApiImplicitParam(name = "accessTokenId", required = true, dataType = "string", paramType = "query", value = "The ID of the application access token") @RequestMapping(value = URL_PROFILE_DELETE_VERIFICATION_TOKEN, method = RequestMethod.POST) @ResponseStatus(HttpStatus.OK) public void deleteVerificationToken( @ApiParam("The ID of the token to delete") @PathVariable(PATH_VAR_ID) String tokenId) throws ProfileException { profileService.deleteVerificationToken(tokenId); } @ResponseBody @RequestMapping(value = URL_PROFILE_UPLOAD_ATTACHMENT,method = RequestMethod.POST) @ApiOperation(value = "Upload a attachment to the current profile.", notes = "If the mime type of the attachment is not on the valid list will fail") @ApiImplicitParam(name = "attachment", required = true, dataType = "file", paramType = "file", value = "File to be uploaded") public ProfileAttachment uploadProfileAttachment(@ApiParam("The profile's ID") @PathVariable(PATH_VAR_ID) String profileId,MultipartFile attachment) throws ProfileException { final Profile profile = profileService.getProfile(profileId); if(profile!=null) { try { return profileService.addProfileAttachment(profile.getId().toString(),attachment.getOriginalFilename(), attachment.getInputStream()); } catch (IOException e) { throw new ProfileException("Unable to upload Attachment",e); } } throw new NoSuchProfileException(profileId); } @RequestMapping(value = URL_PROFILE_GET_ATTACHMENTS,method = RequestMethod.GET) @ResponseBody @ApiOperation(value = "Gets all attachments for the given Profile", notes = "If profile does not exist") public List<ProfileAttachment> getAttachments(@ApiParam("The profile's ID") @PathVariable(PATH_VAR_ID) String profileId) throws ProfileException,IOException { final Profile profile = profileService.getProfile(profileId); if(profile!=null) { return profileService.getProfileAttachments(profile.getId().toString()); } throw new NoSuchProfileException(profileId); } @RequestMapping(value = URL_PROFILE_GET_ATTACHMENTS_DETAILS,method = RequestMethod.GET) @ResponseBody @ApiOperation(value = "Gets all attachments for the given Profile", notes = "If profile does not exist") public ProfileAttachment getAttachmentDetails(@ApiParam("The profile's ID") @PathVariable(PATH_VAR_ID) String profileId,@ApiParam("Attachment Id to get") @PathVariable(PATH_VAR_ATTACHMENT) String attachmentId) throws ProfileException,IOException { final Profile profile = profileService.getProfile(profileId); if(profile!=null) { return profileService.getProfileAttachmentInformation(profile.getId().toString(),attachmentId); } throw new NoSuchProfileException(profileId); } @RequestMapping(value = URL_PROFILE_GET_ATTACHMENT,method = RequestMethod.GET) @ApiOperation(value = "Gets the requested attachment of the given profile", notes = "If Attachment or profile does not exist will throw error, content-type,content-legnth headers are set") public void getAttachment(@ApiParam("The profile's ID") @PathVariable(PATH_VAR_ID) String profileId, @ApiParam("Attachment Id to get") @PathVariable(PATH_VAR_ATTACHMENT) String attachmentId, HttpServletResponse response) throws ProfileException,IOException { final Profile profile = profileService.getProfile(profileId); if(profile!=null) { InputStream input=null; try { input = profileService.getProfileAttachment(attachmentId, profile.getId().toString()); if(input!=null) { final ProfileAttachment attachment = profileService.getProfileAttachmentInformation(profile.getId().toString(), attachmentId); response.setContentType(attachment.getContentType()); response.setContentLength((int)attachment.getFileSizeBytes()); IOUtils.copy(input, response.getOutputStream()); } } catch (ProfileException ex) { response.sendError(HttpServletResponse.SC_NOT_FOUND); response.setContentLength(0); } finally { if(input!=null){ input.close(); } } } throw new NoSuchProfileException(profileId); } protected Map<String, Object> deserializeAttributes(String serializedAttributes) throws ParamDeserializationException { Map<String, Object> attributes = null; if (StringUtils.isNotEmpty(serializedAttributes)) { try { attributes = objectMapper.readValue(serializedAttributes, ATTRIBUTES_TYPE_REFERENCE); } catch (IOException e) { throw new ParamDeserializationException(e); } } return attributes; } }