/**
*
*/
package com.qprogramming.tasq.account;
import com.fasterxml.uuid.Generators;
import com.qprogramming.tasq.config.ResourceService;
import com.qprogramming.tasq.mail.MailMail;
import com.qprogramming.tasq.manage.AppService;
import com.qprogramming.tasq.manage.Theme;
import com.qprogramming.tasq.support.Utils;
import org.apache.commons.lang3.StringUtils;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.VelocityEngine;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.MessageSource;
import org.springframework.core.io.Resource;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.io.StringWriter;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.UUID;
/**
* @author romanjak
* @date 21 maj 2014
*/
@Service
public class AccountService {
private static final String CUR_ACCOUNT = "curAccount";
private static final String THEME = "theme";
private static final String AVATAR = "avatar";
private static final String APPLICATION = "application";
private static final String LINK = "link";
private static final String APPLICATION_NAME = "applicationName";
private static final String ACCOUNT = "account";
private static final Logger LOG = LoggerFactory.getLogger(AccountService.class);
private static final String UTF_8 = "UTF-8";
private static final String EMAIL_TEMP_PATH = "email/";
@Value("${default.locale}")
private String defaultLang;
private AccountRepository accRepo;
private MessageSource msg;
private VelocityEngine velocityEngine;
private ResourceService resourceSrv;
private MailMail mailer;
private PasswordEncoder passwordEncoder;
private AppService appSrv;
private String applicationName;
// @PersistenceContext
// private EntityManager entityManager;
@Autowired
public AccountService(AccountRepository accRepo, MessageSource msg, VelocityEngine velocityEngine,
ResourceService resourceSrv, MailMail mailer, PasswordEncoder passwordEncoder, AppService appSrv) {
this.accRepo = accRepo;
this.msg = msg;
this.velocityEngine = velocityEngine;
this.resourceSrv = resourceSrv;
this.mailer = mailer;
this.passwordEncoder = passwordEncoder;
this.appSrv = appSrv;
applicationName = appSrv.getProperty(AppService.APPLICATION_NAME);
}
@Transactional
public Account save(Account account, boolean passwordReset) {
if (passwordReset) {
account.setPassword(passwordEncoder.encode(account.getPassword()));
}
if (account.getLanguage() == null) {
account.setLanguage(defaultLang);
}
UUID uuid = Generators.timeBasedGenerator().generate();
account.setUuid(uuid.toString());
return accRepo.save(account);
// entityManager.persist(account);
}
public Account findByEmail(String email) {
if (StringUtils.isNotBlank(email)) {
return accRepo.findByEmail(email.toLowerCase());
}
return null;
}
public Account findByUsername(String username) {
if (StringUtils.isNotBlank(username)) {
return accRepo.findByUsername(username.toLowerCase());
}
return null;
}
public Account findByUuid(String uiid) {
return accRepo.findByUuid(uiid);
}
/**
* @param account
*/
@Transactional
public Account update(Account account) {
return accRepo.save(account);
}
/**
* Bulk updates all accounts from list
*
* @param accounts accounts list
*/
@Transactional
public void update(List<Account> accounts) {
accRepo.save(accounts);
}
public Account findById(Long id) {
return accRepo.findById(id);
}
/**
* @return
*/
public List<Account> findAll() {
return accRepo.findAll();
}
public List<Account> findAllWithActiveTask(String taskID) {
return accRepo.findByActiveTask(taskID);
}
public Page<Account> findAll(Pageable p) {
return accRepo.findAll(p);
}
public Page<Account> findByNameSurnameContaining(String term, Pageable p) {
return accRepo.findBySurnameContainingIgnoreCaseOrNameContainingIgnoreCaseOrUsernameContainingIgnoreCase(term, term, term, p);
}
public List<Account> findByNameSurnameContaining(String term) {
return accRepo.findBySurnameContainingIgnoreCaseOrNameContainingIgnoreCaseOrUsernameContainingIgnoreCase(term, term, term);
}
public List<Account> findAdmins() {
return accRepo.findByRole(Roles.ROLE_ADMIN);
}
public boolean sendConfirmationLink(Account account) {
String baseUrl = appSrv.getProperty(AppService.URL);
String confirmlink = baseUrl + "/confirm?id=" + account.getUuid();
String subject = msg.getMessage("signup.register", new Object[]{applicationName}, Utils.getDefaultLocale());
StringWriter stringWriter = new StringWriter();
VelocityContext context = new VelocityContext();
context.put(ACCOUNT, account);
context.put(LINK, confirmlink);
context.put(APPLICATION, baseUrl);
context.put(APPLICATION_NAME, applicationName);
velocityEngine.mergeTemplate(EMAIL_TEMP_PATH + Utils.getDefaultLocale() + "/register.vm", UTF_8, context, stringWriter);
String message = stringWriter.toString();
return mailer.sendMail(MailMail.REGISTER, account.getEmail(), subject, message,
resourceSrv.getBasicResourceMap());
}
public boolean sendResetLink(Account account) {
String baseUrl = appSrv.getProperty(AppService.URL);
StringBuilder url = new StringBuilder(baseUrl);
url.append("/");
url.append("password?id=");
url.append(account.getUuid());
String subject = msg.getMessage("singin.password.reset", new Object[]{applicationName}, new Locale(account.getLanguage()));
VelocityContext context = new VelocityContext();
StringWriter stringWriter = new StringWriter();
context.put(ACCOUNT, account);
context.put(LINK, url);
context.put(APPLICATION, baseUrl);
context.put(APPLICATION_NAME, applicationName);
velocityEngine.mergeTemplate(EMAIL_TEMP_PATH + account.getLanguage() + "/password.vm", UTF_8, context, stringWriter);
String message = stringWriter.toString();
LOG.info(url.toString());
return mailer.sendMail(MailMail.OTHER, account.getEmail(), subject, message, resourceSrv.getBasicResourceMap());
}
public boolean sendInvite(String email, Theme theme) {
String baseUrl = appSrv.getProperty(AppService.URL);
String subject = msg.getMessage("panel.invite.subject", new Object[]{applicationName}, Utils.getDefaultLocale());
StringWriter stringWriter = new StringWriter();
VelocityContext context = new VelocityContext();
context.put(APPLICATION, baseUrl);
context.put(APPLICATION_NAME, applicationName);
context.put(CUR_ACCOUNT, Utils.getCurrentAccount());
context.put(THEME, theme);
velocityEngine.mergeTemplate(EMAIL_TEMP_PATH + Utils.getDefaultLocale() + "/invite.vm", UTF_8, context, stringWriter);
String message = stringWriter.toString();
Map<String, Resource> resources = resourceSrv.getBasicResourceMap();
resources.put(AVATAR, resourceSrv.getUserAvatar());
return mailer.sendMail(MailMail.REGISTER, email, subject, message, resources);
}
/**
* Fetches account once more from database to ensure that security principal was not tampered with, and verifies if entered password is valid
*
* @param account user to be checked for valid password
* @param password user password which will be matched with encoded DB password
* @return
*/
public boolean verifyPassword(Account account, String password) {
Account dbAccount = findById(account.getId());
return passwordEncoder.matches(password, dbAccount.getPassword());
}
}