feat(otter): cli command to toggle admin status
							parent
							
								
									ee9db5ae36
								
							
						
					
					
						commit
						b946e1ce98
					
				|  | @ -7,8 +7,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 | |||
| 
 | ||||
| ## [Unreleased](https://git.rustybever.be/Chewing_Bever/otter) | ||||
| 
 | ||||
| ### Added | ||||
| 
 | ||||
| * Ability for an account to be an admin | ||||
| * CLI command to toggle admin status of users | ||||
| 
 | ||||
| ## [0.3.0](https://git.rustybever.be/Chewing_Bever/otter/src/tag/0.3.0) | ||||
| 
 | ||||
| ### Added | ||||
| 
 | ||||
| * Public sign-up page (disabled by default) | ||||
| * Private sign-up links | ||||
| * New CLI commands | ||||
|  |  | |||
|  | @ -83,6 +83,10 @@ impl GpodderRepository { | |||
|         self.store.insert_user(username, &password_hash) | ||||
|     } | ||||
| 
 | ||||
|     pub fn update_user(&self, user: models::User) -> Result<models::User, AuthErr> { | ||||
|         self.store.update_user(user) | ||||
|     } | ||||
| 
 | ||||
|     pub fn validate_credentials( | ||||
|         &self, | ||||
|         username: &str, | ||||
|  |  | |||
|  | @ -51,6 +51,9 @@ pub trait GpodderAuthStore { | |||
|     /// Insert a new user into the data store
 | ||||
|     fn insert_user(&self, username: &str, password_hash: &str) -> Result<User, AuthErr>; | ||||
| 
 | ||||
|     /// Update the user with the included ID with the new values
 | ||||
|     fn update_user(&self, user: User) -> Result<User, AuthErr>; | ||||
| 
 | ||||
|     /// Create a new session for a user with the given session ID
 | ||||
|     ///
 | ||||
|     /// The `last_seen` timestamp's precision should be at least accurate to the second
 | ||||
|  |  | |||
|  | @ -2,7 +2,7 @@ use diesel::prelude::*; | |||
| 
 | ||||
| use crate::schema::*; | ||||
| 
 | ||||
| #[derive(Clone, Queryable, Selectable)] | ||||
| #[derive(Clone, Queryable, Selectable, AsChangeset)] | ||||
| #[diesel(table_name = users)] | ||||
| #[diesel(check_for_backend(diesel::sqlite::Sqlite))] | ||||
| pub struct User { | ||||
|  |  | |||
|  | @ -24,6 +24,17 @@ impl From<User> for gpodder::User { | |||
|     } | ||||
| } | ||||
| 
 | ||||
| impl From<gpodder::User> for User { | ||||
|     fn from(value: gpodder::User) -> Self { | ||||
|         Self { | ||||
|             id: value.id, | ||||
|             username: value.username, | ||||
|             password_hash: value.password_hash, | ||||
|             admin: value.admin, | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl From<SignupLink> for gpodder::SignupLink { | ||||
|     fn from(value: SignupLink) -> Self { | ||||
|         Self { | ||||
|  | @ -58,6 +69,18 @@ impl gpodder::GpodderAuthStore for SqliteRepository { | |||
|             .map_err(DbError::from)?) | ||||
|     } | ||||
| 
 | ||||
|     fn update_user(&self, user: gpodder::User) -> Result<gpodder::User, AuthErr> { | ||||
|         let conn = &mut self.pool.get().map_err(DbError::from)?; | ||||
|         let user: User = user.into(); | ||||
| 
 | ||||
|         Ok(diesel::update(users::table.filter(users::id.eq(user.id))) | ||||
|             .set(&user) | ||||
|             .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) | ||||
|  |  | |||
|  | @ -1,4 +1,4 @@ | |||
| use clap::{Args, Subcommand}; | ||||
| use clap::{ArgAction, Args, Subcommand}; | ||||
| 
 | ||||
| use super::CliError; | ||||
| 
 | ||||
|  | @ -22,6 +22,12 @@ pub enum UserCommand { | |||
|     Add { username: String, password: String }, | ||||
|     /// Generate a signup link ID
 | ||||
|     GenerateSignupLink, | ||||
|     /// Give or remove admin privileges to a user
 | ||||
|     SetAdmin { | ||||
|         username: String, | ||||
|         #[clap(action=ArgAction::Set)] | ||||
|         is_admin: bool, | ||||
|     }, | ||||
| } | ||||
| 
 | ||||
| impl Command { | ||||
|  | @ -67,6 +73,11 @@ impl UserCommand { | |||
| 
 | ||||
|                 println!("/signup/{}", link.id); | ||||
|             } | ||||
|             Self::SetAdmin { username, is_admin } => { | ||||
|                 let mut user = store.get_user(username)?; | ||||
|                 user.admin = *is_admin; | ||||
|                 store.update_user(user)?; | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         Ok(()) | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue