<commit_before>/**
 * Copyright (c) 2012 <NAME> (born 1979)
 */

package controllers

import com.debiki.v0._
import debiki._
import debiki.DebikiHttp._
import net.liftweb.common.{Box, Full, Empty, Failure}
import play.api._
import play.api.mvc.{Action => _, _}
import Prelude._

object Actions {

  /**
   * A page related request.
   *
   * Sometimes only the browser ip is known (then there'd be no
   * Login/Identity/User).
   */
  // COULD rename RequestInfo to PermsOnPageRequest,
  // and use PageRequest instead.
  case class PageRequest[A](
    tenantId: String,
    ip: String,
    loginId: Option[String],
    identity: Option[Identity],
    user: Option[User],
    /** Ids of groups to which the requester belongs. */
    // userMemships: List[String],
    pagePath: PagePath,
    permsOnPage: PermsOnPage,
    request: Request[A]
  ){
    require(pagePath.tenantId == tenantId) //COULD remove tenantId from pagePath
  }


  def PageReqAction(pathIn: PagePath)(
        f: PageRequest[Option[Any]] => PlainResult)
        : mvc.Action[Option[Any]] =
      PageReqAction(BodyParsers.parse.empty)(pathIn)(f)


  def PageReqAction(maxUrlEncFormBytes: Int)(pathIn: PagePath)(
        f: PageRequest[Map[String, Seq[String]]] => PlainResult)
        : mvc.Action[Map[String, Seq[String]]] =
    PageReqAction(
      BodyParsers.parse.urlFormEncoded(maxLength = maxUrlEncFormBytes))(
      pathIn)(f)


  def PageReqAction[A](parser: BodyParser[A])(pathIn: PagePath)(
        f: PageRequest[A] => PlainResult)
        = CheckSidAndPathAction[A](parser)(pathIn) {
      (sidOk, xsrfOk, pathOk, request) =>

    val tenantId = pathOk.tenantId
    val ip = "?.?.?.?"

    // Load identity and user.
    val (identity, user) = sidOk.loginId match {
      case None => (None, None)
      case Some(lid) =>
        Debiki.Dao.loadUser(withLoginId = lid, tenantId = tenantId) match {
          case Some((identity, user)) => (Some(identity), Some(user))
          case None =>
            // Currently, RelDbDao throws an exception rather than
            // returning None.
            warnDbgDie("RelDbDao did not load user [error DwE01521ku35]")
            (None, None)
        }
    }

    // Load permissions.
    val permsReq = RequestInfo(  // COULD RENAME! to PermsOnPageRequest
      tenantId = tenantId,
      ip = ip,
      loginId = sidOk.loginId,
      identity = identity,
      user = user,
      pagePath = pathOk,
      doo = null) // should be removed

    val permsOnPage = Debiki.Dao.loadPermsOnPage(permsReq)
    if (!permsOnPage.accessPage)
      throwForbidden("DwE403DNI0", "You are not allowed to access that page.")

    // Construct the actual request.
    val pageReq = PageRequest[A](
      tenantId = tenantId,
      ip = ip,
      loginId = sidOk.loginId,
      identity = identity,
      user = user,
      pagePath = pathOk,
      permsOnPage = permsOnPage,
      request = request)

    val result = f(pageReq)
    result
  }


  /**
   * Checks the session id and, for POST request, the xsrf token.
   */
  def CheckSidAndPathAction[A](parser: BodyParser[A])(pathIn: PagePath)(
        f: (SidOk, XsrfOk, PagePath, Request[A]) => PlainResult) =
        RedirBadPathAction[A](parser)(pathIn) { (pathOk, request) =>
    val (sidOk, xsrfOk, newCookies) = AppAuth.checkSidAndXsrfToken(request)
    val resultOldCookies = f(sidOk, xsrfOk, pathOk, request)
    val resultOkSid =
      if (newCookies isEmpty) resultOldCookies
      else resultOldCookies.withCookies(newCookies: _*)
    resultOkSid
  }

  def CheckSidAndPathAction(pathIn: PagePath)(
        f: (SidOk, XsrfOk, PagePath, Request[Option[Any]]) => PlainResult)
        : mvc.Action[Option[Any]] =<commit_msg>WIP: Split PageRequest into PageGetRequest and PagePostRequest.<commit_after>/**
 * Copyright (c) 2012 <NAME> (born 1979)
 */

package controllers

import com.debiki.v0._
import debiki._
import debiki.DebikiHttp._
import net.liftweb.common.{Box, Full, Empty, Failure}
import play.api._
import play.api.mvc.{Action => _, _}
import Prelude._

object Actions {

