feat(gpodder): add signup link admin methods
parent
c48d2a78ca
commit
5cd1f4f736
|
@ -77,3 +77,9 @@ pub struct Page {
|
|||
pub struct UserFilter {
|
||||
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};
|
||||
|
||||
/// Admin view of the repository, providing methods only allowed by admins
|
||||
pub struct AdminRepository<'a> {
|
||||
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> {
|
||||
|
@ -14,4 +17,21 @@ impl<'a> AdminRepository<'a> {
|
|||
) -> Result<Vec<models::User>, AuthErr> {
|
||||
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 {
|
||||
Ok(admin::AdminRepository {
|
||||
store: self.store.as_ref(),
|
||||
user,
|
||||
_user: user,
|
||||
})
|
||||
} else {
|
||||
Err(AuthErr::NotAnAdmin)
|
||||
|
|
|
@ -67,6 +67,35 @@ pub trait GpodderAuthStore {
|
|||
|
||||
/// Return the given page of users, ordered by username
|
||||
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 {
|
||||
|
|
|
@ -7,6 +7,7 @@ use crate::{
|
|||
DbError,
|
||||
models::{
|
||||
session::Session,
|
||||
signup_link::SignupLink,
|
||||
user::{NewUser, User},
|
||||
},
|
||||
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 {
|
||||
fn get_user(&self, username: &str) -> Result<Option<gpodder::models::User>, AuthErr> {
|
||||
Ok(users::table
|
||||
|
@ -170,4 +180,39 @@ impl gpodder::GpodderAuthStore for SqliteRepository {
|
|||
})()
|
||||
.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