/*
* jPOS Project [http://jpos.org]
* Copyright (C) 2000-2017 jPOS Software SRL
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.jpos.qi.eeuser;
import com.vaadin.data.Container;
import com.vaadin.data.Validator;
import com.vaadin.data.fieldgroup.BeanFieldGroup;
import com.vaadin.data.fieldgroup.FieldGroup;
import com.vaadin.data.util.BeanItem;
import com.vaadin.ui.PasswordField;
import org.hibernate.Criteria;
import org.hibernate.criterion.Restrictions;
import org.jpos.ee.*;
import org.jpos.qi.EntityContainer;
import org.jpos.qi.QIHelper;
import org.jpos.util.PasswordGenerator;
import java.util.*;
import java.util.List;
public class UsersHelper extends QIHelper {
public UsersHelper() {
super(User.class);
}
public Container createContainer() {
Map<String, Class> properties = new LinkedHashMap<>();
properties.put("id", Integer.class);
properties.put("nick", String.class);
properties.put("name", String.class);
properties.put("email", String.class);
properties.put("active", Boolean.class);
properties.put("roles", Set.class);
List sortable = Arrays.asList("id", "nick", "name", "email", "active");
return new EntityContainer<>(User.class, properties, sortable);
}
public User getUserByNick (String nick, boolean includeDeleted) {
try {
return (User) DB.exec((db) -> {
Criteria crit = db.session().createCriteria(User.class);
crit = crit.add(Restrictions.eq("nick", nick));
if (!includeDeleted)
crit = crit.add(Restrictions.eq("deleted", false));
return crit.uniqueResult();
});
} catch (Exception e) {
getApp().getLog().error(e);
return null;
}
}
public boolean updateUser (BeanFieldGroup<User> fieldGroup, String currentPass, String newClearPass) throws BLException, FieldGroup.CommitException, CloneNotSupportedException {
BeanItem<User> old = fieldGroup.getItemDataSource();
Object oldUser = old.getBean().clone();
fieldGroup.commit();
BeanItem<User> item = fieldGroup.getItemDataSource();
User u = item.getBean();
boolean userUpdated = false;
try {
userUpdated = (boolean) DB.execWithTransaction((db) -> {
User user = (User) db.session().merge(u);
UserManager mgr = new UserManager(db);
boolean updated = false;
if (!newClearPass.isEmpty()) {
boolean passwordOK = false;
boolean newPasswordOK = false;
try {
passwordOK = mgr.checkPassword(user, currentPass);
newPasswordOK = mgr.checkNewPassword(user, newClearPass);
if (passwordOK && newPasswordOK) {
mgr.setPassword(user, newClearPass);
updated = true;
} else if (!newPasswordOK) {
throw new BLException("This password has already been used");
}
} catch (BLException e) {
// do nothing
return false;
}
}
updated = updated || addRevisionUpdated(db, getEntityName(),
String.valueOf(u.getId()),
oldUser,
u,
new String[]{"nick", "name", "email", "active", "roles", "password"});
return updated;
});
} catch (Exception e) {
getApp().getLog().error(e);
return false;
}
if (userUpdated && u.equals(getApp().getUser())) {
try {
DB.exec((db)->{
db.session().refresh(getApp().getUser());
return null;
});
} catch (Exception e) {
getApp().getLog().error(e);
}
}
return userUpdated;
}
public boolean saveUser (BeanFieldGroup<User> fieldGroup, String clearPass) throws FieldGroup.CommitException, BLException {
fieldGroup.commit();
BeanItem<User> item = fieldGroup.getItemDataSource();
try {
return (boolean) DB.execWithTransaction((db) -> {
User u = item.getBean();
db.save(u);
if (clearPass != null && !clearPass.isEmpty()) {
UserManager mgr = new UserManager(db);
try {
mgr.setPassword(u, clearPass);
} catch (BLException e) {
return false;
}
addRevisionCreated(db,getEntityName(), item.getItemProperty("id").getValue().toString());
u.setForcePasswordChange(true);
db.session().update(u);
return true;
}
return false;
});
} catch (Exception e) {
getApp().getLog().error(e);
return false;
}
}
@Override
public boolean removeEntity (BeanFieldGroup fieldGroup) {
//Users have a deleted flag, they are not completely removed.
BeanItem item = fieldGroup.getItemDataSource();
User t = (User) item.getBean();
try {
return t != null && (boolean) DB.execWithTransaction((db) -> {
User user = db.session().get(User.class, t.getId());
if (user == null) return false;
t.setDeleted(true);
db.session().merge(t);
addRevisionRemoved(db, getEntityName(), String.valueOf(t.getId()));
return true;
});
} catch (Exception e) {
getApp().getLog().error(e);
return false;
}
}
@Override
public boolean updateEntity(BeanFieldGroup fieldGroup) throws FieldGroup.CommitException, BLException, CloneNotSupportedException {
//NOT USED
return false;
}
public List<Role> getRoles() {
try {
return (List<Role>) DB.exec((db) -> {
Criteria crit = db.session().createCriteria(Role.class);
return crit.list();
});
} catch (Exception e) {
getApp().getLog().error(e);
return null;
}
}
public Validator getNickTakenValidator(final User selectedU) {
return new Validator() {
public boolean isValid(Object value) {
String oldNick = selectedU.getNick();
if (oldNick!= null) {
User u = getUserByNick((String)value,true);
return u == null || u.getId().equals(selectedU.getId());
}
else
return getUserByNick((String) value,true) == null;
}
public void validate(Object value) throws InvalidValueException {
if (!isValid(value)) {
throw new InvalidValueException(getApp().getMessage(
"errorMessage.nickAlreadyExists", value)
);
}
}
};
}
public Validator getPasswordsMatchValidator(final PasswordField newPass) {
return (Validator) value -> {
if (!newPass.getValue().equals(value))
throw new Validator.InvalidValueException(getApp().getMessage("error.passwordsMatch"));
};
}
public String resetUserPassword (User user) {
String generatedPassword = PasswordGenerator.generateRandomPassword();
try {
DB.execWithTransaction((db) -> {
db.session().refresh(user);
user.getPasswordhistory(); // hack to avoid LazyInitialization
UserManager mgr = new UserManager(db);
try {
mgr.setPassword(user, generatedPassword);
} catch (BLException e) {
getApp().displayNotification("errorMessage.resetPassword");
return false;
}
user.setForcePasswordChange(true);
user.setLoginAttempts(0); // reset login attempts
db.session().saveOrUpdate(user);
return true;
});
} catch (Exception e) {
getApp().getLog().error(e);
return null;
}
return generatedPassword;
}
public Validator getCurrentPasswordMatchValidator (User user, final PasswordField currentPass) {
return new Validator() {
public boolean isValid (Object value) {
try {
return (boolean) DB.exec((db) -> {
UserManager mgr = new UserManager(db);
try {
return mgr.checkPassword(user, (String) value);
} catch (BLException e) {
return false;
}
});
} catch (Exception e) {
getApp().getLog().error(e);
return false;
}
}
@Override
public void validate(Object value) throws InvalidValueException {
if (!isValid(value)) {
currentPass.focus();
throw new InvalidValueException(getApp().getMessage("error.invalidPassword"));
}
}
};
}
public Validator getNewPasswordNotUsedValidator (User user, final PasswordField newPass) {
return new Validator() {
public boolean isValid (Object value) {
try {
return (boolean) DB.exec((db) -> {
db.session().refresh(user);
UserManager mgr = new UserManager(db);
try {
return mgr.checkNewPassword(user, (String) value);
} catch (BLException e) {
return false;
}
});
} catch (Exception e) {
getApp().getLog().error(e);
return false;
}
}
@Override
public void validate(Object value) throws InvalidValueException {
if (!isValid(value)) {
newPass.focus();
throw new Validator.InvalidValueException(getApp().getMessage("error.passwordUsed"));
}
}
};
}
}