/*
* This file is part of anycook. The new internet cookbook
* Copyright (C) 2014 Jan Graßegger
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see [http://www.gnu.org/licenses/].
*/
package de.anycook.user;
import de.anycook.api.views.PrivateView;
import de.anycook.api.views.PublicView;
import de.anycook.conf.Configuration;
import de.anycook.db.mysql.DBUser;
import de.anycook.image.Image;
import de.anycook.image.UserImage;
import de.anycook.location.GeoCode;
import de.anycook.location.Location;
import de.anycook.news.life.Lifes;
import de.anycook.notifications.Notification;
import de.anycook.sitemap.SiteMapGenerator;
import de.anycook.social.facebook.FacebookHandler;
import de.anycook.utils.enumerations.ImageType;
import de.anycook.utils.enumerations.NotificationType;
import org.apache.commons.lang3.RandomStringUtils;
import org.apache.commons.math3.random.RandomDataGenerator;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import java.io.IOException;
import java.sql.SQLException;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;
/**
* erzeugt neue User und enthaelt Methoden um Userdaten zu ueberpruefen
*
* @author Jan Grassegger
*/
public class User implements Comparable<User> {
private static final Logger logger;
private static final String adminMail;
private final static Pattern passwordRegex =
Pattern.compile("((?=.*\\d)(?=.*[a-zA-Z@#$%]).{6,})");
static {
logger = LogManager.getLogger(User.class);
adminMail = Configuration.getInstance().getAdminMail();
}
public static User init(String nameOrMail)
throws SQLException, DBUser.UserNotFoundException, IOException {
try (DBUser dbuser = new DBUser()) {
int id = dbuser.getUserId(nameOrMail);
return init(id);
}
}
public static User init(int id) throws SQLException, IOException, DBUser.UserNotFoundException {
try (DBUser dbuser = new DBUser()) {
return dbuser.getUser(id);
}
}
public static User initAdmin() {
return new User(99999, "admin", "admin@anycook.de", -1, null, 2, null, null, null, null, -1,
-1,
null, null, null);
}
public static List<User> getAll() throws SQLException {
try (DBUser dbuser = new DBUser()) {
return dbuser.getAllUsers();
}
}
public static boolean checkPassword(String newPw) {
return passwordRegex.matcher(newPw).matches();
}
public static User login(int id, String pwd)
throws SQLException, IOException, DBUser.UserNotFoundException,
LoginException {
try (DBUser dbuser = new DBUser()) {
if (dbuser.login(id, pwd)) {
dbuser.setLastLogin(id);
logger.info(id + " logged in");
return User.init(id);
}
logger.info("Login for " + id + " failed");
throw new LoginException(id);
}
}
public static User login(String cookieId)
throws SQLException, IOException, DBUser.UserNotFoundException,
DBUser.CookieNotFoundException {
try (DBUser dbuser = new DBUser()) {
int userId = dbuser.getUserIdFromCookieId(cookieId);
//exists if admin
if (userId == 99999) {
logger.info("admin logged in");
return User.initAdmin();
}
dbuser.setLastLogin(userId);
logger.info(userId + " logged in");
return User.init(userId);
}
}
public static User facebookLogin(Long uid)
throws SQLException, IOException, DBUser.UserNotFoundException,
LoginException {
try (DBUser dbuser = new DBUser()) {
int userId = dbuser.facebookLogin(uid);
if (userId != -1) {
dbuser.setLastLogin(userId);
logger.info(userId + " logged in via Facebook");
return User.init(userId);
}
logger.info("Login for " + uid + " failed");
throw new LoginException(uid);
}
}
/*public boolean newUser(String mail, String username, String pwd){
try {
return dbuser.newUser(mail, pwd, username);
} catch (SQLException e) {
e.printStackTrace();
return false;
}
}*/
/**
* erzeugt neuen User.
*
* @param mail Mailaddresse des neuen Users
* @param pwd Passwort des neuen Users
* @param username Username des neuen Users
* @return true, wenn erzeugung erfolgreich
*/
public static boolean newUser(String mail, String pwd, String username) throws SQLException {
return newUser(mail, pwd, username, false);
}
public static boolean newUser(String mail, String pwd, String username, boolean active)
throws SQLException {
logger.info("started to add new user");
if (!checkPassword(pwd)) {
logger.info(String.format("bad password: %s %s, %s", mail, username, pwd));
return false;
}
try (DBUser dbuser = new DBUser()) {
String activationID = null;
if (!active) {
activationID = RandomStringUtils.randomAlphanumeric(20);
}
logger.debug("activationId is:" + activationID);
String image = User.getRandomUserpic();
Integer newUserId = dbuser.newUser(mail, pwd, username, activationID, image);
if (newUserId != null) {
if (!active) {
try {
User.sendAccountActivationMail(newUserId, username, activationID);
} catch (DBUser.UserNotFoundException e) {
logger.error(e, e);
}
}
logger.info("user created. Username:" + username + " Mail: " + mail);
return true;
}
logger.warn("failed to create user. Username:" + username + " Mail: " + mail);
return false;
}
}
public static boolean newFacebookUser(String mail, String name, long facebook_id)
throws SQLException {
try (DBUser dbuser = new DBUser()) {
Integer newUserId = dbuser.newFacebookUser(mail, name, facebook_id);
if (newUserId != null) {
activateByUserId(newUserId);
logger.info("user created. Username:" + name + " Mail: " + mail);
return true;
}
logger.warn("failed to create user. Username:" + name + " Mail: " + mail);
return false;
}
}
/**
* ueberprueft ob username schon in der Datenbank vorhanden ist
*
* @param username zu pruefender Username
* @return true, wenn schon vorhanden
*/
public static boolean checkUsername(String username) throws SQLException {
try (DBUser db = new DBUser()) {
return db.checkUsername(username);
}
}
/**
* ueberprueft ob mail schon in der Datenbank vorhanden ist
*
* @param mail zu pruefende mailadresse
* @return true, wenn schon vorhanden
*/
public static boolean checkMail(String mail) throws SQLException {
try (DBUser db = new DBUser()) {
return db.checkMail(mail);
}
}
public static void activateById(String activationId)
throws SQLException, DBUser.ActivationFailedException {
try (DBUser dbuser = new DBUser()) {
int userid = dbuser.activateById(activationId);
Lifes.addLife(Lifes.CaseType.NEW_USER, userid);
SiteMapGenerator.generateProfileSiteMap();
}
}
public static void activateByUserId(int userId) throws SQLException {
try (DBUser dbuser = new DBUser()) {
dbuser.activateUser(userId);
Lifes.addLife(Lifes.CaseType.NEW_USER, userId);
SiteMapGenerator.generateProfileSiteMap();
}
}
public static void resetPassword(String id, String newPw)
throws SQLException, ResetPasswordException {
try (DBUser dbuser = new DBUser()) {
if (dbuser.checkResetPasswordID(id)) {
dbuser.resetPassword(id, newPw);
dbuser.deletePasswordID(id);
} else {
throw new ResetPasswordException(id);
}
}
}
public static void sendAccountActivationMail(int id, String name, String activationKey)
throws SQLException, DBUser.UserNotFoundException {
Map<String, String> data = new HashMap<>();
data.put("userName", name);
data.put("baseUrl", Configuration.getInstance().getRedirectDomain());
data.put("activationKey", activationKey);
Notification.sendNotification(id, NotificationType.ACCOUNT_ACTIVATION, data);
}
public static String getUsername(int userId) throws SQLException, DBUser.UserNotFoundException {
try (DBUser dbuser = new DBUser()) {
return dbuser.getUsername(userId);
}
}
public static String getUseremail(String username)
throws SQLException, DBUser.UserNotFoundException {
try (DBUser dbuser = new DBUser()) {
return dbuser.getUserEmail(username);
}
}
public static String getMailCandidate(int userId)
throws SQLException, DBUser.UserNotFoundException {
try (DBUser dbuser = new DBUser()) {
return dbuser.getMailCandidate(userId);
}
}
public static String getUseremail(int userId)
throws SQLException, DBUser.UserNotFoundException {
try (DBUser dbuser = new DBUser()) {
return dbuser.getUserEmail(userId);
}
}
public static boolean checkPasswordID(String resetPwID) throws SQLException {
try (DBUser dbuser = new DBUser()) {
return dbuser.checkResetPasswordID(resetPwID);
}
}
public static int getUserId(String nameOrMail)
throws SQLException, DBUser.UserNotFoundException {
try (DBUser dbuser = new DBUser()) {
if (nameOrMail.equals(adminMail)) {
return -1;
}
return dbuser.getUserId(nameOrMail);
}
}
public static String getUserImage(int userId, ImageType type)
throws SQLException, IOException, DBUser.UserNotFoundException {
StringBuilder
imagePath =
new StringBuilder(Configuration.getInstance().getImageBasePath()).append("user/");
try (DBUser dbuser = new DBUser()) {
String userImage = dbuser.getUserImage(userId);
switch (type) {
case SMALL:
imagePath.append("small/");
break;
case LARGE:
imagePath.append("big/");
break;
case ORIGINAL:
imagePath.append("original/");
break;
}
if (userImage != null) {
return imagePath.append(userImage).toString();
}
logger.info("userimage was null");
User user = User.init(userId);
if (user != null && user.facebookID != 0) {
return user.getUserImage(type);
}
return imagePath.append(getRandomUserpic()).toString();
}
}
public static List<String> getUsernames(List<User> list) {
List<String> userNames = new LinkedList<>();
for (User user : list) {
userNames.add(user.name);
}
return userNames;
}
public static int getTotal() throws SQLException {
try (DBUser db = new DBUser()) {
return db.getTotal();
}
}
public static String getRandomUserpic() {
RandomDataGenerator random = new RandomDataGenerator();
return String.format("userpic%d.png", random.nextInt(1, 3));
}
public static void createResetPasswordID(String mail)
throws SQLException, IOException, DBUser.UserNotFoundException {
User user = User.init(mail);
String resetPWID = RandomStringUtils.randomAlphanumeric(16);
try (DBUser dbuser = new DBUser()) {
dbuser.setResetPasswordID(user.getId(), resetPWID);
}
user.sendResetPasswordMail(resetPWID);
logger.info(mail + " wants to reset password");
}
public static String generateAndSaveActivationId(int userId) throws SQLException {
String activationId = RandomStringUtils.randomAlphanumeric(20);
try (DBUser dbUser = new DBUser()) {
dbUser.setActivationId(userId, activationId);
return activationId;
}
}
public static void resendActivationId(int userId)
throws SQLException, DBUser.UserNotFoundException {
String username = User.getUsername(userId);
try (DBUser dbUser = new DBUser()) {
String activationId = dbUser.getActivationId(userId);
if (activationId == null) {
activationId = User.generateAndSaveActivationId(userId);
}
User.sendAccountActivationMail(userId, username, activationId);
}
}
/* members */
private int id;
private String name;
private Image image;
@PrivateView
private String mail;
@PrivateView
@PublicView
private long facebookID;
@PrivateView
private String emailCandidate;
@PublicView
@PrivateView
private String text;
@PublicView
@PrivateView
private int level;
@PublicView
@PrivateView
private long createDate;
@PublicView
@PrivateView
private long lastLogin;
@PublicView
@PrivateView
private String place;
@PublicView
@PrivateView
private Location location;
@PublicView
@PrivateView
private List<Integer> following;
@PublicView
@PrivateView
private List<Integer> followers;
public User() {
}
public User(int id, String name, String image) {
this.name = name;
this.id = id;
this.image = new UserImage(image);
this.facebookID = -1;
this.level = -1;
}
public User(int id, String name,
String mail,
long facebookID,
String image,
int level,
String text,
Date createDate,
Date lastLogin,
String place,
double placeLatitude,
double placeLongitude,
List<Integer> following,
List<Integer> followers,
String emailCandidate) {
this.id = id;
this.name = name;
this.mail = mail;
this.facebookID = facebookID;
this.image = new UserImage(image);
this.text = text;
this.level = level;
this.createDate = createDate.getTime();
this.lastLogin = lastLogin != null ? lastLogin.getTime() : -1;
this.place = place;
this.location = new Location(placeLatitude, placeLongitude);
this.following = following;
this.followers = followers;
this.emailCandidate = emailCandidate;
}
public int getId() {
return id;
}
public String getName() {
return name;
}
public String getMail() {
return mail;
}
public Image getImage() {
return image;
}
public String getText() {
return text;
}
public long getCreateDate() {
return createDate;
}
public long getLastLogin() {
return lastLogin;
}
public String getPlace() {
return place;
}
public List<Integer> getFollowing() {
return following;
}
public List<Integer> getFollowers() {
return followers;
}
public long getFacebookID() {
return facebookID;
}
public int getLevel() {
return level;
}
public void setId(int id) {
this.id = id;
}
public void setMail(String mail) {
this.mail = mail;
}
public void setFacebookID(long facebookID) {
this.facebookID = facebookID;
}
public void setImage(Image image) {
this.image = image;
}
public void setLevel(int level) {
this.level = level;
}
public void setCreateDate(long createDate) {
this.createDate = createDate;
}
public void setLastLogin(long lastLogin) {
this.lastLogin = lastLogin;
}
public void setFollowing(List<Integer> following) {
this.following = following;
}
public void setFollowers(List<Integer> followers) {
this.followers = followers;
}
public void setEmailCandidate(String emailCandidate) {
this.emailCandidate = emailCandidate;
}
public Location getLocation() {
return location;
}
//@JsonIgnore
public boolean isAdmin() {
return level == 2;
}
//@JsonIgnore
public String getUserImage(ImageType type)
throws SQLException, IOException, DBUser.UserNotFoundException {
return getUserImage(id, type);
}
//@JsonIgnore
public String getFaceBookAccessToken() throws IOException {
return facebookID == 0 ? null : FacebookHandler.getUsersOAuthToken(facebookID);
}
//@JsonIgnore
public String getFacebookPermissions() throws IOException {
return FacebookHandler.getPermissions(getFaceBookAccessToken(), facebookID);
}
//@JsonView(Views.PrivateUserView.class)
public String getEmailCandidate() {
return emailCandidate;
}
//Mails
public void sendAccountActivationMail(String activationKey) throws SQLException {
try {
sendAccountActivationMail(id, name, activationKey);
} catch (DBUser.UserNotFoundException e) {
logger.error(e, e);
}
}
public void sendResetPasswordMail(String passwordId) throws SQLException {
Map<String, String> data = new HashMap<>();
data.put("resetKey", passwordId);
try {
Notification.sendNotification(id, NotificationType.RESET_PASSWORD, data);
} catch (DBUser.UserNotFoundException e) {
logger.error(e, e);
}
}
public void follow(int userId) throws SQLException {
DBUser db = new DBUser();
db.follow(id, userId);
logger.info(name + " now following " + userId);
db.close();
}
public void unFollow(int userId) throws SQLException {
DBUser db = new DBUser();
db.unFollow(id, userId);
logger.info(name + " unfollowed " + userId);
db.close();
}
public void setImage(String newImage) throws SQLException {
try (DBUser db = new DBUser()) {
db.changeImage(id, newImage);
logger.info(mail + " changed image to " + image);
this.image = new UserImage(newImage);
}
}
public boolean setName(String name) throws SQLException {
if (name == null || this.name != null && this.name.equals(name)) {
return false;
}
try (DBUser db = new DBUser()) {
db.changeName(id, name);
}
this.name = name;
return true;
}
public boolean setPlace(String place) throws SQLException {
if (place == null || this.place != null && this.place.equals(place)) {
return false;
}
try (DBUser db = new DBUser()) {
db.changePlace(id, place);
GeoCode geoCode = new GeoCode();
setLocation(geoCode.getLocation(place));
} catch (GeoCode.LocationNotFoundException | IOException e) {
logger.debug(e, e);
}
this.place = place;
return true;
}
public boolean setText(String text) throws SQLException {
if (text == null || this.text != null && this.text.equals(text)) {
return false;
}
if (text.length() > 140) {
return false;
}
try (DBUser dbuser = new DBUser()) {
dbuser.changeText(id, text);
}
logger.info(mail + " changed text to " + text);
return true;
}
public void setLocation(Location location) throws SQLException {
if (location == null) {
return;
}
try (DBUser dbUser = new DBUser()) {
dbUser.changeLocation(id, location);
}
this.location = location;
logger.info(mail + " changed location to " + location);
}
public void setMailCandidate(String newMail) throws SQLException {
String mailActivationCode = RandomStringUtils.randomAlphanumeric(16);
try (DBUser dbUser = new DBUser()) {
dbUser.setMailCandidate(id, newMail, mailActivationCode);
}
Map<String, String> data = new HashMap<>();
data.put("activationKey", mailActivationCode);
try {
Notification.sendNotification(id, NotificationType.NEW_MAIL, data);
} catch (DBUser.UserNotFoundException e) {
//nope
}
this.emailCandidate = newMail;
logger.info(String.format("%d sets a new mail candidate: %s", id, newMail));
}
public String confirmMailCandidate(String code) throws DBUser.WrongCodeException, SQLException {
String oldMail = this.mail;
try (DBUser dbUser = new DBUser()) {
dbUser.updateMail(this.id, code);
}
this.mail = this.emailCandidate;
this.emailCandidate = null;
logger.info(id + " changed mail from " + oldMail + " to " + mail);
return this.mail;
}
public boolean setNewPassword(String oldPassword, String newPassword) throws SQLException {
try (DBUser dbUser = new DBUser()) {
return dbUser.changePassword(id, oldPassword, newPassword);
}
}
@Override
public int compareTo(User anotherUser) {
return Integer.valueOf(id).compareTo(anotherUser.id);
}
public static List<Integer> getAdminIds() throws SQLException {
try (DBUser dbUser = new DBUser()) {
return dbUser.getAdminIds();
}
}
// inner classes
public static class LoginException extends Exception {
public LoginException(long uid) {
super("login failed for facebook id: " + uid);
}
public LoginException(String s) {
super("login failed for " + s);
}
public LoginException(int s) {
super("login failed for " + s);
}
}
public static class ResetPasswordException extends Exception {
public ResetPasswordException(String id) {
super("failed to reset password for " + id);
}
}
}