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