Merge pull request #1760 from gitbucket/scalatra-2.6

Bump to Scalatra 2.6.0
This commit is contained in:
Naoki Takezoe
2017-11-16 16:53:10 +09:00
committed by GitHub
16 changed files with 133 additions and 43 deletions

View File

@@ -4,7 +4,7 @@ import com.typesafe.sbt.pgp.PgpKeys._
val Organization = "io.github.gitbucket" val Organization = "io.github.gitbucket"
val Name = "gitbucket" val Name = "gitbucket"
val GitBucketVersion = "4.19.0-SNAPSHOT" val GitBucketVersion = "4.19.0-SNAPSHOT"
val ScalatraVersion = "2.5.3" val ScalatraVersion = "2.6.1"
val JettyVersion = "9.4.7.v20170914" val JettyVersion = "9.4.7.v20170914"
lazy val root = (project in file(".")).enablePlugins(SbtTwirl, ScalatraPlugin, JRebelPlugin).settings( lazy val root = (project in file(".")).enablePlugins(SbtTwirl, ScalatraPlugin, JRebelPlugin).settings(
@@ -30,8 +30,8 @@ libraryDependencies ++= Seq(
"org.eclipse.jgit" % "org.eclipse.jgit.archive" % "4.9.0.201710071750-r", "org.eclipse.jgit" % "org.eclipse.jgit.archive" % "4.9.0.201710071750-r",
"org.scalatra" %% "scalatra" % ScalatraVersion, "org.scalatra" %% "scalatra" % ScalatraVersion,
"org.scalatra" %% "scalatra-json" % ScalatraVersion, "org.scalatra" %% "scalatra-json" % ScalatraVersion,
"org.scalatra" %% "scalatra-forms" % ScalatraVersion,
"org.json4s" %% "json4s-jackson" % "3.5.1", "org.json4s" %% "json4s-jackson" % "3.5.1",
"io.github.gitbucket" %% "scalatra-forms" % "1.1.0",
"commons-io" % "commons-io" % "2.5", "commons-io" % "commons-io" % "2.5",
"io.github.gitbucket" % "solidbase" % "1.0.2", "io.github.gitbucket" % "solidbase" % "1.0.2",
"io.github.gitbucket" % "markedj" % "1.0.15", "io.github.gitbucket" % "markedj" % "1.0.15",

View File

@@ -12,10 +12,10 @@ import gitbucket.core.util.Directory._
import gitbucket.core.util.Implicits._ import gitbucket.core.util.Implicits._
import gitbucket.core.util.StringUtil._ import gitbucket.core.util.StringUtil._
import gitbucket.core.util._ import gitbucket.core.util._
import io.github.gitbucket.scalatra.forms._
import org.apache.commons.io.FileUtils import org.apache.commons.io.FileUtils
import org.scalatra.i18n.Messages import org.scalatra.i18n.Messages
import org.scalatra.BadRequest import org.scalatra.BadRequest
import org.scalatra.forms._
class AccountController extends AccountControllerBase class AccountController extends AccountControllerBase
with AccountService with RepositoryService with ActivityService with WikiService with LabelsService with SshKeyService with AccountService with RepositoryService with ActivityService with WikiService with LabelsService with SshKeyService
@@ -137,16 +137,17 @@ trait AccountControllerBase extends AccountManagementControllerBase {
} }
private def accountWebhookEvents = new ValueType[Set[WebHook.Event]]{ private def accountWebhookEvents = new ValueType[Set[WebHook.Event]]{
def convert(name: String, params: Map[String, String], messages: Messages): Set[WebHook.Event] = { def convert(name: String, params: Map[String, Seq[String]], messages: Messages): Set[WebHook.Event] = {
WebHook.Event.values.flatMap { t => WebHook.Event.values.flatMap { t =>
params.get(name + "." + t.name).map(_ => t) params.get(name + "." + t.name).map(_ => t)
}.toSet }.toSet
} }
def validate(name: String, params: Map[String, String], messages: Messages): Seq[(String, String)] = if(convert(name,params,messages).isEmpty){ def validate(name: String, params: Map[String, Seq[String]], messages: Messages): Seq[(String, String)] =
Seq(name -> messages("error.required").format(name)) if(convert(name, params, messages).isEmpty){
} else { Seq(name -> messages("error.required").format(name))
Nil } else {
} Nil
}
} }
@@ -635,9 +636,9 @@ trait AccountControllerBase extends AccountManagementControllerBase {
} }
private def uniqueRepository: Constraint = new Constraint(){ private def uniqueRepository: Constraint = new Constraint(){
override def validate(name: String, value: String, params: Map[String, String], messages: Messages): Option[String] = override def validate(name: String, value: String, params: Map[String, Seq[String]], messages: Messages): Option[String] =
params.get("owner").flatMap { userName => params.get("owner").flatMap { userName =>
getRepositoryNamesOfUser(userName).find(_ == value).map(_ => "Repository already exists.") getRepositoryNamesOfUser(userName.head).find(_ == value).map(_ => "Repository already exists.")
} }
} }

View File

@@ -9,12 +9,11 @@ import gitbucket.core.util.SyntaxSugars._
import gitbucket.core.util.Directory._ import gitbucket.core.util.Directory._
import gitbucket.core.util.Implicits._ import gitbucket.core.util.Implicits._
import gitbucket.core.util._ import gitbucket.core.util._
import gitbucket.core.util.JGitUtil._
import io.github.gitbucket.scalatra.forms._
import org.json4s._ import org.json4s._
import org.scalatra._ import org.scalatra._
import org.scalatra.i18n._ import org.scalatra.i18n._
import org.scalatra.json._ import org.scalatra.json._
import org.scalatra.forms._
import javax.servlet.http.{HttpServletRequest, HttpServletResponse} import javax.servlet.http.{HttpServletRequest, HttpServletResponse}
import javax.servlet.{FilterChain, ServletRequest, ServletResponse} import javax.servlet.{FilterChain, ServletRequest, ServletResponse}
@@ -32,7 +31,7 @@ import org.slf4j.LoggerFactory
* Provides generic features for controller implementations. * Provides generic features for controller implementations.
*/ */
abstract class ControllerBase extends ScalatraFilter abstract class ControllerBase extends ScalatraFilter
with ClientSideValidationFormSupport with JacksonJsonSupport with I18nSupport with FlashMapSupport with Validations with ValidationSupport with JacksonJsonSupport with I18nSupport with FlashMapSupport with Validations
with SystemSettingsService { with SystemSettingsService {
private val logger = LoggerFactory.getLogger(getClass) private val logger = LoggerFactory.getLogger(getClass)
@@ -177,7 +176,7 @@ abstract class ControllerBase extends ScalatraFilter
protected def trim2[T](valueType: SingleValueType[T]): SingleValueType[T] = new SingleValueType[T](){ protected def trim2[T](valueType: SingleValueType[T]): SingleValueType[T] = new SingleValueType[T](){
def convert(value: String, messages: Messages): T = valueType.convert(trim(value), messages) def convert(value: String, messages: Messages): T = valueType.convert(trim(value), messages)
override def validate(name: String, value: String, params: Map[String, String], messages: Messages): Seq[(String, String)] = override def validate(name: String, value: String, params: Map[String, Seq[String]], messages: Messages): Seq[(String, String)] =
valueType.validate(name, trim(value), params, messages) valueType.validate(name, trim(value), params, messages)
private def trim(value: String): String = if(value == null) null else value.replace("\r\n", "").trim private def trim(value: String): String = if(value == null) null else value.replace("\r\n", "").trim
@@ -315,7 +314,7 @@ trait AccountManagementControllerBase extends ControllerBase {
} }
protected def uniqueMailAddress(paramName: String = ""): Constraint = new Constraint(){ protected def uniqueMailAddress(paramName: String = ""): Constraint = new Constraint(){
override def validate(name: String, value: String, params: Map[String, String], messages: Messages): Option[String] = override def validate(name: String, value: String, params: Map[String, Seq[String]], messages: Messages): Option[String] =
getAccountByMailAddress(value, true) getAccountByMailAddress(value, true)
.filter { x => if(paramName.isEmpty) true else Some(x.userName) != params.get(paramName) } .filter { x => if(paramName.isEmpty) true else Some(x.userName) != params.get(paramName) }
.map { _ => "Mail address is already registered." } .map { _ => "Mail address is already registered." }

View File

@@ -1,7 +1,6 @@
package gitbucket.core.controller package gitbucket.core.controller
import gitbucket.core.model.Account import gitbucket.core.model.Account
import gitbucket.core.service.RepositoryService.RepositoryInfo
import gitbucket.core.service.{AccountService, RepositoryService} import gitbucket.core.service.{AccountService, RepositoryService}
import gitbucket.core.servlet.Database import gitbucket.core.servlet.Database
import gitbucket.core.util._ import gitbucket.core.util._

View File

@@ -6,7 +6,7 @@ import gitbucket.core.service._
import gitbucket.core.util.Implicits._ import gitbucket.core.util.Implicits._
import gitbucket.core.util.SyntaxSugars._ import gitbucket.core.util.SyntaxSugars._
import gitbucket.core.util.{Keys, LDAPUtil, ReferrerAuthenticator, UsersAuthenticator} import gitbucket.core.util.{Keys, LDAPUtil, ReferrerAuthenticator, UsersAuthenticator}
import io.github.gitbucket.scalatra.forms._ import org.scalatra.forms._
import org.scalatra.Ok import org.scalatra.Ok

View File

@@ -8,7 +8,7 @@ import gitbucket.core.util.Implicits._
import gitbucket.core.util._ import gitbucket.core.util._
import gitbucket.core.view import gitbucket.core.view
import gitbucket.core.view.Markdown import gitbucket.core.view.Markdown
import io.github.gitbucket.scalatra.forms._ import org.scalatra.forms._
import org.scalatra.{BadRequest, Ok} import org.scalatra.{BadRequest, Ok}

View File

@@ -4,7 +4,7 @@ import gitbucket.core.issues.labels.html
import gitbucket.core.service.{RepositoryService, AccountService, IssuesService, LabelsService} import gitbucket.core.service.{RepositoryService, AccountService, IssuesService, LabelsService}
import gitbucket.core.util.{ReferrerAuthenticator, WritableUsersAuthenticator} import gitbucket.core.util.{ReferrerAuthenticator, WritableUsersAuthenticator}
import gitbucket.core.util.Implicits._ import gitbucket.core.util.Implicits._
import io.github.gitbucket.scalatra.forms._ import org.scalatra.forms._
import org.scalatra.i18n.Messages import org.scalatra.i18n.Messages
import org.scalatra.Ok import org.scalatra.Ok
@@ -82,11 +82,11 @@ trait LabelsControllerBase extends ControllerBase {
} }
private def uniqueLabelName: Constraint = new Constraint(){ private def uniqueLabelName: Constraint = new Constraint(){
override def validate(name: String, value: String, params: Map[String, String], messages: Messages): Option[String] = { override def validate(name: String, value: String, params: Map[String, Seq[String]], messages: Messages): Option[String] = {
val owner = params("owner") val owner = params("owner").head
val repository = params("repository") val repository = params("repository").head
params.get("labelId").map { labelId => params.get("labelId").map { labelId =>
getLabel(owner, repository, value).filter(_.labelId != labelId.toInt).map(_ => "Name has already been taken.") getLabel(owner, repository, value).filter(_.labelId != labelId.head.toInt).map(_ => "Name has already been taken.")
}.getOrElse { }.getOrElse {
getLabel(owner, repository, value).map(_ => "Name has already been taken.") getLabel(owner, repository, value).map(_ => "Name has already been taken.")
} }

View File

@@ -4,7 +4,7 @@ import gitbucket.core.issues.milestones.html
import gitbucket.core.service.{RepositoryService, MilestonesService, AccountService} import gitbucket.core.service.{RepositoryService, MilestonesService, AccountService}
import gitbucket.core.util.{ReferrerAuthenticator, WritableUsersAuthenticator} import gitbucket.core.util.{ReferrerAuthenticator, WritableUsersAuthenticator}
import gitbucket.core.util.Implicits._ import gitbucket.core.util.Implicits._
import io.github.gitbucket.scalatra.forms._ import org.scalatra.forms._
class MilestonesController extends MilestonesControllerBase class MilestonesController extends MilestonesControllerBase
with MilestonesService with RepositoryService with AccountService with MilestonesService with RepositoryService with AccountService

View File

@@ -4,7 +4,7 @@ import gitbucket.core.issues.priorities.html
import gitbucket.core.service.{RepositoryService, AccountService, IssuesService, PrioritiesService} import gitbucket.core.service.{RepositoryService, AccountService, IssuesService, PrioritiesService}
import gitbucket.core.util.{ReferrerAuthenticator, WritableUsersAuthenticator} import gitbucket.core.util.{ReferrerAuthenticator, WritableUsersAuthenticator}
import gitbucket.core.util.Implicits._ import gitbucket.core.util.Implicits._
import io.github.gitbucket.scalatra.forms._ import org.scalatra.forms._
import org.scalatra.i18n.Messages import org.scalatra.i18n.Messages
import org.scalatra.Ok import org.scalatra.Ok
@@ -98,11 +98,11 @@ trait PrioritiesControllerBase extends ControllerBase {
} }
private def uniquePriorityName: Constraint = new Constraint(){ private def uniquePriorityName: Constraint = new Constraint(){
override def validate(name: String, value: String, params: Map[String, String], messages: Messages): Option[String] = { override def validate(name: String, value: String, params: Map[String, Seq[String]], messages: Messages): Option[String] = {
val owner = params("owner") val owner = params("owner").head
val repository = params("repository") val repository = params("repository").head
params.get("priorityId").map { priorityId => params.get("priorityId").map { priorityId =>
getPriority(owner, repository, value).filter(_.priorityId != priorityId.toInt).map(_ => "Name has already been taken.") getPriority(owner, repository, value).filter(_.priorityId != priorityId.head.toInt).map(_ => "Name has already been taken.")
}.getOrElse { }.getOrElse {
getPriority(owner, repository, value).map(_ => "Name has already been taken.") getPriority(owner, repository, value).map(_ => "Name has already been taken.")
} }

View File

@@ -13,7 +13,7 @@ import gitbucket.core.util.SyntaxSugars._
import gitbucket.core.util.Directory._ import gitbucket.core.util.Directory._
import gitbucket.core.util.Implicits._ import gitbucket.core.util.Implicits._
import gitbucket.core.util._ import gitbucket.core.util._
import io.github.gitbucket.scalatra.forms._ import org.scalatra.forms._
import org.eclipse.jgit.api.Git import org.eclipse.jgit.api.Git
import org.eclipse.jgit.lib.PersonIdent import org.eclipse.jgit.lib.PersonIdent

View File

@@ -12,7 +12,7 @@ import gitbucket.core.util.JGitUtil._
import gitbucket.core.util.SyntaxSugars._ import gitbucket.core.util.SyntaxSugars._
import gitbucket.core.util.Implicits._ import gitbucket.core.util.Implicits._
import gitbucket.core.util.Directory._ import gitbucket.core.util.Directory._
import io.github.gitbucket.scalatra.forms._ import org.scalatra.forms._
import org.apache.commons.io.FileUtils import org.apache.commons.io.FileUtils
import org.scalatra.i18n.Messages import org.scalatra.i18n.Messages
import org.eclipse.jgit.api.Git import org.eclipse.jgit.api.Git
@@ -429,12 +429,12 @@ trait RepositorySettingsControllerBase extends ControllerBase {
} }
private def webhookEvents = new ValueType[Set[WebHook.Event]]{ private def webhookEvents = new ValueType[Set[WebHook.Event]]{
def convert(name: String, params: Map[String, String], messages: Messages): Set[WebHook.Event] = { def convert(name: String, params: Map[String, Seq[String]], messages: Messages): Set[WebHook.Event] = {
WebHook.Event.values.flatMap { t => WebHook.Event.values.flatMap { t =>
params.get(name + "." + t.name).map(_ => t) params.get(name + "." + t.name).map(_ => t)
}.toSet }.toSet
} }
def validate(name: String, params: Map[String, String], messages: Messages): Seq[(String, String)] = if(convert(name,params,messages).isEmpty){ def validate(name: String, params: Map[String, Seq[String]], messages: Messages): Seq[(String, String)] = if(convert(name,params,messages).isEmpty){
Seq(name -> messages("error.required").format(name)) Seq(name -> messages("error.required").format(name))
} else { } else {
Nil Nil
@@ -460,10 +460,10 @@ trait RepositorySettingsControllerBase extends ControllerBase {
* Duplicate check for the rename repository name. * Duplicate check for the rename repository name.
*/ */
private def renameRepositoryName: Constraint = new Constraint(){ private def renameRepositoryName: Constraint = new Constraint(){
override def validate(name: String, value: String, params: Map[String, String], messages: Messages): Option[String] = override def validate(name: String, value: String, params: Map[String, Seq[String]], messages: Messages): Option[String] =
params.get("repository").filter(_ != value).flatMap { _ => params.get("repository").filter(_ != value).flatMap { _ =>
params.get("owner").flatMap { userName => params.get("owner").flatMap { userName =>
getRepositoryNamesOfUser(userName).find(_ == value).map(_ => "Repository already exists.") getRepositoryNamesOfUser(userName.head).find(_ == value).map(_ => "Repository already exists.")
} }
} }
} }
@@ -472,7 +472,7 @@ trait RepositorySettingsControllerBase extends ControllerBase {
* *
*/ */
private def featureOption: Constraint = new Constraint(){ private def featureOption: Constraint = new Constraint(){
override def validate(name: String, value: String, params: Map[String, String], messages: Messages): Option[String] = override def validate(name: String, value: String, params: Map[String, Seq[String]], messages: Messages): Option[String] =
if(Seq("DISABLE", "PRIVATE", "PUBLIC", "ALL").contains(value)) None else Some("Option is invalid.") if(Seq("DISABLE", "PRIVATE", "PUBLIC", "ALL").contains(value)) None else Some("Option is invalid.")
} }

View File

@@ -17,7 +17,7 @@ import gitbucket.core.model.{Account, CommitState, CommitStatus, WebHook}
import gitbucket.core.service.WebHookService._ import gitbucket.core.service.WebHookService._
import gitbucket.core.view import gitbucket.core.view
import gitbucket.core.view.helpers import gitbucket.core.view.helpers
import io.github.gitbucket.scalatra.forms._ import org.scalatra.forms._
import org.apache.commons.io.FileUtils import org.apache.commons.io.FileUtils
import org.eclipse.jgit.api.{ArchiveCommand, Git} import org.eclipse.jgit.api.{ArchiveCommand, Git}
import org.eclipse.jgit.archive.{TgzFormat, ZipFormat} import org.eclipse.jgit.archive.{TgzFormat, ZipFormat}

View File

@@ -12,7 +12,7 @@ import gitbucket.core.util.Implicits._
import gitbucket.core.util.SyntaxSugars._ import gitbucket.core.util.SyntaxSugars._
import gitbucket.core.util.Directory._ import gitbucket.core.util.Directory._
import gitbucket.core.util.StringUtil._ import gitbucket.core.util.StringUtil._
import io.github.gitbucket.scalatra.forms._ import org.scalatra.forms._
import org.apache.commons.io.{FileUtils, IOUtils} import org.apache.commons.io.{FileUtils, IOUtils}
import org.scalatra.i18n.Messages import org.scalatra.i18n.Messages
import com.github.zafarkhaja.semver.{Version => Semver} import com.github.zafarkhaja.semver.{Version => Semver}

View File

@@ -0,0 +1,91 @@
package gitbucket.core.controller
import org.json4s.{JField, JObject, JString}
import org.scalatra._
import org.scalatra.json._
import org.scalatra.forms._
import org.scalatra.i18n.I18nSupport
import org.scalatra.servlet.ServletBase
/**
* Extends scalatra-forms to support the client-side validation and Ajax requests as well.
*/
trait ValidationSupport extends FormSupport { self: ServletBase with JacksonJsonSupport with I18nSupport =>
def get[T](path: String, form: ValueType[T])(action: T => Any): Route = {
registerValidate(path, form)
get(path){
validate(form)(errors => BadRequest(), form => action(form))
}
}
def post[T](path: String, form: ValueType[T])(action: T => Any): Route = {
registerValidate(path, form)
post(path){
validate(form)(errors => BadRequest(), form => action(form))
}
}
def put[T](path: String, form: ValueType[T])(action: T => Any): Route = {
registerValidate(path, form)
put(path){
validate(form)(errors => BadRequest(), form => action(form))
}
}
def delete[T](path: String, form: ValueType[T])(action: T => Any): Route = {
registerValidate(path, form)
delete(path){
validate(form)(errors => BadRequest(), form => action(form))
}
}
def ajaxGet[T](path: String, form: ValueType[T])(action: T => Any): Route = {
get(path){
validate(form)(errors => ajaxError(errors), form => action(form))
}
}
def ajaxPost[T](path: String, form: ValueType[T])(action: T => Any): Route = {
post(path){
validate(form)(errors => ajaxError(errors), form => action(form))
}
}
def ajaxDelete[T](path: String, form: ValueType[T])(action: T => Any): Route = {
delete(path){
validate(form)(errors => ajaxError(errors), form => action(form))
}
}
def ajaxPut[T](path: String, form: ValueType[T])(action: T => Any): Route = {
put(path){
validate(form)(errors => ajaxError(errors), form => action(form))
}
}
private def registerValidate[T](path: String, form: ValueType[T]) = {
post(path.replaceFirst("/$", "") + "/validate"){
contentType = "application/json"
toJson(form.validate("", multiParams, messages))
}
}
/**
* Responds errors for ajax requests.
*/
private def ajaxError(errors: Seq[(String, String)]): JObject = {
status = 400
contentType = "application/json"
toJson(errors)
}
/**
* Converts errors to JSON.
*/
private def toJson(errors: Seq[(String, String)]): JObject =
JObject(errors.map { case (key, value) =>
JField(key, JString(value))
}.toList)
}

View File

@@ -10,7 +10,7 @@ import gitbucket.core.util.StringUtil._
import gitbucket.core.util.SyntaxSugars._ import gitbucket.core.util.SyntaxSugars._
import gitbucket.core.util.Implicits._ import gitbucket.core.util.Implicits._
import gitbucket.core.util.Directory._ import gitbucket.core.util.Directory._
import io.github.gitbucket.scalatra.forms._ import org.scalatra.forms._
import org.eclipse.jgit.api.Git import org.eclipse.jgit.api.Git
import org.scalatra.i18n.Messages import org.scalatra.i18n.Messages
@@ -226,8 +226,8 @@ trait WikiControllerBase extends ControllerBase {
}) })
private def unique: Constraint = new Constraint(){ private def unique: Constraint = new Constraint(){
override def validate(name: String, value: String, params: Map[String, String], messages: Messages): Option[String] = override def validate(name: String, value: String, params: Map[String, Seq[String]], messages: Messages): Option[String] =
getWikiPageList(params("owner"), params("repository")).find(_ == value).map(_ => "Page already exists.") getWikiPageList(params("owner").head, params("repository").head).find(_ == value).map(_ => "Page already exists.")
} }
private def pagename: Constraint = new Constraint(){ private def pagename: Constraint = new Constraint(){

View File

@@ -1,6 +1,6 @@
package gitbucket.core.util package gitbucket.core.util
import io.github.gitbucket.scalatra.forms._ import org.scalatra.forms._
import org.scalatra.i18n.Messages import org.scalatra.i18n.Messages
trait Validations { trait Validations {