171 lines
5.9 KiB
Rust
171 lines
5.9 KiB
Rust
/*
|
|
* 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 <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
// TODO: add authentification for API endpoints
|
|
// TODO: use the authentification for the logged in status
|
|
|
|
use crate::{database::Database, task, templates};
|
|
use actix_web::HttpRequest;
|
|
use actix_web::{http::StatusCode, web, HttpResponse, HttpResponseBuilder, HttpServer, Responder};
|
|
use askama::Template;
|
|
use include_dir::{Dir, include_dir};
|
|
use std::net::SocketAddr;
|
|
use std::sync::Arc;
|
|
|
|
pub struct App {
|
|
pub server: actix_web::dev::Server,
|
|
}
|
|
|
|
static STATIC_DIR: Dir = include_dir!("$CARGO_MANIFEST_DIR/static");
|
|
|
|
impl App {
|
|
pub async fn new(addr: SocketAddr, db: Arc<Database>) -> anyhow::Result<Self> {
|
|
let db = db.clone();
|
|
let server = HttpServer::new(move || {
|
|
actix_web::App::new()
|
|
.app_data(web::Data::new(db.clone()))
|
|
.route("/", web::get().to(index))
|
|
.route("/static/{file}", web::get().to(static_file))
|
|
.route("/users", web::get().to(users))
|
|
.route("/task", web::get().to(tasks))
|
|
.route("/admin", web::get().to(admin))
|
|
.route("/create", web::get().to(create))
|
|
.route("/login", web::get().to(login))
|
|
.route("/register", web::get().to(register))
|
|
.route("/api/task/create", web::post().to(create_task))
|
|
.route("/api/task/move", web::post().to(move_task))
|
|
//.route("/api/task/sort", web::post().to(sort_task)),
|
|
.route("/api/login", web::post().to(login_user))
|
|
.route("/api/register", web::post().to(register_user))
|
|
.route("/api/logout", web::get().to(logout))
|
|
})
|
|
.bind(addr)?
|
|
.run();
|
|
Ok(App { server })
|
|
}
|
|
}
|
|
|
|
async fn static_file(file: web::Path<String>) -> impl Responder {
|
|
STATIC_DIR.get_file(file.into_inner()).map(|v| v.contents())
|
|
}
|
|
|
|
async fn index(db: web::Data<Arc<Database>>) -> impl Responder {
|
|
let index = templates::Index { logged_in: None };
|
|
let html = index.render().unwrap();
|
|
HttpResponseBuilder::new(StatusCode::OK).body(html)
|
|
}
|
|
|
|
async fn tasks(db: web::Data<Arc<Database>>) -> impl Responder {
|
|
// TODO: fix this
|
|
//let tasks = db.get_tasks().await;
|
|
let vec = vec![templates::Task {
|
|
title: "finish tmtd".to_string(),
|
|
date: "yesterday".to_string(),
|
|
status: "assigned".to_string(),
|
|
assignee: "tmtd contributers".to_string(),
|
|
description: "DO SOMETHING AAAAAAA".to_string(),
|
|
id: 1,
|
|
}];
|
|
let tasks = templates::Tasks {
|
|
tasks: vec,
|
|
logged_in: None,
|
|
};
|
|
let html = tasks.render().unwrap();
|
|
HttpResponseBuilder::new(StatusCode::OK).body(html)
|
|
}
|
|
|
|
async fn users(db: web::Data<Arc<Database>>) -> impl Responder {
|
|
let users = templates::Users { logged_in: None };
|
|
let html = users.render().unwrap();
|
|
HttpResponseBuilder::new(StatusCode::OK).body(html)
|
|
}
|
|
|
|
async fn admin(db: web::Data<Arc<Database>>) -> impl Responder {
|
|
let admin_panel = templates::AdminPanel { logged_in: None };
|
|
let html = admin_panel.render().unwrap();
|
|
HttpResponseBuilder::new(StatusCode::OK).body(html)
|
|
}
|
|
|
|
async fn create(db: web::Data<Arc<Database>>) -> impl Responder {
|
|
let create = templates::CreateTask { logged_in: None };
|
|
let html = create.render().unwrap();
|
|
HttpResponseBuilder::new(StatusCode::OK).body(html)
|
|
}
|
|
|
|
async fn login(db: web::Data<Arc<Database>>) -> impl Responder {
|
|
let login = templates::Login { logged_in: None };
|
|
let html = login.render().unwrap();
|
|
HttpResponseBuilder::new(StatusCode::OK).body(html)
|
|
}
|
|
|
|
async fn register(db: web::Data<Arc<Database>>) -> impl Responder {
|
|
let register = templates::Register { logged_in: None };
|
|
let html = register.render().unwrap();
|
|
HttpResponseBuilder::new(StatusCode::OK).body(html)
|
|
}
|
|
|
|
async fn create_task(
|
|
req: web::Form<task::CreateTask>,
|
|
db: web::Data<Arc<Database>>,
|
|
) -> 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<task::MoveTask>, db: web::Data<Arc<Database>>) -> 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<task::SortTask>) -> 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<task::Login>, db: web::Data<Arc<Database>>) -> impl Responder {
|
|
db.check_password(&req.username, &req.password).await;
|
|
HttpResponse::SeeOther()
|
|
.insert_header(("Location", "/"))
|
|
.finish()
|
|
}
|
|
|
|
async fn register_user(
|
|
req: web::Form<task::Register>,
|
|
db: web::Data<Arc<Database>>,
|
|
) -> impl Responder {
|
|
db.register(&req.username, &req.password).await;
|
|
HttpResponse::SeeOther()
|
|
.insert_header(("Location", "/"))
|
|
.finish()
|
|
}
|
|
|
|
async fn logout(db: web::Data<Arc<Database>>) -> impl Responder {
|
|
// TODO: log the user out
|
|
HttpResponse::SeeOther()
|
|
.insert_header(("Location", "/"))
|
|
.finish()
|
|
}
|