1 /*
2  *  Make.org Core API
3  *  Copyright (C) 2018 Make.org
4  *
5  * This program is free software: you can redistribute it and/or modify
6  *  it under the terms of the GNU Affero General Public License as
7  *  published by the Free Software Foundation, either version 3 of the
8  *  License, or (at your option) any later version.
9  *
10  *  This program is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  *  GNU Affero General Public License for more details.
14  *
15  *  You should have received a copy of the GNU Affero General Public License
16  *  along with this program.  If not, see <https://www.gnu.org/licenses/>.
17  *
18  */
19 
20 package org.make.api.technical.auth
21 
22 import java.util.UUID
23 
24 import org.make.api.technical.security.SecurityHelper
25 
26 import scala.concurrent.ExecutionContext.Implicits.global
27 import scala.concurrent.Future
28 
29 trait TokenGeneratorComponent {
30   def tokenGenerator: TokenGenerator
31 }
32 
33 trait TokenGenerator {
34   val MAX_RETRY = 3
35 
36   def tokenToHash(token: String): String
37   def generateToken(tokenExistsFunction: String => Future[Boolean], depth: Int = MAX_RETRY): Future[(String, String)]
38   def newRandomToken(): (String, String)
39 }
40 
41 trait DefaultTokenGeneratorComponent extends TokenGeneratorComponent {
42 
43   override lazy val tokenGenerator: TokenGenerator = new DefaultTokenGenerator
44 
45   class DefaultTokenGenerator extends TokenGenerator {
46 
47     override def tokenToHash(token: String): String =
48       SecurityHelper.defaultHash(token).toUpperCase()
49 
50     @SuppressWarnings(Array("org.wartremover.warts.Recursion"))
51     override def generateToken(
52       tokenExistsFunction: String => Future[Boolean],
53       depth: Int = MAX_RETRY
54     ): Future[(String, String)] = {
55       if (depth <= 0) {
56         Future.failed(new RuntimeException("Token generation failed due to max retries reached."))
57       } else {
58         val (token, hashedToken): (String, String) = newRandomToken()
59         tokenExistsFunction(hashedToken).flatMap { exists =>
60           if (exists) {
61             generateToken(tokenExistsFunction, depth - 1)
62           } else {
63             Future.successful((token, hashedToken))
64           }
65         }
66       }
67     }
68 
69     override def newRandomToken(): (String, String) = {
70       val token = UUID.randomUUID().toString
71 
72       (token, tokenToHash(token))
73     }
74   }
75 }
Line Stmt Id Pos Tree Symbol Tests Code
34 124 1063 - 1064 Literal <nosymbol> org.make.api.technical.auth.defaulttokengeneratorcomponenttest 3
48 15 1537 - 1584 Apply java.lang.String.toUpperCase org.make.api.technical.auth.defaulttokengeneratorcomponenttest org.make.api.technical.security.SecurityHelper.defaultHash(token).toUpperCase()
55 222 1811 - 1821 Apply scala.Int.<= org.make.api.technical.auth.defaulttokengeneratorcomponenttest depth.<=(0)
56 32 1833 - 1923 Apply scala.concurrent.Future.failed scala.concurrent.Future.failed[Nothing](new scala.`package`.RuntimeException("Token generation failed due to max retries reached."))
56 234 1833 - 1923 Block scala.concurrent.Future.failed scala.concurrent.Future.failed[Nothing](new scala.`package`.RuntimeException("Token generation failed due to max retries reached."))
56 93 1847 - 1922 Apply java.lang.RuntimeException.<init> new scala.`package`.RuntimeException("Token generation failed due to max retries reached.")
57 311 1937 - 2252 Block <nosymbol> org.make.api.technical.auth.defaulttokengeneratorcomponenttest { <synthetic> <artifact> private[this] val x$1: (String, String) = (DefaultTokenGenerator.this.newRandomToken(): (String, String)) match { case (_1: String, _2: String): (String, String)((token @ _), (hashedToken @ _)) => scala.Tuple2.apply[String, String](token, hashedToken) }; val token: String = x$1._1; val hashedToken: String = x$1._2; tokenExistsFunction.apply(hashedToken).flatMap[(String, String)](((exists: Boolean) => if (exists) DefaultTokenGenerator.this.generateToken(tokenExistsFunction, depth.-(1)) else scala.concurrent.Future.successful[(String, String)](scala.Tuple2.apply[String, String](token, hashedToken))))(scala.concurrent.ExecutionContext.Implicits.global) }
58 116 1952 - 1952 Select scala.Tuple2._1 org.make.api.technical.auth.defaulttokengeneratorcomponenttest x$1._1
58 316 1959 - 1959 Select scala.Tuple2._2 org.make.api.technical.auth.defaulttokengeneratorcomponenttest x$1._2
59 235 2058 - 2058 Select scala.concurrent.ExecutionContext.Implicits.global org.make.api.technical.auth.defaulttokengeneratorcomponenttest scala.concurrent.ExecutionContext.Implicits.global
59 117 2017 - 2244 ApplyToImplicitArgs scala.concurrent.Future.flatMap org.make.api.technical.auth.defaulttokengeneratorcomponenttest tokenExistsFunction.apply(hashedToken).flatMap[(String, String)](((exists: Boolean) => if (exists) DefaultTokenGenerator.this.generateToken(tokenExistsFunction, depth.-(1)) else scala.concurrent.Future.successful[(String, String)](scala.Tuple2.apply[String, String](token, hashedToken))))(scala.concurrent.ExecutionContext.Implicits.global)
61 8 2106 - 2151 Block org.make.api.technical.auth.DefaultTokenGeneratorComponent.DefaultTokenGenerator.generateToken DefaultTokenGenerator.this.generateToken(tokenExistsFunction, depth.-(1))
61 125 2106 - 2151 Apply org.make.api.technical.auth.DefaultTokenGeneratorComponent.DefaultTokenGenerator.generateToken DefaultTokenGenerator.this.generateToken(tokenExistsFunction, depth.-(1))
61 253 2141 - 2150 Apply scala.Int.- depth.-(1)
63 88 2183 - 2222 Apply scala.concurrent.Future.successful scala.concurrent.Future.successful[(String, String)](scala.Tuple2.apply[String, String](token, hashedToken))
63 210 2201 - 2221 Apply scala.Tuple2.apply scala.Tuple2.apply[String, String](token, hashedToken)
63 27 2183 - 2222 Block scala.concurrent.Future.successful scala.concurrent.Future.successful[(String, String)](scala.Tuple2.apply[String, String](token, hashedToken))
70 191 2334 - 2360 Apply java.util.UUID.toString org.make.api.technical.auth.defaulttokengeneratorcomponenttest java.util.UUID.randomUUID().toString()
72 10 2368 - 2395 Apply scala.Tuple2.apply org.make.api.technical.auth.defaulttokengeneratorcomponenttest scala.Tuple2.apply[String, String](token, DefaultTokenGenerator.this.tokenToHash(token))
72 123 2376 - 2394 Apply org.make.api.technical.auth.DefaultTokenGeneratorComponent.DefaultTokenGenerator.tokenToHash org.make.api.technical.auth.defaulttokengeneratorcomponenttest DefaultTokenGenerator.this.tokenToHash(token)