GamigoAuthServiceImpl

package com.tgi.platform.account.service.impl;

import com.tgi.platform.account.dao.AccountHistoryDao;

import com.tgi.platform.account.domain.RegisteredUser;

import com.tgi.platform.account.dto.AuthenticatedUserResponse;

import com.tgi.platform.account.dto.ReserveUserResponse;

import com.tgi.platform.account.service.AuthService;

import com.tgi.platform.account.service.GamigoAuthService;

import com.tgi.platform.account.service.UserReservationService;

import com.tgi.platform.account.service.UserService;

import com.tgi.platform.account.service.impl.gamigoauth.GamigoAuthenticationExceptionWrapper;

import com.tgi.platform.account.service.impl.gamigoauth.GamigoAuthenticationResult;

import com.tgi.platform.account.service.impl.gamigoauth.TestAuthenticationServiceService;

import com.tgi.platform.dto.ErrorResponse;

import com.tgi.platform.dto.ResponseI;

import com.tgi.platform.exceptions.ExceptionCode;

import com.tgi.platform.exceptions.GeneralException;

import org.apache.commons.codec.binary.Hex;

import org.apache.commons.lang.StringUtils;

import org.apache.log4j.Logger;

import org.springframework.beans.factory.annotation.Autowired;

import java.io.UnsupportedEncodingException;

import java.security.MessageDigest;

import java.security.NoSuchAlgorithmException;

import java.util.ArrayList;

import java.util.concurrent.*;

import static com.tgi.platform.PlatformConstants.FAILURE;

import static com.tgi.platform.PlatformConstants.SUCCESS;

import static com.tgi.platform.exceptions.ExceptionCode.*;

import static com.tgi.platform.messages.UserMessages.*;

public class GamigoAuthServiceImpl

