<commit_before>package http

import akka.http.scaladsl.model.StatusCodes
import com.github.scribejava.core.model.{ OAuthRequest, Verb }
import com.softwaremill.session._
import akka.http.scaladsl.server._
import com.softwaremill.session.SessionDirectives._
import com.softwaremill.session.CsrfDirectives._
import com.softwaremill.session.CsrfOptions._
import com.softwaremill.session.SessionOptions._

import scala.concurrent.{ Future, ExecutionContext }
import scala.util.Try
import org.mindrot.jbcrypt.BCrypt

trait SecurityRouter extends DefaultRestMicroservice with Directives { mixin: MicroKernel ⇒

  def googleApiKey: String
  def googleApiSecret: String
  def twitterApiKey: String
  def twitterApiSecret: String
  def githubApiKey: String
  def githubApiSecret: String

  val salt = BCrypt.gensalt()

  lazy val (google, twitter, github) = {
    (http.oauth.Oauth[com.github.scribejava.apis.GoogleApi20].setKeySecret(googleApiKey, googleApiSecret),
      http.oauth.Oauth[com.github.scribejava.apis.TwitterApi].setKeySecret(twitterApiKey, twitterApiSecret),
      http.oauth.Oauth[com.github.scribejava.apis.GitHubApi].setKeySecret(githubApiKey, githubApiSecret))
  }

  implicit def serializer: SessionSerializer[ServerSession, String] =
    new SingleValueSessionSerializer({ session: ServerSession ⇒ (session.user + "-" + session.password) }, { v: (String) ⇒
      val kv = v.split("-")
      Try(ServerSession(kv(0), kv(1)))
    })

  val sessionConfig = SessionConfig.default(system.settings.config.getString("http.secret"))
  implicit val sessionManager = new SessionManager[ServerSession](sessionConfig)

  implicit val refreshTokenStorage = new InMemoryRefreshTokenStorage[ServerSession] {
    def log(msg: String) = system.log.info(msg)
  }

  def requiredHttpSession(implicit ec: ExecutionContext) = requiredSession(oneOff, usingCookies)

  //https://github.com/softwaremill/akka-http-session
  abstract override def configureApi() =
    super.configureApi() ~
      Api(route = Option { ec: ExecutionContext ⇒ securityRoute(ec) },
        postAction = Option(() ⇒ system.log.info(s"\n★ ★ ★ [$httpPrefixAddress/login|logout] routes was stopped on $httpPrefixAddress ★ ★ ★")),
        urls = s"[$httpPrefixAddress/$pathPrefix/login, $httpPrefixAddress/$pathPrefix/login-twitter, $httpPrefixAddress/$pathPrefix/logout]")

  private def githubR(implicit ec: ExecutionContext): Route =
    path("login-github") {
      val service = github.oAuthService.callback(s"http://$domain:$httpPort/$pathPrefix/github-sign-in").build()
      // Obtain the Authorization URL
      val url = service.getAuthorizationUrl(null)
      redirect(akka.http.scaladsl.model.Uri(url), StatusCodes.PermanentRedirect)
    } ~ path("github-sign-in") {
      get {
        parameterMap { params ⇒
          complete {
            Future {
              val service = github.oAuthService.callback(s"http://$domain:$httpPort/$pathPrefix/github-sign-in").build()
              val (k, v) = params.head
              val verifier = new com.github.scribejava.core.model.Verifier(v)

              // Obtain the AccessToken
              val accessToken = service.getAccessToken(null, verifier)
              val token = accessToken.getToken

              val request = new OAuthRequest(Verb.GET, github.protectedUrl, service)
              service.signRequest(accessToken, request)

              val response = request.send
              if(response.getCode == 200) {
                import spray.json._
                val json = response.getBody.parseJson.asJsObject
                val user = json.fields("name").toString().replace("\"", "")
                s"$user has been authorized by github\nAuthorizationUrl: http://$localAddress:$httpPort/$pathPrefix/login?user=$user:github&password=$token"
              } else {
                response.getBody
              }
            }(ec)
          }
        }
      }
    }

  private def googleR(implicit ec: ExecutionContext): Route =
    path("login-google") {
      val service = google.oAuthService.callback(s"http://$domain:$httpPort/$pathPrefix/google-sign-in").build()
      // Obtain the Authorization URL
      val url = service.getAuthorizationUrl(null)
      redirect(akka.http.scaladsl.model.Uri(url), StatusCodes.PermanentRedirect)
    } ~ path("google-sign-in") {
      get {
        parameterMap { params ⇒
          complete {
            Future {
              val service = google.oAuthService.callback(s"http://$domain:$httpPort/$pathPrefix/google-sign-in").build()
              val (k, v) = params.head
              val verifier = new com.github.scribejava.core.model.Verifier(v)

              // Obtain the AccessToken
              val accessToken = service.getAccessToken(null, verifier)
              val token = accessToken.getToken

              val request = new OAuthRequest(Verb.GET, google.protectedUrl, service)
              service.signRequest(accessToken, request)

              val response = request.send

              import spray.json._
              if(response.getCode == 200) {
                val googleResponse = response.getBody
                val json = googleResponse.parseJson.asJsObject
                val user = json.fields("displayName").toString().replace("\"", "")
                s"$user has been authorized by google\nAuthorizationUrl: http://$localAddress:$httpPort/$pathPrefix/login?user=$user:google&password=$<PASSWORD>"
              } else {
                response.getBody
              }
            }(ec)
          }
        }
      }
    }

