Search code examples
javascalaplayframework-2.0persistencesecuresocial

Persisting User Data with securesocial in Play 2.3 Java


I am attempting to create a Java application using Play 2.3 and the master snap-shot of securesocial that will allow users to login using either Facebook , Google+ or Twitter the allow users to link their accounts together and persist this information to a database . I have been having trouble writing a UserService (particularly when linking accounts) that will allow for this. I have found examples using earlier versions of Play/securesocial but have been unable to find an example using the master snap-shot.

If anyone has any examples they could share it would be appreciated.


Solution

  • I was able to create the UserService.

    User Model

    import play.db.ebean.Model;
    import javax.persistence.*;
    import java.util.ArrayList;
    import java.util.Date;
    import java.util.List;
    
    @Entity
    @Table(name = "users")
    public class User extends Model {
    
       @Id
       @GeneratedValue
       public Long id;
    
       public Date lastLogin;
    
       @OneToMany(mappedBy = "user", cascade = CascadeType.ALL)
       public List<Profile> identities;
    
       public User(Profile profile){
    
           identities = new ArrayList<Profile>();
           this.identities.add(profile);
           lastLogin = new Date();
       }
    
       public static Finder<String ,User> find = new Finder<String, User>(String.class, User.class);
    
    
    }
    

    Profile Model

     import play.db.ebean.Model;
    import securesocial.core.BasicProfile;
    
    import javax.persistence.*;
    
    @Entity
    @Table(name = "profiles")
    public class Profile extends Model {
    
        @Id
        @GeneratedValue
        public Long id;
    
        public String providerId;
        public String authUserId;
        public String firstName;
        public String lastName;
        public String fullName;
        public String email;
        public String avatarUrl;
    
        @ManyToOne
        @JoinColumn(name = "user_id")
        public User user;
    
        public Profile(BasicProfile profile){
            this.providerId = profile.providerId();
            this.authUserId  = profile.userId();
            if(profile.firstName().isDefined())
                firstName = profile.firstName().get();
    
            if(profile.lastName().isDefined())
                lastName  = profile.lastName().get();
            if(profile.fullName().isDefined())
                fullName = profile.fullName().get();
            if(profile.email().isDefined())
                email = profile.email().get();
            if(profile.avatarUrl().isDefined())
                avatarUrl = profile.avatarUrl().get();
    
    
        }
    }
    

    And the User Service

    package services;
    import models.Profile;
    import models.User;
    import play.libs.F;
    import securesocial.core.BasicProfile;
    import securesocial.core.PasswordInfo;
    import securesocial.core.java.BaseUserService;
    import securesocial.core.java.Token;
    import securesocial.core.services.SaveMode;
    
    import java.util.Date;
    import java.util.List;
    
    public class DemoUserService extends BaseUserService<User> {
    
        @Override
        public F.Promise<User> doSave(BasicProfile basicProfile, SaveMode saveMode) {
         User result = null;
         if(saveMode == SaveMode.SignUp()){
             Profile profile = new Profile(basicProfile);
             result = new User(profile);
             profile.user = result;
             result.save();
         }else if(saveMode == SaveMode.LoggedIn()){
             List<User> users = User.find.all();
             for(User user: users){
                 for(Profile p : user.identities) {
                     if (p.authUserId.equals(basicProfile.userId()) && p.providerId.equals(basicProfile.providerId())) {
                        result = user;
                        result.lastLogin = new Date();
                        result.update();
                     }
                 }
             }
         }else{
             throw new RuntimeException("Unknown mode");
         }
         return F.Promise.pure(result);
        }
    
        @Override
        public F.Promise<User> doLink(User user, BasicProfile basicProfile) {
            User target;
            User u = User.find.byId(user.id.toString());
            if(u == null) {
                throw new RuntimeException("Cant find user");
            }
            target = u;
    
    
            boolean linked = false;
            for(Profile p : target.identities){
                if(p.authUserId.equals(basicProfile.userId()) && p.providerId.equals(basicProfile.providerId())){
                    linked = true;
                }
            }
            if(!linked) {
                target.identities.add(new Profile(basicProfile));
                target.update();
            }
    
            return F.Promise.pure(target);
        }
    
        @Override
        public F.Promise<BasicProfile> doFind(String providerId, String userId) {
            BasicProfile found = null;
            List<User> users = User.find.all();
            for(User u: users){
                for(Profile i : u.identities){
                    if(i.providerId.equals(providerId) && i.authUserId.equals(userId)){
                        found = new BasicProfile(providerId , userId , null , null , null , null , null , null , null , null , null);
                        break;
                    }
                }
            }
            return F.Promise.pure(found);
        }
    
        @Override
        public F.Promise<BasicProfile> doFindByEmailAndProvider(String s, String s1) {
            return null;
        }
    
        @Override
        public F.Promise<Token> doSaveToken(Token token) {
            return null;
        }
    
        @Override
        public F.Promise<Token> doDeleteToken(String s) {
            return null;
        }
    
        @Override
        public void doDeleteExpiredTokens() {
    
        }
    
        @Override
        public F.Promise<Token> doFindToken(String s) {
            return null;
        }
    
        @Override
        public F.Promise<PasswordInfo> doPasswordInfoFor(User user) {
            return null;
        }
    
        @Override
        public F.Promise<BasicProfile> doUpdatePasswordInfo(User user, PasswordInfo passwordInfo) {
            return null;
        }
    }