-
Notifications
You must be signed in to change notification settings - Fork 633
/
Copy pathKeyAuthSrv.scala
55 lines (43 loc) · 1.96 KB
/
KeyAuthSrv.scala
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
package services
import java.util.Base64
import javax.inject.{Inject, Singleton}
import scala.concurrent.{ExecutionContext, Future}
import scala.util.Random
import play.api.libs.json.JsArray
import play.api.mvc.RequestHeader
import akka.stream.Materializer
import akka.stream.scaladsl.Sink
import org.elastic4play.controllers.Fields
import org.elastic4play.services.{AuthCapability, AuthContext, AuthSrv}
import org.elastic4play.{AuthenticationError, BadRequestError}
@Singleton
class KeyAuthSrv @Inject()(userSrv: UserSrv, implicit val ec: ExecutionContext, implicit val mat: Materializer) extends AuthSrv {
override val name = "key"
final protected def generateKey(): String = {
val bytes = Array.ofDim[Byte](24)
Random.nextBytes(bytes)
Base64.getEncoder.encodeToString(bytes)
}
override val capabilities = Set(AuthCapability.authByKey)
override def authenticate(key: String)(implicit request: RequestHeader): Future[AuthContext] = {
import org.elastic4play.services.QueryDSL._
// key attribute is sensitive so it is not possible to search on that field
userSrv
.find("status" ~= "Ok", Some("all"), Nil)
._1
.filter(_.key().contains(key))
.runWith(Sink.headOption)
.flatMap {
case Some(user) ⇒ userSrv.getFromUser(request, user, name)
case None ⇒ Future.failed(AuthenticationError("Authentication failure"))
}
}
override def renewKey(username: String)(implicit authContext: AuthContext): Future[String] = {
val newKey = generateKey()
userSrv.update(username, Fields.empty.set("key", newKey)).map(_ ⇒ newKey)
}
override def getKey(username: String)(implicit authContext: AuthContext): Future[String] =
userSrv.get(username).map(_.key().getOrElse(throw BadRequestError(s"User $username hasn't key")))
override def removeKey(username: String)(implicit authContext: AuthContext): Future[Unit] =
userSrv.update(username, Fields.empty.set("key", JsArray())).map(_ ⇒ ())
}