Skip to content

Commit

Permalink
Add validation checks for forms
Browse files Browse the repository at this point in the history
Also refactored code for creating messages to allow multiple messages to
be created within a single route
  • Loading branch information
SL-Lee committed Mar 8, 2021
1 parent 847361c commit f01eae6
Show file tree
Hide file tree
Showing 5 changed files with 194 additions and 42 deletions.
70 changes: 70 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,4 @@ scrypt = "0.6.3"
serde = "1.0.123"
serde_json = "1.0.64"
tera = "1.6.1"
validator = { version = "0.12.0", features = ["derive"] }
23 changes: 21 additions & 2 deletions src/forms.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,33 @@
use serde::Deserialize;
use validator::Validate;

#[derive(Debug, Deserialize)]
#[derive(Debug, Deserialize, Validate)]
pub struct LoginForm {
#[validate(length(
max = 32,
message = "Username must not be longer than 32 characters."
))]
pub username: String,
#[validate(length(
min = 8,
max = 32,
message = "Password length must be between 8 and 32 characters."
))]
pub password: String,
}

#[derive(Debug, Deserialize)]
#[derive(Debug, Deserialize, Validate)]
pub struct SignupForm {
#[validate(length(
max = 32,
message = "Username must not be longer than 32 characters."
))]
pub username: String,
#[validate(length(
min = 8,
max = 32,
message = "Password length must be between 8 and 32 characters."
))]
pub password: String,
}

Expand Down
20 changes: 11 additions & 9 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ pub fn create_response_for_template(
serde_json::from_str::<Vec<Message>>(messages_cookie.value())
{
context.insert("messages", &messages);
messages_cookie.set_value("");
messages_cookie.set_value("[]");
HttpResponse::Ok().cookie(messages_cookie).take()
} else {
HttpResponse::Ok()
Expand All @@ -55,17 +55,20 @@ pub fn create_response_for_template(
}
}

pub fn get_messages_cookie(req: &HttpRequest) -> Cookie {
req.cookie("messages").unwrap_or(
Cookie::build("messages", "[]")
.same_site(actix_web::cookie::SameSite::Lax)
.finish(),
)
}

pub fn create_message(
req: &HttpRequest,
messages_cookie: &mut Cookie,
message_category: String,
message_title: String,
message_content: String,
) -> Cookie {
let mut messages_cookie = req.cookie("messages").unwrap_or(
Cookie::build("messages", "[]")
.same_site(actix_web::cookie::SameSite::Lax)
.finish(),
);
) {
let mut messages =
serde_json::from_str::<Vec<Message>>(messages_cookie.value())
.unwrap_or(vec![]);
Expand All @@ -75,5 +78,4 @@ pub fn create_message(
content: message_content,
});
messages_cookie.set_value(serde_json::to_string(&messages).unwrap());
messages_cookie
}
122 changes: 91 additions & 31 deletions src/scopes/main_scope.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ use scrypt::{
Scrypt,
};
use tera::Tera;
use validator::Validate;

use crate::{
create_message, create_response_for_template,
Expand All @@ -18,7 +19,7 @@ use crate::{
schema::user,
},
forms::{LoginForm, SignupForm},
initialize_context, DbConnectionPool,
get_messages_cookie, initialize_context, DbConnectionPool,
};

pub fn get_scope() -> Scope {
Expand Down Expand Up @@ -73,6 +74,30 @@ async fn process_login(
return HttpResponse::Found().header("location", "/").finish();
}

let mut messages_cookie = get_messages_cookie(&req);

if let Err(validation_errors) = form_data.validate() {
validation_errors.field_errors().iter().for_each(
|(_, &field_errors)| {
field_errors
.iter()
.filter_map(|error| error.message.as_ref())
.for_each(|error_message| {
create_message(
&mut messages_cookie,
"danger".to_string(),
"Login unsuccessful".to_string(),
error_message.to_string(),
);
});
},
);
return HttpResponse::Found()
.header("location", "/login")
.cookie(messages_cookie)
.finish();
}

let db_connection =
pool.get().expect("Couldn't get db connection from pool");
let user = user::table
Expand All @@ -88,36 +113,43 @@ async fn process_login(
{
Ok(_) => {
identity.remember(user.username.clone());
create_message(
&mut messages_cookie,
"success".to_string(),
"Login successful".to_string(),
"Logged in successfully.".to_string(),
);
HttpResponse::Found()
.header("location", "/app")
.cookie(create_message(
&req,
"success".to_string(),
"Login successful".to_string(),
"Logged in successfully.".to_string(),
))
.cookie(messages_cookie)
.finish()
}
Err(_) => HttpResponse::Found()
.header("location", "/login")
.cookie(create_message(
&req,
Err(_) => {
create_message(
&mut messages_cookie,
"danger".to_string(),
"Login unsuccessful".to_string(),
"Incorrect username and/or password.".to_string(),
))
.finish(),
);
HttpResponse::Found()
.header("location", "/login")
.cookie(messages_cookie)
.finish()
}
}
}
Err(_) => HttpResponse::Found()
.header("location", "/login")
.cookie(create_message(
&req,
Err(_) => {
create_message(
&mut messages_cookie,
"danger".to_string(),
"Login unsuccessful".to_string(),
"Incorrect username and/or password.".to_string(),
))
.finish(),
);
HttpResponse::Found()
.header("location", "/login")
.cookie(messages_cookie)
.finish()
}
}
}

Expand Down Expand Up @@ -147,6 +179,30 @@ async fn process_signup(
return HttpResponse::Found().header("location", "/").finish();
}

let mut messages_cookie = get_messages_cookie(&req);

if let Err(validation_errors) = form_data.validate() {
validation_errors.field_errors().iter().for_each(
|(_, &field_errors)| {
field_errors
.iter()
.filter_map(|error| error.message.as_ref())
.for_each(|error_message| {
create_message(
&mut messages_cookie,
"danger".to_string(),
"Signup unsuccessful".to_string(),
error_message.to_string(),
);
});
},
);
return HttpResponse::Found()
.header("location", "/signup")
.cookie(messages_cookie)
.finish();
}

let password = form_data.password.as_bytes();
let salt = SaltString::generate(&mut OsRng);
let password_hash = Scrypt
Expand All @@ -170,27 +226,31 @@ async fn process_signup(
{
Ok(_) => {
identity.remember(form_data.username.clone());
create_message(
&mut messages_cookie,
"success".to_string(),
"Signup successful".to_string(),
"Signed up in successfully.".to_string(),
);
HttpResponse::Found()
.header("location", "/app")
.cookie(create_message(
&req,
"success".to_string(),
"Signup successful".to_string(),
"Signed up in successfully.".to_string(),
))
.cookie(messages_cookie)
.finish()
}
Err(_) => HttpResponse::Found()
.header("location", "/signup")
.cookie(create_message(
&req,
Err(_) => {
create_message(
&mut messages_cookie,
"danger".to_string(),
"Signup unsuccessful".to_string(),
"An account with this username already exists. Please try \
again with a different username."
.to_string(),
))
.finish(),
);
HttpResponse::Found()
.header("location", "/signup")
.cookie(messages_cookie)
.finish()
}
}
}

Expand Down

0 comments on commit f01eae6

Please sign in to comment.