#[macro_use] extern crate diesel; use actix_files::NamedFile; use actix_web::web::{HttpResponse, HttpRequest, 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::data::{Claims, CreateAccountRequest, Token}; use crate::database::{create_user, get_user, user_exists}; use crate::files::list_files; mod data; mod database; mod files; #[post("/register")] async fn register(user: Json) -> impl Responder { if !user.username.is_empty() && user.password.len() > 5 && user.password == user.confirmation { if user_exists(&user.username) { HttpResponse::BadRequest() } else if let Some(_user) = create_user(&user.username, &user.password) { HttpResponse::Ok() } else { HttpResponse::InternalServerError() } } else { HttpResponse::BadRequest() } } #[post("/login")] async fn login(creds: Json) -> impl Responder { if let Some(user) = get_user(&creds.username, &creds.password) { let claims = Claims { sub: user.id.to_string(), exp: (Utc::now() + Duration::days(3)).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(_claims: Claims, req: Json) -> impl Responder { println!("{}", req.path); let path = &req.path; if let Some(path) = is_valid_path(path) { let files = list_files(path); HttpResponse::Ok().json(files.unwrap_or_default()) } else { HttpResponse::BadRequest().finish() } } fn is_valid_path(path: &str) -> Option { match path { path if path.contains("..") => None, path => { let path = PathBuf::from(path); if path.is_relative() { let mut full_path = PathBuf::from(dotenv::var("BASE_PATH").unwrap()); full_path.push(path); Some(full_path) } else { None } } } } #[get("/image")] async fn image(_claims: Claims, request: HttpRequest, req: Json) -> impl Responder { if let Some(path) = is_valid_path(&req.path) { if let Ok(file) = NamedFile::open(path) { file.into_response(&request).unwrap() } else { HttpResponse::NotFound().finish() } } else { HttpResponse::NotFound().finish() } } #[actix_rt::main] async fn main() -> std::io::Result<()> { HttpServer::new(|| { App::new() .service(login) .service(list_photos) .service(register) .service(image) }) .bind("127.0.0.1:8088")? .run() .await }