package org.dicadeveloper.weplantaforest.user;
import java.io.IOException;
import java.util.List;
import java.util.UUID;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.dicadeveloper.weplantaforest.FileSystemInjector;
import org.dicadeveloper.weplantaforest.common.errorHandling.ErrorCodes;
import org.dicadeveloper.weplantaforest.common.errorHandling.IpatException;
import org.dicadeveloper.weplantaforest.common.errorHandling.IpatPreconditions;
import org.dicadeveloper.weplantaforest.common.image.ImageHelper;
import org.dicadeveloper.weplantaforest.common.mail.MailHelper;
import org.dicadeveloper.weplantaforest.common.support.Language;
import org.dicadeveloper.weplantaforest.common.user.Role;
import org.dicadeveloper.weplantaforest.encryption.PasswordEncrypter;
import org.dicadeveloper.weplantaforest.messages.MessageByLocaleService;
import org.dicadeveloper.weplantaforest.reports.co2.Co2Repository;
import org.dicadeveloper.weplantaforest.reports.rankings.RankingRepository;
import org.dicadeveloper.weplantaforest.reports.rankings.TreeRankedUserData;
import org.dicadeveloper.weplantaforest.support.CommonValidator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
@Service
@RequiredArgsConstructor(onConstructor = @__(@Autowired) )
public class UserService {
protected final Log LOG = LogFactory.getLog(UserService.class.getName());
private @NonNull PasswordEncrypter _passwordEncrypter;
private @NonNull UserRepository _userRepository;
private @NonNull Co2Repository _co2Repository;
private @NonNull RankingRepository _rankingRepository;
private @NonNull ImageHelper _imageHelper;
private @NonNull MailHelper _mailHelper;
private @NonNull MessageByLocaleService _messageByLocaleService;
private @NonNull Environment _env;
private final static String ANONYMOUS = "Anonymous";
private User convertUserRegDataToUser(UserRegistrationData userRegistrationData) {
Long currentTime = System.currentTimeMillis();
User user = new User();
user.setName(userRegistrationData.getUsername());
user.setNewsletter(userRegistrationData.isNewsLetter());
user.setPassword(_passwordEncrypter.encryptPassword(userRegistrationData.getPassword()));
user.setMail(userRegistrationData.getMail());
user.setOrganizationType(OrganizationType.valueOf(userRegistrationData.getOrgType()));
user.setLang(Language.valueOf(userRegistrationData.getLanguage()));
user.setEnabled(false);
user.setBanned(false);
user.setRegDate(currentTime);
user.setLastVisit(currentTime);
user.addRole(Role.USER);
user.setActivationKey(UUID.randomUUID()
.toString());
return user;
}
private String createUserRegistrationMailText(User user, String ipatHost, String mailText) {
String activationLink = "/userActivation" + "?id=" + user.getId() + "&key=" + user.getActivationKey();
mailText = mailText.replace("%activationLink%", activationLink);
mailText = mailText.replace("%userName%", user.getName());
mailText = mailText.replace("%ipatHost%", ipatHost);
return mailText;
}
private String createForgotPasswordMail(User user, String ipatHost, String mailText) {
String resetLink = "/password_reset" + "?id=" + user.getId() + "&key=" + user.getActivationKey();
mailText = mailText.replace("%resetLink%", resetLink);
mailText = mailText.replace("%userName%", user.getName());
mailText = mailText.replace("%ipatHost%", ipatHost);
return mailText;
}
public User createAnonymous() throws IpatException {
User user = null;
final long currentTimeMillis = System.currentTimeMillis();
final String randomString = UUID.randomUUID()
.toString();
final long anonymousCount = _userRepository.countAnonymUser();
String userName = ANONYMOUS + (anonymousCount + 1);
user = new User();
user.setName(userName);
user.setEnabled(false);
user.setBanned(false);
user.setRegDate(currentTimeMillis);
user.setLastVisit(currentTimeMillis);
user.setOrganizationType(OrganizationType.PRIVATE);
user.addRole(Role.USER);
user.setActivationKey(randomString);
user.setLang(Language.DEUTSCH);
boolean userSaved = false;
int tryCount = 1;
while (!userSaved && tryCount <= 100) {
if (_userRepository.userExists(userName) == 0) {
_userRepository.save(user);
userSaved = true;
return user;
} else {
// if such a user already exists, try again with the same name
// added by one(100tries)
userName = ANONYMOUS + (anonymousCount + 1 + tryCount);
user.setName(userName);
tryCount++;
}
}
LOG.error("unable to save anonymous user after 100 tries.");
throw new IpatException(ErrorCodes.NO_ANONYMOUS_CREATED);
}
public UserReportData getUserDetails(String userName, boolean isEditAllowed) {
UserReportData userReportData = _userRepository.getUserDetails(userName);
userReportData.setCo2Data(_co2Repository.getAllTreesAndCo2SavingForUserName(System.currentTimeMillis(), userName));
userReportData.setRank(calcUserRank(userReportData.getUserName(), userReportData.getCo2Data()
.getTreesCount()));
userReportData.setEditAllowed(isEditAllowed);
return userReportData;
}
public void editUser(String userName, String toEdit, String newEntry) throws IpatException {
User user = getUser(userName);
switch (toEdit) {
case "NAME":
IpatPreconditions.checkArgument((_userRepository.userExists(newEntry) == 0), ErrorCodes.USER_ALREADY_EXISTS);
user.setName(newEntry);
break;
case "ABOUTME":
user.setAboutMe(newEntry);
break;
case "LOCATION":
user.setLocation(newEntry);
break;
case "ORGANISATION":
user.setOrganisation(newEntry);
break;
case "HOMEPAGE":
user.setHomepage(newEntry);
break;
case "MAIL":
IpatPreconditions.checkArgument(CommonValidator.isValidEmailAddress(newEntry), ErrorCodes.INVALID_MAIL);
IpatPreconditions.checkArgument((_userRepository.userWithMailExists(newEntry) == 0), ErrorCodes.MAIL_ALREADY_EXISTS);
user.setMail(newEntry);
break;
case "NEWSLETTER":
user.setNewsletter(newEntry.equals("JA") ? true : false);
break;
case "ORGANIZATION_TYPE":
user.setOrganizationType(OrganizationType.valueOf(newEntry));
break;
case "LANGUAGE":
user.setLang(Language.valueOf(newEntry));
break;
case "PASSWORD":
user.setPassword(_passwordEncrypter.encryptPassword(newEntry));
break;
default:
break;
}
_userRepository.save(user);
}
public void uploadUserImage(String userName, MultipartFile file) throws IpatException {
IpatPreconditions.checkArgument(!file.isEmpty(), ErrorCodes.EMPTY_FILE);
User user = getUser(userName);
String imageFolder = FileSystemInjector.getUserFolder();
String imageName = user.getName() + file.getOriginalFilename()
.substring(file.getOriginalFilename()
.indexOf("."));
try {
_imageHelper.storeImage(file, imageFolder, imageName, true);
user.setImageName(imageName);
_userRepository.save(user);
} catch (IOException e) {
throw new IpatException(ErrorCodes.SERVER_ERROR);
}
}
public void registrateUser(UserRegistrationData userRegistrationData) throws IpatException {
String userName = userRegistrationData.getUsername();
String mail = userRegistrationData.getMail();
IpatPreconditions.checkArgument((_userRepository.userExists(userName) == 0), ErrorCodes.USER_ALREADY_EXISTS);
IpatPreconditions.checkArgument(CommonValidator.isValidEmailAddress(mail), ErrorCodes.INVALID_MAIL);
IpatPreconditions.checkArgument((_userRepository.userWithMailExists(mail) == 0), ErrorCodes.MAIL_ALREADY_EXISTS);
User user = convertUserRegDataToUser(userRegistrationData);
_userRepository.save(user);
String mailSubject = _messageByLocaleService.getMessage("mail.registration.subject", user.getLang()
.getLocale());
String mailTemplateText = _messageByLocaleService.getMessage("mail.registration.text", user.getLang()
.getLocale());
String mailText = createUserRegistrationMailText(user, _env.getProperty("ipat.host"), mailTemplateText);
new Thread(new Runnable() {
public void run() {
_mailHelper.sendAMessage(mailSubject, mailText, user.getMail());
}
}).start();
}
public void activateUser(long userId, String key) throws IpatException {
User user = getUser(userId);
IpatPreconditions.checkArgument(!user.isEnabled(), ErrorCodes.USER_ALREADY_ACTIVATED);
IpatPreconditions.checkArgument(key.equals(user.getActivationKey()), ErrorCodes.INVALID_ACTIVATION_KEY);
user.setEnabled(true);
_userRepository.save(user);
}
public void createPasswordResetMail(String userName) throws IpatException {
User user = getUser(userName);
IpatPreconditions.checkArgument(user.isEnabled(), ErrorCodes.USER_NOT_ACTIVATED);
user.setActivationKey(UUID.randomUUID()
.toString());
_userRepository.save(user);
String mailSubject = _messageByLocaleService.getMessage("mail.forgot.password.subject", user.getLang()
.getLocale());
String mailTemplateText = _messageByLocaleService.getMessage("mail.forgot.password.text", user.getLang()
.getLocale());
String mailText = createForgotPasswordMail(user, _env.getProperty("ipat.host"), mailTemplateText);
new Thread(new Runnable() {
public void run() {
_mailHelper.sendAMessage(mailSubject, mailText, user.getMail());
}
}).start();
}
public String verifiyPasswordResetLink(long userId, String key) throws IpatException {
User user = getUser(userId);
IpatPreconditions.checkArgument(key.equals(user.getActivationKey()), ErrorCodes.INVALID_ACTIVATION_KEY);
return user.getName();
}
public String resetPasswordForUser(long userId, String key, String password) throws IpatException {
User user = getUser(userId);
IpatPreconditions.checkArgument(key.equals(user.getActivationKey()), ErrorCodes.INVALID_ACTIVATION_KEY);
user.setPassword(_passwordEncrypter.encryptPassword(password));
_userRepository.save(user);
return user.getName();
}
private User getUser(long userId) throws IpatException{
User user = _userRepository.findOne(userId);
IpatPreconditions.checkNotNull(user, ErrorCodes.USER_NOT_FOUND);
return user;
}
private User getUser(String userName) throws IpatException{
User user = _userRepository.findByName(userName);
IpatPreconditions.checkNotNull(user, ErrorCodes.USER_NOT_FOUND);
return user;
}
private long calcUserRank(String userName, long treeCountOfUser) {
List<TreeRankedUserData> userList = _rankingRepository.getBestUserList(System.currentTimeMillis());
long rank = 1;
for (TreeRankedUserData user : userList) {
if (treeCountOfUser < user.getAmount()) {
rank++;
}
if (user.getName()
.equals(userName)) {
break;
}
}
return rank;
}
}