feat(gpodder): add signup link admin methods
parent
c48d2a78ca
commit
5cd1f4f736
|
@ -77,3 +77,9 @@ pub struct Page {
|
||||||
pub struct UserFilter {
|
pub struct UserFilter {
|
||||||
pub username: Option<String>,
|
pub username: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||||
|
pub struct SignupLink {
|
||||||
|
pub id: i64,
|
||||||
|
pub time_created: DateTime<Utc>,
|
||||||
|
}
|
||||||
|
|
|
@ -1,9 +1,12 @@
|
||||||
|
use chrono::Utc;
|
||||||
|
use rand::Rng;
|
||||||
|
|
||||||
use crate::{AuthErr, Page, models};
|
use crate::{AuthErr, Page, models};
|
||||||
|
|
||||||
/// Admin view of the repository, providing methods only allowed by admins
|
/// Admin view of the repository, providing methods only allowed by admins
|
||||||
pub struct AdminRepository<'a> {
|
pub struct AdminRepository<'a> {
|
||||||
pub(crate) store: &'a (dyn super::GpodderStore + Send + Sync),
|
pub(crate) store: &'a (dyn super::GpodderStore + Send + Sync),
|
||||||
pub(crate) user: &'a models::User,
|
pub(crate) _user: &'a models::User,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> AdminRepository<'a> {
|
impl<'a> AdminRepository<'a> {
|
||||||
|
@ -14,4 +17,21 @@ impl<'a> AdminRepository<'a> {
|
||||||
) -> Result<Vec<models::User>, AuthErr> {
|
) -> Result<Vec<models::User>, AuthErr> {
|
||||||
self.store.paginated_users(page, filter)
|
self.store.paginated_users(page, filter)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Generate a new unique signup link ID
|
||||||
|
pub fn generate_signup_link(&self) -> Result<models::SignupLink, AuthErr> {
|
||||||
|
let link = models::SignupLink {
|
||||||
|
id: rand::thread_rng().r#gen(),
|
||||||
|
time_created: Utc::now(),
|
||||||
|
};
|
||||||
|
|
||||||
|
self.store.insert_signup_link(&link)?;
|
||||||
|
|
||||||
|
Ok(link)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Remove the signup link with the given ID, if it exists
|
||||||
|
pub fn remove_signup_link(&self, id: i64) -> Result<bool, AuthErr> {
|
||||||
|
self.store.remove_signup_link(id)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,7 +47,7 @@ impl GpodderRepository {
|
||||||
if user.admin {
|
if user.admin {
|
||||||
Ok(admin::AdminRepository {
|
Ok(admin::AdminRepository {
|
||||||
store: self.store.as_ref(),
|
store: self.store.as_ref(),
|
||||||
user,
|
_user: user,
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
Err(AuthErr::NotAnAdmin)
|
Err(AuthErr::NotAnAdmin)
|
||||||
|
|
|
@ -67,6 +67,35 @@ pub trait GpodderAuthStore {
|
||||||
|
|
||||||
/// Return the given page of users, ordered by username
|
/// Return the given page of users, ordered by username
|
||||||
fn paginated_users(&self, page: Page, filter: &UserFilter) -> Result<Vec<User>, AuthErr>;
|
fn paginated_users(&self, page: Page, filter: &UserFilter) -> Result<Vec<User>, AuthErr>;
|
||||||
|
|
||||||
|
/// Insert the signup link into the database.
|
||||||
|
///
|
||||||
|
/// # Errors
|
||||||
|
///
|
||||||
|
/// If a database failure occurs
|
||||||
|
fn insert_signup_link(&self, link: &SignupLink) -> Result<(), AuthErr>;
|
||||||
|
|
||||||
|
/// Get the signup link associated with the given ID
|
||||||
|
///
|
||||||
|
/// # Returns
|
||||||
|
///
|
||||||
|
/// Some(link) if the ID corresponds to an existing signup link; None otherwise
|
||||||
|
///
|
||||||
|
/// # Errors
|
||||||
|
///
|
||||||
|
/// If a database failure occurs
|
||||||
|
fn get_signup_link(&self, id: i64) -> Result<Option<SignupLink>, AuthErr>;
|
||||||
|
|
||||||
|
/// Remove the signup link with the given ID.
|
||||||
|
///
|
||||||
|
/// # Returns
|
||||||
|
///
|
||||||
|
/// True if the ID existed in the database; false otherwise
|
||||||
|
///
|
||||||
|
/// # Errors
|
||||||
|
///
|
||||||
|
/// If a database failure occurs
|
||||||
|
fn remove_signup_link(&self, id: i64) -> Result<bool, AuthErr>;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait GpodderDeviceStore {
|
pub trait GpodderDeviceStore {
|
||||||
|
|
|
@ -7,6 +7,7 @@ use crate::{
|
||||||
DbError,
|
DbError,
|
||||||
models::{
|
models::{
|
||||||
session::Session,
|
session::Session,
|
||||||
|
signup_link::SignupLink,
|
||||||
user::{NewUser, User},
|
user::{NewUser, User},
|
||||||
},
|
},
|
||||||
schema::*,
|
schema::*,
|
||||||
|
@ -23,6 +24,15 @@ impl From<User> for gpodder::User {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<SignupLink> for gpodder::SignupLink {
|
||||||
|
fn from(value: SignupLink) -> Self {
|
||||||
|
Self {
|
||||||
|
id: value.id,
|
||||||
|
time_created: DateTime::from_timestamp(value.created_at, 0).unwrap(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl gpodder::GpodderAuthStore for SqliteRepository {
|
impl gpodder::GpodderAuthStore for SqliteRepository {
|
||||||
fn get_user(&self, username: &str) -> Result<Option<gpodder::models::User>, AuthErr> {
|
fn get_user(&self, username: &str) -> Result<Option<gpodder::models::User>, AuthErr> {
|
||||||
Ok(users::table
|
Ok(users::table
|
||||||
|
@ -170,4 +180,39 @@ impl gpodder::GpodderAuthStore for SqliteRepository {
|
||||||
})()
|
})()
|
||||||
.map_err(AuthErr::from)
|
.map_err(AuthErr::from)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_signup_link(&self, id: i64) -> Result<Option<gpodder::SignupLink>, AuthErr> {
|
||||||
|
match signup_links::table
|
||||||
|
.find(id)
|
||||||
|
.select(SignupLink::as_select())
|
||||||
|
.first(&mut self.pool.get().map_err(DbError::from)?)
|
||||||
|
.optional()
|
||||||
|
{
|
||||||
|
Ok(Some(link)) => Ok(Some(gpodder::SignupLink::from(link))),
|
||||||
|
Ok(None) => Ok(None),
|
||||||
|
Err(err) => Err(DbError::from(err).into()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn insert_signup_link(&self, link: &gpodder::SignupLink) -> Result<(), AuthErr> {
|
||||||
|
diesel::insert_into(signup_links::table)
|
||||||
|
.values(SignupLink {
|
||||||
|
id: link.id,
|
||||||
|
created_at: link.time_created.timestamp(),
|
||||||
|
})
|
||||||
|
.execute(&mut self.pool.get().map_err(DbError::from)?)
|
||||||
|
.map_err(DbError::from)?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn remove_signup_link(&self, id: i64) -> Result<bool, AuthErr> {
|
||||||
|
match diesel::delete(signup_links::table.filter(signup_links::id.eq(id)))
|
||||||
|
.execute(&mut self.pool.get().map_err(DbError::from)?)
|
||||||
|
{
|
||||||
|
Ok(0) => Ok(false),
|
||||||
|
Ok(_) => Ok(true),
|
||||||
|
Err(err) => Err(DbError::from(err).into()),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue