forked from Ruderverein-Donau-Linz/rowt
add tests; add authentication cookie
This commit is contained in:
parent
38d757cf4a
commit
387d93bbaf
17
src/lib.rs
17
src/lib.rs
@ -1,2 +1,19 @@
|
||||
pub mod model;
|
||||
pub mod rest;
|
||||
|
||||
#[cfg(test)]
|
||||
#[macro_export]
|
||||
macro_rules! testdb {
|
||||
() => {{
|
||||
let pool = SqlitePool::connect(":memory:").await.unwrap();
|
||||
sqlx::query_file!("./migration.sql")
|
||||
.execute(&pool)
|
||||
.await
|
||||
.unwrap();
|
||||
sqlx::query_file!("./seeds.sql")
|
||||
.execute(&pool)
|
||||
.await
|
||||
.unwrap();
|
||||
pool
|
||||
}};
|
||||
}
|
||||
|
@ -1,8 +1,14 @@
|
||||
use argon2::{password_hash::SaltString, Argon2, PasswordHasher};
|
||||
use serde::Serialize;
|
||||
use rocket::{
|
||||
async_trait,
|
||||
http::Status,
|
||||
request::{self, FromRequest, Outcome},
|
||||
Request,
|
||||
};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use sqlx::{FromRow, SqlitePool};
|
||||
|
||||
#[derive(FromRow, Debug, Serialize)]
|
||||
#[derive(FromRow, Debug, Serialize, Deserialize)]
|
||||
pub struct User {
|
||||
id: i64,
|
||||
name: String,
|
||||
@ -16,6 +22,7 @@ pub struct User {
|
||||
pub enum LoginError {
|
||||
SqlxError(sqlx::Error),
|
||||
InvalidAuthenticationCombo,
|
||||
NotLoggedIn,
|
||||
}
|
||||
|
||||
impl From<sqlx::Error> for LoginError {
|
||||
@ -58,28 +65,31 @@ WHERE name like ?
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl<'r> FromRequest<'r> for User {
|
||||
type Error = LoginError;
|
||||
|
||||
async fn from_request(req: &'r Request<'_>) -> request::Outcome<Self, Self::Error> {
|
||||
match req.cookies().get_private("loggedin_user") {
|
||||
Some(user) => {
|
||||
let user: User = serde_json::from_str(&user.value()).unwrap(); //TODO: fixme
|
||||
Outcome::Success(user)
|
||||
}
|
||||
None => Outcome::Failure((Status::Unauthorized, LoginError::NotLoggedIn)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use crate::testdb;
|
||||
|
||||
use super::User;
|
||||
use sqlx::SqlitePool;
|
||||
|
||||
async fn setup() -> SqlitePool {
|
||||
let pool = SqlitePool::connect(":memory:").await.unwrap();
|
||||
sqlx::query_file!("./migration.sql")
|
||||
.execute(&pool)
|
||||
.await
|
||||
.unwrap();
|
||||
sqlx::query_file!("./seeds.sql")
|
||||
.execute(&pool)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
pool
|
||||
}
|
||||
|
||||
#[sqlx::test]
|
||||
fn succ_login_with_test_db() {
|
||||
let pool = setup().await;
|
||||
let pool = testdb!();
|
||||
User::login(&pool, "admin".into(), "admin".into())
|
||||
.await
|
||||
.unwrap();
|
||||
@ -87,7 +97,7 @@ mod test {
|
||||
|
||||
#[sqlx::test]
|
||||
fn wrong_pw() {
|
||||
let pool = setup().await;
|
||||
let pool = testdb!();
|
||||
assert!(User::login(&pool, "admin".into(), "admi".into())
|
||||
.await
|
||||
.is_err());
|
||||
@ -95,7 +105,7 @@ mod test {
|
||||
|
||||
#[sqlx::test]
|
||||
fn wrong_username() {
|
||||
let pool = setup().await;
|
||||
let pool = testdb!();
|
||||
assert!(User::login(&pool, "admi".into(), "admin".into())
|
||||
.await
|
||||
.is_err());
|
||||
|
@ -38,7 +38,7 @@ async fn login(
|
||||
) -> Flash<Redirect> {
|
||||
let user = User::login(db, login.name.clone(), login.password.clone()).await;
|
||||
|
||||
//TODO: be able to use for find_by_name. This would get rid of the following match clause.
|
||||
//TODO: be able to use ? for login. This would get rid of the following match clause.
|
||||
let user = match user {
|
||||
Ok(user) => user,
|
||||
Err(_) => {
|
||||
@ -47,7 +47,7 @@ async fn login(
|
||||
};
|
||||
|
||||
let user_json: String = format!("{}", json!(user));
|
||||
cookies.add_private(Cookie::new("user", user_json));
|
||||
cookies.add_private(Cookie::new("loggedin_user", user_json));
|
||||
|
||||
Flash::success(Redirect::to("/"), "Login erfolgreich")
|
||||
}
|
||||
|
@ -1,48 +1,51 @@
|
||||
use rocket::{get, routes, Build, Rocket};
|
||||
use rocket::{catch, catchers, get, response::Redirect, routes, Build, Rocket};
|
||||
use rocket_dyn_templates::{context, Template};
|
||||
use sqlx::SqlitePool;
|
||||
|
||||
use crate::model::user::User;
|
||||
|
||||
mod auth;
|
||||
|
||||
#[get("/")]
|
||||
fn index() -> Template {
|
||||
fn index(_user: User) -> Template {
|
||||
Template::render("index", context! {})
|
||||
}
|
||||
|
||||
#[catch(401)] //unauthorized
|
||||
fn unauthorized_error() -> Redirect {
|
||||
Redirect::to("/auth")
|
||||
}
|
||||
|
||||
pub fn start(db: SqlitePool) -> Rocket<Build> {
|
||||
rocket::build()
|
||||
.manage(db)
|
||||
.mount("/", routes![index])
|
||||
.mount("/auth", auth::routes())
|
||||
.register("/", catchers![unauthorized_error])
|
||||
.attach(Template::fairing())
|
||||
}
|
||||
|
||||
//#[cfg(test)]
|
||||
//mod test {
|
||||
// use super::start;
|
||||
// use rocket::http::Status;
|
||||
// use rocket::local::asynchronous::Client;
|
||||
// use rocket::uri;
|
||||
// use sqlx::SqlitePool;
|
||||
//
|
||||
// #[sqlx::test]
|
||||
// fn hello_world() {
|
||||
// let pool = SqlitePool::connect(":memory:").await.unwrap();
|
||||
// sqlx::query_file!("./migration.sql")
|
||||
// .execute(&pool)
|
||||
// .await
|
||||
// .unwrap();
|
||||
// sqlx::query_file!("./seeds.sql")
|
||||
// .execute(&pool)
|
||||
// .await
|
||||
// .unwrap();
|
||||
//
|
||||
// let client = Client::tracked(start())
|
||||
// .await
|
||||
// .expect("valid rocket instance");
|
||||
// let response = client.get(uri!(super::index)).dispatch().await;
|
||||
//
|
||||
// assert_eq!(response.status(), Status::Ok);
|
||||
// assert_eq!(response.into_string().await, Some("Hello, world!".into()));
|
||||
// }
|
||||
//}
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use crate::testdb;
|
||||
|
||||
use super::start;
|
||||
use rocket::http::Status;
|
||||
use rocket::local::asynchronous::Client;
|
||||
use rocket::uri;
|
||||
use sqlx::SqlitePool;
|
||||
|
||||
#[sqlx::test]
|
||||
fn test_not_logged_in() {
|
||||
let pool = testdb!();
|
||||
|
||||
let client = Client::tracked(start(pool))
|
||||
.await
|
||||
.expect("valid rocket instance");
|
||||
let response = client.get(uri!(super::index)).dispatch().await;
|
||||
|
||||
assert_eq!(response.status(), Status::SeeOther);
|
||||
let location = response.headers().get("Location").next().unwrap();
|
||||
assert_eq!(location, "/auth");
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user