Improvements for validation.

This commit is contained in:
takezoe
2013-04-15 12:35:15 +09:00
parent 6fe7e19cb1
commit aa40822436
4 changed files with 92 additions and 72 deletions

View File

@@ -13,6 +13,13 @@ import org.apache.commons.io._
*/ */
class CreateRepositoryServlet extends ServletBase { class CreateRepositoryServlet extends ServletBase {
case class RepositoryCreationForm(name: String, description: String)
val form = mapping(
"name" -> trim(label("Repository name", text(required, maxlength(40), repository))),
"description" -> trim(label("Description" , text()))
)(RepositoryCreationForm.apply)
/** /**
* Show the new repository form. * Show the new repository form.
*/ */
@@ -23,53 +30,41 @@ class CreateRepositoryServlet extends ServletBase {
/** /**
* Create new repository. * Create new repository.
*/ */
post("/") { post("/", form) { form =>
withValidation(form, params){ form => val gitdir = getRepositoryDir(LoginUser, form.name)
val gitdir = getRepositoryDir(LoginUser, form.name) val repository = new RepositoryBuilder().setGitDir(gitdir).setBare.build
val repository = new RepositoryBuilder().setGitDir(gitdir).setBare.build
repository.create
val config = repository.getConfig
config.setBoolean("http", null, "receivepack", true)
config.save
val tmpdir = getInitRepositoryDir(LoginUser, form.name)
try {
// Clone the repository
Git.cloneRepository.setURI(gitdir.toURI.toString).setDirectory(tmpdir).call
// Create README.md
FileUtils.writeStringToFile(new File(tmpdir, "README.md"), if(form.description.nonEmpty){
form.name + "\n===============\n\n" + form.description
} else {
form.name + "\n===============\n"
}, "UTF-8")
val git = Git.open(tmpdir)
git.add.addFilepattern("README.md").call
git.commit.setMessage("Initial commit").call
git.push.call
} finally {
FileUtils.deleteDirectory(tmpdir)
}
// redirect to the repository
redirect("/%s/%s".format(LoginUser, form.name))
}
}
get("/validate") {
contentType = "application/json"
form.validateAsJSON(params)
}
val form = mapping(
"name" -> trim(label("Repository name", text(required, maxlength(40), repository))),
"description" -> trim(label("Description" , text()))
)(RepositoryCreationForm.apply)
repository.create
val config = repository.getConfig
config.setBoolean("http", null, "receivepack", true)
config.save
val tmpdir = getInitRepositoryDir(LoginUser, form.name)
try {
// Clone the repository
Git.cloneRepository.setURI(gitdir.toURI.toString).setDirectory(tmpdir).call
// Create README.md
FileUtils.writeStringToFile(new File(tmpdir, "README.md"), if(form.description.nonEmpty){
form.name + "\n===============\n\n" + form.description
} else {
form.name + "\n===============\n"
}, "UTF-8")
val git = Git.open(tmpdir)
git.add.addFilepattern("README.md").call
git.commit.setMessage("Initial commit").call
git.push.call
} finally {
FileUtils.deleteDirectory(tmpdir)
}
// redirect to the repository
redirect("/%s/%s".format(LoginUser, form.name))
}
def repository: Constraint = new Constraint(){ def repository: Constraint = new Constraint(){
def validate(name: String, value: String): Option[String] = { def validate(name: String, value: String): Option[String] = {
if(!value.matches("^[a-z0-9\\-_]+$")){ if(!value.matches("^[a-z0-9\\-_]+$")){
@@ -82,6 +77,4 @@ class CreateRepositoryServlet extends ServletBase {
} }
} }
case class RepositoryCreationForm(name: String, description: String)
} }

View File

@@ -1,5 +1,7 @@
package app package app
import util.Validations._
import org.scalatra._ import org.scalatra._
import org.scalatra.json._ import org.scalatra.json._
import org.json4s._ import org.json4s._
@@ -15,4 +17,29 @@ abstract class ServletBase extends ScalatraServlet with JacksonJsonSupport {
// TODO get from session // TODO get from session
val LoginUser = System.getProperty("user.name") val LoginUser = System.getProperty("user.name")
def get[T](path: String, form: MappingValueType[T])(action: T => Any) = {
super.get(path){
withValidation(form, params){ obj: T =>
action(obj)
}
}
registerValidate(path, form)
}
def post[T](path: String, form: MappingValueType[T])(action: T => Any) = {
super.post(path){
withValidation(form, params){ obj: T =>
action(obj)
}
}
registerValidate(path, form)
}
private def registerValidate[T](path: String, form: MappingValueType[T]) = {
super.post(path.replaceFirst("/$", "") + "/validate"){
contentType = "application/json"
form.validateAsJSON(params)
}
}
} }

View File

@@ -248,28 +248,28 @@ object Validations {
override def validate(name: String, value: String): Seq[(String, String)] = valueType.validate(name, value.trim) override def validate(name: String, value: String): Seq[(String, String)] = valueType.validate(name, value.trim)
} }
/** // /**
* ValueType wrapper to trim all parameters. // * ValueType wrapper to trim all parameters.
* // *
* {{{ // * {{{
* val form = trim(mapping( // * val form = trim(mapping(
* "name" -> text(required), // * "name" -> text(required),
* "mail" -> text(required) // * "mail" -> text(required)
* )) // * ))
* }}} // * }}}
*/ // */
def trim[T](valueType: MappingValueType[T]): MappingValueType[T] = new MappingValueType[T](){ // def trim[T](valueType: MappingValueType[T]): MappingValueType[T] = new MappingValueType[T](){
def validate(name: String, params: Map[String, String]): Seq[(String, String)] = // override def validate(name: String, params: Map[String, String]): Seq[(String, String)] =
fields.map { case (name, valueType) => valueType.validate(name, trimMap(params)) }.flatten // fields.map { case (name, valueType) => valueType.validate(name, trimMap(params)) }.flatten
//
def validateAsJSON(params: Map[String, String]): JObject = { // override def validateAsJSON(params: Map[String, String]): JObject = {
JObject(validate("form", trimMap(params)).map { case (key, value) => // JObject(validate("form", trimMap(params)).map { case (key, value) =>
JField(key, JString(value)) // JField(key, JString(value))
}.toList) // }.toList)
} // }
//
private def trimMap(params: Map[String, String]): Map[String, String] = params.map{ x => x._1 -> x._2.trim } // private def trimMap(params: Map[String, String]): Map[String, String] = params.map{ x => x._1 -> x._2.trim }
} // }
/** /**
* ValueType wrapper to specified a property name which is used in the error message. * ValueType wrapper to specified a property name which is used in the error message.

View File

@@ -12,7 +12,7 @@ function validate(e){
} }
// TODO use $.post() instead of $.getJSON // TODO use $.post() instead of $.getJSON
$.getJSON(form.attr('action') + '/validate', $(e.target).serialize(), function(data){ $.post(form.attr('action') + '/validate', $(e.target).serialize(), function(data){
// clear all error messages // clear all error messages
$('.error-message').text(''); $('.error-message').text('');
@@ -24,6 +24,6 @@ function validate(e){
$('#error-' + key).text(value); $('#error-' + key).text(value);
}); });
} }
}); }, 'json');
return false; return false;
} }