Files
ImageApi/src/main.rs
Cameron Cordes 536300e0a1 Serving files is working
Right now we're not doing any streaming and this isn't ideal. I'll need
to figure it out at some point.
2020-07-08 21:38:21 -04:00

111 lines
3.0 KiB
Rust

#[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<CreateAccountRequest>) -> 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<LoginRequest>) -> 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<ThumbnailRequest>) -> 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<PathBuf> {
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<ThumbnailRequest>) -> 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
}