diff --git a/Cargo.lock b/Cargo.lock index f6e5c6f..d9283ec 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -379,13 +379,34 @@ version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" +[[package]] +name = "block-buffer" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0940dc441f31689269e10ac70eb1002a3a1d3ad1390e030043662eb7fe4688b" +dependencies = [ + "block-padding", + "byte-tools", + "byteorder", + "generic-array 0.12.3", +] + [[package]] name = "block-cipher" version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fa136449e765dc7faa244561ccae839c394048667929af599b5d931ebe7b7f10" dependencies = [ - "generic-array", + "generic-array 0.14.2", +] + +[[package]] +name = "block-padding" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa79dedbb091f449f1f39e53edf88d5dbe95f895dae6135a8d7b881fb5af73f5" +dependencies = [ + "byte-tools", ] [[package]] @@ -425,6 +446,12 @@ version = "3.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2e8c087f005730276d1096a652e92a8bacee2e2472bcc9715a74d2bec38b5820" +[[package]] +name = "byte-tools" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" + [[package]] name = "byteorder" version = "1.3.4" @@ -496,6 +523,16 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "crypto-mac" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4434400df11d95d556bac068ddfedd482915eb18fe8bea89bc80b6e4b1c179e5" +dependencies = [ + "generic-array 0.12.3", + "subtle", +] + [[package]] name = "derive_more" version = "0.99.9" @@ -529,6 +566,15 @@ dependencies = [ "syn", ] +[[package]] +name = "digest" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3d0c8c8752312f9713efd397ff63acb9f85585afbf179282e720e7704954dd5" +dependencies = [ + "generic-array 0.12.3", +] + [[package]] name = "dotenv" version = "0.15.0" @@ -590,6 +636,12 @@ dependencies = [ "synstructure", ] +[[package]] +name = "fake-simd" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" + [[package]] name = "flate2" version = "1.0.16" @@ -741,6 +793,15 @@ dependencies = [ "winapi 0.3.9", ] +[[package]] +name = "generic-array" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c68f0274ae0e023facc3c97b2e00f076be70e254bc851d972503b328db79b2ec" +dependencies = [ + "typenum", +] + [[package]] name = "generic-array" version = "0.14.2" @@ -805,6 +866,16 @@ dependencies = [ "libc", ] +[[package]] +name = "hmac" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5dcb5e64cda4c23119ab41ba960d1e170a774c8e4b9d9e6a9bc18aabf5e59695" +dependencies = [ + "crypto-mac", + "digest", +] + [[package]] name = "hostname" version = "0.3.1" @@ -851,12 +922,15 @@ dependencies = [ "actix-rt", "actix-web", "bcrypt", + "chrono", "diesel", "dotenv", "futures", + "hmac", "jsonwebtoken", "serde", "serde_json", + "sha2", ] [[package]] @@ -1461,6 +1535,18 @@ version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2579985fda508104f7587689507983eadd6a6e84dd35d6d115361f530916fa0d" +[[package]] +name = "sha2" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a256f46ea78a0c0d9ff00077504903ac881a1dafdc20da66545699e7776b3e69" +dependencies = [ + "block-buffer", + "digest", + "fake-simd", + "opaque-debug", +] + [[package]] name = "signal-hook-registry" version = "1.2.0" @@ -1512,6 +1598,12 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" +[[package]] +name = "subtle" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d67a5a62ba6e01cb2192ff309324cb4875d0c451d55fe2319433abe7a05a8ee" + [[package]] name = "syn" version = "1.0.33" diff --git a/Cargo.toml b/Cargo.toml index 3b955e0..19c5a76 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,5 +14,8 @@ jsonwebtoken = "7.2.0" serde = "1.0" serde_json = "1.0" diesel = { version = "1.4.4", features = ["sqlite"] } +hmac = "0.7.1" +sha2 = "0.8.2" +chrono = "0.4.11" dotenv = "0.15" bcrypt = "0.8.1" diff --git a/src/data/mod.rs b/src/data/mod.rs index eba0bd6..44f4d0a 100644 --- a/src/data/mod.rs +++ b/src/data/mod.rs @@ -2,31 +2,42 @@ use actix_web::error::ErrorUnauthorized; use actix_web::{dev, http::header, Error, FromRequest, HttpRequest}; use futures::future::{err, ok, Ready}; use jsonwebtoken::{decode, Algorithm, DecodingKey, Validation}; -use serde::Deserialize; +use serde::{Deserialize, Serialize}; use std::str::FromStr; -#[derive(Deserialize)] +#[derive(Serialize)] +pub struct Token<'a> { + pub token: &'a str, +} + +#[derive(Deserialize, Serialize)] pub struct Claims { pub sub: String, - pub exp: u32, + pub exp: i64, } impl FromStr for Claims { type Err = jsonwebtoken::errors::Error; fn from_str(s: &str) -> Result { - println!("Parsing token: {}", s); + let token = *(s + .split("Bearer ") + .collect::>() + .last() + .unwrap_or(&"")); + println!("Parsing token: '{}'", token); - let claims = match decode::( - s, + match decode::( + &token, &DecodingKey::from_secret("secret_token".as_ref()), &Validation::new(Algorithm::HS256), ) { Ok(data) => Ok(data.claims), - Err(other) => Err(other), - }; - - return claims; + Err(other) => { + println!("DecodeError: {}", other); + Err(other) + } + } } } diff --git a/src/database/mod.rs b/src/database/mod.rs index e8c5cbe..f345735 100644 --- a/src/database/mod.rs +++ b/src/database/mod.rs @@ -50,7 +50,7 @@ pub fn get_user(user: &str, pass: &str) -> Option { match users .filter(username.eq(user)) .load::(&connect()) - .unwrap_or(Vec::::new()) + .unwrap_or_default() .first() { Some(u) if verify(pass, &u.password).unwrap_or(false) => Some(u.clone()), diff --git a/src/files.rs b/src/files.rs index 6907d1a..cfdf444 100644 --- a/src/files.rs +++ b/src/files.rs @@ -25,9 +25,9 @@ fn is_image_or_video(path: &Path) -> bool { .unwrap_or_else(|| "") .to_lowercase(); - return extension == &"png" - || extension == &"jpg" - || extension == &"jpeg" - || extension == &"rs" - || extension == &"mp4"; + extension == "png" + || extension == "jpg" + || extension == "jpeg" + || extension == "rs" + || extension == "mp4" } diff --git a/src/main.rs b/src/main.rs index 2d6f04c..88b8e82 100644 --- a/src/main.rs +++ b/src/main.rs @@ -3,11 +3,14 @@ extern crate diesel; use actix_web::web::{HttpResponse, Json}; use actix_web::{get, post, App, HttpServer, Responder}; +use chrono::{Duration, Utc}; use data::{LoginRequest, ThumbnailRequest}; +use jsonwebtoken::{encode, EncodingKey, Header}; use std::path::PathBuf; -use crate::files::list_files; +use crate::data::{Claims, Token}; use crate::database::{create_user, get_user}; +use crate::files::list_files; mod data; mod database; @@ -23,14 +26,24 @@ async fn register() -> impl Responder { #[post("/login")] async fn login(creds: Json) -> impl Responder { if let Some(user) = get_user(&creds.username, &creds.password) { - HttpResponse::Ok().json(user) + let claims = Claims { + sub: user.id.to_string(), + exp: (Utc::now() + Duration::seconds(30)).timestamp(), + }; + let token = encode( + &Header::default(), + &claims, + &EncodingKey::from_secret("secret_token".as_ref()), + ) + .unwrap(); + HttpResponse::Ok().json(Token { token: &token }) } else { HttpResponse::NotFound().finish() } } #[get("/photos")] -async fn list_photos(req: Json) -> impl Responder { +async fn list_photos(_claims: Claims, req: Json) -> impl Responder { println!("{}", req.path); let path = &req.path; @@ -54,8 +67,13 @@ async fn list_photos(req: Json) -> impl Responder { #[actix_rt::main] async fn main() -> std::io::Result<()> { - HttpServer::new(|| App::new().service(login).service(list_photos).service(register)) - .bind("127.0.0.1:8088")? - .run() - .await + HttpServer::new(|| { + App::new() + .service(login) + .service(list_photos) + .service(register) + }) + .bind("127.0.0.1:8088")? + .run() + .await }