package io.pivotal.accounts.service;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import io.pivotal.accounts.domain.Account;
import io.pivotal.accounts.exception.AuthenticationException;
import io.pivotal.accounts.exception.NoRecordsFoundException;
import io.pivotal.accounts.repository.AccountRepository;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
/**
* The service in the accounts microservice.
*
* @author David Ferreira Pinto
*
*/
@Service
public class AccountService {
private static final Logger logger = LoggerFactory.getLogger(AccountService.class);
/**
* The accounts repository.
*/
@Autowired
AccountRepository accounts;
/**
* Retrieve an account with given id. The id here is the unique id value of
* the account managed by the repository (auto-increment).
*
* @param id
* The id of the account.
* @return The account object if found or throws a NoRecordsFoundException.
*/
public Account findAccount(Integer id) {
logger.debug("AccountService.findAccount: id=" + id);
Account account = accounts.findOne(id);
if (account == null) {
logger.warn("AccountService.findAccount: could not find account with id: " + id);
throw new NoRecordsFoundException();
}
logger.info(String.format("AccountService.findAccount - retrieved account with id: %s. Payload is: %s", id, account));
return account;
}
/**
* Retrieve an account with given id. The id here is the unique user id
* value of the account, ie the username.
*
* @param id
* The user id of the account.
* @return The account object if found or throws a NoRecordsFoundException.
*/
public Account findAccount(String id) {
logger.debug("AccountService.findAccount: id=" + id);
Account account = accounts.findByUserid(id);
if (account == null) {
logger.warn("AccountService.findAccount: could not find account with id: " + id);
throw new NoRecordsFoundException();
}
logger.info(String.format("AccountService.findAccount - retrieved account with id: %s. Payload is: %s", id, account));
return account;
}
/**
* Retrieves the account by the authorization token associated with that
* account and current login.
*
* @param token
* The token to search for.
* @return The account object if found or AuthenticationException otherwise.
*/
@Cacheable(value = "authorizationCache")
public Account findAccountprofileByAuthtoken(String token) {
logger.debug("AccountService.findAccountprofileByAuthtoken looking for authToken: " + token);
if (token == null) {
// TODO: no point in checking database. throw exception here.
logger.error("AccountService.findAccountprofileByAuthtoken(): token is null");
throw new AuthenticationException("Authorization Token is null");
}
Account accountProfile = null;
accountProfile = accounts.findByAuthtoken(token);
if (accountProfile == null) {
logger.error("AccountService.findAccountprofileByAuthtoken(): accountProfile is null for token=" + token);
throw new AuthenticationException("Authorization Token not found");
}
return accountProfile;
}
/**
* Saves the given account in the repository.
*
* @param accountRequest
* The account to save.
* @return the id of the account.
*/
public Integer saveAccount(Account accountRequest) {
logger.debug("AccountService.saveAccount:" + accountRequest.toString());
// need to set some stuff that cannot be null!
if (accountRequest.getLogincount() == null) {
accountRequest.setLogincount(0);
}
if (accountRequest.getLogoutcount() == null) {
accountRequest.setLogoutcount(0);
}
Account account = accounts.save(accountRequest);
logger.info("AccountService.saveAccount: account saved: " + account);
return account.getId();
}
/**
* Attempts to login the user with the given username and password. Throws
* AuthenticationException if an account with the given username and
* password cannot be found.
*
* @param username
* The username to login.
* @param password
* The password to use.
* @return a map with the authtoken, account Id.
*/
public Map<String, Object> login(String username, String password) {
logger.debug("login in user: " + username);
Map<String, Object> loginResponse = null;
Account account = accounts.findByUseridAndPasswd(username, password);
if (account != null) {
logger.debug("Found Account for user: " + username);
account.setAuthtoken(UUID.randomUUID().toString());
account.setLogincount(account.getLogincount() + 1);
account.setLastlogin(new Date());
account = accounts.save(account); // persist new auth token and last
// login
loginResponse = new HashMap<String, Object>();
loginResponse.put("authToken", account.getAuthtoken());
loginResponse.put("accountid", account.getId());
// loginResponse.put("password", account.getPasswd());
logger.info("AccountService.login success for " + username + " username::token=" + loginResponse.get("authToken"));
} else {
logger.warn("AccountService.login failed to find username=" + username + " password=" + password);
throw new AuthenticationException("Login failed for user: " + username);
}
return loginResponse;
}
/**
* logs the give user out of the system.
*
* @param userId
* the userid to logout.
* @return The account object or null;
*/
public Account logout(String userId) {
logger.debug("AccountService.logout: Logging out account with userId: " + userId);
Account account = accounts.findByUserid(userId);
if (account != null) {
account.setAuthtoken(null); // remove token
account.setLogoutcount(account.getLogoutcount() + 1);
accounts.save(account);
logger.info("AccountService.logout: Account logged out: " + account.getUserid());
} else {
logger.warn("AccountService.logout: Could not find account to logout with userId: " + userId);
}
return account;
}
}