Add set-role command

This commit is contained in:
silverpill 2023-01-25 05:52:58 +00:00
parent 01f956b6ce
commit 1f9669ad7c
6 changed files with 71 additions and 1 deletions

View file

@ -13,6 +13,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- Implemented roles & permissions.
- Added "read-only user" role.
- Added configuration option for automatic assigning of "read-only user" role after registration.
- Added `set-role` command.
### Deprecated

View file

@ -38,6 +38,12 @@ Set or change password:
mitractl set-password <user-id> <password>
```
Change user's role:
```shell
mitractl set-role <user-id> <role-name>
```
Delete profile:
```shell

View file

@ -39,7 +39,9 @@ use mitra::models::{
get_invite_codes,
get_user_by_id,
set_user_password,
set_user_role,
},
users::types::Role,
};
use mitra::monero::{
helpers::check_expired_invoice,
@ -70,6 +72,7 @@ pub enum SubCommand {
GenerateInviteCode(GenerateInviteCode),
ListInviteCodes(ListInviteCodes),
SetPassword(SetPassword),
SetRole(SetRole),
RefetchActor(RefetchActor),
DeleteProfile(DeleteProfile),
DeletePost(DeletePost),
@ -169,6 +172,25 @@ impl SetPassword {
}
}
/// Change user's role
#[derive(Parser)]
pub struct SetRole {
id: Uuid,
role: String,
}
impl SetRole {
pub async fn execute(
&self,
db_client: &impl DatabaseClient,
) -> Result<(), Error> {
let role = Role::from_name(&self.role)?;
set_user_role(db_client, &self.id, role).await?;
println!("role changed");
Ok(())
}
}
/// Re-fetch actor profile by actor ID
#[derive(Parser)]
pub struct RefetchActor {

View file

@ -32,6 +32,7 @@ async fn main() {
SubCommand::GenerateInviteCode(cmd) => cmd.execute(db_client).await.unwrap(),
SubCommand::ListInviteCodes(cmd) => cmd.execute(db_client).await.unwrap(),
SubCommand::SetPassword(cmd) => cmd.execute(db_client).await.unwrap(),
SubCommand::SetRole(cmd) => cmd.execute(db_client).await.unwrap(),
SubCommand::RefetchActor(cmd) => cmd.execute(&config, db_client).await.unwrap(),
SubCommand::DeleteProfile(cmd) => cmd.execute(&config, db_client).await.unwrap(),
SubCommand::DeletePost(cmd) => cmd.execute(&config, db_client).await.unwrap(),

View file

@ -9,7 +9,7 @@ use crate::identity::{did::Did, did_pkh::DidPkh};
use crate::models::profiles::queries::create_profile;
use crate::models::profiles::types::{DbActorProfile, ProfileCreateData};
use crate::utils::currencies::Currency;
use super::types::{DbUser, User, UserCreateData};
use super::types::{DbUser, Role, User, UserCreateData};
use super::utils::generate_invite_code;
pub async fn create_invite_code(
@ -154,6 +154,24 @@ pub async fn set_user_password(
Ok(())
}
pub async fn set_user_role(
db_client: &impl DatabaseClient,
user_id: &Uuid,
role: Role,
) -> Result<(), DatabaseError> {
let updated_count = db_client.execute(
"
UPDATE user_account SET user_role = $1
WHERE id = $2
",
&[&role, &user_id],
).await?;
if updated_count == 0 {
return Err(DatabaseError::NotFound("user"));
};
Ok(())
}
pub async fn get_user_by_id(
db_client: &impl DatabaseClient,
user_id: &Uuid,
@ -307,4 +325,16 @@ mod tests {
let result = create_user(db_client, another_user_data).await;
assert!(matches!(result, Err(DatabaseError::AlreadyExists("user"))));
}
#[tokio::test]
#[serial]
async fn test_set_user_role() {
let db_client = &mut create_test_database().await;
let user_data = UserCreateData::default();
let user = create_user(db_client, user_data).await.unwrap();
assert_eq!(user.role, Role::NormalUser);
set_user_role(db_client, &user.id, Role::ReadOnlyUser).await.unwrap();
let user = get_user_by_id(db_client, &user.id).await.unwrap();
assert_eq!(user.role, Role::ReadOnlyUser);
}
}

View file

@ -31,6 +31,16 @@ impl Default for Role {
}
impl Role {
pub fn from_name(name: &str) -> Result<Self, ValidationError> {
let role = match name {
"user" => Self::NormalUser,
"admin" => Self::Admin,
"read_only_user" => Self::ReadOnlyUser,
_ => return Err(ValidationError("unknown role")),
};
Ok(role)
}
pub fn get_permissions(&self) -> Vec<Permission> {
match self {
Self::Guest => vec![],