package com.porterhead.user.resource; import com.porterhead.resource.BaseResource; import com.porterhead.user.Role; import com.porterhead.user.User; import com.porterhead.user.UserService; import com.porterhead.user.VerificationTokenService; import com.porterhead.user.api.ApiUser; import com.porterhead.user.api.CreateUserRequest; import com.porterhead.user.api.CreateUserResponse; import com.porterhead.user.api.UpdateUserRequest; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.security.oauth2.common.OAuth2AccessToken; import org.springframework.security.oauth2.provider.ClientDetails; import org.springframework.security.oauth2.provider.ClientDetailsService; import org.springframework.security.oauth2.provider.OAuth2Authentication; import org.springframework.security.oauth2.provider.OAuth2Request; import org.springframework.security.oauth2.provider.token.DefaultTokenServices; import org.springframework.stereotype.Component; import org.springframework.util.StringUtils; import javax.annotation.security.PermitAll; import javax.annotation.security.RolesAllowed; import javax.ws.rs.*; import javax.ws.rs.core.*; import java.io.Serializable; import java.net.URI; import java.util.*; @Path("/v1.0/users") @Component @Produces({MediaType.APPLICATION_JSON}) @Consumes({MediaType.APPLICATION_JSON}) public class UserResource extends BaseResource { private UserService userService; private VerificationTokenService verificationTokenService; private DefaultTokenServices tokenServices; private PasswordEncoder passwordEncoder; private ClientDetailsService clientDetailsService; public UserResource(){} @Autowired public UserResource(final UserService userService, final VerificationTokenService verificationTokenService, final DefaultTokenServices defaultTokenServices, final PasswordEncoder passwordEncoder, ClientDetailsService clientDetailsService) { this.userService = userService; this.verificationTokenService = verificationTokenService; this.tokenServices = defaultTokenServices; this.passwordEncoder = passwordEncoder; this.clientDetailsService = clientDetailsService; } @PermitAll @POST public Response signupUser(final CreateUserRequest request, @Context SecurityContext sc, @Context UriInfo uriInfo) { ApiUser user = userService.createUser(request); CreateUserResponse createUserResponse = new CreateUserResponse(user, createTokenForNewUser( user.getId(), request.getPassword().getPassword(), sc.getUserPrincipal().getName())); verificationTokenService.sendEmailRegistrationToken(createUserResponse.getApiUser().getId()); URI location = uriInfo.getAbsolutePathBuilder().path(createUserResponse.getApiUser().getId()).build(); return Response.created(location).entity(createUserResponse).build(); } @RolesAllowed({"ROLE_USER"}) @Path("{id}") @GET public ApiUser getUser(final @PathParam("id") String userId, final @Context SecurityContext securityContext) { User requestingUser = ensureUserIsAuthorized(securityContext, userId); return userService.getUser(requestingUser.getId()); } private OAuth2AccessToken createTokenForNewUser(String userId, String password, String clientId) { String hashedPassword = passwordEncoder.encode(password); UsernamePasswordAuthenticationToken userAuthentication = new UsernamePasswordAuthenticationToken( userId, hashedPassword, Collections.singleton(new SimpleGrantedAuthority(Role.ROLE_USER.toString()))); ClientDetails authenticatedClient = clientDetailsService.loadClientByClientId(clientId); OAuth2Request oAuth2Request = createOAuth2Request(null, clientId, Collections.singleton(new SimpleGrantedAuthority(Role.ROLE_USER.toString())), true, authenticatedClient.getScope(), null, null, null, null); OAuth2Authentication oAuth2Authentication = new OAuth2Authentication(oAuth2Request, userAuthentication); return tokenServices.createAccessToken(oAuth2Authentication); } @RolesAllowed({"ROLE_USER"}) @Path("{userId}") @PUT public Response updateUser(@Context SecurityContext sc, @PathParam("userId") String userId, UpdateUserRequest request) { User requestingUser = ensureUserIsAuthorized(sc, userId); boolean sendVerificationToken = StringUtils.hasLength(request.getEmailAddress()) && !request.getEmailAddress().equals(requestingUser.getEmailAddress()); ApiUser savedUser = userService.saveUser(userId, request); if(sendVerificationToken) { verificationTokenService.sendEmailVerificationToken(savedUser.getId()); } return Response.ok().build(); } private OAuth2Request createOAuth2Request(Map<String, String> requestParameters, String clientId, Collection<? extends GrantedAuthority> authorities, boolean approved, Collection<String> scope, Set<String> resourceIds, String redirectUri, Set<String> responseTypes, Map<String, Serializable> extensionProperties) { return new OAuth2Request(requestParameters, clientId, authorities, approved, scope == null ? null : new LinkedHashSet<String>(scope), resourceIds, redirectUri, responseTypes, extensionProperties); } }