Add set-role command
This commit is contained in:
parent
01f956b6ce
commit
1f9669ad7c
|
@ -13,6 +13,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
||||||
- Implemented roles & permissions.
|
- Implemented roles & permissions.
|
||||||
- Added "read-only user" role.
|
- Added "read-only user" role.
|
||||||
- Added configuration option for automatic assigning of "read-only user" role after registration.
|
- Added configuration option for automatic assigning of "read-only user" role after registration.
|
||||||
|
- Added `set-role` command.
|
||||||
|
|
||||||
### Deprecated
|
### Deprecated
|
||||||
|
|
||||||
|
|
|
@ -38,6 +38,12 @@ Set or change password:
|
||||||
mitractl set-password <user-id> <password>
|
mitractl set-password <user-id> <password>
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Change user's role:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
mitractl set-role <user-id> <role-name>
|
||||||
|
```
|
||||||
|
|
||||||
Delete profile:
|
Delete profile:
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
|
|
|
@ -39,7 +39,9 @@ use mitra::models::{
|
||||||
get_invite_codes,
|
get_invite_codes,
|
||||||
get_user_by_id,
|
get_user_by_id,
|
||||||
set_user_password,
|
set_user_password,
|
||||||
|
set_user_role,
|
||||||
},
|
},
|
||||||
|
users::types::Role,
|
||||||
};
|
};
|
||||||
use mitra::monero::{
|
use mitra::monero::{
|
||||||
helpers::check_expired_invoice,
|
helpers::check_expired_invoice,
|
||||||
|
@ -70,6 +72,7 @@ pub enum SubCommand {
|
||||||
GenerateInviteCode(GenerateInviteCode),
|
GenerateInviteCode(GenerateInviteCode),
|
||||||
ListInviteCodes(ListInviteCodes),
|
ListInviteCodes(ListInviteCodes),
|
||||||
SetPassword(SetPassword),
|
SetPassword(SetPassword),
|
||||||
|
SetRole(SetRole),
|
||||||
RefetchActor(RefetchActor),
|
RefetchActor(RefetchActor),
|
||||||
DeleteProfile(DeleteProfile),
|
DeleteProfile(DeleteProfile),
|
||||||
DeletePost(DeletePost),
|
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
|
/// Re-fetch actor profile by actor ID
|
||||||
#[derive(Parser)]
|
#[derive(Parser)]
|
||||||
pub struct RefetchActor {
|
pub struct RefetchActor {
|
||||||
|
|
|
@ -32,6 +32,7 @@ async fn main() {
|
||||||
SubCommand::GenerateInviteCode(cmd) => cmd.execute(db_client).await.unwrap(),
|
SubCommand::GenerateInviteCode(cmd) => cmd.execute(db_client).await.unwrap(),
|
||||||
SubCommand::ListInviteCodes(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::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::RefetchActor(cmd) => cmd.execute(&config, db_client).await.unwrap(),
|
||||||
SubCommand::DeleteProfile(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(),
|
SubCommand::DeletePost(cmd) => cmd.execute(&config, db_client).await.unwrap(),
|
||||||
|
|
|
@ -9,7 +9,7 @@ use crate::identity::{did::Did, did_pkh::DidPkh};
|
||||||
use crate::models::profiles::queries::create_profile;
|
use crate::models::profiles::queries::create_profile;
|
||||||
use crate::models::profiles::types::{DbActorProfile, ProfileCreateData};
|
use crate::models::profiles::types::{DbActorProfile, ProfileCreateData};
|
||||||
use crate::utils::currencies::Currency;
|
use crate::utils::currencies::Currency;
|
||||||
use super::types::{DbUser, User, UserCreateData};
|
use super::types::{DbUser, Role, User, UserCreateData};
|
||||||
use super::utils::generate_invite_code;
|
use super::utils::generate_invite_code;
|
||||||
|
|
||||||
pub async fn create_invite_code(
|
pub async fn create_invite_code(
|
||||||
|
@ -154,6 +154,24 @@ pub async fn set_user_password(
|
||||||
Ok(())
|
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(
|
pub async fn get_user_by_id(
|
||||||
db_client: &impl DatabaseClient,
|
db_client: &impl DatabaseClient,
|
||||||
user_id: &Uuid,
|
user_id: &Uuid,
|
||||||
|
@ -307,4 +325,16 @@ mod tests {
|
||||||
let result = create_user(db_client, another_user_data).await;
|
let result = create_user(db_client, another_user_data).await;
|
||||||
assert!(matches!(result, Err(DatabaseError::AlreadyExists("user"))));
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,6 +31,16 @@ impl Default for Role {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl 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> {
|
pub fn get_permissions(&self) -> Vec<Permission> {
|
||||||
match self {
|
match self {
|
||||||
Self::Guest => vec![],
|
Self::Guest => vec![],
|
||||||
|
|
Loading…
Reference in a new issue