/* * tmtd - Suckless To Do list * Copyright (C) 2022 C4TG1RL5 * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ use crate::{database::Database, task, templates}; use actix_web::{http::StatusCode, web, HttpResponse, HttpResponseBuilder, HttpServer, Responder}; use askama::Template; use std::net::SocketAddr; use std::sync::Arc; pub struct App { pub server: actix_web::dev::Server, } impl App { pub async fn new(addr: SocketAddr, db: Arc) -> anyhow::Result { let db = db.clone(); let server = HttpServer::new(move || { actix_web::App::new().service(( web::resource("/").route(web::get().to(index)), web::resource("/users").route(web::get().to(users)), web::resource("/task") .app_data(web::Data::new(db.clone())) .route(web::get().to(tasks)), web::resource("/admin").route(web::get().to(admin)), web::resource("/create").route(web::get().to(create)), web::resource("/login").route(web::get().to(login)), web::resource("/register").route(web::get().to(register)), web::resource("/api/task/create") .app_data(web::Data::new(db.clone())) .route(web::post().to(create_task)), web::resource("/api/task/move") .app_data(web::Data::new(db.clone())) .route(web::post().to(move_task)), web::resource("/api/task/sort").route(web::post().to(sort_task)), web::resource("/api/login") .app_data(web::Data::new(db.clone())) .route(web::post().to(login_user)), web::resource("/api/register") .app_data(web::Data::new(db.clone())) .route(web::post().to(register_user)), )) }) .bind(addr)? .run(); Ok(App { server }) } } async fn index() -> impl Responder { let index = templates::Index {}; let html = index.render().unwrap(); HttpResponseBuilder::new(StatusCode::OK).body(html) } async fn tasks(db: web::Data>) -> impl Responder { let tasks = db.get_tasks(); let html = tasks.render().unwrap(); HttpResponseBuilder::new(StatusCode::OK).body(html) } async fn users() -> impl Responder { let users = templates::Users {}; let html = users.render().unwrap(); HttpResponseBuilder::new(StatusCode::OK).body(html) } async fn admin() -> impl Responder { let admin_panel = templates::AdminPanel {}; let html = admin_panel.render().unwrap(); HttpResponseBuilder::new(StatusCode::OK).body(html) } async fn create() -> impl Responder { let create = templates::CreateTask {}; let html = create.render().unwrap(); HttpResponseBuilder::new(StatusCode::OK).body(html) } async fn login() -> impl Responder { let login = templates::Login {}; let html = login.render().unwrap(); HttpResponseBuilder::new(StatusCode::OK).body(html) } async fn register() -> impl Responder { let register = templates::Register {}; let html = register.render().unwrap(); HttpResponseBuilder::new(StatusCode::OK).body(html) } async fn create_task( req: web::Form, db: web::Data>, ) -> impl Responder { tracing::debug!("Got POST request on /api/task/create: {:#?}", req); let db = db.clone(); let task = req.into_inner(); db.create_task(&task).await; HttpResponse::SeeOther() .insert_header(("Location", "/task")) .finish() } async fn move_task(req: web::Form, db: web::Data>) -> impl Responder { tracing::debug!("Got POST request on /api/task/move: {:#?}", req); let db = db.clone(); let task = req.into_inner(); db.move_task(&task).await; HttpResponse::SeeOther() .insert_header(("Location", "/task")) .finish() } async fn sort_task(req: web::Form) -> impl Responder { tracing::debug!("Got POST request on /api/task/sort: {:#?}", req); // TODO: save selected categories in a cookie or something HttpResponse::SeeOther() .insert_header(("Location", "/task")) .finish() } async fn login_user(req: web::Form, db: web::Data>) -> impl Responder { tracing::debug!("Got POST request on /api/login"); db.login(&req.username, &req.password).await; HttpResponse::SeeOther() .insert_header(("Location", "/task")) .finish() } async fn register_user( req: web::Form, db: web::Data>, ) -> impl Responder { tracing::debug!("Got POST request on /api/register"); let db = db.clone(); db.register(&req.username, &req.password).await; HttpResponse::SeeOther() .insert_header(("Location", "/task")) .finish() }