summaryrefslogtreecommitdiffstats
path: root/src/admin.rs
blob: 2efe02fdbbae9a576f14d4c0f038fb56cc9c0727 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
use std::str::FromStr;

use actix::Addr;
use actix_http::error::ResponseError;
use actix_identity::Identity;
use actix_web::{http::header, web, HttpResponse};
use askama::Template;
use serde::Deserialize;

use crate::error::ServiceError;
use crate::model::{DbExecutor, NewUser};
use crate::util::UserRequest;
use crate::Secret;

pub mod user_creation;
use user_creation::{PassHashExecutor, PassHashRequest, SaveUserRequest};

#[derive(Template)]
#[template(path = "admin.htm")]
struct AdminTemplate;

pub async fn index(ident: Identity, db: web::Data<Addr<DbExecutor>>) -> HttpResponse {
    if let Some(name) = ident.identity() {
        ident.remember(name.clone());
        let user = match db.send(UserRequest(name.clone())).await.unwrap() {
            Ok(v) => v,
            Err(_) => {
                ident.forget();
                return HttpResponse::Found()
                    .header(header::LOCATION, "/login")
                    .finish();
            }
        };
        if user.power_level != 9001 {
            return ServiceError::Unauthorized.error_response();
        }

        let page = AdminTemplate.render().unwrap();

        HttpResponse::Ok().content_type("text/html").body(page)
    } else {
        HttpResponse::Found()
            .header(header::LOCATION, "/user/login")
            .finish()
    }
}

#[derive(Deserialize, Debug)]
#[serde(rename_all = "kebab-case")]
pub struct UserData {
    pub user: String,
    pub balance: String,
    pub password: String,
}

pub async fn create_user(
    ident: Identity,
    params: web::Form<UserData>,
    db: web::Data<Addr<DbExecutor>>,
    hasher: web::Data<Addr<PassHashExecutor>>,
    sec: web::Data<Secret>,
) -> HttpResponse {
    if let Some(name) = ident.identity() {
        ident.remember(name.clone());
        let user = match db.send(UserRequest(name.clone())).await.unwrap() {
            Ok(v) => v,
            Err(_) => {
                ident.forget();
                return HttpResponse::Found()
                    .header(header::LOCATION, "/login")
                    .finish();
            }
        };
        if user.power_level != 9001 {
            return ServiceError::Unauthorized.error_response();
        }
        let new_login = params.into_inner();

        let balance = match u64::from_str(&new_login.balance) {
            Ok(v) => v,
            Err(e) => {
                return HttpResponse::Ok()
                    .content_type("text/html")
                    .body(e.to_string())
            }
        };

        let hash = hasher
            .send(PassHashRequest::new(new_login.password, sec.0.clone()))
            .await
            .unwrap()
            .unwrap();

        let new_user = NewUser {
            name: new_login.user,
            // TODO Let the admin pick
            power_level: 0,
            balance: balance,
        };

        db.send(SaveUserRequest::new(new_user, hash))
            .await
            .unwrap()
            .unwrap();

        HttpResponse::Found()
            .header(header::LOCATION, "/admin")
            .finish()
    } else {
        HttpResponse::Found()
            .header(header::LOCATION, "/login")
            .finish()
    }
}