summaryrefslogtreecommitdiffstats
path: root/src/admin/user_creation.rs
blob: 563b6601d8e77ebe5fb96085fcc4bf6d0a760f95 (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
use actix::{Actor, Handler, Message, SyncContext};
use argonautica::{input::SecretKey, Hasher};
use diesel::MysqlConnection;
use diesel::{
    dsl::sql,
    types::{Bigint, Unsigned},
    RunQueryDsl,
};

use crate::error::ServiceError;
use crate::model::{DbExecutor, NewPassword, NewUser};
use crate::schema::passwords::dsl::passwords;
use crate::schema::users::dsl::users;

static LAST_ID_SQL: &'static str = "SELECT LAST_INSERT_ID()";

pub struct PassHashExecutor(pub Hasher<'static>);

impl Actor for PassHashExecutor {
    type Context = SyncContext<Self>;
}

pub struct PassHashRequest {
    password: String,
    secret: String,
}

impl PassHashRequest {
    pub fn new(password: String, secret: String) -> Self {
        Self { password, secret }
    }
}

impl Message for PassHashRequest {
    type Result = Result<String, ServiceError>;
}

impl Handler<PassHashRequest> for PassHashExecutor {
    type Result = Result<String, ServiceError>;

    fn handle(&mut self, req: PassHashRequest, _: &mut Self::Context) -> Self::Result {
        let secret = SecretKey::from_base64_encoded(req.secret)?;
        Ok(self
            .0
            .with_password(req.password)
            .with_secret_key(secret)
            .hash()?)
    }
}

pub struct SaveUserRequest {
    user: NewUser,
    pass_hash: String,
}

impl SaveUserRequest {
    pub fn new(user: NewUser, pass_hash: String) -> Self {
        Self { user, pass_hash }
    }
}

impl Message for SaveUserRequest {
    type Result = Result<(), ServiceError>;
}

impl Handler<SaveUserRequest> for DbExecutor {
    type Result = Result<(), ServiceError>;

    fn handle(&mut self, msg: SaveUserRequest, _: &mut Self::Context) -> Self::Result {
        let conn: &MysqlConnection = &self.0.get().unwrap();

        diesel::insert_into(users).values(&msg.user).execute(conn)?;

        let id = sql::<Unsigned<Bigint>>(LAST_ID_SQL).get_result(conn)?;

        let new_pass = NewPassword {
            id: id,
            hash: &msg.pass_hash,
        };

        diesel::insert_into(passwords)
            .values(&new_pass)
            .execute(conn)?;

        Ok(())
    }
}