Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
179 lines (158 sloc) 6.206 kB
/**
* Copyright 2012 Jorge Aliss (jaliss at gmail dot com) - twitter: @jaliss
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package service
import play.api.Logger
import securesocial.core._
import securesocial.core.providers.{ UsernamePasswordProvider, MailToken }
import scala.concurrent.Future
import securesocial.core.services.{ UserService, SaveMode }
/**
* A Sample In Memory user service in Scala
*
* IMPORTANT: This is just a sample and not suitable for a production environment since
* it stores everything in memory.
*/
class InMemoryUserService extends UserService[DemoUser] {
val logger = Logger("application.controllers.InMemoryUserService")
//
var users = Map[(String, String), DemoUser]()
//private var identities = Map[String, BasicProfile]()
private var tokens = Map[String, MailToken]()
def find(providerId: String, userId: String): Future[Option[BasicProfile]] = {
if (logger.isDebugEnabled) {
logger.debug("users = %s".format(users))
}
val result = for (
user <- users.values;
basicProfile <- user.identities.find(su => su.providerId == providerId && su.userId == userId)
) yield {
basicProfile
}
Future.successful(result.headOption)
}
def findByEmailAndProvider(email: String, providerId: String): Future[Option[BasicProfile]] = {
if (logger.isDebugEnabled) {
logger.debug("users = %s".format(users))
}
val someEmail = Some(email)
val result = for (
user <- users.values;
basicProfile <- user.identities.find(su => su.providerId == providerId && su.email == someEmail)
) yield {
basicProfile
}
Future.successful(result.headOption)
}
private def findProfile(p: BasicProfile) = {
users.find {
case (key, value) if value.identities.exists(su => su.providerId == p.providerId && su.userId == p.userId) => true
case _ => false
}
}
private def updateProfile(user: BasicProfile, entry: ((String, String), DemoUser)): Future[DemoUser] = {
val identities = entry._2.identities
val updatedList = identities.patch(identities.indexWhere(i => i.providerId == user.providerId && i.userId == user.userId), Seq(user), 1)
val updatedUser = entry._2.copy(identities = updatedList)
users = users + (entry._1 -> updatedUser)
Future.successful(updatedUser)
}
def save(user: BasicProfile, mode: SaveMode): Future[DemoUser] = {
mode match {
case SaveMode.SignUp =>
val newUser = DemoUser(user, List(user))
users = users + ((user.providerId, user.userId) -> newUser)
Future.successful(newUser)
case SaveMode.LoggedIn =>
// first see if there is a user with this BasicProfile already.
findProfile(user) match {
case Some(existingUser) =>
updateProfile(user, existingUser)
case None =>
val newUser = DemoUser(user, List(user))
users = users + ((user.providerId, user.userId) -> newUser)
Future.successful(newUser)
}
case SaveMode.PasswordChange =>
findProfile(user).map { entry => updateProfile(user, entry) }.getOrElse(
// this should not happen as the profile will be there
throw new Exception("missing profile)")
)
}
}
def link(current: DemoUser, to: BasicProfile): Future[DemoUser] = {
if (current.identities.exists(i => i.providerId == to.providerId && i.userId == to.userId)) {
Future.successful(current)
} else {
val added = to :: current.identities
val updatedUser = current.copy(identities = added)
users = users + ((current.main.providerId, current.main.userId) -> updatedUser)
Future.successful(updatedUser)
}
}
def saveToken(token: MailToken): Future[MailToken] = {
Future.successful {
tokens += (token.uuid -> token)
token
}
}
def findToken(token: String): Future[Option[MailToken]] = {
Future.successful { tokens.get(token) }
}
def deleteToken(uuid: String): Future[Option[MailToken]] = {
Future.successful {
tokens.get(uuid) match {
case Some(token) =>
tokens -= uuid
Some(token)
case None => None
}
}
}
// def deleteTokens(): Future {
// tokens = Map()
// }
def deleteExpiredTokens() {
tokens = tokens.filter(!_._2.isExpired)
}
override def updatePasswordInfo(user: DemoUser, info: PasswordInfo): Future[Option[BasicProfile]] = {
Future.successful {
for (
found <- users.values.find(_ == user);
identityWithPasswordInfo <- found.identities.find(_.providerId == UsernamePasswordProvider.UsernamePassword)
) yield {
val idx = found.identities.indexOf(identityWithPasswordInfo)
val updated = identityWithPasswordInfo.copy(passwordInfo = Some(info))
val updatedIdentities = found.identities.patch(idx, Seq(updated), 1)
val updatedEntry = found.copy(identities = updatedIdentities)
users = users + ((updatedEntry.main.providerId, updatedEntry.main.userId) -> updatedEntry)
updated
}
}
}
override def passwordInfoFor(user: DemoUser): Future[Option[PasswordInfo]] = {
Future.successful {
for (
found <- users.values.find(u => u.main.providerId == user.main.providerId && u.main.userId == user.main.userId);
identityWithPasswordInfo <- found.identities.find(_.providerId == UsernamePasswordProvider.UsernamePassword)
) yield {
identityWithPasswordInfo.passwordInfo.get
}
}
}
}
// a simple User class that can have multiple identities
case class DemoUser(main: BasicProfile, identities: List[BasicProfile])
Jump to Line
Something went wrong with that request. Please try again.