185 lines
5.7 KiB
Rust
185 lines
5.7 KiB
Rust
use chrono::DateTime;
|
|
use diesel::prelude::*;
|
|
use rand::Rng;
|
|
|
|
use super::SqliteRepository;
|
|
use crate::{
|
|
db::{self, schema::*},
|
|
gpodder::{self, AuthErr},
|
|
};
|
|
|
|
impl From<diesel::r2d2::PoolError> for gpodder::AuthErr {
|
|
fn from(value: diesel::r2d2::PoolError) -> Self {
|
|
Self::Other(Box::new(value))
|
|
}
|
|
}
|
|
|
|
impl From<diesel::result::Error> for gpodder::AuthErr {
|
|
fn from(value: diesel::result::Error) -> Self {
|
|
Self::Other(Box::new(value))
|
|
}
|
|
}
|
|
|
|
impl From<db::User> for gpodder::User {
|
|
fn from(value: db::User) -> Self {
|
|
Self {
|
|
id: value.id,
|
|
username: value.username,
|
|
password_hash: value.password_hash,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl gpodder::AuthRepository for SqliteRepository {
|
|
fn validate_credentials(
|
|
&self,
|
|
username: &str,
|
|
password: &str,
|
|
) -> Result<gpodder::models::User, AuthErr> {
|
|
if let Some(user) = users::table
|
|
.select(db::User::as_select())
|
|
.filter(users::username.eq(username))
|
|
.first(&mut self.pool.get()?)
|
|
.optional()?
|
|
{
|
|
if user.verify_password(password) {
|
|
Ok(gpodder::User {
|
|
id: user.id,
|
|
username: user.username,
|
|
password_hash: user.password_hash,
|
|
})
|
|
} else {
|
|
Err(gpodder::AuthErr::InvalidPassword)
|
|
}
|
|
} else {
|
|
Err(gpodder::AuthErr::UnknownUser)
|
|
}
|
|
}
|
|
|
|
fn validate_session(&self, session_id: i64) -> Result<gpodder::User, gpodder::AuthErr> {
|
|
match sessions::dsl::sessions
|
|
.inner_join(users::table)
|
|
.filter(sessions::id.eq(session_id))
|
|
.select(db::User::as_select())
|
|
.get_result(&mut self.pool.get()?)
|
|
{
|
|
Ok(user) => Ok(gpodder::User {
|
|
id: user.id,
|
|
username: user.username,
|
|
password_hash: user.password_hash,
|
|
}),
|
|
Err(diesel::result::Error::NotFound) => Err(gpodder::AuthErr::UnknownSession),
|
|
Err(err) => Err(gpodder::AuthErr::Other(Box::new(err))),
|
|
}
|
|
}
|
|
|
|
fn create_session(
|
|
&self,
|
|
username: &str,
|
|
password: &str,
|
|
) -> Result<(i64, gpodder::models::User), gpodder::AuthErr> {
|
|
if let Some(user) = users::table
|
|
.select(db::User::as_select())
|
|
.filter(users::username.eq(username))
|
|
.first(&mut self.pool.get()?)
|
|
.optional()?
|
|
{
|
|
if user.verify_password(password) {
|
|
let id: i64 = rand::thread_rng().gen();
|
|
|
|
let session_id = db::Session {
|
|
id,
|
|
user_id: user.id,
|
|
last_seen: chrono::Utc::now().timestamp(),
|
|
}
|
|
.insert_into(sessions::table)
|
|
.returning(sessions::id)
|
|
.get_result(&mut self.pool.get()?)?;
|
|
|
|
Ok((
|
|
session_id,
|
|
gpodder::User {
|
|
id: user.id,
|
|
username: user.username,
|
|
password_hash: user.password_hash,
|
|
},
|
|
))
|
|
} else {
|
|
Err(gpodder::AuthErr::InvalidPassword)
|
|
}
|
|
} else {
|
|
Err(gpodder::AuthErr::UnknownUser)
|
|
}
|
|
}
|
|
|
|
fn remove_session(&self, username: &str, session_id: i64) -> Result<(), gpodder::AuthErr> {
|
|
let conn = &mut self.pool.get()?;
|
|
|
|
if let Some(user) = sessions::table
|
|
.inner_join(users::table)
|
|
.filter(sessions::id.eq(session_id))
|
|
.select(db::User::as_select())
|
|
.get_result(conn)
|
|
.optional()?
|
|
{
|
|
if user.username == username {
|
|
Ok(
|
|
diesel::delete(sessions::table.filter(sessions::id.eq(session_id)))
|
|
.execute(conn)
|
|
.map(|_| ())?,
|
|
)
|
|
} else {
|
|
Err(AuthErr::UnknownUser)
|
|
}
|
|
} else {
|
|
Ok(())
|
|
}
|
|
}
|
|
}
|
|
|
|
impl gpodder::AuthStore for SqliteRepository {
|
|
fn get_user(&self, username: &str) -> Result<Option<gpodder::models::User>, AuthErr> {
|
|
Ok(users::table
|
|
.select(db::User::as_select())
|
|
.filter(users::username.eq(username))
|
|
.first(&mut self.pool.get()?)
|
|
.optional()?
|
|
.map(gpodder::User::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((db::Session::as_select(), db::User::as_select()))
|
|
.get_result(&mut self.pool.get()?)
|
|
{
|
|
Ok((session, user)) => Ok(Some(gpodder::Session {
|
|
id: session.id,
|
|
last_seen: DateTime::from_timestamp(session.last_seen, 0).unwrap(),
|
|
user: user.into(),
|
|
})),
|
|
Err(err) => Err(AuthErr::from(err)),
|
|
}
|
|
}
|
|
|
|
fn remove_session(&self, session_id: i64) -> Result<(), AuthErr> {
|
|
Ok(
|
|
diesel::delete(sessions::table.filter(sessions::id.eq(session_id)))
|
|
.execute(&mut self.pool.get()?)
|
|
.map(|_| ())?,
|
|
)
|
|
}
|
|
|
|
fn insert_session(&self, session: &gpodder::Session) -> Result<(), AuthErr> {
|
|
Ok(db::Session {
|
|
id: session.id,
|
|
user_id: session.user.id,
|
|
last_seen: session.last_seen.timestamp(),
|
|
}
|
|
.insert_into(sessions::table)
|
|
.execute(&mut self.pool.get()?)
|
|
.map(|_| ())?)
|
|
}
|
|
}
|