package models;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import play.data.validation.Constraints;
import play.db.ebean.Model;
import com.avaje.ebean.Ebean;
import com.avaje.ebean.ExpressionList;
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;
@Entity
@Table(name = "users")
public class User extends Model {
/**
*
*/
private static final long serialVersionUID = 1L;
@Id
public Long id;
@Constraints.Email
// if you make this unique, keep in mind that users *must* merge/link their
// accounts then on signup with additional providers
// @Column(unique = true)
public String email;
public String name;
public boolean active;
public boolean emailValidated;
@OneToMany(cascade = CascadeType.ALL)
public List<LinkedAccount> linkedAccounts;
public static final Finder<Long, User> find = new Finder<Long, User>(
Long.class, User.class);
public static boolean existsByAuthUserIdentity(
final AuthUserIdentity identity) {
final ExpressionList<User> exp = getAuthUserFind(identity);
return exp.findRowCount() > 0;
}
private static ExpressionList<User> getAuthUserFind(
final AuthUserIdentity identity) {
return find.where().eq("active", true)
.eq("linkedAccounts.providerUserId", identity.getId())
.eq("linkedAccounts.providerKey", identity.getProvider());
}
public static User findByAuthUserIdentity(final AuthUserIdentity identity) {
if (identity == null) {
return null;
}
return getAuthUserFind(identity).findUnique();
}
public void merge(final User 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;
Ebean.save(Arrays.asList(new User[] { otherUser, this }));
}
public static User create(final AuthUser authUser) {
final User user = new User();
user.active = true;
user.linkedAccounts = 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!
user.email = identity.getEmail();
user.emailValidated = false;
}
if (authUser instanceof NameIdentity) {
final NameIdentity identity = (NameIdentity) authUser;
final String name = identity.getName();
if (name != null) {
user.name = name;
}
}
user.save();
return user;
}
public static void merge(final AuthUser oldUser, final AuthUser newUser) {
User.findByAuthUserIdentity(oldUser).merge(
User.findByAuthUserIdentity(newUser));
}
public Set<String> getProviders() {
final Set<String> providerKeys = new HashSet<String>(
linkedAccounts.size());
for (final LinkedAccount acc : linkedAccounts) {
providerKeys.add(acc.providerKey);
}
return providerKeys;
}
public static void addLinkedAccount(final AuthUser oldUser,
final AuthUser newUser) {
final User u = User.findByAuthUserIdentity(oldUser);
u.linkedAccounts.add(LinkedAccount.create(newUser));
u.save();
}
public static User findByEmail(final String email) {
return getEmailUserFind(email).findUnique();
}
private static ExpressionList<User> getEmailUserFind(final String email) {
return find.where().eq("active", true).eq("email", email);
}
public LinkedAccount getAccountByProvider(final String providerKey) {
return LinkedAccount.findByProviderKey(this, providerKey);
}
}