package org.hadatac.console.models;
import be.objectify.deadbolt.core.models.Permission;
import be.objectify.deadbolt.core.models.Role;
import be.objectify.deadbolt.core.models.Subject;
import com.feth.play.module.pa.providers.password.UsernamePasswordAuthUser;
import com.feth.play.module.pa.user.AuthUser;
import com.feth.play.module.pa.user.AuthUserIdentity;
import com.feth.play.module.pa.user.EmailIdentity;
import com.feth.play.module.pa.user.NameIdentity;
import com.feth.play.module.pa.user.FirstLastNameIdentity;
import org.hadatac.console.controllers.AuthApplication;
import org.hadatac.console.models.TokenAction.Type;
import play.Play;
import play.data.format.Formats;
import play.data.validation.Constraints;
import org.apache.solr.client.solrj.SolrClient;
import org.apache.solr.client.solrj.SolrQuery;
import org.apache.solr.client.solrj.SolrServerException;
import org.apache.solr.client.solrj.beans.Field;
import org.apache.solr.client.solrj.impl.HttpSolrClient;
import org.apache.solr.client.solrj.response.QueryResponse;
import org.apache.solr.client.solrj.response.UpdateResponse;
import org.apache.solr.common.SolrDocument;
import org.apache.solr.common.SolrDocumentList;
import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;
import org.joda.time.format.ISODateTimeFormat;
import org.noggit.JSONUtil;
import java.io.IOException;
import java.util.*;
import javax.swing.text.StyledEditorKit.BoldAction;
import org.hadatac.entity.pojo.Measurement;
import org.hadatac.entity.pojo.User;
import org.hadatac.utils.Collections;
/**
* Initial version based on work by Steve Chaloner (steve@objectify.be) for
* Deadbolt2
*/
public class SysUser implements Subject {
/**
*
*/
private static final long serialVersionUID = 1L;
public Long id;
@Field("id")
private String id_s;
@Field("uri")
private String uri;
@Constraints.Email
@Field("email")
private String email;
@Field("name")
private String name;
@Field("first_name")
private String firstName;
@Field("last_name")
private String lastName;
@Field("last_login")
private String lastLogin;
@Field("active")
private boolean active;
@Field("email_validated")
private boolean emailValidated;
private DateTime lastLogin_j;
private List<SecurityRole> roles;
private List<LinkedAccount> linkedAccounts;
private List<UserPermission> permissions;
public SysUser() {
roles = new ArrayList<SecurityRole>();
}
public String getId() {
return id_s;
}
public void setId(String id) {
this.id_s = id;
}
public String getUri() {
return uri;
}
public void setUri(String uri) {
this.uri = uri;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getLastLogin() {
DateTimeFormatter formatter = ISODateTimeFormat.dateTime();
return formatter.withZone(DateTimeZone.UTC).print(this.lastLogin_j);
}
public void setLastLogin(String lastLogin) {
DateTimeFormatter formatter = DateTimeFormat.forPattern("EEE MMM dd HH:mm:ss zzz yyyy");
lastLogin_j = formatter.parseDateTime(lastLogin);
}
public boolean getActive() {
return active;
}
public void setActive(boolean active) {
this.active = active;
}
public boolean getEmailValidated() {
return emailValidated;
}
public void setEmailValidated(boolean emailValidated) {
this.emailValidated = emailValidated;
}
public List<LinkedAccount> getLinkedAccounts() {
return linkedAccounts;
}
public void setLinkedAccounts(List<LinkedAccount> linkedAccounts) {
this.linkedAccounts = linkedAccounts;
}
public List<String> getSecurityRoleId() {
List<String> list = new ArrayList<String>();
Iterator<SecurityRole> roleIterator = roles.iterator();
while (roleIterator.hasNext()) {
SecurityRole role = roleIterator.next();
list.add(role.id_s);
}
return list;
}
@Field("security_role_id")
public void setSecurityRoleId(List<String> list) {
Iterator<String> listIterator = list.iterator();
while (listIterator.hasNext()) {
String id = listIterator.next();
SecurityRole role = new SecurityRole();
role.id_s = id;
roles.add(role);
}
}
public boolean isDataManager() {
SecurityRole target = SecurityRole.findByRoleNameSolr(AuthApplication.DATA_MANAGER_ROLE);
for(SecurityRole r : roles) {
if(r.id_s.equals(target.id_s)){
return true;
}
}
return false;
}
public boolean isEmailValidated() {
return emailValidated;
}
public void addSecurityRole(String role_name) {
SecurityRole new_role = SecurityRole.findByRoleNameSolr(role_name);
boolean isRoleExisted = false;
Iterator<SecurityRole> iterRoles = roles.iterator();
while (iterRoles.hasNext()) {
SecurityRole role = iterRoles.next();
if(role.id_s.equals(new_role.id_s)){
isRoleExisted = true;
}
}
if(!isRoleExisted){
roles.add(new_role);
}
}
public void removeSecurityRole(String role_name) {
SecurityRole new_role = SecurityRole.findByRoleNameSolr(role_name);
Iterator<SecurityRole> iterRoles = roles.iterator();
while (iterRoles.hasNext()) {
SecurityRole role = iterRoles.next();
if(role.id_s.equals(new_role.id_s)){
iterRoles.remove();
}
}
}
public List<String> getUserPermissionId() {
List<String> list = new ArrayList<String>();
Iterator<UserPermission> permissionIterator = permissions.iterator();
while (permissionIterator.hasNext()) {
UserPermission permission = permissionIterator.next();
list.add(permission.id_s);
}
return list;
}
@Field("user_permission_id")
public void setUserPermissionId(List<String> list) {
Iterator<String> listIterator = list.iterator();
while (listIterator.hasNext()) {
String id = listIterator.next();
UserPermission permission = new UserPermission();
permission.id_s = id;
permissions.add(permission);
}
}
@Override
public String getIdentifier() {
return Long.toString(this.id);
}
@Override
public List<? extends Role> getRoles() {
return this.roles;
}
@Override
public List<? extends Permission> getPermissions() {
return this.permissions;
}
public static boolean existsByAuthUserIdentity(
final AuthUserIdentity identity) {
return existsByAuthUserIdentitySolr(identity);
}
public static boolean existsByAuthUserIdentitySolr(
final AuthUserIdentity identity) {
final List<SysUser> users;
if (identity instanceof UsernamePasswordAuthUser) {
users = getUsernamePasswordAuthUserFindSolr((UsernamePasswordAuthUser) identity);
} else {
users = getAuthUserFindSolr(identity);
}
return !users.isEmpty();
}
private static List<SysUser> getAuthUserFindSolr(
final AuthUserIdentity identity) {
SolrClient solrClient = new HttpSolrClient(
Play.application().configuration().getString("hadatac.solr.users")
+ Collections.AUTHENTICATE_USERS);
String query = "active:true AND provider_user_id:" + identity.getId() + " AND provider_key:" + identity.getProvider();
SolrQuery solrQuery = new SolrQuery(query);
List<SysUser> users = new ArrayList<SysUser>();
try {
QueryResponse queryResponse = solrClient.query(solrQuery);
solrClient.close();
SolrDocumentList list = queryResponse.getResults();
Iterator<SolrDocument> i = list.iterator();
while (i.hasNext()) {
SysUser user = convertSolrDocumentToUser(i.next());
users.add(user);
}
} catch (Exception e) {
System.out.println("[ERROR] User.getAuthUserFindSolr - Exception message: " + e.getMessage());
}
return users;
}
public static SysUser findByAuthUserIdentity(final AuthUserIdentity identity) {
return findByAuthUserIdentitySolr(identity);
}
public static SysUser findByAuthUserIdentitySolr(final AuthUserIdentity identity) {
if (identity == null) {
return null;
}
if (identity instanceof UsernamePasswordAuthUser) {
return findByUsernamePasswordIdentitySolr((UsernamePasswordAuthUser) identity);
} else {
List<SysUser> users = getAuthUserFindSolr(identity);
if (users.size() == 1) {
return users.get(0);
} else {
return null;
}
}
}
public static SysUser findByUsernamePasswordIdentity(
final UsernamePasswordAuthUser identity) {
return findByUsernamePasswordIdentitySolr(identity);
}
public static SysUser findByUsernamePasswordIdentitySolr(
final UsernamePasswordAuthUser identity) {
List<SysUser> users = getUsernamePasswordAuthUserFindSolr(identity);
if (users.size() == 1) {
return users.get(0);
} else {
return null;
}
}
public static SysUser findByIdSolr(final String id) {
SolrClient solrClient = new HttpSolrClient(
Play.application().configuration().getString("hadatac.solr.users")
+ Collections.AUTHENTICATE_USERS);
SolrQuery solrQuery = new SolrQuery("id:" + id);
SysUser user = null;
try {
QueryResponse queryResponse = solrClient.query(solrQuery);
solrClient.close();
SolrDocumentList list = queryResponse.getResults();
if (list.size() == 1) {
user = convertSolrDocumentToUser(list.get(0));
}
} catch (Exception e) {
System.out.println("[ERROR] TokenAction.findByTokenSolr - Exception message: " + e.getMessage());
}
return user;
}
private static List<SysUser> getUsernamePasswordAuthUserFindSolr(
final UsernamePasswordAuthUser identity) {
return getEmailUserFindSolr(identity.getEmail(), identity.getProvider());
}
public void merge(final SysUser otherUser) {
mergeSolr(otherUser);
}
public void mergeSolr(final SysUser otherUser) {
for (final LinkedAccount acc : otherUser.linkedAccounts) {
this.linkedAccounts.add(LinkedAccount.create(acc));
}
// do all other merging stuff here - like resources, etc.
// deactivate the merged user that got added to this one
otherUser.active = false;
this.save();
otherUser.save();
}
public static SysUser create(final AuthUser authUser, String uri) {
final SysUser sys_user = new SysUser();
sys_user.roles.add(SecurityRole
.findByRoleNameSolr(AuthApplication.DATA_OWNER_ROLE));
sys_user.permissions = new ArrayList<UserPermission>();
sys_user.active = true;
sys_user.lastLogin = (new Date()).toString();
sys_user.linkedAccounts = java.util.Collections.singletonList(LinkedAccount
.create(authUser));
if (authUser instanceof EmailIdentity) {
final EmailIdentity identity = (EmailIdentity) authUser;
// Remember, even when getting them from FB & Co., emails should be
// verified within the application as a security breach there might
// break your security as well!
sys_user.email = identity.getEmail();
sys_user.emailValidated = false;
}
if (authUser instanceof NameIdentity) {
final NameIdentity identity = (NameIdentity) authUser;
final String name = identity.getName();
if (name != null) {
sys_user.name = name;
}
}
if (authUser instanceof FirstLastNameIdentity) {
final FirstLastNameIdentity identity = (FirstLastNameIdentity) authUser;
final String firstName = identity.getFirstName();
final String lastName = identity.getLastName();
if (firstName != null) {
sys_user.firstName = firstName;
}
if (lastName != null) {
sys_user.lastName = lastName;
}
}
sys_user.id_s = UUID.randomUUID().toString();
if (!SysUser.existsSolr()) {
sys_user.roles.add(SecurityRole
.findByRoleNameSolr(AuthApplication.DATA_MANAGER_ROLE));
sys_user.emailValidated = true;
String admin_uri = "http://localhost/users#admin";
User user = new User();
user.setName(sys_user.name);
user.setEmail(sys_user.email);
user.setUri(admin_uri);
if(null == uri){
sys_user.uri = admin_uri;
}
else{
sys_user.uri = uri;
}
user.save();
sys_user.save();
return sys_user;
}
if(null == uri) {
sys_user.uri = "";
}
else {
sys_user.uri = uri;
}
sys_user.save();
return sys_user;
}
public static boolean existsSolr() {
SolrClient solrClient = new HttpSolrClient(
Play.application().configuration().getString("hadatac.solr.users")
+ Collections.AUTHENTICATE_USERS);
SolrQuery solrQuery = new SolrQuery("*:*");
try {
QueryResponse queryResponse = solrClient.query(solrQuery);
solrClient.close();
SolrDocumentList list = queryResponse.getResults();
if (list.size() > 0) {
return true;
}
} catch (Exception e) {
System.out.println("[ERROR] User.existsSolr - Exception message: " + e.getMessage());
}
return false;
}
public static SysUser create(final AuthUser authUser) {
final SysUser sys_user = new SysUser();
sys_user.roles.add(SecurityRole
.findByRoleNameSolr(org.hadatac.console.controllers.AuthApplication.DATA_OWNER_ROLE));
sys_user.permissions = new ArrayList<UserPermission>();
sys_user.active = true;
sys_user.lastLogin = (new Date()).toString();
sys_user.linkedAccounts = java.util.Collections.singletonList(LinkedAccount
.create(authUser));
if (authUser instanceof EmailIdentity) {
final EmailIdentity identity = (EmailIdentity) authUser;
// Remember, even when getting them from FB & Co., emails should be
// verified within the application as a security breach there might
// break your security as well!
sys_user.email = identity.getEmail();
sys_user.emailValidated = false;
}
if (authUser instanceof NameIdentity) {
final NameIdentity identity = (NameIdentity) authUser;
final String name = identity.getName();
if (name != null) {
sys_user.name = name;
}
}
if (authUser instanceof FirstLastNameIdentity) {
final FirstLastNameIdentity identity = (FirstLastNameIdentity) authUser;
final String firstName = identity.getFirstName();
final String lastName = identity.getLastName();
if (firstName != null) {
sys_user.firstName = firstName;
}
if (lastName != null) {
sys_user.lastName = lastName;
}
}
sys_user.id_s = UUID.randomUUID().toString();
User user = new User();
user.setName(sys_user.name);
user.setEmail(sys_user.email);
if (SysUser.existsSolr() == false) {
sys_user.roles.add(SecurityRole
.findByRoleNameSolr(org.hadatac.console.controllers.AuthApplication.DATA_MANAGER_ROLE));
sys_user.emailValidated = true;
user.setUri("http://localhost/users#admin");
}
user.save();
sys_user.save();
return sys_user;
}
public void save() {
SolrClient solrClient = new HttpSolrClient(
Play.application().configuration().getString("hadatac.solr.users")
+ Collections.AUTHENTICATE_USERS);
try {
solrClient.addBean(this);
solrClient.commit();
solrClient.close();
} catch (Exception e) {
e.printStackTrace();
}
Iterator<LinkedAccount> i = linkedAccounts.iterator();
while (i.hasNext()) {
LinkedAccount account = i.next();
account.user = this;
account.save();
}
}
public int delete() {
try {
SolrClient solr = new HttpSolrClient(
Play.application().configuration().getString("hadatac.solr.users")
+ Collections.AUTHENTICATE_USERS);
UpdateResponse response = solr.deleteById(this.id_s);
solr.commit();
solr.close();
return response.getStatus();
} catch (SolrServerException e) {
System.out.println("[ERROR] SysUser.delete() - SolrServerException message: " + e.getMessage());
} catch (IOException e) {
System.out.println("[ERROR] SysUser.delete() - IOException message: " + e.getMessage());
} catch (Exception e) {
System.out.println("[ERROR] SysUser.delete() - Exception message: " + e.getMessage());
}
return -1;
}
public static void merge(final AuthUser oldUser, final AuthUser newUser) {
mergeSolr(oldUser, newUser);
}
public static void mergeSolr(final AuthUser oldUser, final AuthUser newUser) {
SysUser.findByAuthUserIdentitySolr(oldUser).merge(
SysUser.findByAuthUserIdentitySolr(newUser));
}
public Set<String> getProviders() {
final Set<String> providerKeys = new HashSet<String>(
this.linkedAccounts.size());
for (final LinkedAccount acc : this.linkedAccounts) {
providerKeys.add(acc.providerKey);
}
return providerKeys;
}
public static void addLinkedAccount(final AuthUser oldUser,
final AuthUser newUser) {
final SysUser u = SysUser.findByAuthUserIdentity(oldUser);
if (null != u) {
u.linkedAccounts.add(LinkedAccount.create(newUser));
u.save();
}
}
public static void setLastLoginDate(final AuthUser knownUser) {
final SysUser u = SysUser.findByAuthUserIdentity(knownUser);
if (null != u) {
u.lastLogin = (new Date()).toString();
u.save();
}
}
public static SysUser findByEmail(final String email) {
return findByEmailSolr(email);
}
public static SysUser findByEmailSolr(final String email) {
List<SysUser> users = getEmailUserFindSolr(email);
if (users.size() == 1) {
return users.get(0);
} else {
return null;
}
}
private static List<SysUser> getEmailUserFindSolr(final String email) {
return getEmailUserFindSolr(email, "");
}
private static List<SysUser> getEmailUserFindSolr(final String email, final String providerKey) {
SolrClient solrClient = new HttpSolrClient(
Play.application().configuration().getString("hadatac.solr.users")
+ Collections.AUTHENTICATE_USERS);
String query = "email:" + email + " AND active:true";
SolrQuery solrQuery = new SolrQuery(query);
List<SysUser> users = new ArrayList<SysUser>();
try {
QueryResponse queryResponse = solrClient.query(solrQuery);
solrClient.close();
SolrDocumentList list = queryResponse.getResults();
Iterator<SolrDocument> i = list.iterator();
while (i.hasNext()) {
SysUser user = convertSolrDocumentToUser(i.next());
users.add(user);
if (!providerKey.isEmpty()) {
LinkedAccount account = LinkedAccount.findByProviderKeySolr(user, providerKey);
if (account == null) {
users.remove(user);
}
}
}
} catch (Exception e) {
System.out.println("[ERROR] User.getEmailUserFindSolr - Exception message: " + e.getMessage());
}
return users;
}
public static String outputAsJson() {
SolrClient solrClient = new HttpSolrClient(
Play.application().configuration().getString("hadatac.solr.users")
+ Collections.AUTHENTICATE_USERS);
String query = "*:*";
SolrQuery solrQuery = new SolrQuery(query);
try {
QueryResponse queryResponse = solrClient.query(solrQuery);
solrClient.close();
SolrDocumentList docs = queryResponse.getResults();
return JSONUtil.toJSON(docs);
} catch (Exception e) {
System.out.println("[ERROR] SysUser.outputAsJson - Exception message: " + e.getMessage());
}
return "";
}
public LinkedAccount getAccountByProvider(final String providerKey) {
return LinkedAccount.findByProviderKey(this, providerKey);
}
public LinkedAccount getAccountByProviderSolr(final String providerKey) {
return LinkedAccount.findByProviderKeySolr(this, providerKey);
}
public static void verify(final SysUser unverified) {
// You might want to wrap this into a transaction
unverified.emailValidated = true;
unverified.save();
TokenAction.deleteByUser(unverified, Type.EMAIL_VERIFICATION);
}
public void changePassword(final UsernamePasswordAuthUser authUser,
final boolean create) {
changePasswordSolr(authUser, create);
}
public void changePasswordSolr(final UsernamePasswordAuthUser authUser,
final boolean create) {
LinkedAccount a = this.getAccountByProviderSolr(authUser.getProvider());
if (a == null) {
if (create) {
a = LinkedAccount.create(authUser);
a.user = this;
} else {
throw new RuntimeException(
"Account not enabled for password usage");
}
}
a.providerUserId = authUser.getHashedPassword();
a.save();
}
public void resetPassword(final UsernamePasswordAuthUser authUser,
final boolean create) {
// You might want to wrap this into a transaction
resetPasswordSolr(authUser, create);
}
public void resetPasswordSolr(final UsernamePasswordAuthUser authUser,
final boolean create) {
// You might want to wrap this into a transaction
this.changePassword(authUser, create);
TokenAction.deleteByUserSolr(this, Type.PASSWORD_RESET);
}
private static SysUser convertSolrDocumentToUser(SolrDocument doc) {
SysUser user = new SysUser();
user.id_s = doc.getFieldValue("id").toString();
user.uri = doc.getFieldValue("uri").toString();
user.email = doc.getFieldValue("email").toString();
user.name = doc.getFieldValue("name").toString();
user.firstName = doc.getFieldValue("first_name").toString();
user.lastName = doc.getFieldValue("last_name").toString();
if (null == doc.getFieldValue("last_login")) {
user.setLastLogin((new Date()).toString());
}
else {
user.setLastLogin(doc.getFieldValue("last_login").toString());
}
user.active = Boolean.parseBoolean(doc.getFieldValue("active").toString());
user.emailValidated = Boolean.parseBoolean(doc.getFieldValue("email_validated").toString());
user.roles = new ArrayList<SecurityRole>();
Iterator<Object> i = doc.getFieldValues("security_role_id").iterator();
while (i.hasNext()) {
user.roles.add(SecurityRole.findByIdSolr(i.next().toString()));
}
user.permissions = new ArrayList<UserPermission>();
if (doc.getFieldValues("user_permission_id") != null) {
i = doc.getFieldValues("user_permission_id").iterator();
while (i.hasNext()) {
user.permissions.add(UserPermission.findByIdSolr(i.next().toString()));
}
}
user.linkedAccounts = LinkedAccount.findByIdSolr(user);
return user;
}
}