feat(gpodder): add create_user method to AuthStore
parent
2a8917f21d
commit
b44a47fefd
|
@ -1,8 +1,8 @@
|
|||
use std::{collections::HashSet, sync::Arc};
|
||||
|
||||
use argon2::{Argon2, PasswordHash, PasswordVerifier};
|
||||
use argon2::{password_hash::SaltString, Argon2, PasswordHash, PasswordHasher, PasswordVerifier};
|
||||
use chrono::{DateTime, TimeDelta, Utc};
|
||||
use rand::Rng;
|
||||
use rand::{rngs::OsRng, Rng};
|
||||
|
||||
use crate::{
|
||||
models,
|
||||
|
@ -41,6 +41,17 @@ impl GpodderRepository {
|
|||
self.store.get_user(username)?.ok_or(AuthErr::UnknownUser)
|
||||
}
|
||||
|
||||
pub fn create_user(&self, username: &str, password: &str) -> Result<models::User, AuthErr> {
|
||||
let salt = SaltString::generate(&mut OsRng);
|
||||
|
||||
let password_hash = Argon2::default()
|
||||
.hash_password(password.as_bytes(), &salt)
|
||||
.unwrap()
|
||||
.to_string();
|
||||
|
||||
self.store.insert_user(username, &password_hash)
|
||||
}
|
||||
|
||||
pub fn validate_credentials(
|
||||
&self,
|
||||
username: &str,
|
||||
|
|
|
@ -41,6 +41,9 @@ pub trait AuthStore {
|
|||
/// Retrieve the user with the given username
|
||||
fn get_user(&self, username: &str) -> Result<Option<User>, AuthErr>;
|
||||
|
||||
/// Insert a new user into the data store
|
||||
fn insert_user(&self, username: &str, password_hash: &str) -> Result<User, AuthErr>;
|
||||
|
||||
/// Create a new session for a user with the given session ID
|
||||
fn insert_session(&self, session: &Session) -> Result<(), AuthErr>;
|
||||
|
||||
|
|
|
@ -14,9 +14,9 @@ pub struct User {
|
|||
#[derive(Insertable)]
|
||||
#[diesel(table_name = users)]
|
||||
#[diesel(check_for_backend(diesel::sqlite::Sqlite))]
|
||||
pub struct NewUser {
|
||||
pub username: String,
|
||||
pub password_hash: String,
|
||||
pub struct NewUser<'a> {
|
||||
pub username: &'a str,
|
||||
pub password_hash: &'a str,
|
||||
}
|
||||
|
||||
// impl NewUser {
|
||||
|
|
|
@ -4,7 +4,10 @@ use gpodder::AuthErr;
|
|||
|
||||
use super::SqliteRepository;
|
||||
use crate::{
|
||||
models::{session::Session, user::User},
|
||||
models::{
|
||||
session::Session,
|
||||
user::{NewUser, User},
|
||||
},
|
||||
schema::*,
|
||||
DbError,
|
||||
};
|
||||
|
@ -30,18 +33,34 @@ impl gpodder::AuthStore for SqliteRepository {
|
|||
.map(gpodder::User::from))
|
||||
}
|
||||
|
||||
fn insert_user(&self, username: &str, password_hash: &str) -> Result<gpodder::User, AuthErr> {
|
||||
let conn = &mut self.pool.get().map_err(DbError::from)?;
|
||||
|
||||
Ok(diesel::insert_into(users::table)
|
||||
.values(NewUser {
|
||||
username,
|
||||
password_hash,
|
||||
})
|
||||
.returning(User::as_returning())
|
||||
.get_result(conn)
|
||||
.map(gpodder::User::from)
|
||||
.map_err(DbError::from)?)
|
||||
}
|
||||
|
||||
fn get_session(&self, session_id: i64) -> Result<Option<gpodder::models::Session>, AuthErr> {
|
||||
match sessions::table
|
||||
.inner_join(users::table)
|
||||
.filter(sessions::id.eq(session_id))
|
||||
.select((Session::as_select(), User::as_select()))
|
||||
.get_result(&mut self.pool.get().map_err(DbError::from)?)
|
||||
.optional()
|
||||
{
|
||||
Ok((session, user)) => Ok(Some(gpodder::Session {
|
||||
Ok(Some((session, user))) => Ok(Some(gpodder::Session {
|
||||
id: session.id,
|
||||
last_seen: DateTime::from_timestamp(session.last_seen, 0).unwrap(),
|
||||
user: user.into(),
|
||||
})),
|
||||
Ok(None) => Ok(None),
|
||||
Err(err) => Err(DbError::from(err).into()),
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue