package org.fluxtream.core.api; import com.wordnik.swagger.annotations.*; import org.fluxtream.core.Configuration; import org.fluxtream.core.api.models.LoggedInGuestModel; import org.fluxtream.core.auth.AuthHelper; import org.fluxtream.core.auth.FlxUserDetails; import org.fluxtream.core.domain.Guest; import org.fluxtream.core.domain.GuestDetails; import org.fluxtream.core.domain.oauth2.AuthorizationToken; import org.fluxtream.core.services.GuestService; import org.fluxtream.core.services.OAuth2MgmtService; import org.fluxtream.core.services.impl.ExistingEmailException; import org.fluxtream.core.services.impl.UsernameAlreadyTakenException; import org.joda.time.DateTime; import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Scope; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.authentication.BadCredentialsException; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.Authentication; import org.springframework.stereotype.Component; import javax.ws.rs.*; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import java.io.UnsupportedEncodingException; import java.net.URISyntaxException; /** * Created by candide on 22/12/14. */ @Component("RESTMobileGuestController") @Scope("request") @Path("/v1/mobile") @Api(value = "/v1/mobile", description = "Mobile Signin & Registration API") public class MobileGuestController { @Autowired Configuration env; @Autowired GuestService guestService; @Autowired AuthenticationManager authenticationManager; @Autowired OAuth2MgmtService oAuth2MgmtService; @Autowired BeanFactory beanFactory; @GET @Path("/guest") @ApiOperation(value = "Get detailed info about ", response = LoggedInGuestModel.class) @Produces(MediaType.APPLICATION_JSON) public Response getLoggedInGuestInfo(@ApiParam(value="The device ID", required=true) @QueryParam("device_id") final String deviceId) { final Guest guest = AuthHelper.getGuest(); final AuthorizationToken authorizationToken = oAuth2MgmtService.getAuthorizationToken(guest.getId(), deviceId, new DateTime().plusYears(1000).getMillis()); final GuestDetails details = guestService.getGuestDetails(guest.getId()); LoggedInGuestModel info = new LoggedInGuestModel(guest, details, authorizationToken.accessToken); return Response.ok(info).build(); } @POST @Path("/signup") @ApiOperation(value = "Sign a new user up") @ApiResponses({ @ApiResponse(code = 400, message = "If either username is already taken, email is already used or password is too short - " + "the reason is given in the response body") }) @Produces(MediaType.APPLICATION_JSON) public Response register(@ApiParam(value="E-mail", required=true) @FormParam("email") final String email, @ApiParam(value="Username", required=true) @FormParam("username") final String username, @ApiParam(value="First name", required=true) @FormParam("firstname") final String firstname, @ApiParam(value="Last name", required=true) @FormParam("lastname") final String lastname, @ApiParam(value="Password", required=true) @FormParam("password") final String password, @ApiParam(value="The device ID", required=true) @FormParam("device_id") final String deviceId) throws URISyntaxException, UnsupportedEncodingException { if (password.length()<8) { return Response.status(Response.Status.BAD_REQUEST).entity("Password is too short").build(); } try { final Guest guest = guestService.createGuest(username, firstname, lastname, password, email, Guest.RegistrationMethod.REGISTRATION_METHOD_FORM, null); final AuthorizationToken authorizationToken = oAuth2MgmtService.getAuthorizationToken(guest.getId(), deviceId, new DateTime().plusYears(1000).getMillis()); final GuestDetails details = guestService.getGuestDetails(guest.getId()); LoggedInGuestModel info = new LoggedInGuestModel(guest, details, authorizationToken.accessToken); return Response.ok(info).build(); } catch (ExistingEmailException e) { return Response.status(Response.Status.BAD_REQUEST).entity("This e-mail address is already used").build(); } catch (UsernameAlreadyTakenException e) { return Response.status(Response.Status.BAD_REQUEST).entity("This username is already taken").build(); } } @POST @Path("/signin") @ApiOperation(value = "Basic sign-in") @ApiResponses({ @ApiResponse(code = 401, message = "on bad credentials") }) @Produces(MediaType.APPLICATION_JSON) public Response mobileSignin(@ApiParam(value="Username", required=true) @FormParam("username") final String usernameOrEmail, @ApiParam(value="Password", required=true) @FormParam("password") final String password, @ApiParam(value="The device ID", required=true) @FormParam("device_id") final String deviceId) throws UnsupportedEncodingException { Authentication authentication = getAuthentication(usernameOrEmail, password); if (authentication==null||!authentication.isAuthenticated()) { Guest guest = guestService.getGuestByEmail(usernameOrEmail); if (guest==null) return Response.status(Response.Status.UNAUTHORIZED).build(); authentication = getAuthentication(guest.username, password); } if (authentication!=null&&authentication.isAuthenticated()) { FlxUserDetails principal = (FlxUserDetails) authentication.getPrincipal(); Guest guest = principal.getGuest(); final AuthorizationToken authorizationToken = oAuth2MgmtService.getAuthorizationToken(guest.getId(), deviceId, new DateTime().plusYears(1000).getMillis()); final GuestDetails details = guestService.getGuestDetails(guest.getId()); LoggedInGuestModel info = new LoggedInGuestModel(guest, details, authorizationToken.accessToken); return Response.ok(info).build(); } else return Response.status(Response.Status.UNAUTHORIZED).build(); } private Authentication getAuthentication(String username, String password) { UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(username, password); Authentication authentication = null; try {authentication = authenticationManager.authenticate(authRequest);} catch (Throwable t) {/*ignore authentication errors*/} return authentication; } }