You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
245 lines
6.9 KiB
245 lines
6.9 KiB
pub mod forms;
|
|
pub mod db;
|
|
|
|
use bcrypt::{
|
|
hash,
|
|
verify,
|
|
DEFAULT_COST
|
|
};
|
|
use rocket::{
|
|
form::Form,
|
|
response::Redirect,
|
|
State
|
|
};
|
|
use forms::{
|
|
UserLoginForm,
|
|
NewUserForm,
|
|
NewListForm,
|
|
PermsForm,
|
|
NewNoteForm,
|
|
};
|
|
use db::{
|
|
List,
|
|
Notes,
|
|
Note,
|
|
Result,
|
|
add_permission,
|
|
get_user_from_email,
|
|
get_user_lists,
|
|
get_user_lists_from_perms,
|
|
get_notes_from_list,
|
|
add_note_to_list,
|
|
User,
|
|
};
|
|
|
|
#[macro_use] extern crate rocket;
|
|
use rocket_dyn_templates::{Template, context};
|
|
use rocket_db_pools::{
|
|
Database,
|
|
Connection,
|
|
sqlx::{
|
|
self,
|
|
Row,
|
|
},
|
|
};
|
|
use rocket::{
|
|
serde::{
|
|
Serialize
|
|
},
|
|
http::{
|
|
Cookie,
|
|
CookieJar,
|
|
RawStr,
|
|
},
|
|
};
|
|
|
|
#[get("/hello/<name>/<age>")]
|
|
async fn hello(name: &str, age: u8) -> String {
|
|
format!("Hello, {} year old named {}!", age, name)
|
|
}
|
|
|
|
#[get("/")]
|
|
async fn home() -> Template {
|
|
Template::render("index", context!{})
|
|
}
|
|
#[get("/create")]
|
|
async fn create() -> Template {
|
|
Template::render("new", context!{})
|
|
}
|
|
|
|
#[post("/new", data="<user>")]
|
|
async fn new_user(user: Form<NewUserForm<'_>>, mut db: Connection<Notes>) -> Result<String> {
|
|
let check_exists = sqlx::query!("SELECT id FROM users WHERE username = $1 OR email = $2", user.username, user.email)
|
|
.fetch_optional(&mut *db)
|
|
.await?;
|
|
if check_exists.is_some() {
|
|
return Ok(format!("This account already exists!"));
|
|
}
|
|
let hashed_pass = match hash(user.password, DEFAULT_COST) {
|
|
Ok(pass) => pass,
|
|
Err(e) => panic!("Could not hash a password! {}", e)
|
|
};
|
|
sqlx::query!("INSERT INTO users (username,password,email) VALUES ($1, $2, $3)", user.username, hashed_pass, user.email)
|
|
.execute(&mut *db)
|
|
.await?;
|
|
Ok(format!("Thanks, {}, for creating an account on our service.", user.username))
|
|
}
|
|
|
|
#[post("/login", data="<user>")]
|
|
async fn login(user: Form<UserLoginForm<'_>>, mut db: Connection<Notes>, cookies: &CookieJar<'_>) -> Result<String> {
|
|
match cookies.get_private("user_uuid") {
|
|
Some(crumb) => println!("UUID: {:?}", crumb.value()),
|
|
_ => {}
|
|
};
|
|
let result = sqlx::query!("SELECT * FROM users WHERE username=$1", user.username)
|
|
.fetch_optional(&mut *db)
|
|
.await?;
|
|
let success = match result {
|
|
Some(ref db_user) => verify(&user.password, &db_user.password).unwrap(),
|
|
_ => false,
|
|
};
|
|
if success {
|
|
cookies.add_private(Cookie::new("user_uuid", result.unwrap().uuid));
|
|
Ok(format!("Yay! Thanks for logging in to our service!"))
|
|
} else {
|
|
Ok(format!("Incorrect login!"))
|
|
}
|
|
}
|
|
|
|
#[post("/list", data="<new_list>")]
|
|
async fn new_list(mut db: Connection<Notes>, user: User, new_list: Form<NewListForm<'_>>) -> Result<String> {
|
|
sqlx::query!("INSERT INTO list (owner_id, name) VALUES ($1, $2)", user.id, new_list.name)
|
|
.execute(&mut *db)
|
|
.await?;
|
|
Ok(format!("You added a new list: {}", new_list.name))
|
|
}
|
|
#[post("/list", data="<new_list>", rank=2)]
|
|
async fn new_list_not_logged_in(new_list: Form<NewListForm<'_>>) -> Redirect {
|
|
Redirect::to(uri!(home))
|
|
}
|
|
|
|
#[get("/lists")]
|
|
async fn show_list(mut db: Connection<Notes>, user: User) -> Result<Template> {
|
|
Ok(Template::render("show_lists", context!{
|
|
lists: get_user_lists(&mut db, user.id).await?,
|
|
perm_lists: get_user_lists_from_perms(&mut db, user.id).await?
|
|
}))
|
|
}
|
|
#[get("/lists", rank=2)]
|
|
async fn show_list_not_logged_in() -> Redirect {
|
|
Redirect::to(uri!(home))
|
|
}
|
|
|
|
#[get("/new/list")]
|
|
async fn new_list_form(_user: User) -> Template {
|
|
Template::render("new_list", context!{})
|
|
}
|
|
#[get("/new/list", rank=2)]
|
|
async fn new_list_form_not_logged_in() -> Redirect {
|
|
Redirect::to(uri!(home))
|
|
}
|
|
#[get("/new/note/<list_uuid>")]
|
|
async fn new_note_form(mut db: Connection<Notes>, user: User, list_uuid: String) -> Result<Template> {
|
|
Ok(Template::render("new_note_form", context!{
|
|
list_uuid: list_uuid
|
|
}))
|
|
}
|
|
#[post("/note", data="<note>")]
|
|
async fn new_note(mut db: Connection<Notes>, user: User, note: Form<NewNoteForm<'_>>) -> Result<String> {
|
|
let list = match List::from_uuid(note.list_uuid.to_string(), &mut *db).await? {
|
|
Some(l) => l,
|
|
None => return Ok(format!("List not found!")),
|
|
};
|
|
match add_note_to_list(&mut *db, list.id, note.content.to_string(), user.id).await {
|
|
Ok(_) => Ok(format!("Added note!")),
|
|
Err(_) => Ok(format!("Error!"))
|
|
}
|
|
}
|
|
|
|
#[post("/perms", data="<perms>")]
|
|
async fn new_perms(perms: Form<PermsForm<'_>>, user: User, mut db: Connection<Notes>) -> Result<String> {
|
|
let perm_user = match get_user_from_email(&mut db, perms.user_email.to_string()).await? {
|
|
Some(u) => {
|
|
if u.id == user.id { return Ok(format!("You may not grant yourself a permission.")); } else { u }
|
|
},
|
|
None => return Ok(format!("Permission is added.")),
|
|
};
|
|
match add_permission(&mut db, perm_user.id, perms.list_id, perms.perm).await {
|
|
Err(_) => Ok(format!("There was an error adding this permission.")),
|
|
Ok(_) => Ok(format!("Permission is added.")),
|
|
}
|
|
}
|
|
#[post("/perms", data="<perms>", rank=2)]
|
|
async fn new_perms_not_logged_in(perms: Form<PermsForm<'_>>) -> Redirect {
|
|
Redirect::to(uri!(home))
|
|
}
|
|
|
|
#[get("/new/perms")]
|
|
async fn add_perms_form(mut db: Connection<Notes>, user: User) -> Result<Template> {
|
|
Ok(Template::render("new_perms", context!{
|
|
lists: get_user_lists(&mut db, user.id).await?
|
|
}))
|
|
}
|
|
#[get("/new/perms", rank=2)]
|
|
async fn add_perms_form_not_logged_in() -> Redirect {
|
|
Redirect::to(uri!(home))
|
|
}
|
|
|
|
#[get("/logout")]
|
|
async fn logout(mut db: Connection<Notes>, cookies: &CookieJar<'_>) -> Result<String> {
|
|
let uuid = cookies.get_private("user_uuid");
|
|
if uuid.is_none() {
|
|
return Ok(format!("You aren't logged in, lol!"));
|
|
}
|
|
cookies.remove_private(Cookie::named("user_uuid"));
|
|
let actual_uuid = uuid.unwrap();
|
|
let result = sqlx::query!("SELECT * FROM users WHERE uuid = $1", actual_uuid.value())
|
|
.fetch_optional(&mut *db)
|
|
.await?;
|
|
if let Some(user) = result {
|
|
Ok(format!("User '{}', logged out.", user.username))
|
|
} else {
|
|
Ok(format!("We don't know what happened..."))
|
|
}
|
|
}
|
|
|
|
#[get("/notes/<list_uuid>")]
|
|
async fn show_notes(user: User, mut db: Connection<Notes>, list_uuid: String) -> Result<Template> {
|
|
let list = match List::from_uuid(list_uuid, &mut *db).await? {
|
|
Some(list) => list,
|
|
None => panic!("LOL!"),
|
|
};
|
|
Ok(Template::render("show_notes", context!{
|
|
notes: get_notes_from_list(list.id, &mut *db).await?
|
|
}))
|
|
}
|
|
|
|
#[launch]
|
|
fn rocket() -> _ {
|
|
rocket::build()
|
|
.attach(Template::fairing())
|
|
.attach(Notes::init())
|
|
.mount("/", routes![
|
|
hello,
|
|
home,
|
|
login,
|
|
new_user,
|
|
create,
|
|
logout
|
|
])
|
|
.mount("/new", routes![
|
|
new_list, new_list_not_logged_in,
|
|
new_perms, new_perms_not_logged_in,
|
|
new_note, //new_note_not_logged_in,
|
|
])
|
|
.mount("/show", routes![
|
|
show_list, show_list_not_logged_in,
|
|
show_notes,
|
|
])
|
|
.mount("/forms", routes![
|
|
add_perms_form, add_perms_form_not_logged_in,
|
|
new_list_form, new_list_form_not_logged_in,
|
|
new_note_form,
|
|
])
|
|
}
|