aboutsummaryrefslogtreecommitdiff
path: root/src/controller/login.rs
blob: dd50a3a2adc6bfad1df4cbbe9e542c7d7cc8c549 (plain)
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
115
116
117
118
use bcrypt;
use http_body_util::Full;
use hyper::body::Bytes;
use hyper::header::SET_COOKIE;
use hyper::Response;
use sqlx::sqlite::SqlitePool;
use std::collections::HashMap;
use tera::{Context, Tera};

use crate::controller::utils::with_headers;
use crate::controller::wallet::Wallet;
use crate::controller::{error, utils};
use crate::db;
use crate::model::config::Config;
use crate::model::user::User;
use crate::utils::cookie;
use crate::validation;

pub async fn page(
    assets: &HashMap<String, String>,
    templates: &Tera,
    error: Option<&str>,
) -> Response<Full<Bytes>> {
    let connected_user: Option<User> = None;

    let mut context = Context::new();
    context.insert("connected_user", &connected_user);
    context.insert("error", &error);

    utils::template(assets, templates, "login.html", context)
}

pub async fn login(
    config: &Config,
    assets: &HashMap<String, String>,
    templates: &Tera,
    form: HashMap<String, String>,
    pool: SqlitePool,
) -> Response<Full<Bytes>> {
    match validation::login::login(&form) {
        Some(login) => {
            match db::users::get_password_hash(&pool, login.email.clone()).await
            {
                Some(hash) => match bcrypt::verify(login.password, &hash) {
                    Ok(true) => {
                        let login_token = cookie::generate_token();

                        if db::users::set_login_token(
                            &pool,
                            login.email,
                            login_token.clone().to_string(),
                        )
                        .await
                        {
                            match cookie::login(config, &login_token) {
                                Ok(str) => with_headers(
                                    utils::redirect("/"),
                                    vec![(SET_COOKIE, &str)],
                                ),
                                Err(msg) => {
                                    server_error(
                                        assets,
                                        templates,
                                        &format!(
                                            "Error generating cookie: {msg}"
                                        ),
                                    )
                                    .await
                                }
                            }
                        } else {
                            server_error(assets, templates, "Erreur server")
                                .await
                        }
                    }
                    Ok(false) => not_authorized(assets, templates).await,
                    Err(err) => {
                        error!("Error verifying bcrypt password: {:?}", err);
                        server_error(assets, templates, "Erreur serveur").await
                    }
                },
                None => not_authorized(assets, templates).await,
            }
        }
        None => not_authorized(assets, templates).await,
    }
}

async fn server_error(
    assets: &HashMap<String, String>,
    templates: &Tera,
    msg: &str,
) -> Response<Full<Bytes>> {
    page(assets, templates, Some(msg)).await
}

async fn not_authorized(
    assets: &HashMap<String, String>,
    templates: &Tera,
) -> Response<Full<Bytes>> {
    page(
        assets,
        templates,
        Some("Vous n’êtes pas autorisé à vous connecter."),
    )
    .await
}

pub async fn logout(config: &Config, wallet: &Wallet) -> Response<Full<Bytes>> {
    if db::users::remove_login_token(&wallet.pool, wallet.user.id).await {
        with_headers(
            utils::redirect("/"),
            vec![(SET_COOKIE, &cookie::logout(config))],
        )
    } else {
        error::error(wallet, "Erreur serveur", "Erreur serveur")
    }
}