diff options
Diffstat (limited to 'src/user/login.rs')
| -rw-r--r-- | src/user/login.rs | 77 |
1 files changed, 77 insertions, 0 deletions
diff --git a/src/user/login.rs b/src/user/login.rs new file mode 100644 index 0000000..67d4c24 --- /dev/null +++ b/src/user/login.rs @@ -0,0 +1,77 @@ +use actix::{Actor, Handler, Message, SyncContext}; +use argonautica::{input::SecretKey, Verifier}; +use diesel::MysqlConnection; +use diesel::{ExpressionMethods, QueryDsl, RunQueryDsl}; + +use crate::error::ServiceError; +use crate::model::DbExecutor; +use crate::model::User; +use crate::schema::passwords::{columns as password_columns, dsl::passwords}; +use crate::schema::users::{columns as user_columns, dsl::users}; + +pub struct HashVerifyExecutor(pub Verifier<'static>); + +impl Actor for HashVerifyExecutor { + type Context = SyncContext<Self>; +} + +pub struct HashVerifyRequest { + hash: String, + password: String, + secret: String, +} + +impl HashVerifyRequest { + pub fn new(hash: String, password: String, secret: String) -> Self { + Self { + hash, + password, + secret, + } + } +} + +impl Message for HashVerifyRequest { + type Result = Result<bool, ServiceError>; +} + +impl Handler<HashVerifyRequest> for HashVerifyExecutor { + type Result = Result<bool, ServiceError>; + + fn handle(&mut self, req: HashVerifyRequest, _: &mut Self::Context) -> Self::Result { + let secret = SecretKey::from_base64_encoded(req.secret)?; + Ok(self + .0 + .with_hash(req.hash) + .with_password(req.password) + .with_secret_key(secret) + .verify()?) + } +} + +pub struct LoginRequest(pub String); + +impl Message for LoginRequest { + type Result = Result<(User, String), ServiceError>; +} + +impl Handler<LoginRequest> for DbExecutor { + type Result = Result<(User, String), ServiceError>; + + fn handle(&mut self, login: LoginRequest, _: &mut Self::Context) -> Self::Result { + let conn: &MysqlConnection = &self.0.get().unwrap(); + + let user = users + .filter(user_columns::name.eq(login.0)) + .first::<User>(conn) + .map_err(|_| ServiceError::NotFound)?; + + let hash = passwords + .filter(password_columns::id.eq(user.id)) + .select(password_columns::hash) + .first::<String>(conn) + .map_err(|_| ServiceError::NotFound)?; + + Ok((user, hash)) + } +} |