implements AuthService {

private static Logger log = Logger.getLogger(GamigoAuthServiceImpl.class);

@Autowired

AccountHistoryDao accountHistoryDao;

@Autowired

UserService userService;

@Autowired

private UserReservationService userReservationService;

private final TestAuthenticationServiceService service = new TestAuthenticationServiceService();

private static final ThreadGroup group = new ThreadGroup(GamigoAuthServiceImpl.class.getName());

private static int threadCount = 0;

private final ExecutorService executorService = Executors.newFixedThreadPool(10, new ThreadFactory() {

public Thread newThread(Runnable r) {

return new Thread(group, r, group.getName() + " " + threadCount++);

}

});

public ResponseI authenticateUser(String ipAddr,

final String userName,

String password,

String gameSKU,

String getDisplayName) {

log.info("Executing service authenticateUser with params:" + " userName=" + userName + " password=**** gameSku=" + gameSKU);

if (StringUtils.isBlank(gameSKU)) {

return new ErrorResponse(Missing_Game_SKU, missing_GameSku);

}

if (StringUtils.isBlank(ipAddr)) {

return new ErrorResponse(Missing_Value, missing_IpAddr);

}

if (StringUtils.isBlank(userName)) {

return new ErrorResponse(Missing_Value, missing_UserName);

}

if (StringUtils.isBlank(password)) {

return new ErrorResponse(Missing_Value, missing_PWD);

}

String opResult;

String opDesc = "";

final String encodedPassword;

GamigoAuthenticationResult gamigoAuthResult;

ResponseI theResponse;

try {

encodedPassword = Hex.encodeHexString(MessageDigest.getInstance("SHA-256").digest(password.getBytes("UTF-8")));

Callable<GamigoAuthenticationResult> callable = new Callable<GamigoAuthenticationResult>() {

public GamigoAuthenticationResult call() throws Exception {

return service.getTestAuthenticationServicePort().authenticate(userName, encodedPassword);

}

};

Future<GamigoAuthenticationResult> authenticationResultFuture = executorService.submit(callable);

gamigoAuthResult = authenticationResultFuture.get(10, TimeUnit.SECONDS);// blocking call

// Handle codes

switch (gamigoAuthResult.getCode()) {

case SUCCESS:

opResult = SUCCESS;

theResponse = new AuthenticatedUserResponse();

((AuthenticatedUserResponse) theResponse).setUid(gamigoAuthResult.getGameAccountId());

if (getDisplayName != null && getDisplayName.equalsIgnoreCase("yes")) {

((AuthenticatedUserResponse) theResponse).setDisplayName(gamigoAuthResult.getUsername());

}

// theResponse.setTgt(gamigoAuthResult.get); Don't have anything from Gamigo for this at the moment.

// Create a user in LDAP

ResponseI reservationResponse = userService.reserveUser(userName,

GamigoAuthService.GAMIGO_PWD_PLACEHOLDER,

GamigoAuthService.GAMIGO_DATE_PLACEHOLDER,

userName + GamigoAuthService.GAMIGO_EMAILDOMAIN_PLACEHOLDER,

ipAddr,

"",

"",

gameSKU,

userName);

if (reservationResponse instanceof ReserveUserResponse) { // Success case

String reservationCode = ((ReserveUserResponse) reservationResponse).getReservationCode();

// Handle setting the UID on the account. This is a special case because Gamigo supplies the UID, whereas in other cases

// we create one ourselves.

RegisteredUser registeredUser;

synchronized (this) {

registeredUser = userReservationService.getUserReservation(reservationCode);

}

if (registeredUser == null) {

throw new GeneralException(Reservation_Not_Found, "Unable to find reservation associated with " + reservationCode);

}

registeredUser.getTgiAccount().setUid(gamigoAuthResult.getGameAccountId());

// Now create the user with that reservationCode

userService.createUser(reservationCode);

}

else if (reservationResponse instanceof ErrorResponse) { // error case

// If an error occurs here, it's incidental to authentication. Log it, but otherwise, do nothing.

ErrorResponse errorResponse = (ErrorResponse) reservationResponse;

boolean duplicateAccount = errorResponse.getCode() == User_Name_Taken.getCode() ||

errorResponse.getCode() == Email_Taken.getCode() || errorResponse.getCode() == Display_Name_Taken.getCode();

if (duplicateAccount) {

log.error("LDAP account for " + userName + " already existed. Odd.");

}

if (errorResponse.getCode() == ExceptionCode.Reservation_Not_Found.getCode()) {

log.error("Failed to create LDAP account for " + userName + " : " + errorResponse.getErrorMessage());

}

}

break;

case UNKNOWN_USERNAME:

theResponse = new ErrorResponse(User_Not_Found, auth_deny_user_passwd);

opResult = FAILURE;

break;

case USER_BANNED:

theResponse = new ErrorResponse(User_Banned, auth_deny_ban);

opResult = FAILURE;

break;

case AUTHENTICATION_FAILED:

theResponse = new ErrorResponse(User_Pwd_Not_Found, auth_deny_user_passwd);

opResult = FAILURE;

break;

default:

theResponse = new ErrorResponse(External_Error, External_Error.getCode() + ": Unknown error code from Gamigo auth server: [" + gamigoAuthResult.getCode() + "]");

opResult = FAILURE;

break;

}

} catch (TimeoutException e) {

opDesc = "Timeout while authenticating with Gamigo.";

log.error(opDesc);

theResponse = new ErrorResponse(Operation_Timout, opDesc);

opResult = FAILURE;

} catch (NoSuchAlgorithmException e) {

opDesc = "Failure to encode password. This is a programming error and should not happen.";

log.error(opDesc);

theResponse = new ErrorResponse(Operation_Error, opDesc);

opResult = FAILURE;

} catch (UnsupportedEncodingException e) {

opDesc = "Failure to encode password. This is a programming error and should not happen.";

log.error(opDesc);

theResponse = new ErrorResponse(Operation_Error, opDesc);

opResult = FAILURE;

} catch (Exception e) {

if (e.getCause() instanceof GamigoAuthenticationExceptionWrapper) {

opDesc = "GamigoAuthenticationException: " + e.getMessage();

log.error(opDesc);

theResponse = new ErrorResponse(External_Error, opDesc);

opResult = FAILURE;

}

else {

opDesc = "Unknown failure while authenticating with Gamigo: " + e.getMessage();

log.error(opDesc);

theResponse = new ErrorResponse(External_Error, opDesc);

opResult = FAILURE;

}

}

accountHistoryDao.createAuthenticationRecord(ipAddr, userName, opResult, opDesc, gameSKU);

return theResponse;

}

}