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
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
use serde::{Deserialize, Serialize};
pub use super::auth;
use crate::ctx::Ctx;
use crate::db;
use crate::errors::*;
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct AccountCheckResp {
pub exists: bool,
}
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct ChangePasswordReqest {
pub password: String,
pub new_password: String,
pub confirm_new_password: String,
}
impl Ctx {
pub async fn email_exists(&self, email: &str) -> ServiceResult<AccountCheckResp> {
let resp = AccountCheckResp {
exists: self.db.email_exists(email).await?,
};
Ok(resp)
}
pub async fn set_email(&self, username: &str, new_email: &str) -> ServiceResult<()> {
self.creds.email(new_email)?;
let username = self.creds.username(username)?;
let payload = db::UpdateEmail {
username: &username,
new_email,
};
self.db.update_email(&payload).await?;
Ok(())
}
pub async fn username_exists(&self, username: &str) -> ServiceResult<AccountCheckResp> {
let processed_uname = self.creds.username(username)?;
let resp = AccountCheckResp {
exists: self.db.username_exists(&processed_uname).await?,
};
Ok(resp)
}
pub async fn update_username(
&self,
current_username: &str,
new_username: &str,
) -> ServiceResult<String> {
let processed_uname = self.creds.username(new_username)?;
self.db
.update_username(current_username, &processed_uname)
.await?;
Ok(processed_uname)
}
async fn authenticate(&self, username: &str, password: &str) -> ServiceResult<()> {
use argon2_creds::Config;
let username = self.creds.username(username)?;
let resp = self
.db
.get_password(&db::Login::Username(&username))
.await?;
if Config::verify(&resp.hash, password)? {
Ok(())
} else {
Err(ServiceError::WrongPassword)
}
}
pub async fn delete_user(&self, username: &str, password: &str) -> ServiceResult<()> {
let username = self.creds.username(username)?;
self.authenticate(&username, password).await?;
self.db.delete_user(&username).await?;
Ok(())
}
pub async fn change_password(
&self,
username: &str,
payload: &ChangePasswordReqest,
) -> ServiceResult<()> {
if payload.new_password != payload.confirm_new_password {
return Err(ServiceError::PasswordsDontMatch);
}
self.authenticate(username, &payload.password).await?;
let hash = self.creds.password(&payload.new_password)?;
let username = self.creds.username(username)?;
let db_payload = db::NameHash { username, hash };
self.db.update_password(&db_payload).await?;
Ok(())
}
}