package com.weEat.models import codes.reactive.scalatime._ import org.bson.types.ObjectId import com.weEat.shared.models.UserAuthorization import java.security.SecureRandom import java.time.{Duration,Instant} import java.util.Base64 import scala.concurrent.duration.FiniteDuration import scala.language.postfixOps import scalaoauth2.provider.AccessToken /* Basic User information */ case class User ( val _id: ObjectId, val fname: String, val lname: String, val email: String, val password: String, val created: Instant = Instant.now(), val isAdmin: Boolean = false ) { def toShared() = com.weEat.shared.models.User( _id, fname, lname, email ) } object User extends Collectable[User] { import com.weEat.shared.models.UserRegistration import com.github.t3hnar.bcrypt.BCryptStrOps val collectionName = "users" def apply(reg: UserRegistration): User = User( new ObjectId(), reg.fname, reg.lname, reg.email, reg.password.boundedBcrypt ) } class Authorization ( val accessToken: Array[Byte], val refreshToken: Array[Byte], val created: Instant, val email: String, val userId: ObjectId, val hasAdminPermissions: Boolean ) { def accessExpiration() = created + Authorization.accessFreshTime def refreshExpiration() = created + Authorization.refreshFreshTime implicit def asFiniteDuration(d: java.time.Duration) = scala.concurrent.duration.Duration.fromNanos(d.toNanos) implicit def asDate(d: java.time.Instant) = new java.util.Date(d.toEpochMilli()) def toToken() = new AccessToken( Authorization.encodeToken(accessToken), Some(Authorization.encodeToken(refreshToken)), Some(Set.concat( Option.when(hasAdminPermissions)("admin") ).mkString(" ")), Some(Duration.between(Instant.now(), accessExpiration()).getSeconds()), created ) def toUserAuth() = UserAuthorization( Authorization.encodeToken(accessToken), "Bearer", Duration.between(Instant.now(), accessExpiration()), Authorization.encodeToken(refreshToken), Set.concat( Option.when(hasAdminPermissions)("admin") ) ) } object Authorization extends Collectable[Authorization] { val accessFreshTime = 1 hour val refreshFreshTime = 10 hour val collectionName = "authorizations" private val rand = new SecureRandom() private def generateSecureBytes(n: Int = 32): Array[Byte] = { val token = new Array[Byte](n); rand.nextBytes(token) token } def encodeToken(token: Array[Byte]) = Base64.getEncoder.encodeToString(token) def decodeToken(token: String) = Base64.getDecoder.decode(token) def apply(user: User) = new Authorization( generateSecureBytes(), generateSecureBytes(), Instant.now(), user.email, user._id, user.isAdmin ) }