Actually validate forms
This commit is contained in:
parent
c81bb9ec25
commit
153400959c
|
@ -1,4 +1,4 @@
|
||||||
-- Your SQL goes here
|
l-- Your SQL goes here
|
||||||
CREATE TABLE instances (
|
CREATE TABLE instances (
|
||||||
id SERIAL PRIMARY KEY,
|
id SERIAL PRIMARY KEY,
|
||||||
local_domain VARCHAR NOT NULL,
|
local_domain VARCHAR NOT NULL,
|
||||||
|
|
|
@ -5,7 +5,7 @@ use rocket::{
|
||||||
};
|
};
|
||||||
use rocket_contrib::Template;
|
use rocket_contrib::Template;
|
||||||
use serde_json;
|
use serde_json;
|
||||||
use validator::{Validate, ValidationError};
|
use validator::{Validate, ValidationError, ValidationErrors};
|
||||||
|
|
||||||
use plume_common::activity_pub::ActivityStream;
|
use plume_common::activity_pub::ActivityStream;
|
||||||
use plume_common::utils;
|
use plume_common::utils;
|
||||||
|
@ -66,15 +66,22 @@ fn valid_slug(title: &str) -> Result<(), ValidationError> {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[post("/blogs/new", data = "<data>")]
|
#[post("/blogs/new", data = "<data>")]
|
||||||
fn create(conn: DbConn, data: LenientForm<NewBlogForm>, user: User) -> Redirect {
|
fn create(conn: DbConn, data: LenientForm<NewBlogForm>, user: User) -> Result<Redirect, Template> {
|
||||||
let form = data.get();
|
let form = data.get();
|
||||||
let slug = utils::make_actor_id(form.title.to_string());
|
let slug = utils::make_actor_id(form.title.to_string());
|
||||||
|
let slug_taken_err = Blog::find_local(&*conn, slug.clone()).ok_or(ValidationError::new("existing_slug"));
|
||||||
|
|
||||||
if Blog::find_local(&*conn, slug.clone()).is_some() || slug.len() == 0 {
|
let mut errors = match form.validate() {
|
||||||
Redirect::to(uri!(new))
|
Ok(_) => ValidationErrors::new(),
|
||||||
} else {
|
Err(e) => e
|
||||||
|
};
|
||||||
|
if let Err(e) = slug_taken_err {
|
||||||
|
errors.add("title", e)
|
||||||
|
}
|
||||||
|
|
||||||
|
if errors.is_empty() {
|
||||||
let blog = Blog::insert(&*conn, NewBlog::new_local(
|
let blog = Blog::insert(&*conn, NewBlog::new_local(
|
||||||
slug.to_string(),
|
slug.clone(),
|
||||||
form.title.to_string(),
|
form.title.to_string(),
|
||||||
String::from(""),
|
String::from(""),
|
||||||
Instance::local_id(&*conn)
|
Instance::local_id(&*conn)
|
||||||
|
@ -87,7 +94,12 @@ fn create(conn: DbConn, data: LenientForm<NewBlogForm>, user: User) -> Redirect
|
||||||
is_owner: true
|
is_owner: true
|
||||||
});
|
});
|
||||||
|
|
||||||
Redirect::to(uri!(details: name = slug))
|
Ok(Redirect::to(uri!(details: name = slug.clone())))
|
||||||
|
} else {
|
||||||
|
Err(Template::render("blogs/new", json!({
|
||||||
|
"account": user,
|
||||||
|
"errors": errors.inner()
|
||||||
|
})))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,7 @@ use rocket::{
|
||||||
request::LenientForm,
|
request::LenientForm,
|
||||||
response::Redirect
|
response::Redirect
|
||||||
};
|
};
|
||||||
|
use rocket_contrib::Template;
|
||||||
use serde_json;
|
use serde_json;
|
||||||
use validator::Validate;
|
use validator::Validate;
|
||||||
|
|
||||||
|
@ -24,22 +25,44 @@ struct NewCommentForm {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[post("/~/<blog_name>/<slug>/comment", data = "<data>")]
|
#[post("/~/<blog_name>/<slug>/comment", data = "<data>")]
|
||||||
fn create(blog_name: String, slug: String, data: LenientForm<NewCommentForm>, user: User, conn: DbConn) -> Redirect {
|
fn create(blog_name: String, slug: String, data: LenientForm<NewCommentForm>, user: User, conn: DbConn) -> Result<Redirect, Template> {
|
||||||
let blog = Blog::find_by_fqn(&*conn, blog_name.clone()).unwrap();
|
let blog = Blog::find_by_fqn(&*conn, blog_name.clone()).unwrap();
|
||||||
let post = Post::find_by_slug(&*conn, slug.clone(), blog.id).unwrap();
|
let post = Post::find_by_slug(&*conn, slug.clone(), blog.id).unwrap();
|
||||||
let form = data.get();
|
let form = data.get();
|
||||||
|
form.validate()
|
||||||
|
.map(|_| {
|
||||||
|
let (new_comment, id) = NewComment::build()
|
||||||
|
.content(form.content.clone())
|
||||||
|
.in_response_to_id(form.responding_to.clone())
|
||||||
|
.post(post.clone())
|
||||||
|
.author(user.clone())
|
||||||
|
.create(&*conn);
|
||||||
|
|
||||||
let (new_comment, id) = NewComment::build()
|
let instance = Instance::get_local(&*conn).unwrap();
|
||||||
.content(form.content.clone())
|
instance.received(&*conn, serde_json::to_value(new_comment.clone()).expect("JSON serialization error"))
|
||||||
.in_response_to_id(form.responding_to.clone())
|
.expect("We are not compatible with ourselve: local broadcast failed (new comment)");
|
||||||
.post(post)
|
broadcast(&user, new_comment, user.get_followers(&*conn));
|
||||||
.author(user.clone())
|
|
||||||
.create(&*conn);
|
|
||||||
|
|
||||||
let instance = Instance::get_local(&*conn).unwrap();
|
Redirect::to(format!("/~/{}/{}/#comment-{}", blog_name, slug, id))
|
||||||
instance.received(&*conn, serde_json::to_value(new_comment.clone()).expect("JSON serialization error"))
|
})
|
||||||
.expect("We are not compatible with ourselve: local broadcast failed (new comment)");
|
.map_err(|errors| {
|
||||||
broadcast(&user, new_comment, user.get_followers(&*conn));
|
// TODO: de-duplicate this code
|
||||||
|
let comments = Comment::list_by_post(&*conn, post.id);
|
||||||
|
|
||||||
Redirect::to(format!("/~/{}/{}/#comment-{}", blog_name, slug, id))
|
Template::render("posts/details", json!({
|
||||||
|
"author": post.get_authors(&*conn)[0].to_json(&*conn),
|
||||||
|
"post": post,
|
||||||
|
"blog": blog,
|
||||||
|
"comments": comments.into_iter().map(|c| c.to_json(&*conn)).collect::<Vec<serde_json::Value>>(),
|
||||||
|
"n_likes": post.get_likes(&*conn).len(),
|
||||||
|
"has_liked": user.has_liked(&*conn, &post),
|
||||||
|
"n_reshares": post.get_reshares(&*conn).len(),
|
||||||
|
"has_reshared": user.has_reshared(&*conn, &post),
|
||||||
|
"account": user,
|
||||||
|
"date": &post.creation_date.timestamp(),
|
||||||
|
"previous": form.responding_to.map(|r| Comment::get(&*conn, r).expect("Error retrieving previous comment").to_json(&*conn)),
|
||||||
|
"user_fqn": user.get_fqn(&*conn),
|
||||||
|
"errors": errors
|
||||||
|
}))
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,7 @@ use rocket::request::LenientForm;
|
||||||
use rocket::response::{Redirect, Flash};
|
use rocket::response::{Redirect, Flash};
|
||||||
use rocket_contrib::Template;
|
use rocket_contrib::Template;
|
||||||
use serde_json;
|
use serde_json;
|
||||||
use validator::{Validate, ValidationError};
|
use validator::{Validate, ValidationError, ValidationErrors};
|
||||||
|
|
||||||
use plume_common::activity_pub::{broadcast, ActivityStream};
|
use plume_common::activity_pub::{broadcast, ActivityStream};
|
||||||
use plume_common::utils;
|
use plume_common::utils;
|
||||||
|
@ -94,22 +94,32 @@ fn valid_slug(title: &str) -> Result<(), ValidationError> {
|
||||||
let slug = title.to_string().to_kebab_case();
|
let slug = title.to_string().to_kebab_case();
|
||||||
if slug.len() == 0 {
|
if slug.len() == 0 {
|
||||||
Err(ValidationError::new("empty_slug"))
|
Err(ValidationError::new("empty_slug"))
|
||||||
|
} else if slug == "new" {
|
||||||
|
Err(ValidationError::new("invalid_slug"))
|
||||||
} else {
|
} else {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[post("/~/<blog_name>/new", data = "<data>")]
|
#[post("/~/<blog_name>/new", data = "<data>")]
|
||||||
fn create(blog_name: String, data: LenientForm<NewPostForm>, user: User, conn: DbConn) -> Redirect {
|
fn create(blog_name: String, data: LenientForm<NewPostForm>, user: User, conn: DbConn) -> Result<Redirect, Template> {
|
||||||
let blog = Blog::find_by_fqn(&*conn, blog_name.to_string()).unwrap();
|
let blog = Blog::find_by_fqn(&*conn, blog_name.to_string()).unwrap();
|
||||||
let form = data.get();
|
let form = data.get();
|
||||||
let slug = form.title.to_string().to_kebab_case();
|
let slug = form.title.to_string().to_kebab_case();
|
||||||
|
let slug_taken_err = Blog::find_local(&*conn, slug.clone()).ok_or(ValidationError::new("existing_slug"));
|
||||||
|
|
||||||
|
let mut errors = match form.validate() {
|
||||||
|
Ok(_) => ValidationErrors::new(),
|
||||||
|
Err(e) => e
|
||||||
|
};
|
||||||
|
if let Err(e) = slug_taken_err {
|
||||||
|
errors.add("title", e)
|
||||||
|
}
|
||||||
|
|
||||||
if !user.is_author_in(&*conn, blog.clone()) {
|
if errors.is_empty() {
|
||||||
Redirect::to(uri!(super::blogs::details: name = blog_name))
|
if !user.is_author_in(&*conn, blog.clone()) {
|
||||||
} else {
|
// actually it's not "Ok"…
|
||||||
if slug == "new" || Post::find_by_slug(&*conn, slug.clone(), blog.id).is_some() {
|
Ok(Redirect::to(uri!(super::blogs::details: name = blog_name)))
|
||||||
Redirect::to(uri!(new: blog = blog_name))
|
|
||||||
} else {
|
} else {
|
||||||
let (content, mentions) = utils::md_to_html(form.content.to_string().as_ref());
|
let (content, mentions) = utils::md_to_html(form.content.to_string().as_ref());
|
||||||
|
|
||||||
|
@ -135,7 +145,12 @@ fn create(blog_name: String, data: LenientForm<NewPostForm>, user: User, conn: D
|
||||||
let act = post.create_activity(&*conn);
|
let act = post.create_activity(&*conn);
|
||||||
broadcast(&user, act, user.get_followers(&*conn));
|
broadcast(&user, act, user.get_followers(&*conn));
|
||||||
|
|
||||||
Redirect::to(uri!(details: blog = blog_name, slug = slug))
|
Ok(Redirect::to(uri!(details: blog = blog_name, slug = slug)))
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
Err(Template::render("posts/new", json!({
|
||||||
|
"account": user,
|
||||||
|
"errors": errors.inner()
|
||||||
|
})))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,10 @@
|
||||||
use gettextrs::gettext;
|
|
||||||
use rocket::{
|
use rocket::{
|
||||||
http::{Cookie, Cookies, uri::Uri},
|
http::{Cookie, Cookies, uri::Uri},
|
||||||
response::{Redirect, status::NotFound},
|
response::Redirect,
|
||||||
request::{LenientForm,FlashMessage}
|
request::{LenientForm,FlashMessage}
|
||||||
};
|
};
|
||||||
use rocket_contrib::Template;
|
use rocket_contrib::Template;
|
||||||
use validator::{Validate, ValidationError};
|
use validator::{Validate, ValidationError, ValidationErrors};
|
||||||
|
|
||||||
use plume_models::{
|
use plume_models::{
|
||||||
db_conn::DbConn,
|
db_conn::DbConn,
|
||||||
|
@ -42,28 +41,33 @@ struct LoginForm {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[post("/login", data = "<data>")]
|
#[post("/login", data = "<data>")]
|
||||||
fn create(conn: DbConn, data: LenientForm<LoginForm>, flash: Option<FlashMessage>, mut cookies: Cookies) -> Result<Redirect, NotFound<String>> {
|
fn create(conn: DbConn, data: LenientForm<LoginForm>, flash: Option<FlashMessage>, mut cookies: Cookies) -> Result<Redirect, Template> {
|
||||||
let form = data.get();
|
let form = data.get();
|
||||||
let user = match User::find_by_email(&*conn, form.email_or_name.to_string()) {
|
let user = User::find_by_email(&*conn, form.email_or_name.to_string())
|
||||||
Some(usr) => Ok(usr),
|
.map(|u| Ok(u))
|
||||||
None => match User::find_local(&*conn, form.email_or_name.to_string()) {
|
.unwrap_or_else(|| User::find_local(&*conn, form.email_or_name.to_string()).map(|u| Ok(u)).unwrap_or(Err(())));
|
||||||
Some(usr) => Ok(usr),
|
|
||||||
None => Err(gettext("Invalid username or password"))
|
let mut errors = match form.validate() {
|
||||||
}
|
Ok(_) => ValidationErrors::new(),
|
||||||
|
Err(e) => e
|
||||||
};
|
};
|
||||||
match user {
|
if let Err(_) = user.clone() {
|
||||||
Ok(usr) => {
|
errors.add("email_or_name", ValidationError::new("invalid_login"))
|
||||||
if usr.auth(form.password.to_string()) {
|
} else if !user.clone().expect("User not found").auth(form.password.clone()) {
|
||||||
cookies.add_private(Cookie::new(AUTH_COOKIE, usr.id.to_string()));
|
errors.add("email_or_name", ValidationError::new("invalid_login"))
|
||||||
Ok(Redirect::to(Uri::new(flash
|
}
|
||||||
.and_then(|f| if f.name() == "callback" { Some(f.msg().to_owned()) } else { None })
|
|
||||||
.unwrap_or("/".to_owned()))
|
if errors.is_empty() {
|
||||||
))
|
cookies.add_private(Cookie::new(AUTH_COOKIE, user.unwrap().id.to_string()));
|
||||||
} else {
|
Ok(Redirect::to(Uri::new(flash
|
||||||
Err(NotFound(gettext("Invalid username or password")))
|
.and_then(|f| if f.name() == "callback" { Some(f.msg().to_owned()) } else { None })
|
||||||
}
|
.unwrap_or("/".to_owned()))
|
||||||
},
|
))
|
||||||
Err(e) => Err(NotFound(String::from(e)))
|
} else {
|
||||||
|
Err(Template::render("session/login", json!({
|
||||||
|
"account": user,
|
||||||
|
"errors": errors.inner()
|
||||||
|
})))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -180,29 +180,24 @@ fn passwords_match(form: &NewUserForm) -> Result<(), ValidationError> {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[post("/users/new", data = "<data>")]
|
#[post("/users/new", data = "<data>")]
|
||||||
fn create(conn: DbConn, data: LenientForm<NewUserForm>) -> Result<Redirect, String> {
|
fn create(conn: DbConn, data: LenientForm<NewUserForm>) -> Result<Redirect, Template> {
|
||||||
let form = data.get();
|
let form = data.get();
|
||||||
|
form.validate()
|
||||||
if form.username.clone().len() < 1 {
|
.map(|_| {
|
||||||
Err(String::from("Username is required"))
|
NewUser::new_local(
|
||||||
} else if form.email.clone().len() < 1 {
|
&*conn,
|
||||||
Err(String::from("Email is required"))
|
form.username.to_string(),
|
||||||
} else if form.password.clone().len() < 8 {
|
form.username.to_string(),
|
||||||
Err(String::from("Password should be at least 8 characters long"))
|
false,
|
||||||
} else if form.password == form.password_confirmation {
|
String::from(""),
|
||||||
NewUser::new_local(
|
form.email.to_string(),
|
||||||
&*conn,
|
User::hash_pass(form.password.to_string())
|
||||||
form.username.to_string(),
|
).update_boxes(&*conn);
|
||||||
form.username.to_string(),
|
Redirect::to(uri!(super::session::new))
|
||||||
false,
|
})
|
||||||
String::from(""),
|
.map_err(|e| Template::render("users/new", json!({
|
||||||
form.email.to_string(),
|
"errors": e.inner()
|
||||||
User::hash_pass(form.password.to_string())
|
})))
|
||||||
).update_boxes(&*conn);
|
|
||||||
Ok(Redirect::to(uri!(super::session::new)))
|
|
||||||
} else {
|
|
||||||
Err(String::from("Passwords don't match"))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[get("/@/<name>/outbox")]
|
#[get("/@/<name>/outbox")]
|
||||||
|
|
Loading…
Reference in New Issue