/* * 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("/") .app_data(web::Data::new(db.clone())) .route(web::get().to(index)), web::resource("/users") .app_data(web::Data::new(db.clone())) .route(web::get().to(users)), web::resource("/task") .app_data(web::Data::new(db.clone())) .route(web::get().to(tasks)), web::resource("/admin") .app_data(web::Data::new(db.clone())) .route(web::get().to(admin)), web::resource("/create") .app_data(web::Data::new(db.clone())) .route(web::get().to(create)), web::resource("/login") .app_data(web::Data::new(db.clone())) .route(web::get().to(login)), web::resource("/register") .app_data(web::Data::new(db.clone())) .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)), web::resource("/api/logout") .app_data(web::Data::new(db.clone())) .route(web::get().to(logout)), )) }) .bind(addr)? .run(); Ok(App { server }) } } async fn index(db: web::Data>) -> impl Responder { let logged_in = db.logged_in().await; let index = templates::Index { logged_in }; let html = index.render().unwrap(); HttpResponseBuilder::new(StatusCode::OK).body(html) } async fn tasks(db: web::Data>) -> impl Responder { let tasks = db.get_tasks().await; let html = tasks.render().unwrap(); HttpResponseBuilder::new(StatusCode::OK).body(html) } async fn users(db: web::Data>) -> impl Responder { let logged_in = db.logged_in().await; let users = templates::Users { logged_in }; let html = users.render().unwrap(); HttpResponseBuilder::new(StatusCode::OK).body(html) } async fn admin(db: web::Data>) -> impl Responder { let logged_in = db.logged_in().await; let admin_panel = templates::AdminPanel { logged_in }; let html = admin_panel.render().unwrap(); HttpResponseBuilder::new(StatusCode::OK).body(html) } async fn create(db: web::Data>) -> impl Responder { let logged_in = db.logged_in().await; let create = templates::CreateTask { logged_in }; let html = create.render().unwrap(); HttpResponseBuilder::new(StatusCode::OK).body(html) } async fn login(db: web::Data>) -> impl Responder { let logged_in = db.logged_in().await; let login = templates::Login { logged_in }; let html = login.render().unwrap(); HttpResponseBuilder::new(StatusCode::OK).body(html) } async fn register(db: web::Data>) -> impl Responder { let logged_in = db.logged_in().await; let register = templates::Register { logged_in }; let html = register.render().unwrap(); HttpResponseBuilder::new(StatusCode::OK).body(html) } async fn create_task( req: web::Form, db: web::Data>, ) -> impl Responder { 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 { 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 { // 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 { db.login(&req.username, &req.password).await; HttpResponse::SeeOther() .insert_header(("Location", "/")) .finish() } async fn register_user( req: web::Form, db: web::Data>, ) -> impl Responder { db.register(&req.username, &req.password).await; HttpResponse::SeeOther() .insert_header(("Location", "/")) .finish() } async fn logout(db: web::Data>) -> impl Responder { // TODO: log the user out HttpResponse::SeeOther() .insert_header(("Location", "/")) .finish() }