0

Это моя реализация класса UserService. Это немного измененная версия этой реализации (http://www.shrikar.com/blog/2013/10/26/playframework-securesocial-and-mongodb/)MongoUserService for SecureSocial (Play Framework) постоянно поддерживает одного пользователя.

Я использую его с по умолчанию securesocial FacebookProvider. Все работает отлично, за исключением того, что он дублирует записи пользователя каждый раз, когда я вхожу в систему. Я хотел бы сохранить пользователя только один раз. Я думал, что это было обработано самим плагином, но я не уверен, что это так. Это зависит от меня, чтобы проверить, существует ли пользователь и вставить зарегистрированного пользователя, только если нет других записей для одного и того же пользователя? Или что-то еще не так?

class MongoUserService(application: Application) extends UserServicePlugin(application) with Controller with MongoController { 
    def collection: JSONCollection = db.collection[JSONCollection]("users") 
    def tokens: JSONCollection = db.collection[JSONCollection]("tokens") 
    val outPutUser = (__ \ "id").json.prune 

    def retIdentity(json: JsObject): Identity = { 
    val userid = (json \ "userid").as[String] 

    val provider = (json \ "provider").as[String] 
    val firstname = (json \ "firstname").as[String] 
    val lastname = (json \ "lastname").as[String] 
    val email = (json \ "email").as[String] 
    val avatar = (json \ "avatar").as[String] 
    val hash = (json \ "password" \ "hasher").as[String] 
    val password = (json \ "password" \ "password").as[String] 
    println("password : " + password) 
    val salt = (json \ "password" \ "salt").asOpt[String] 
    val authmethod = (json \ "authmethod").as[String] 

    val identity: IdentityId = new IdentityId(userid, authmethod) 
    val authMethod: AuthenticationMethod = new AuthenticationMethod(authmethod) 
    val pwdInfo: PasswordInfo = new PasswordInfo(hash, password) 
    val serial:Integer=((json\"serial").as[Long]).toInt 
    val user: NWOUser = new NWOUser(identity, firstname, lastname, firstname, Some(email), Some(avatar), authMethod, None, None, Some(pwdInfo),serial) 
    user 
    } 

    def generateSerial():Integer={ 
    val collection = db[JSONCollection]("serial") 
    val cursor = collection.find(Json.obj()).cursor[JsObject] 
    val futureserial = cursor.headOption.map { 
     case Some(i) => i 
     case None => 0 
    } 
    val jobj = Await.result(futureserial, 5 seconds) 
    val newSerial=jobj match { 
     case x: Boolean => 0 
     case _ =>retSerial(jobj.asInstanceOf[JsObject])+1 

    } 
    collection.update(Json.obj(), Json.obj("$set"->Json.obj("serial"->newSerial))).onComplete { 
    case _=>println("updated") 
} 
    newSerial 
    } 
    def retSerial(json: JsObject): Integer = { 
    println(json) 
    val serial=(json \ "serial").as[Long] 
    serial.toInt 
    } 

    def findByEmailAndProvider(email: String, providerId: String): Option[Identity] = { 
    val cursor = collection.find(Json.obj("userid" -> email, "provider" -> providerId)).cursor[JsObject] 
    val futureuser = cursor.headOption.map { 
     case Some(user) => user 
     case None => false 
    } 
    val jobj = Await.result(futureuser, 5 seconds) 

    jobj match { 
     case x: Boolean => None 
     case _ => Some(retIdentity(jobj.asInstanceOf[JsObject])) 

    } 
    } 

    def save(user: Identity): Identity = { 

    val email = user.email match { 
     case Some(email) => email 
     case _ => "N/A" 
    } 

    val avatar = user.avatarUrl match { 
     case Some(url) => url 
     case _ => "N/A" 
    } 
    val savejson = Json.obj(
     "userid" -> user.identityId.userId, 
     "provider" -> user.identityId.providerId, 
     "firstname" -> user.firstName, 
     "lastname" -> user.lastName, 
     "email" -> email, 
     "avatar" -> avatar, 
     "authmethod" -> user.authMethod.method, 
     "serial"->this.generateSerial.toLong, 
     user.passwordInfo match { 
     case None =>"password" -> Json.obj( "hasher" -> "", 
      "password" -> "", 
      "salt" -> "") 

     case x =>"password" -> Json.obj(
      "hasher" -> x.get.hasher, 
      "password" -> x.get.password, 
      "salt" -> x.get.salt) 

     }, 
     "created_at" -> Json.obj("$date" -> new Date()), 
     "updated_at" -> Json.obj("$date" -> new Date())) 
    println(Json.toJson(savejson)) 
    collection.insert(savejson) 
    user 
    } 

    def find(id: IdentityId): Option[Identity] = { 
    findByEmailAndProvider(id.userId, id.providerId) 
    } 

    def save(token: Token) { 
    val tokentosave = Json.obj(
     "uuid" -> token.uuid, 
     "email" -> token.email, 
     "creation_time" -> Json.obj("$date" -> token.creationTime), 
     "expiration_time" -> Json.obj("$date" -> token.expirationTime), 
     "isSignUp" -> token.isSignUp) 
    tokens.save(tokentosave) 
    } 

    def findToken(token: String): Option[Token] = { 

    val cursor = tokens.find(Json.obj("uuid" -> token)).cursor[JsObject] 
    val futureuser = cursor.headOption.map { 
     case Some(user) => user 
     case None => false 
    } 
    val jobj = Await.result(futureuser, 5 seconds) 
    jobj match { 
     case x: Boolean => None 
     case obj: JsObject => { 
     println(obj) 
     val uuid = (obj \ "uuid").as[String] 
     val email = (obj \ "email").as[String] 
     val created = (obj \ "creation_time" \ "$date").as[Long] 
     val expire = (obj \ "expiration_time" \ "$date").as[Long] 
     val signup = (obj \ "isSignUp").as[Boolean] 
     val df = DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss") 
     Some(new Token(uuid, email, new DateTime(created), new DateTime(expire), signup)) 
     } 
    } 
    } 

    def deleteToken(uuid: String) {} 

    def deleteExpiredTokens() {} 
} 

ответ

1

Вы можете решить с помощью db.collection.[update][1] с upsert=true, а не insert. С помощью этого флага он будет вставлять объект, идентифицированный первым элементом (запросом) в вызове, когда он не существует, и обновлять существующий.

Таким образом, вместо

collection.insert(savejson) 

попробовать

collection.update(
    Json.obj("userid" -> user.identityId.userId), 
    savejson, 
    Json.obj("upsert" -> true) 
)