  /**
   * A page related request.
   *
   * Sometimes only the browser ip is known (then there'd be no
   * Login/Identity/User).
   */
  // COULD rename RequestInfo to PermsOnPageRequest,
  // and use PageRequest instead.
  case class PageRequest[A](
    tenantId: String,
    ip: String,
    sid: SidOk,
    xsrfToken: XsrfOk,
    loginId: Option[String],
    identity: Option[Identity],
    user: Option[User],
    /** Ids of groups to which the requester belongs. */
    // userMemships: List[String],
    pagePath: PagePath,
    permsOnPage: PermsOnPage,
    request: Request[A]
  ){
    require(pagePath.tenantId == tenantId) //COULD remove tenantId from pagePath
  }


  /**
   * A PageRequest with no post data.
   */
  type PageGetRequest = PageRequest[Option[Any]]


  /**
   * Same as PageRequest, but the user is always known and logged in.
   */
  case class PagePostRequest(
    tenantId: String,
    ip: String,
    sid: SidOk,
    xsrfToken: XsrfOk,
    loginId: String,
    identity: Identity,
    user: User,
    pagePath: PagePath,
    permsOnPage: PermsOnPage,
    request: Request[Map[String, Seq[String]]])


  def PageGetAction(pathIn: PagePath)(
        f: PageGetRequest => PlainResult)
        : mvc.Action[Option[Any]] =
      PageReqAction(BodyParsers.parse.empty)(pathIn)(f)


  def PagePostAction(maxUrlEncFormBytes: Int)(pathIn: PagePath)(
        f: PagePostRequest => PlainResult)
        : mvc.Action[Map[String, Seq[String]]] =
    PageReqAction(
      BodyParsers.parse.urlFormEncoded(maxLength = maxUrlEncFormBytes))(
      pathIn)(pageRequest => {
        def die[A]: A = { throwBadReq("DwE390fC2", "Not logged in?") }
        val r = pageRequest
        f(PagePostRequest(
          tenantId = r.tenantId,
          ip = r.ip,
          sid = r.sid,
          xsrfToken = r.xsrfToken,
          loginId = r.loginId getOrElse die,
          identity = r.identity getOrElse die,
          user = r.user getOrElse die,
          pagePath = r.pagePath,
          permsOnPage = r.permsOnPage,
          request = r.request))
      })


  def PageReqAction[A](parser: BodyParser[A])(pathIn: PagePath)(
        f: PageRequest[A] => PlainResult)
        = CheckSidAndPathAction[A](parser)(pathIn) {
      (sidOk, xsrfOk, pathOk, request) =>

    val tenantId = pathOk.tenantId
    val ip = "?.?.?.?"

    // Load identity and user.
    val (identity, user) = sidOk.loginId match {
      case None => (None, None)
      case Some(lid) =>
        Debiki.Dao.loadUser(withLoginId = lid, tenantId = tenantId) match {
          case Some((identity, user)) => (Some(identity), Some(user))
          case None =>
            // Currently, RelDbDao throws an exception rather than
            // returning None.
            warnDbgDie("RelDbDao did not load user [error DwE01521ku35]")
            (None, None)
        }
    }

    // Load permissions.
    val permsReq = RequestInfo(  // COULD RENAME! to PermsOnPageRequest
      tenantId = tenantId,
      ip = ip,
      loginId = sidOk.loginId,
      identity = identity,
      user = user,
      pagePath = pathOk,
      doo = null) // should be removed

    val permsOnPage = Debiki.Dao.loadPermsOnPage(permsReq)
    if (!permsOnPage.accessPage)
      throwForbidden("DwE403DNI0", "You are not allowed to access that page.")

    // Construct the actual request.
    val pageReq = PageRequest[A](
      tenantId = tenantId,
      ip = ip,
      sid = sidOk,
      xsrfToken = xsrfOk,
      loginId = sidOk.loginId,
      identity = identity,
      user = user,
      pagePath = pathOk,
      permsOnPage = permsOnPage,
      request = request)

    val result = f(pageReq)
    result
  }


  /**
   * Checks the session id and, for POST request, the xsrf token.
   */
  def CheckSidAndPathAction[A](parser: BodyParser[A])(pathIn: PagePath)(
        f: (SidOk, XsrfOk, PagePath, Request[A]) => PlainResult) =
        RedirBadPathAction[A](parser)(pathIn) { (pathOk, request) =>
    val (sidOk, xsrfOk, newCookies) = AppAuth.checkSidAndXsrfToken(request)
    val resultOldCookies = f(sidOk, xsrfOk, pathOk, request)
    val resultOkSid =
      if (newCookies isEmpty) resultOldCookies
      else resultOldCookies.withCookies(newCookies: _*)
    resultOkSid
  }

  def CheckSidAndPathAction(pathIn: PagePath)(
        f: (SidOk, XsrfOk, PagePath, Request[Option[Any]]) => PlainResult)
        : mvc.Action[Option[Any]] =
{'fraction_non_alphanumeric': 0.11601229895931883, 'fraction_numerical': 0.005203405865657522, 'mean_word_length': 2.7403803626713845, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 30, 'https://': 0, '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': '4894266', 'n_tokens_mistral': 2864, 'n_tokens_neox': 2760, 'n_words': 683}