  private def twitterR(implicit ec: ExecutionContext): Route =
    path("login-twitter") {
      get {
        val service = twitter.oAuthService.callback(s"http://$localAddress:$httpPort/$pathPrefix/twitter-sign-in").build()
        val requestToken = service.getRequestToken
        val url = service.getAuthorizationUrl(requestToken)
        redirect(akka.http.scaladsl.model.Uri(url), StatusCodes.PermanentRedirect)
      }
    } ~ path("twitter-sign-in") {
      get {
        parameters(('oauth_token.as[String]), ('oauth_verifier.as[String])) { (oauthToken, oauthVerifier) ⇒
          /**
           * Converting the request token to an access token
           *
           * To render the request token into a usable access token,
           * your application must make a request to the POST oauth / access_token endpoint,
           * containing the oauth_verifier value obtained in prev step.
           * The request token is also passed in the oauth_token portion of the header,
           * but this will have been added by the signing process.
           *
           * Source https://dev.twitter.com/web/sign-in/implementing
           */
          complete {
            Future {
              val service = twitter.oAuthService.build()
              val requestToken = new com.github.scribejava.core.model.Token(oauthToken, oauthVerifier)
              val verifier = new com.github.scribejava.core.model.Verifier(oauthVerifier)
              val accessToken = service.getAccessToken(requestToken, verifier)
              val oAuthRequest = new com.github.scribejava.core.model.OAuthRequest(Verb.GET, twitter.protectedUrl, service)
              service.signRequest(accessToken, oAuthRequest)
              val twitterResponse = oAuthRequest.send()
              if(twitterResponse.getCode == 200) {
                import spray.json._
                val json = twitterResponse.getBody.parseJson.asJsObject
                val user = json.getFields("name").head.toString().replace("\"", "")
                s"$user has been authorized by twitter\nAuthorizationUrl: http://$localAddress:$httpPort/$pathPrefix/login?user=$user:twitter&password=$<PASSWORD>"
              } else {
                twitterResponse.getBody
              }
            }(ec)<commit_msg>Formatting<commit_after>package http

import akka.http.scaladsl.model.StatusCodes
import com.github.scribejava.core.model.{ OAuthRequest, Verb }
import com.softwaremill.session._
import akka.http.scaladsl.server._
import com.softwaremill.session.SessionDirectives._
import com.softwaremill.session.CsrfDirectives._
import com.softwaremill.session.CsrfOptions._
import com.softwaremill.session.SessionOptions._

import scala.concurrent.{ Future, ExecutionContext }
import scala.util.Try
import org.mindrot.jbcrypt.BCrypt

trait SecurityRouter extends DefaultRestMicroservice with Directives { mixin: MicroKernel ⇒

  def googleApiKey: String
  def googleApiSecret: String
  def twitterApiKey: String
  def twitterApiSecret: String
  def githubApiKey: String
  def githubApiSecret: String

  val salt = BCrypt.gensalt()

  lazy val (google, twitter, github) = {
    (http.oauth.Oauth[com.github.scribejava.apis.GoogleApi20].setKeySecret(googleApiKey, googleApiSecret),
      http.oauth.Oauth[com.github.scribejava.apis.TwitterApi].setKeySecret(twitterApiKey, twitterApiSecret),
      http.oauth.Oauth[com.github.scribejava.apis.GitHubApi].setKeySecret(githubApiKey, githubApiSecret))
  }

  implicit def serializer: SessionSerializer[ServerSession, String] =
    new SingleValueSessionSerializer({ session: ServerSession ⇒ (session.user + "-" + session.password) }, { v: (String) ⇒
      val kv = v.split("-")
      Try(ServerSession(kv(0), kv(1)))
    })

  val sessionConfig = SessionConfig.default(system.settings.config.getString("http.secret"))
  implicit val sessionManager = new SessionManager[ServerSession](sessionConfig)

  implicit val refreshTokenStorage = new InMemoryRefreshTokenStorage[ServerSession] {
    def log(msg: String) = system.log.info(msg)
  }

  def requiredHttpSession(implicit ec: ExecutionContext) = requiredSession(oneOff, usingCookies)

  //https://github.com/softwaremill/akka-http-session
  abstract override def configureApi() =
    super.configureApi() ~
      Api(route = Option { ec: ExecutionContext ⇒ securityRoute(ec) },
        postAction = Option(() ⇒ system.log.info(s"\n★ ★ ★ [$httpPrefixAddress/login|logout] routes was stopped on $httpPrefixAddress ★ ★ ★")),
        urls = s"[$httpPrefixAddress/$pathPrefix/login, $httpPrefixAddress/$pathPrefix/login-twitter, $httpPrefixAddress/$pathPrefix/logout]")

  private def githubR(implicit ec: ExecutionContext): Route =
    path("login-github") {
      val service = github.oAuthService.callback(s"http://$domain:$httpPort/$pathPrefix/github-sign-in").build()
      // Obtain the Authorization URL
      val url = service.getAuthorizationUrl(null)
      redirect(akka.http.scaladsl.model.Uri(url), StatusCodes.PermanentRedirect)
    } ~ path("github-sign-in") {
      get {
        parameterMap { params ⇒
          complete {
            Future {
              val service = github.oAuthService.callback(s"http://$domain:$httpPort/$pathPrefix/github-sign-in").build()
              val (k, v) = params.head
              val verifier = new com.github.scribejava.core.model.Verifier(v)

              // Obtain the AccessToken
              val accessToken = service.getAccessToken(null, verifier)
              val token = accessToken.getToken

              val request = new OAuthRequest(Verb.GET, github.protectedUrl, service)
              service.signRequest(accessToken, request)

              val response = request.send
              if (response.getCode == 200) {
                import spray.json._
                val json = response.getBody.parseJson.asJsObject
                val user = json.fields("name").toString().replace("\"", "")
                s"$user has been authorized by github\nAuthorizationUrl: http://$localAddress:$httpPort/$pathPrefix/login?user=$user:github&password=$token"
              } else {
                response.getBody
              }
            }(ec)
          }
        }
      }
    }

  private def googleR(implicit ec: ExecutionContext): Route =
    path("login-google") {
      val service = google.oAuthService.callback(s"http://$domain:$httpPort/$pathPrefix/google-sign-in").build()
      // Obtain the Authorization URL
      val url = service.getAuthorizationUrl(null)
      redirect(akka.http.scaladsl.model.Uri(url), StatusCodes.PermanentRedirect)
    } ~ path("google-sign-in") {
      get {
        parameterMap { params ⇒
          complete {
            Future {
              val service = google.oAuthService.callback(s"http://$domain:$httpPort/$pathPrefix/google-sign-in").build()
              val (k, v) = params.head
              val verifier = new com.github.scribejava.core.model.Verifier(v)

              // Obtain the AccessToken
              val accessToken = service.getAccessToken(null, verifier)
              val token = accessToken.getToken

              val request = new OAuthRequest(Verb.GET, google.protectedUrl, service)
              service.signRequest(accessToken, request)

              val response = request.send

              import spray.json._
              if (response.getCode == 200) {
                val googleResponse = response.getBody
                val json = googleResponse.parseJson.asJsObject
                val user = json.fields("displayName").toString().replace("\"", "")
                s"$user has been authorized by google\nAuthorizationUrl: http://$localAddress:$httpPort/$pathPrefix/login?user=$user:google&password=$<PASSWORD>"
              } else {
                response.getBody
              }
            }(ec)
          }
        }
      }
    }

  private def twitterR(implicit ec: ExecutionContext): Route =
    path("login-twitter") {
      get {
        val service = twitter.oAuthService.callback(s"http://$localAddress:$httpPort/$pathPrefix/twitter-sign-in").build()
        val requestToken = service.getRequestToken
        val url = service.getAuthorizationUrl(requestToken)
        redirect(akka.http.scaladsl.model.Uri(url), StatusCodes.PermanentRedirect)
      }
    } ~ path("twitter-sign-in") {
      get {
        parameters(('oauth_token.as[String]), ('oauth_verifier.as[String])) { (oauthToken, oauthVerifier) ⇒
          /**
           * Converting the request token to an access token
           *
           * To render the request token into a usable access token,
           * your application must make a request to the POST oauth / access_token endpoint,
           * containing the oauth_verifier value obtained in prev step.
           * The request token is also passed in the oauth_token portion of the header,
           * but this will have been added by the signing process.
           *
           * Source https://dev.twitter.com/web/sign-in/implementing
           */
          complete {
            Future {
              val service = twitter.oAuthService.build()
              val requestToken = new com.github.scribejava.core.model.Token(oauthToken, oauthVerifier)
              val verifier = new com.github.scribejava.core.model.Verifier(oauthVerifier)
              val accessToken = service.getAccessToken(requestToken, verifier)
              val oAuthRequest = new com.github.scribejava.core.model.OAuthRequest(Verb.GET, twitter.protectedUrl, service)
              service.signRequest(accessToken, oAuthRequest)
              val twitterResponse = oAuthRequest.send()
              if (twitterResponse.getCode == 200) {
                import spray.json._
                val json = twitterResponse.getBody.parseJson.asJsObject
                val user = json.getFields("name").head.toString().replace("\"", "")
                s"$user has been authorized by twitter\nAuthorizationUrl: http://$localAddress:$httpPort/$pathPrefix/login?user=$user:twitter&password=$<PASSWORD>"
              } else {
                twitterResponse.getBody
              }
            }(ec)
{'fraction_non_alphanumeric': 0.10793569788211278, 'fraction_numerical': 0.001658586374075019, 'mean_word_length': 2.6407338597306085, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 7, 'https://': 4, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '513920', 'n_tokens_mistral': 4388, 'n_tokens_neox': 4266, 'n_words': 882}