feat: implement basic authetication session
This commit is contained in:
parent
5807c00b2f
commit
36f4da1457
183
Cargo.lock
generated
183
Cargo.lock
generated
@ -30,7 +30,7 @@ dependencies = [
|
||||
"actix-service",
|
||||
"actix-utils",
|
||||
"ahash 0.8.3",
|
||||
"base64",
|
||||
"base64 0.21.2",
|
||||
"bitflags",
|
||||
"brotli",
|
||||
"bytes",
|
||||
@ -58,6 +58,22 @@ dependencies = [
|
||||
"zstd",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "actix-identity"
|
||||
version = "0.5.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1224c9f9593dc27c9077b233ce04adedc1d7febcfc35ee9f53ea3c24df180bec"
|
||||
dependencies = [
|
||||
"actix-service",
|
||||
"actix-session",
|
||||
"actix-utils",
|
||||
"actix-web",
|
||||
"anyhow",
|
||||
"futures-core",
|
||||
"serde",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "actix-macros"
|
||||
version = "0.2.3"
|
||||
@ -120,6 +136,23 @@ dependencies = [
|
||||
"pin-project-lite",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "actix-session"
|
||||
version = "0.7.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "43da8b818ae1f11049a4d218975345fe8e56ce5a5f92c11f972abcff5ff80e87"
|
||||
dependencies = [
|
||||
"actix-service",
|
||||
"actix-utils",
|
||||
"actix-web",
|
||||
"anyhow",
|
||||
"async-trait",
|
||||
"derive_more",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "actix-utils"
|
||||
version = "3.0.1"
|
||||
@ -189,6 +222,41 @@ version = "1.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
|
||||
|
||||
[[package]]
|
||||
name = "aead"
|
||||
version = "0.5.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d122413f284cf2d62fb1b7db97e02edb8cda96d769b16e443a4f6195e35662b0"
|
||||
dependencies = [
|
||||
"crypto-common",
|
||||
"generic-array",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "aes"
|
||||
version = "0.8.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ac1f845298e95f983ff1944b728ae08b8cebab80d684f0a832ed0fc74dfa27e2"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"cipher",
|
||||
"cpufeatures",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "aes-gcm"
|
||||
version = "0.10.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "209b47e8954a928e1d72e86eca7000ebb6655fe1436d33eefc2201cad027e237"
|
||||
dependencies = [
|
||||
"aead",
|
||||
"aes",
|
||||
"cipher",
|
||||
"ctr",
|
||||
"ghash",
|
||||
"subtle",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ahash"
|
||||
version = "0.7.6"
|
||||
@ -408,6 +476,17 @@ version = "4.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ecc7ab41815b3c653ccd2978ec3255c81349336702dfdf62ee6f7069b12a3aae"
|
||||
|
||||
[[package]]
|
||||
name = "async-trait"
|
||||
version = "0.1.69"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7b2d0f03b3640e3a630367e40c468cb7f309529c708ed1d88597047b0e7c6ef7"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.18",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "atoi"
|
||||
version = "1.0.0"
|
||||
@ -429,6 +508,12 @@ version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
|
||||
|
||||
[[package]]
|
||||
name = "base64"
|
||||
version = "0.20.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0ea22880d78093b0cbe17c89f64a7d457941e65759157ec6cb31a31d652b05e5"
|
||||
|
||||
[[package]]
|
||||
name = "base64"
|
||||
version = "0.21.2"
|
||||
@ -493,6 +578,8 @@ dependencies = [
|
||||
name = "brass"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"actix-identity",
|
||||
"actix-session",
|
||||
"actix-web",
|
||||
"anyhow",
|
||||
"argon2",
|
||||
@ -565,6 +652,16 @@ version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
|
||||
[[package]]
|
||||
name = "cipher"
|
||||
version = "0.4.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad"
|
||||
dependencies = [
|
||||
"crypto-common",
|
||||
"inout",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "concurrent-queue"
|
||||
version = "2.2.0"
|
||||
@ -586,7 +683,14 @@ version = "0.16.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e859cd57d0710d9e06c381b550c06e76992472a8c6d527aecd2fc673dcc231fb"
|
||||
dependencies = [
|
||||
"aes-gcm",
|
||||
"base64 0.20.0",
|
||||
"hkdf",
|
||||
"hmac",
|
||||
"percent-encoding",
|
||||
"rand",
|
||||
"sha2",
|
||||
"subtle",
|
||||
"time",
|
||||
"version_check",
|
||||
]
|
||||
@ -650,9 +754,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3"
|
||||
dependencies = [
|
||||
"generic-array",
|
||||
"rand_core",
|
||||
"typenum",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ctr"
|
||||
version = "0.9.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0369ee1ad671834580515889b80f2ea915f23b8be8d0daa4bbaf2ac5c7590835"
|
||||
dependencies = [
|
||||
"cipher",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "derive_more"
|
||||
version = "0.99.17"
|
||||
@ -894,6 +1008,16 @@ dependencies = [
|
||||
"wasi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ghash"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d930750de5717d2dd0b8c0d42c076c0e884c81a73e6cab859bbd2339c71e3e40"
|
||||
dependencies = [
|
||||
"opaque-debug",
|
||||
"polyval",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gloo-timers"
|
||||
version = "0.2.6"
|
||||
@ -979,6 +1103,24 @@ version = "0.4.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
|
||||
|
||||
[[package]]
|
||||
name = "hkdf"
|
||||
version = "0.12.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "791a029f6b9fc27657f6f188ec6e5e43f6911f6f878e0dc5501396e09809d437"
|
||||
dependencies = [
|
||||
"hmac",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hmac"
|
||||
version = "0.12.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e"
|
||||
dependencies = [
|
||||
"digest",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "http"
|
||||
version = "0.2.9"
|
||||
@ -1031,6 +1173,15 @@ dependencies = [
|
||||
"hashbrown 0.12.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "inout"
|
||||
version = "0.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a0c10553d664a4d0bcff9f4215d0aac67a639cc68ef660840afe309b807bc9f5"
|
||||
dependencies = [
|
||||
"generic-array",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "instant"
|
||||
version = "0.1.12"
|
||||
@ -1249,6 +1400,12 @@ version = "1.18.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d"
|
||||
|
||||
[[package]]
|
||||
name = "opaque-debug"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5"
|
||||
|
||||
[[package]]
|
||||
name = "parking"
|
||||
version = "2.1.0"
|
||||
@ -1380,6 +1537,18 @@ dependencies = [
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "polyval"
|
||||
version = "0.6.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d52cff9d1d4dee5fe6d03729099f4a310a41179e0a10dbf542039873f2e826fb"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"cpufeatures",
|
||||
"opaque-debug",
|
||||
"universal-hash",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ppv-lite86"
|
||||
version = "0.2.17"
|
||||
@ -1525,7 +1694,7 @@ version = "1.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d194b56d58803a43635bdc398cd17e383d6f71f9182b9a192c127ca42494a59b"
|
||||
dependencies = [
|
||||
"base64",
|
||||
"base64 0.21.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -1975,6 +2144,16 @@ version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "39ec24b3121d976906ece63c9daad25b85969647682eee313cb5779fdd69e14e"
|
||||
|
||||
[[package]]
|
||||
name = "universal-hash"
|
||||
version = "0.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fc1de2c688dc15305988b563c3854064043356019f97a4b46276fe734c4f07ea"
|
||||
dependencies = [
|
||||
"crypto-common",
|
||||
"subtle",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "untrusted"
|
||||
version = "0.7.1"
|
||||
|
@ -10,6 +10,8 @@ sqlx = { version = "0.6", features = [ "runtime-async-std-rustls", "sqlite" ] }
|
||||
actix-web = { version = "4" }
|
||||
askama = "0.12.0"
|
||||
serde = { version = "1.0.164", features = [ "derive"]}
|
||||
argon2 = "0.5.0"
|
||||
argon2 = { version = "0.5.0", features = [ "std"]}
|
||||
anyhow = "1.0.71"
|
||||
dotenv = "0.15.0"
|
||||
actix-session = { version = "0.7.2", features = ["cookie-session"] }
|
||||
actix-identity = "0.5.2"
|
||||
|
@ -9,9 +9,10 @@ INSERT OR REPLACE INTO roles(id, definition) values(2, "Administrator");
|
||||
|
||||
CREATE TABLE IF NOT EXISTS users
|
||||
(
|
||||
id INTEGER PRIMARY KEY NOT NULL,
|
||||
name TEXT NOT NULL,
|
||||
password TEXT NOT NULL,
|
||||
role INTEGER NOT NULL,
|
||||
FOREIGN KEY(role) REFERENCES roles(roleId)
|
||||
id INTEGER PRIMARY KEY NOT NULL,
|
||||
name TEXT NOT NULL,
|
||||
password_hash TEXT NOT NULL,
|
||||
salt TEXT NOT NULL,
|
||||
role_id INTEGER NOT NULL,
|
||||
FOREIGN KEY(role_id) REFERENCES roles(id)
|
||||
);
|
||||
|
@ -1,74 +0,0 @@
|
||||
use actix_web::{Responder, web, HttpResponse};
|
||||
use askama::Template;
|
||||
use serde::Deserialize;
|
||||
use sqlx::sqlite::SqlitePool;
|
||||
|
||||
use crate::auth::utils::hash_plain_password;
|
||||
use crate::models::Role;
|
||||
|
||||
pub fn init(cfg: &mut web::ServiceConfig) {
|
||||
cfg.service(get_login);
|
||||
cfg.service(post_login);
|
||||
cfg.service(get_register);
|
||||
cfg.service(post_register);
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
struct LoginForm {
|
||||
name: String,
|
||||
password: String
|
||||
}
|
||||
|
||||
#[derive(Template)]
|
||||
#[template(path = "login.html")]
|
||||
struct LoginTemplate {
|
||||
}
|
||||
|
||||
#[derive(Template)]
|
||||
#[template(path = "register.html")]
|
||||
struct RegisterTemplate {
|
||||
roles: Vec<Role>
|
||||
}
|
||||
|
||||
#[actix_web::get("/login")]
|
||||
async fn get_login() -> impl Responder {
|
||||
let bla = LoginTemplate {};
|
||||
|
||||
HttpResponse::Ok()
|
||||
.body(bla.render().unwrap())
|
||||
}
|
||||
|
||||
#[actix_web::post("/login")]
|
||||
async fn post_login(web::Form(form): web::Form<LoginForm>) -> impl Responder {
|
||||
println!("{} - {}", form.name, form.password);
|
||||
|
||||
let hash = hash_plain_password(&form.password);
|
||||
|
||||
println!("{hash}");
|
||||
|
||||
"dfgdg"
|
||||
}
|
||||
|
||||
#[actix_web::get("/register")]
|
||||
async fn get_register(pool: web::Data<SqlitePool>) -> impl Responder {
|
||||
let roles = match Role::GetAll(pool.get_ref()).await {
|
||||
Ok(value) => value,
|
||||
Err(error) => return HttpResponse::InternalServerError().body(error.to_string())
|
||||
};
|
||||
|
||||
let bla = RegisterTemplate { roles };
|
||||
|
||||
HttpResponse::Ok()
|
||||
.body(bla.render().unwrap())
|
||||
}
|
||||
|
||||
#[actix_web::post("/register")]
|
||||
async fn post_register(web::Form(form): web::Form<LoginForm>) -> impl Responder {
|
||||
println!("{} - {}", form.name, form.password);
|
||||
|
||||
let hash = hash_plain_password(&form.password);
|
||||
|
||||
println!("{hash}");
|
||||
|
||||
"dfgdg"
|
||||
}
|
20
src/auth/routes/get_login.rs
Normal file
20
src/auth/routes/get_login.rs
Normal file
@ -0,0 +1,20 @@
|
||||
use actix_identity::Identity;
|
||||
use actix_web::{Responder, HttpResponse, http::header::LOCATION};
|
||||
use askama::Template;
|
||||
|
||||
#[derive(Template)]
|
||||
#[template(path = "login.html")]
|
||||
struct LoginTemplate {}
|
||||
|
||||
#[actix_web::get("/login")]
|
||||
async fn route(user: Option<Identity>) -> impl Responder {
|
||||
if let Some(_) = user {
|
||||
return HttpResponse::PermanentRedirect()
|
||||
.insert_header((LOCATION, "/"))
|
||||
.finish();
|
||||
} else {
|
||||
let bla = LoginTemplate {};
|
||||
|
||||
return HttpResponse::Ok().body(bla.render().unwrap());
|
||||
}
|
||||
}
|
23
src/auth/routes/get_register.rs
Normal file
23
src/auth/routes/get_register.rs
Normal file
@ -0,0 +1,23 @@
|
||||
use actix_web::{web, HttpResponse, Responder};
|
||||
use askama::Template;
|
||||
use sqlx::SqlitePool;
|
||||
|
||||
use crate::models::Role;
|
||||
|
||||
#[derive(Template)]
|
||||
#[template(path = "register.html")]
|
||||
struct RegisterTemplate {
|
||||
roles: Vec<Role>,
|
||||
}
|
||||
|
||||
#[actix_web::get("/register")]
|
||||
async fn route(pool: web::Data<SqlitePool>) -> impl Responder {
|
||||
let roles = match Role::GetAll(pool.get_ref()).await {
|
||||
Ok(value) => value,
|
||||
Err(error) => return HttpResponse::InternalServerError().body(error.to_string()),
|
||||
};
|
||||
|
||||
let bla = RegisterTemplate { roles };
|
||||
|
||||
HttpResponse::Ok().body(bla.render().unwrap())
|
||||
}
|
13
src/auth/routes/mod.rs
Normal file
13
src/auth/routes/mod.rs
Normal file
@ -0,0 +1,13 @@
|
||||
mod get_login;
|
||||
mod get_register;
|
||||
mod post_login;
|
||||
mod post_register;
|
||||
|
||||
use actix_web::web;
|
||||
|
||||
pub fn init(cfg: &mut web::ServiceConfig) {
|
||||
cfg.service(self::get_login::route);
|
||||
cfg.service(self::post_login::route);
|
||||
cfg.service(self::get_register::route);
|
||||
cfg.service(self::post_register::route);
|
||||
}
|
34
src/auth/routes/post_login.rs
Normal file
34
src/auth/routes/post_login.rs
Normal file
@ -0,0 +1,34 @@
|
||||
use actix_identity::Identity;
|
||||
use actix_web::{web, HttpMessage, HttpRequest, HttpResponse, Responder};
|
||||
use serde::Deserialize;
|
||||
use sqlx::SqlitePool;
|
||||
|
||||
use crate::{auth::utils::hash_plain_password_with_salt, models::user::User};
|
||||
|
||||
#[derive(Deserialize)]
|
||||
struct LoginForm {
|
||||
name: String,
|
||||
password: String,
|
||||
}
|
||||
|
||||
#[actix_web::post("/login")]
|
||||
async fn route(
|
||||
web::Form(form): web::Form<LoginForm>,
|
||||
request: HttpRequest,
|
||||
pool: web::Data<SqlitePool>,
|
||||
) -> impl Responder {
|
||||
match User::read_by_name(pool.get_ref(), &form.name).await {
|
||||
Some(potential_user) => {
|
||||
let hash = hash_plain_password_with_salt(&form.password, &potential_user.salt).unwrap();
|
||||
|
||||
if hash == potential_user.password_hash {
|
||||
Identity::login(&request.extensions(), potential_user.id.to_string());
|
||||
|
||||
return HttpResponse::Ok().body("Angemeldet!");
|
||||
} else {
|
||||
return HttpResponse::Unauthorized().body("Nutzername oder Passwort falsch.");
|
||||
}
|
||||
}
|
||||
None => return HttpResponse::Unauthorized().body("Nutzername oder Passwort falsch."),
|
||||
}
|
||||
}
|
31
src/auth/routes/post_register.rs
Normal file
31
src/auth/routes/post_register.rs
Normal file
@ -0,0 +1,31 @@
|
||||
use actix_web::{http::header::LOCATION, web, HttpResponse, Responder};
|
||||
use serde::Deserialize;
|
||||
use sqlx::SqlitePool;
|
||||
|
||||
use crate::{auth::utils::generate_salt_and_hash_plain_password, models::user::User};
|
||||
|
||||
#[derive(Deserialize)]
|
||||
struct RegisterForm {
|
||||
name: String,
|
||||
password: String,
|
||||
role: i64,
|
||||
}
|
||||
|
||||
#[actix_web::post("/register")]
|
||||
async fn route(
|
||||
web::Form(form): web::Form<RegisterForm>,
|
||||
pool: web::Data<SqlitePool>,
|
||||
) -> impl Responder {
|
||||
let (hash, salt) = generate_salt_and_hash_plain_password(&form.password).unwrap();
|
||||
|
||||
let result = User::create(pool.get_ref(), form.name, hash, salt, form.role).await;
|
||||
|
||||
match result {
|
||||
Ok(_) => {
|
||||
return HttpResponse::PermanentRedirect()
|
||||
.insert_header((LOCATION, "/"))
|
||||
.finish()
|
||||
}
|
||||
Err(err) => return HttpResponse::BadRequest().body(err.to_string()),
|
||||
}
|
||||
}
|
@ -1,20 +1,25 @@
|
||||
use argon2::{
|
||||
password_hash::{rand_core::OsRng, PasswordHash, PasswordHasher, SaltString},
|
||||
password_hash::{rand_core::OsRng, PasswordHasher, SaltString},
|
||||
Argon2,
|
||||
};
|
||||
|
||||
pub fn hash_plain_password(plain: &str) -> String {
|
||||
pub fn generate_salt_and_hash_plain_password(plain: &str) -> anyhow::Result<(String, String)> {
|
||||
let salt = SaltString::generate(&mut OsRng);
|
||||
|
||||
// Argon2 with default params (Argon2id v19)
|
||||
Argon2::default()
|
||||
.hash_password(plain.as_bytes(), &salt)
|
||||
.unwrap()
|
||||
.to_string()
|
||||
let hash = Argon2::default()
|
||||
.hash_password(plain.as_bytes(), &salt)?
|
||||
.to_string();
|
||||
|
||||
// Verify password against PHC string.
|
||||
//
|
||||
// NOTE: hash params from `parsed_hash` are used instead of what is configured in the
|
||||
// `Argon2` instance.
|
||||
// PasswordHash::new(&password_hash).unwrap().to_string()
|
||||
Ok((hash, salt.to_string()))
|
||||
}
|
||||
|
||||
pub fn hash_plain_password_with_salt(plain: &str, salt_string: &str) -> anyhow::Result<String> {
|
||||
let salt = SaltString::from_b64(salt_string)?;
|
||||
|
||||
let hash = Argon2::default()
|
||||
.hash_password(plain.as_bytes(), &salt)?
|
||||
.to_string();
|
||||
|
||||
Ok(hash)
|
||||
}
|
||||
|
3
src/calendar/mod.rs
Normal file
3
src/calendar/mod.rs
Normal file
@ -0,0 +1,3 @@
|
||||
pub mod routes;
|
||||
|
||||
pub use routes::init;
|
12
src/calendar/routes.rs
Normal file
12
src/calendar/routes.rs
Normal file
@ -0,0 +1,12 @@
|
||||
use actix_identity::Identity;
|
||||
use actix_web::{Responder, web, HttpResponse};
|
||||
|
||||
pub fn init(cfg: &mut web::ServiceConfig) {
|
||||
cfg.service(get_login);
|
||||
}
|
||||
|
||||
#[actix_web::get("/")]
|
||||
async fn get_login(user: Identity) -> impl Responder {
|
||||
|
||||
HttpResponse::Ok().body("Hierfür muss man angemeldet sein!")
|
||||
}
|
21
src/main.rs
21
src/main.rs
@ -1,21 +1,34 @@
|
||||
use std::env;
|
||||
|
||||
use actix_web::{App, HttpServer, web};
|
||||
use sqlx::sqlite::SqlitePool;
|
||||
use actix_identity::IdentityMiddleware;
|
||||
use actix_session::{storage::CookieSessionStore, SessionMiddleware};
|
||||
use actix_web::cookie::Key;
|
||||
use actix_web::{web, App, HttpServer};
|
||||
use dotenv::dotenv;
|
||||
use sqlx::sqlite::SqlitePool;
|
||||
|
||||
mod auth;
|
||||
mod calendar;
|
||||
mod models;
|
||||
|
||||
#[actix_web::main]
|
||||
async fn main() -> anyhow::Result<()> {
|
||||
dotenv()?;
|
||||
let pool = SqlitePool::connect(&env::var("DATABASE_URL")?).await?;
|
||||
let secret_key = Key::generate();
|
||||
|
||||
println!("Starting server on http://localhost:8080.");
|
||||
|
||||
HttpServer::new(move || {
|
||||
App::new()
|
||||
.app_data(web::Data::new(pool.clone()))
|
||||
.configure(auth::init)
|
||||
.app_data(web::Data::new(pool.clone()))
|
||||
.configure(auth::init)
|
||||
.configure(calendar::init)
|
||||
.wrap(IdentityMiddleware::default())
|
||||
.wrap(SessionMiddleware::new(
|
||||
CookieSessionStore::default(),
|
||||
secret_key.clone(),
|
||||
))
|
||||
})
|
||||
.bind(("127.0.0.1", 8080))?
|
||||
.run()
|
||||
|
@ -1,3 +1,5 @@
|
||||
pub mod user;
|
||||
|
||||
use sqlx::sqlite::SqlitePool;
|
||||
|
||||
pub struct Role {
|
||||
|
81
src/models/user.rs
Normal file
81
src/models/user.rs
Normal file
@ -0,0 +1,81 @@
|
||||
use sqlx::sqlite::SqlitePool;
|
||||
|
||||
pub struct User {
|
||||
pub id: i64,
|
||||
pub name: String,
|
||||
pub password_hash: String,
|
||||
pub salt: String,
|
||||
pub role_id: i64,
|
||||
}
|
||||
|
||||
impl User {
|
||||
pub async fn create(
|
||||
pool: &SqlitePool,
|
||||
name: String,
|
||||
password_hash: String,
|
||||
salt: String,
|
||||
role_id: i64,
|
||||
) -> anyhow::Result<i64> {
|
||||
let created = sqlx::query!(
|
||||
r#"
|
||||
INSERT INTO users (name, password_hash, salt, role_id)
|
||||
VALUES (?1, ?2, ?3, ?4);
|
||||
"#,
|
||||
name,
|
||||
password_hash,
|
||||
salt,
|
||||
role_id
|
||||
)
|
||||
.execute(pool)
|
||||
.await;
|
||||
|
||||
match created {
|
||||
Ok(result) => Ok(result.last_insert_rowid()),
|
||||
Err(err) => Err(err.into()),
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn read_by_id(pool: &SqlitePool, id: i64) -> Option<User> {
|
||||
let record = sqlx::query_as!(
|
||||
User,
|
||||
r#"
|
||||
SELECT *
|
||||
FROM users
|
||||
WHERE id = ?1;
|
||||
"#,
|
||||
id,
|
||||
)
|
||||
.fetch_one(pool)
|
||||
.await;
|
||||
|
||||
match record {
|
||||
Ok(record) => Some(record),
|
||||
Err(err) => {
|
||||
println!("User.read({id}): {err}");
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn read_by_name(pool: &SqlitePool, name: &str) -> Option<User> {
|
||||
let record = sqlx::query_as!(
|
||||
User,
|
||||
r#"
|
||||
SELECT *
|
||||
FROM users
|
||||
WHERE name = ?1;
|
||||
"#,
|
||||
name
|
||||
)
|
||||
.fetch_one(pool)
|
||||
.await;
|
||||
|
||||
match record {
|
||||
Ok(record) => Some(record),
|
||||
Err(err) => {
|
||||
println!("User.read({name}): {err}");
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user