Restructuring: Move permission code in separate modules
This commit is contained in:
parent
b964063dbb
commit
82e89baeeb
12 changed files with 799 additions and 784 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
|
@ -46,6 +46,7 @@ checksum = "8901269c6307e8d93993578286ac0edf7f195079ffff5ebdeea6a59ffb7e36bc"
|
|||
name = "app"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"dao",
|
||||
"dao_impl",
|
||||
"rest",
|
||||
"service_impl",
|
||||
|
|
|
|||
|
|
@ -8,12 +8,15 @@ edition = "2021"
|
|||
[dependencies.rest]
|
||||
path = "../rest"
|
||||
|
||||
[dependencies.service_impl]
|
||||
path = "../service_impl"
|
||||
|
||||
[dependencies.dao_impl]
|
||||
path = "../dao_impl"
|
||||
|
||||
[dependencies.dao]
|
||||
path = "../dao"
|
||||
|
||||
[dependencies.service_impl]
|
||||
path = "../service_impl"
|
||||
|
||||
[dependencies.tokio]
|
||||
version = "1.37.0"
|
||||
features = ["full"]
|
||||
|
|
|
|||
|
|
@ -49,6 +49,30 @@ impl RestStateImpl {
|
|||
}
|
||||
}
|
||||
|
||||
async fn create_dev_admin_user(pool: Arc<SqlitePool>) {
|
||||
use dao::PermissionDao;
|
||||
// On development create the DEVUSER and give it admin permissions.
|
||||
let permission_dao = dao_impl::PermissionDaoImpl::new(pool);
|
||||
|
||||
let users = permission_dao.all_users().await.expect("Expected users");
|
||||
let contains_admin_user = users.iter().any(|user| user.name.as_ref() == "DEVUSER");
|
||||
if !contains_admin_user {
|
||||
permission_dao
|
||||
.create_user(
|
||||
&dao::UserEntity {
|
||||
name: "DEVUSER".into(),
|
||||
},
|
||||
"dev-first-start",
|
||||
)
|
||||
.await
|
||||
.expect("Expected being able to create the DEVUSER");
|
||||
permission_dao
|
||||
.add_user_role("DEVUSER", "admin", "dev-first-start")
|
||||
.await
|
||||
.expect("Expected being able to make DEVUSER an admin");
|
||||
}
|
||||
}
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() {
|
||||
let pool = Arc::new(
|
||||
|
|
@ -56,6 +80,8 @@ async fn main() {
|
|||
.await
|
||||
.expect("Could not connect to database"),
|
||||
);
|
||||
let rest_state = RestStateImpl::new(pool);
|
||||
|
||||
let rest_state = RestStateImpl::new(pool.clone());
|
||||
create_dev_admin_user(pool.clone()).await;
|
||||
rest::start_server(rest_state).await
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,6 +4,14 @@ use async_trait::async_trait;
|
|||
use mockall::automock;
|
||||
use thiserror::Error;
|
||||
|
||||
mod permission;
|
||||
|
||||
pub use permission::MockPermissionDao;
|
||||
pub use permission::PermissionDao;
|
||||
pub use permission::PrivilegeEntity;
|
||||
pub use permission::RoleEntity;
|
||||
pub use permission::UserEntity;
|
||||
|
||||
#[derive(Error, Debug)]
|
||||
pub enum DaoError {
|
||||
#[error("Database query error: {0}")]
|
||||
|
|
@ -15,49 +23,3 @@ pub enum DaoError {
|
|||
pub trait HelloDao {
|
||||
async fn get_hello(&self) -> Result<Arc<str>, DaoError>;
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
pub struct UserEntity {
|
||||
pub name: Arc<str>,
|
||||
}
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
pub struct RoleEntity {
|
||||
pub name: Arc<str>,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
pub struct PrivilegeEntity {
|
||||
pub name: Arc<str>,
|
||||
}
|
||||
|
||||
#[automock]
|
||||
#[async_trait]
|
||||
pub trait PermissionDao {
|
||||
async fn has_privilege(&self, user: &str, privilege: &str) -> Result<bool, DaoError>;
|
||||
|
||||
async fn create_user(&self, user: &UserEntity, process: &str) -> Result<(), DaoError>;
|
||||
async fn all_users(&self) -> Result<Arc<[UserEntity]>, DaoError>;
|
||||
async fn delete_user(&self, username: &str) -> Result<(), DaoError>;
|
||||
|
||||
async fn create_role(&self, role: &RoleEntity, process: &str) -> Result<(), DaoError>;
|
||||
async fn all_roles(&self) -> Result<Arc<[RoleEntity]>, DaoError>;
|
||||
async fn delete_role(&self, rolename: &str) -> Result<(), DaoError>;
|
||||
|
||||
async fn create_privilege(
|
||||
&self,
|
||||
privilege: &PrivilegeEntity,
|
||||
process: &str,
|
||||
) -> Result<(), DaoError>;
|
||||
async fn all_privileges(&self) -> Result<Arc<[PrivilegeEntity]>, DaoError>;
|
||||
async fn delete_privilege(&self, privilege: &str) -> Result<(), DaoError>;
|
||||
|
||||
async fn add_user_role(&self, user: &str, role: &str, process: &str) -> Result<(), DaoError>;
|
||||
async fn add_role_privilege(
|
||||
&self,
|
||||
role: &str,
|
||||
privilege: &str,
|
||||
process: &str,
|
||||
) -> Result<(), DaoError>;
|
||||
async fn delete_role_privilege(&self, role: &str, privilege: &str) -> Result<(), DaoError>;
|
||||
async fn delete_user_role(&self, user: &str, role: &str) -> Result<(), DaoError>;
|
||||
}
|
||||
|
|
|
|||
52
dao/src/permission.rs
Normal file
52
dao/src/permission.rs
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
use std::sync::Arc;
|
||||
|
||||
use async_trait::async_trait;
|
||||
use mockall::automock;
|
||||
|
||||
use crate::DaoError;
|
||||
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
pub struct UserEntity {
|
||||
pub name: Arc<str>,
|
||||
}
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
pub struct RoleEntity {
|
||||
pub name: Arc<str>,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
pub struct PrivilegeEntity {
|
||||
pub name: Arc<str>,
|
||||
}
|
||||
|
||||
#[automock]
|
||||
#[async_trait]
|
||||
pub trait PermissionDao {
|
||||
async fn has_privilege(&self, user: &str, privilege: &str) -> Result<bool, DaoError>;
|
||||
|
||||
async fn create_user(&self, user: &UserEntity, process: &str) -> Result<(), DaoError>;
|
||||
async fn all_users(&self) -> Result<Arc<[UserEntity]>, DaoError>;
|
||||
async fn delete_user(&self, username: &str) -> Result<(), DaoError>;
|
||||
|
||||
async fn create_role(&self, role: &RoleEntity, process: &str) -> Result<(), DaoError>;
|
||||
async fn all_roles(&self) -> Result<Arc<[RoleEntity]>, DaoError>;
|
||||
async fn delete_role(&self, rolename: &str) -> Result<(), DaoError>;
|
||||
|
||||
async fn create_privilege(
|
||||
&self,
|
||||
privilege: &PrivilegeEntity,
|
||||
process: &str,
|
||||
) -> Result<(), DaoError>;
|
||||
async fn all_privileges(&self) -> Result<Arc<[PrivilegeEntity]>, DaoError>;
|
||||
async fn delete_privilege(&self, privilege: &str) -> Result<(), DaoError>;
|
||||
|
||||
async fn add_user_role(&self, user: &str, role: &str, process: &str) -> Result<(), DaoError>;
|
||||
async fn add_role_privilege(
|
||||
&self,
|
||||
role: &str,
|
||||
privilege: &str,
|
||||
process: &str,
|
||||
) -> Result<(), DaoError>;
|
||||
async fn delete_role_privilege(&self, role: &str, privilege: &str) -> Result<(), DaoError>;
|
||||
async fn delete_user_role(&self, user: &str, role: &str) -> Result<(), DaoError>;
|
||||
}
|
||||
|
|
@ -1,3 +1,4 @@
|
|||
use serde::{Deserialize, Serialize};
|
||||
use std::sync::Arc;
|
||||
|
||||
use axum::{
|
||||
|
|
@ -7,7 +8,6 @@ use axum::{
|
|||
routing::{delete, get, post},
|
||||
Json, Router,
|
||||
};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::{error_handler, RestStateDef};
|
||||
use service::PermissionService;
|
||||
|
|
@ -243,7 +243,7 @@ pub async fn get_all_users<RestState: RestStateDef>(rest_state: State<RestState>
|
|||
.get_all_users()
|
||||
.await?
|
||||
.iter()
|
||||
.map(|u| User::from(u))
|
||||
.map(User::from)
|
||||
.collect();
|
||||
Ok(Response::builder()
|
||||
.status(200)
|
||||
|
|
@ -262,7 +262,7 @@ pub async fn get_all_roles<RestState: RestStateDef>(rest_state: State<RestState>
|
|||
.get_all_roles()
|
||||
.await?
|
||||
.iter()
|
||||
.map(|u| Role::from(u))
|
||||
.map(Role::from)
|
||||
.collect();
|
||||
Ok(Response::builder()
|
||||
.status(200)
|
||||
|
|
@ -281,7 +281,7 @@ pub async fn get_all_privileges<RestState: RestStateDef>(rest_state: State<RestS
|
|||
.get_all_privileges()
|
||||
.await?
|
||||
.iter()
|
||||
.map(|u| Privilege::from(u))
|
||||
.map(Privilege::from)
|
||||
.collect();
|
||||
Ok(Response::builder()
|
||||
.status(200)
|
||||
|
|
|
|||
|
|
@ -3,6 +3,14 @@ use mockall::automock;
|
|||
use std::{future::Future, sync::Arc};
|
||||
use thiserror::Error;
|
||||
|
||||
pub mod permission;
|
||||
|
||||
pub use permission::MockPermissionService;
|
||||
pub use permission::PermissionService;
|
||||
pub use permission::Privilege;
|
||||
pub use permission::Role;
|
||||
pub use permission::User;
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum ServiceError {
|
||||
#[error("Database query error: {0}")]
|
||||
|
|
@ -17,65 +25,6 @@ pub trait HelloService {
|
|||
fn hello(&self) -> impl Future<Output = Result<Arc<str>, ServiceError>> + Send;
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
pub struct User {
|
||||
pub name: Arc<str>,
|
||||
}
|
||||
impl From<&dao::UserEntity> for User {
|
||||
fn from(user: &dao::UserEntity) -> Self {
|
||||
Self {
|
||||
name: user.name.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
pub struct Role {
|
||||
pub name: Arc<str>,
|
||||
}
|
||||
impl From<&dao::RoleEntity> for Role {
|
||||
fn from(role: &dao::RoleEntity) -> Self {
|
||||
Self {
|
||||
name: role.name.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
pub struct Privilege {
|
||||
pub name: Arc<str>,
|
||||
}
|
||||
impl From<&dao::PrivilegeEntity> for Privilege {
|
||||
fn from(privilege: &dao::PrivilegeEntity) -> Self {
|
||||
Self {
|
||||
name: privilege.name.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[automock]
|
||||
#[async_trait]
|
||||
pub trait PermissionService {
|
||||
async fn check_permission(&self, privilege: &str) -> Result<(), ServiceError>;
|
||||
|
||||
async fn create_user(&self, user: &str) -> Result<(), ServiceError>;
|
||||
async fn delete_user(&self, user: &str) -> Result<(), ServiceError>;
|
||||
async fn get_all_users(&self) -> Result<Arc<[User]>, ServiceError>;
|
||||
|
||||
async fn create_role(&self, role: &str) -> Result<(), ServiceError>;
|
||||
async fn delete_role(&self, role: &str) -> Result<(), ServiceError>;
|
||||
async fn get_all_roles(&self) -> Result<Arc<[Role]>, ServiceError>;
|
||||
|
||||
async fn create_privilege(&self, privilege: &str) -> Result<(), ServiceError>;
|
||||
async fn delete_privilege(&self, privilege: &str) -> Result<(), ServiceError>;
|
||||
async fn get_all_privileges(&self) -> Result<Arc<[Privilege]>, ServiceError>;
|
||||
|
||||
async fn add_user_role(&self, user: &str, role: &str) -> Result<(), ServiceError>;
|
||||
async fn add_role_privilege(&self, role: &str, privilege: &str) -> Result<(), ServiceError>;
|
||||
async fn delete_role_privilege(&self, role: &str, privilege: &str) -> Result<(), ServiceError>;
|
||||
async fn delete_user_role(&self, user: &str, role: &str) -> Result<(), ServiceError>;
|
||||
}
|
||||
|
||||
#[automock]
|
||||
#[async_trait]
|
||||
pub trait UserService {
|
||||
|
|
|
|||
65
service/src/permission.rs
Normal file
65
service/src/permission.rs
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
use std::sync::Arc;
|
||||
|
||||
use async_trait::async_trait;
|
||||
use mockall::automock;
|
||||
|
||||
use crate::ServiceError;
|
||||
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
pub struct User {
|
||||
pub name: Arc<str>,
|
||||
}
|
||||
impl From<&dao::UserEntity> for User {
|
||||
fn from(user: &dao::UserEntity) -> Self {
|
||||
Self {
|
||||
name: user.name.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
pub struct Role {
|
||||
pub name: Arc<str>,
|
||||
}
|
||||
impl From<&dao::RoleEntity> for Role {
|
||||
fn from(role: &dao::RoleEntity) -> Self {
|
||||
Self {
|
||||
name: role.name.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
pub struct Privilege {
|
||||
pub name: Arc<str>,
|
||||
}
|
||||
impl From<&dao::PrivilegeEntity> for Privilege {
|
||||
fn from(privilege: &dao::PrivilegeEntity) -> Self {
|
||||
Self {
|
||||
name: privilege.name.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[automock]
|
||||
#[async_trait]
|
||||
pub trait PermissionService {
|
||||
async fn check_permission(&self, privilege: &str) -> Result<(), ServiceError>;
|
||||
|
||||
async fn create_user(&self, user: &str) -> Result<(), ServiceError>;
|
||||
async fn delete_user(&self, user: &str) -> Result<(), ServiceError>;
|
||||
async fn get_all_users(&self) -> Result<Arc<[User]>, ServiceError>;
|
||||
|
||||
async fn create_role(&self, role: &str) -> Result<(), ServiceError>;
|
||||
async fn delete_role(&self, role: &str) -> Result<(), ServiceError>;
|
||||
async fn get_all_roles(&self) -> Result<Arc<[Role]>, ServiceError>;
|
||||
|
||||
async fn create_privilege(&self, privilege: &str) -> Result<(), ServiceError>;
|
||||
async fn delete_privilege(&self, privilege: &str) -> Result<(), ServiceError>;
|
||||
async fn get_all_privileges(&self) -> Result<Arc<[Privilege]>, ServiceError>;
|
||||
|
||||
async fn add_user_role(&self, user: &str, role: &str) -> Result<(), ServiceError>;
|
||||
async fn add_role_privilege(&self, role: &str, privilege: &str) -> Result<(), ServiceError>;
|
||||
async fn delete_role_privilege(&self, role: &str, privilege: &str) -> Result<(), ServiceError>;
|
||||
async fn delete_user_role(&self, user: &str, role: &str) -> Result<(), ServiceError>;
|
||||
}
|
||||
|
|
@ -2,6 +2,12 @@ use std::sync::Arc;
|
|||
|
||||
use async_trait::async_trait;
|
||||
|
||||
mod permission;
|
||||
#[cfg(test)]
|
||||
mod test;
|
||||
|
||||
pub use permission::PermissionServiceImpl;
|
||||
|
||||
pub struct HelloServiceImpl<HelloDao, PermissionService>
|
||||
where
|
||||
HelloDao: dao::HelloDao + Sync + Send,
|
||||
|
|
@ -35,167 +41,6 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
pub struct PermissionServiceImpl<PermissionDao, UserService>
|
||||
where
|
||||
PermissionDao: dao::PermissionDao + Send + Sync,
|
||||
UserService: service::UserService + Send + Sync,
|
||||
{
|
||||
permission_dao: Arc<PermissionDao>,
|
||||
user_service: Arc<UserService>,
|
||||
}
|
||||
impl<PermissionDao, UserService> PermissionServiceImpl<PermissionDao, UserService>
|
||||
where
|
||||
PermissionDao: dao::PermissionDao + Send + Sync,
|
||||
UserService: service::UserService + Send + Sync,
|
||||
{
|
||||
pub fn new(permission_dao: Arc<PermissionDao>, user_service: Arc<UserService>) -> Self {
|
||||
Self {
|
||||
permission_dao,
|
||||
user_service,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const PERMISSION_SERVICE_PROCESS: &str = "permission-service";
|
||||
|
||||
#[async_trait]
|
||||
impl<PermissionDao, UserService> service::PermissionService
|
||||
for PermissionServiceImpl<PermissionDao, UserService>
|
||||
where
|
||||
PermissionDao: dao::PermissionDao + Send + Sync,
|
||||
UserService: service::UserService + Send + Sync,
|
||||
{
|
||||
async fn check_permission(&self, privilege: &str) -> Result<(), service::ServiceError> {
|
||||
let current_user = self.user_service.current_user().await?;
|
||||
if self
|
||||
.permission_dao
|
||||
.has_privilege(current_user.as_ref(), privilege)
|
||||
.await?
|
||||
{
|
||||
Ok(())
|
||||
} else {
|
||||
Err(service::ServiceError::Forbidden)
|
||||
}
|
||||
}
|
||||
|
||||
async fn create_user(&self, user: &str) -> Result<(), service::ServiceError> {
|
||||
self.check_permission("admin").await?;
|
||||
self.permission_dao
|
||||
.create_user(
|
||||
&dao::UserEntity { name: user.into() },
|
||||
PERMISSION_SERVICE_PROCESS,
|
||||
)
|
||||
.await?;
|
||||
Ok(())
|
||||
}
|
||||
async fn delete_user(&self, user: &str) -> Result<(), service::ServiceError> {
|
||||
self.check_permission("admin").await?;
|
||||
self.permission_dao.delete_user(user).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn get_all_users(&self) -> Result<Arc<[service::User]>, service::ServiceError> {
|
||||
self.check_permission("admin").await?;
|
||||
Ok(self
|
||||
.permission_dao
|
||||
.all_users()
|
||||
.await?
|
||||
.iter()
|
||||
.map(service::User::from)
|
||||
.collect())
|
||||
}
|
||||
|
||||
async fn create_role(&self, role: &str) -> Result<(), service::ServiceError> {
|
||||
self.check_permission("admin").await?;
|
||||
self.permission_dao
|
||||
.create_role(
|
||||
&dao::RoleEntity { name: role.into() },
|
||||
PERMISSION_SERVICE_PROCESS,
|
||||
)
|
||||
.await?;
|
||||
Ok(())
|
||||
}
|
||||
async fn delete_role(&self, role: &str) -> Result<(), service::ServiceError> {
|
||||
self.check_permission("admin").await?;
|
||||
self.permission_dao.delete_role(role).await?;
|
||||
Ok(())
|
||||
}
|
||||
async fn get_all_roles(&self) -> Result<Arc<[service::Role]>, service::ServiceError> {
|
||||
self.check_permission("admin").await?;
|
||||
Ok(self
|
||||
.permission_dao
|
||||
.all_roles()
|
||||
.await?
|
||||
.iter()
|
||||
.map(service::Role::from)
|
||||
.collect())
|
||||
}
|
||||
|
||||
async fn create_privilege(&self, privilege: &str) -> Result<(), service::ServiceError> {
|
||||
self.check_permission("admin").await?;
|
||||
self.permission_dao
|
||||
.create_privilege(
|
||||
&dao::PrivilegeEntity {
|
||||
name: privilege.into(),
|
||||
},
|
||||
PERMISSION_SERVICE_PROCESS,
|
||||
)
|
||||
.await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn delete_privilege(&self, privilege: &str) -> Result<(), service::ServiceError> {
|
||||
self.check_permission("admin").await?;
|
||||
self.permission_dao.delete_privilege(privilege).await?;
|
||||
Ok(())
|
||||
}
|
||||
async fn get_all_privileges(&self) -> Result<Arc<[service::Privilege]>, service::ServiceError> {
|
||||
self.check_permission("admin").await?;
|
||||
Ok(self
|
||||
.permission_dao
|
||||
.all_privileges()
|
||||
.await?
|
||||
.iter()
|
||||
.map(service::Privilege::from)
|
||||
.collect())
|
||||
}
|
||||
|
||||
async fn add_user_role(&self, user: &str, role: &str) -> Result<(), service::ServiceError> {
|
||||
self.check_permission("admin").await?;
|
||||
self.permission_dao
|
||||
.add_user_role(user, role, PERMISSION_SERVICE_PROCESS)
|
||||
.await?;
|
||||
Ok(())
|
||||
}
|
||||
async fn add_role_privilege(
|
||||
&self,
|
||||
role: &str,
|
||||
privilege: &str,
|
||||
) -> Result<(), service::ServiceError> {
|
||||
self.check_permission("admin").await?;
|
||||
self.permission_dao
|
||||
.add_role_privilege(role, privilege, PERMISSION_SERVICE_PROCESS)
|
||||
.await?;
|
||||
Ok(())
|
||||
}
|
||||
async fn delete_role_privilege(
|
||||
&self,
|
||||
role: &str,
|
||||
privilege: &str,
|
||||
) -> Result<(), service::ServiceError> {
|
||||
self.check_permission("admin").await?;
|
||||
self.permission_dao
|
||||
.delete_role_privilege(role, privilege)
|
||||
.await?;
|
||||
Ok(())
|
||||
}
|
||||
async fn delete_user_role(&self, user: &str, role: &str) -> Result<(), service::ServiceError> {
|
||||
self.check_permission("admin").await?;
|
||||
self.permission_dao.delete_user_role(user, role).await?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
pub struct UserServiceDev;
|
||||
|
||||
#[async_trait]
|
||||
|
|
@ -204,513 +49,3 @@ impl service::UserService for UserServiceDev {
|
|||
Ok("DEVUSER".into())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use mockall::predicate::eq;
|
||||
use service::{HelloService, MockPermissionService, PermissionService};
|
||||
use tokio;
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_get_hello_successful() {
|
||||
let mut hello_dao = dao::MockHelloDao::new();
|
||||
hello_dao
|
||||
.expect_get_hello()
|
||||
.times(1)
|
||||
.returning(|| Ok("Hello, world!".into()));
|
||||
let mut permission_service = MockPermissionService::new();
|
||||
permission_service
|
||||
.expect_check_permission()
|
||||
.times(1)
|
||||
.returning(|_| Ok(()));
|
||||
|
||||
let hello_service =
|
||||
HelloServiceImpl::new(Arc::new(hello_dao), Arc::new(permission_service));
|
||||
assert_eq!(
|
||||
"Hello, world!",
|
||||
hello_service.hello().await.unwrap().as_ref()
|
||||
);
|
||||
}
|
||||
|
||||
fn test_forbidden<T>(result: &Result<T, service::ServiceError>) {
|
||||
if let Err(service::ServiceError::Forbidden) = result {
|
||||
// All good
|
||||
} else {
|
||||
panic!("Expected forbidden error");
|
||||
}
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_get_hello_no_permission() {
|
||||
let hello_dao = dao::MockHelloDao::new();
|
||||
|
||||
let mut permission_service = MockPermissionService::new();
|
||||
permission_service
|
||||
.expect_check_permission()
|
||||
.times(1)
|
||||
.returning(|_| Err(service::ServiceError::Forbidden));
|
||||
|
||||
let hello_service =
|
||||
HelloServiceImpl::new(Arc::new(hello_dao), Arc::new(permission_service));
|
||||
test_forbidden(&hello_service.hello().await);
|
||||
}
|
||||
|
||||
fn generate_dependencies_mocks_permission(
|
||||
grant: bool,
|
||||
privilege: &'static str,
|
||||
) -> (dao::MockPermissionDao, service::MockUserService) {
|
||||
let mut permission_dao = dao::MockPermissionDao::new();
|
||||
permission_dao
|
||||
.expect_has_privilege()
|
||||
.with(eq("DEVUSER"), eq(privilege))
|
||||
.returning(move |_, _| Ok(grant));
|
||||
|
||||
let mut user_service = service::MockUserService::new();
|
||||
user_service
|
||||
.expect_current_user()
|
||||
.returning(|| Ok("DEVUSER".into()));
|
||||
(permission_dao, user_service)
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_check_permission() {
|
||||
let (permission_dao, user_service) = generate_dependencies_mocks_permission(true, "hello");
|
||||
|
||||
let permission_service =
|
||||
PermissionServiceImpl::new(Arc::new(permission_dao), Arc::new(user_service));
|
||||
let result = permission_service.check_permission("hello").await;
|
||||
result.expect("Expected successful authorization");
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_check_permission_denied() {
|
||||
let (permission_dao, user_service) = generate_dependencies_mocks_permission(false, "hello");
|
||||
|
||||
let permission_service =
|
||||
PermissionServiceImpl::new(Arc::new(permission_dao), Arc::new(user_service));
|
||||
let result = permission_service.check_permission("hello").await;
|
||||
test_forbidden(&result);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_user_service_dev() {
|
||||
use service::UserService;
|
||||
let user_service = UserServiceDev;
|
||||
assert_eq!(
|
||||
"DEVUSER",
|
||||
user_service.current_user().await.unwrap().as_ref()
|
||||
);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_create_user() {
|
||||
let (mut permission_dao, user_service) =
|
||||
generate_dependencies_mocks_permission(true, "admin");
|
||||
permission_dao
|
||||
.expect_create_user()
|
||||
.with(
|
||||
eq(dao::UserEntity {
|
||||
name: "testuser".into(),
|
||||
}),
|
||||
eq("permission-service"),
|
||||
)
|
||||
.times(1)
|
||||
.returning(|_, _| Ok(()));
|
||||
|
||||
let permission_service =
|
||||
PermissionServiceImpl::new(Arc::new(permission_dao), Arc::new(user_service));
|
||||
permission_service
|
||||
.create_user("testuser")
|
||||
.await
|
||||
.expect("Extected successful user creation");
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_create_user_without_permission() {
|
||||
let (permission_dao, user_service) = generate_dependencies_mocks_permission(false, "admin");
|
||||
let permission_service =
|
||||
PermissionServiceImpl::new(Arc::new(permission_dao), Arc::new(user_service));
|
||||
test_forbidden(&permission_service.create_user("testuser").await);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_delete_user() {
|
||||
let (mut permission_dao, user_service) =
|
||||
generate_dependencies_mocks_permission(true, "admin");
|
||||
permission_dao
|
||||
.expect_delete_user()
|
||||
.with(eq("testuser"))
|
||||
.times(1)
|
||||
.returning(|_| Ok(()));
|
||||
|
||||
let permission_service =
|
||||
PermissionServiceImpl::new(Arc::new(permission_dao), Arc::new(user_service));
|
||||
|
||||
permission_service
|
||||
.delete_user("testuser")
|
||||
.await
|
||||
.expect("Expected successful delete");
|
||||
}
|
||||
#[tokio::test]
|
||||
async fn test_delete_user_without_permission() {
|
||||
let (permission_dao, user_service) = generate_dependencies_mocks_permission(false, "admin");
|
||||
let permission_service =
|
||||
PermissionServiceImpl::new(Arc::new(permission_dao), Arc::new(user_service));
|
||||
test_forbidden(&permission_service.delete_user("testuser").await);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_create_role() {
|
||||
let (mut permission_dao, user_service) =
|
||||
generate_dependencies_mocks_permission(true, "admin");
|
||||
permission_dao
|
||||
.expect_create_role()
|
||||
.with(
|
||||
eq(dao::RoleEntity {
|
||||
name: "testrole".into(),
|
||||
}),
|
||||
eq("permission-service"),
|
||||
)
|
||||
.times(1)
|
||||
.returning(|_, _| Ok(()));
|
||||
|
||||
let permission_service =
|
||||
PermissionServiceImpl::new(Arc::new(permission_dao), Arc::new(user_service));
|
||||
permission_service
|
||||
.create_role("testrole")
|
||||
.await
|
||||
.expect("Extected successful role creation");
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_create_role_without_permission() {
|
||||
let (permission_dao, user_service) = generate_dependencies_mocks_permission(false, "admin");
|
||||
let permission_service =
|
||||
PermissionServiceImpl::new(Arc::new(permission_dao), Arc::new(user_service));
|
||||
test_forbidden(&permission_service.create_role("testrole").await);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_delete_role() {
|
||||
let (mut permission_dao, user_service) =
|
||||
generate_dependencies_mocks_permission(true, "admin");
|
||||
permission_dao
|
||||
.expect_delete_role()
|
||||
.with(eq("testrole"))
|
||||
.times(1)
|
||||
.returning(|_| Ok(()));
|
||||
|
||||
let permission_service =
|
||||
PermissionServiceImpl::new(Arc::new(permission_dao), Arc::new(user_service));
|
||||
|
||||
permission_service
|
||||
.delete_role("testrole")
|
||||
.await
|
||||
.expect("Expected successful delete");
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_delete_role_without_permission() {
|
||||
let (permission_dao, user_service) = generate_dependencies_mocks_permission(false, "admin");
|
||||
let permission_service =
|
||||
PermissionServiceImpl::new(Arc::new(permission_dao), Arc::new(user_service));
|
||||
test_forbidden(&permission_service.delete_role("testrole").await);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_create_privilege() {
|
||||
let (mut permission_dao, user_service) =
|
||||
generate_dependencies_mocks_permission(true, "admin");
|
||||
permission_dao
|
||||
.expect_create_privilege()
|
||||
.with(
|
||||
eq(dao::PrivilegeEntity {
|
||||
name: "testprivilege".into(),
|
||||
}),
|
||||
eq("permission-service"),
|
||||
)
|
||||
.times(1)
|
||||
.returning(|_, _| Ok(()));
|
||||
|
||||
let permission_service =
|
||||
PermissionServiceImpl::new(Arc::new(permission_dao), Arc::new(user_service));
|
||||
|
||||
permission_service
|
||||
.create_privilege("testprivilege")
|
||||
.await
|
||||
.expect("Extected successful privilege creation");
|
||||
}
|
||||
#[tokio::test]
|
||||
async fn test_create_privilege_without_permission() {
|
||||
let (permission_dao, user_service) = generate_dependencies_mocks_permission(false, "admin");
|
||||
let permission_service =
|
||||
PermissionServiceImpl::new(Arc::new(permission_dao), Arc::new(user_service));
|
||||
test_forbidden(&permission_service.create_privilege("testprivilege").await);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_delete_privilege() {
|
||||
let (mut permission_dao, user_service) =
|
||||
generate_dependencies_mocks_permission(true, "admin");
|
||||
permission_dao
|
||||
.expect_delete_privilege()
|
||||
.with(eq("testprivilege"))
|
||||
.times(1)
|
||||
.returning(|_| Ok(()));
|
||||
|
||||
let permission_service =
|
||||
PermissionServiceImpl::new(Arc::new(permission_dao), Arc::new(user_service));
|
||||
|
||||
permission_service
|
||||
.delete_privilege("testprivilege")
|
||||
.await
|
||||
.expect("Expected successful delete");
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_delete_privilege_without_permission() {
|
||||
let (permission_dao, user_service) = generate_dependencies_mocks_permission(false, "admin");
|
||||
let permission_service =
|
||||
PermissionServiceImpl::new(Arc::new(permission_dao), Arc::new(user_service));
|
||||
test_forbidden(&permission_service.delete_privilege("testprivilege").await);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_add_user_role() {
|
||||
let (mut permission_dao, user_service) =
|
||||
generate_dependencies_mocks_permission(true, "admin");
|
||||
permission_dao
|
||||
.expect_add_user_role()
|
||||
.with(eq("testuser"), eq("testrole"), eq("permission-service"))
|
||||
.times(1)
|
||||
.returning(|_, _, _| Ok(()));
|
||||
|
||||
let permission_service =
|
||||
PermissionServiceImpl::new(Arc::new(permission_dao), Arc::new(user_service));
|
||||
|
||||
permission_service
|
||||
.add_user_role("testuser", "testrole")
|
||||
.await
|
||||
.expect("Extected successful user role creation");
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_add_user_role_without_permission() {
|
||||
let (permission_dao, user_service) = generate_dependencies_mocks_permission(false, "admin");
|
||||
let permission_service =
|
||||
PermissionServiceImpl::new(Arc::new(permission_dao), Arc::new(user_service));
|
||||
test_forbidden(
|
||||
&permission_service
|
||||
.add_user_role("testuser", "testrole")
|
||||
.await,
|
||||
);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_add_role_privilege() {
|
||||
let (mut permission_dao, user_service) =
|
||||
generate_dependencies_mocks_permission(true, "admin");
|
||||
permission_dao
|
||||
.expect_add_role_privilege()
|
||||
.with(
|
||||
eq("testrole"),
|
||||
eq("testprivilege"),
|
||||
eq("permission-service"),
|
||||
)
|
||||
.times(1)
|
||||
.returning(|_, _, _| Ok(()));
|
||||
|
||||
let permission_service =
|
||||
PermissionServiceImpl::new(Arc::new(permission_dao), Arc::new(user_service));
|
||||
|
||||
permission_service
|
||||
.add_role_privilege("testrole", "testprivilege")
|
||||
.await
|
||||
.expect("Extected successful role privilege creation");
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_add_role_privilege_without_permission() {
|
||||
let (permission_dao, user_service) = generate_dependencies_mocks_permission(false, "admin");
|
||||
let permission_service =
|
||||
PermissionServiceImpl::new(Arc::new(permission_dao), Arc::new(user_service));
|
||||
test_forbidden(
|
||||
&permission_service
|
||||
.add_role_privilege("testrole", "testprivilege")
|
||||
.await,
|
||||
);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_delete_role_privilege() {
|
||||
let (mut permission_dao, user_service) =
|
||||
generate_dependencies_mocks_permission(true, "admin");
|
||||
permission_dao
|
||||
.expect_delete_role_privilege()
|
||||
.with(eq("testrole"), eq("testprivilege"))
|
||||
.times(1)
|
||||
.returning(|_, _| Ok(()));
|
||||
|
||||
let permission_service =
|
||||
PermissionServiceImpl::new(Arc::new(permission_dao), Arc::new(user_service));
|
||||
|
||||
permission_service
|
||||
.delete_role_privilege("testrole", "testprivilege")
|
||||
.await
|
||||
.expect("Extected successful role privilege deletion");
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_delete_role_privilege_without_permission() {
|
||||
let (permission_dao, user_service) = generate_dependencies_mocks_permission(false, "admin");
|
||||
let permission_service =
|
||||
PermissionServiceImpl::new(Arc::new(permission_dao), Arc::new(user_service));
|
||||
test_forbidden(
|
||||
&permission_service
|
||||
.delete_role_privilege("testrole", "testprivilege")
|
||||
.await,
|
||||
);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_delete_user_role() {
|
||||
let (mut permission_dao, user_service) =
|
||||
generate_dependencies_mocks_permission(true, "admin");
|
||||
permission_dao
|
||||
.expect_delete_user_role()
|
||||
.with(eq("testuser"), eq("testrole"))
|
||||
.times(1)
|
||||
.returning(|_, _| Ok(()));
|
||||
|
||||
let permission_service =
|
||||
PermissionServiceImpl::new(Arc::new(permission_dao), Arc::new(user_service));
|
||||
|
||||
permission_service
|
||||
.delete_user_role("testuser", "testrole")
|
||||
.await
|
||||
.expect("Extected successful user role deletion");
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_delete_user_role_without_permission() {
|
||||
let (permission_dao, user_service) = generate_dependencies_mocks_permission(false, "admin");
|
||||
let permission_service =
|
||||
PermissionServiceImpl::new(Arc::new(permission_dao), Arc::new(user_service));
|
||||
test_forbidden(
|
||||
&permission_service
|
||||
.delete_user_role("testuser", "testrole")
|
||||
.await,
|
||||
);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_all_roles() {
|
||||
let (mut permission_dao, user_service) =
|
||||
generate_dependencies_mocks_permission(true, "admin");
|
||||
permission_dao.expect_all_roles().times(1).returning(|| {
|
||||
Ok(Arc::new([
|
||||
dao::RoleEntity {
|
||||
name: "testrole".into(),
|
||||
},
|
||||
dao::RoleEntity {
|
||||
name: "testrole2".into(),
|
||||
},
|
||||
]))
|
||||
});
|
||||
|
||||
let permission_service =
|
||||
PermissionServiceImpl::new(Arc::new(permission_dao), Arc::new(user_service));
|
||||
|
||||
let all_roles = permission_service
|
||||
.get_all_roles()
|
||||
.await
|
||||
.expect("Expected roles successfully");
|
||||
assert_eq!(all_roles.len(), 2);
|
||||
assert_eq!(all_roles[0].name.as_ref(), "testrole");
|
||||
assert_eq!(all_roles[1].name.as_ref(), "testrole2");
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_all_roles_without_permission() {
|
||||
let (permission_dao, user_service) = generate_dependencies_mocks_permission(false, "admin");
|
||||
let permission_service =
|
||||
PermissionServiceImpl::new(Arc::new(permission_dao), Arc::new(user_service));
|
||||
test_forbidden(&permission_service.get_all_roles().await);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_all_users() {
|
||||
let (mut permission_dao, user_service) =
|
||||
generate_dependencies_mocks_permission(true, "admin");
|
||||
permission_dao.expect_all_users().times(1).returning(|| {
|
||||
Ok(Arc::new([
|
||||
dao::UserEntity {
|
||||
name: "testuser".into(),
|
||||
},
|
||||
dao::UserEntity {
|
||||
name: "testuser2".into(),
|
||||
},
|
||||
]))
|
||||
});
|
||||
|
||||
let permission_service =
|
||||
PermissionServiceImpl::new(Arc::new(permission_dao), Arc::new(user_service));
|
||||
|
||||
let all_users = permission_service
|
||||
.get_all_users()
|
||||
.await
|
||||
.expect("Expected users successfully");
|
||||
|
||||
assert_eq!(all_users.len(), 2);
|
||||
assert_eq!(all_users[0].name.as_ref(), "testuser");
|
||||
assert_eq!(all_users[1].name.as_ref(), "testuser2");
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_all_users_without_permission() {
|
||||
let (permission_dao, user_service) = generate_dependencies_mocks_permission(false, "admin");
|
||||
let permission_service =
|
||||
PermissionServiceImpl::new(Arc::new(permission_dao), Arc::new(user_service));
|
||||
test_forbidden(&permission_service.get_all_users().await);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_all_privileges() {
|
||||
let (mut permission_dao, user_service) =
|
||||
generate_dependencies_mocks_permission(true, "admin");
|
||||
permission_dao
|
||||
.expect_all_privileges()
|
||||
.times(1)
|
||||
.returning(|| {
|
||||
Ok(Arc::new([
|
||||
dao::PrivilegeEntity {
|
||||
name: "testprivilege".into(),
|
||||
},
|
||||
dao::PrivilegeEntity {
|
||||
name: "testprivilege2".into(),
|
||||
},
|
||||
]))
|
||||
});
|
||||
|
||||
let permission_service =
|
||||
PermissionServiceImpl::new(Arc::new(permission_dao), Arc::new(user_service));
|
||||
|
||||
let all_privileges = permission_service
|
||||
.get_all_privileges()
|
||||
.await
|
||||
.expect("Expected privileges successfully");
|
||||
|
||||
assert_eq!(all_privileges.len(), 2);
|
||||
assert_eq!(all_privileges[0].name.as_ref(), "testprivilege");
|
||||
assert_eq!(all_privileges[1].name.as_ref(), "testprivilege2");
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_all_privileges_without_permission() {
|
||||
let (permission_dao, user_service) = generate_dependencies_mocks_permission(false, "admin");
|
||||
let permission_service =
|
||||
PermissionServiceImpl::new(Arc::new(permission_dao), Arc::new(user_service));
|
||||
test_forbidden(&permission_service.get_all_privileges().await);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
164
service_impl/src/permission.rs
Normal file
164
service_impl/src/permission.rs
Normal file
|
|
@ -0,0 +1,164 @@
|
|||
use std::sync::Arc;
|
||||
|
||||
use async_trait::async_trait;
|
||||
|
||||
pub struct PermissionServiceImpl<PermissionDao, UserService>
|
||||
where
|
||||
PermissionDao: dao::PermissionDao + Send + Sync,
|
||||
UserService: service::UserService + Send + Sync,
|
||||
{
|
||||
permission_dao: Arc<PermissionDao>,
|
||||
user_service: Arc<UserService>,
|
||||
}
|
||||
impl<PermissionDao, UserService> PermissionServiceImpl<PermissionDao, UserService>
|
||||
where
|
||||
PermissionDao: dao::PermissionDao + Send + Sync,
|
||||
UserService: service::UserService + Send + Sync,
|
||||
{
|
||||
pub fn new(permission_dao: Arc<PermissionDao>, user_service: Arc<UserService>) -> Self {
|
||||
Self {
|
||||
permission_dao,
|
||||
user_service,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const PERMISSION_SERVICE_PROCESS: &str = "permission-service";
|
||||
|
||||
#[async_trait]
|
||||
impl<PermissionDao, UserService> service::PermissionService
|
||||
for PermissionServiceImpl<PermissionDao, UserService>
|
||||
where
|
||||
PermissionDao: dao::PermissionDao + Send + Sync,
|
||||
UserService: service::UserService + Send + Sync,
|
||||
{
|
||||
async fn check_permission(&self, privilege: &str) -> Result<(), service::ServiceError> {
|
||||
let current_user = self.user_service.current_user().await?;
|
||||
if self
|
||||
.permission_dao
|
||||
.has_privilege(current_user.as_ref(), privilege)
|
||||
.await?
|
||||
{
|
||||
Ok(())
|
||||
} else {
|
||||
Err(service::ServiceError::Forbidden)
|
||||
}
|
||||
}
|
||||
|
||||
async fn create_user(&self, user: &str) -> Result<(), service::ServiceError> {
|
||||
self.check_permission("admin").await?;
|
||||
self.permission_dao
|
||||
.create_user(
|
||||
&dao::UserEntity { name: user.into() },
|
||||
PERMISSION_SERVICE_PROCESS,
|
||||
)
|
||||
.await?;
|
||||
Ok(())
|
||||
}
|
||||
async fn delete_user(&self, user: &str) -> Result<(), service::ServiceError> {
|
||||
self.check_permission("admin").await?;
|
||||
self.permission_dao.delete_user(user).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn get_all_users(&self) -> Result<Arc<[service::User]>, service::ServiceError> {
|
||||
self.check_permission("admin").await?;
|
||||
Ok(self
|
||||
.permission_dao
|
||||
.all_users()
|
||||
.await?
|
||||
.iter()
|
||||
.map(service::User::from)
|
||||
.collect())
|
||||
}
|
||||
|
||||
async fn create_role(&self, role: &str) -> Result<(), service::ServiceError> {
|
||||
self.check_permission("admin").await?;
|
||||
self.permission_dao
|
||||
.create_role(
|
||||
&dao::RoleEntity { name: role.into() },
|
||||
PERMISSION_SERVICE_PROCESS,
|
||||
)
|
||||
.await?;
|
||||
Ok(())
|
||||
}
|
||||
async fn delete_role(&self, role: &str) -> Result<(), service::ServiceError> {
|
||||
self.check_permission("admin").await?;
|
||||
self.permission_dao.delete_role(role).await?;
|
||||
Ok(())
|
||||
}
|
||||
async fn get_all_roles(&self) -> Result<Arc<[service::Role]>, service::ServiceError> {
|
||||
self.check_permission("admin").await?;
|
||||
Ok(self
|
||||
.permission_dao
|
||||
.all_roles()
|
||||
.await?
|
||||
.iter()
|
||||
.map(service::Role::from)
|
||||
.collect())
|
||||
}
|
||||
|
||||
async fn create_privilege(&self, privilege: &str) -> Result<(), service::ServiceError> {
|
||||
self.check_permission("admin").await?;
|
||||
self.permission_dao
|
||||
.create_privilege(
|
||||
&dao::PrivilegeEntity {
|
||||
name: privilege.into(),
|
||||
},
|
||||
PERMISSION_SERVICE_PROCESS,
|
||||
)
|
||||
.await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn delete_privilege(&self, privilege: &str) -> Result<(), service::ServiceError> {
|
||||
self.check_permission("admin").await?;
|
||||
self.permission_dao.delete_privilege(privilege).await?;
|
||||
Ok(())
|
||||
}
|
||||
async fn get_all_privileges(&self) -> Result<Arc<[service::Privilege]>, service::ServiceError> {
|
||||
self.check_permission("admin").await?;
|
||||
Ok(self
|
||||
.permission_dao
|
||||
.all_privileges()
|
||||
.await?
|
||||
.iter()
|
||||
.map(service::Privilege::from)
|
||||
.collect())
|
||||
}
|
||||
|
||||
async fn add_user_role(&self, user: &str, role: &str) -> Result<(), service::ServiceError> {
|
||||
self.check_permission("admin").await?;
|
||||
self.permission_dao
|
||||
.add_user_role(user, role, PERMISSION_SERVICE_PROCESS)
|
||||
.await?;
|
||||
Ok(())
|
||||
}
|
||||
async fn add_role_privilege(
|
||||
&self,
|
||||
role: &str,
|
||||
privilege: &str,
|
||||
) -> Result<(), service::ServiceError> {
|
||||
self.check_permission("admin").await?;
|
||||
self.permission_dao
|
||||
.add_role_privilege(role, privilege, PERMISSION_SERVICE_PROCESS)
|
||||
.await?;
|
||||
Ok(())
|
||||
}
|
||||
async fn delete_role_privilege(
|
||||
&self,
|
||||
role: &str,
|
||||
privilege: &str,
|
||||
) -> Result<(), service::ServiceError> {
|
||||
self.check_permission("admin").await?;
|
||||
self.permission_dao
|
||||
.delete_role_privilege(role, privilege)
|
||||
.await?;
|
||||
Ok(())
|
||||
}
|
||||
async fn delete_user_role(&self, user: &str, role: &str) -> Result<(), service::ServiceError> {
|
||||
self.check_permission("admin").await?;
|
||||
self.permission_dao.delete_user_role(user, role).await?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
1
service_impl/src/test/mod.rs
Normal file
1
service_impl/src/test/mod.rs
Normal file
|
|
@ -0,0 +1 @@
|
|||
mod permission_test;
|
||||
457
service_impl/src/test/permission_test.rs
Normal file
457
service_impl/src/test/permission_test.rs
Normal file
|
|
@ -0,0 +1,457 @@
|
|||
use crate::*;
|
||||
use mockall::predicate::eq;
|
||||
use service::PermissionService;
|
||||
use tokio;
|
||||
|
||||
fn generate_dependencies_mocks_permission(
|
||||
grant: bool,
|
||||
privilege: &'static str,
|
||||
) -> (dao::MockPermissionDao, service::MockUserService) {
|
||||
let mut permission_dao = dao::MockPermissionDao::new();
|
||||
permission_dao
|
||||
.expect_has_privilege()
|
||||
.with(eq("DEVUSER"), eq(privilege))
|
||||
.returning(move |_, _| Ok(grant));
|
||||
|
||||
let mut user_service = service::MockUserService::new();
|
||||
user_service
|
||||
.expect_current_user()
|
||||
.returning(|| Ok("DEVUSER".into()));
|
||||
(permission_dao, user_service)
|
||||
}
|
||||
|
||||
fn test_forbidden<T>(result: &Result<T, service::ServiceError>) {
|
||||
if let Err(service::ServiceError::Forbidden) = result {
|
||||
// All good
|
||||
} else {
|
||||
panic!("Expected forbidden error");
|
||||
}
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_check_permission() {
|
||||
let (permission_dao, user_service) = generate_dependencies_mocks_permission(true, "hello");
|
||||
|
||||
let permission_service =
|
||||
PermissionServiceImpl::new(Arc::new(permission_dao), Arc::new(user_service));
|
||||
let result = permission_service.check_permission("hello").await;
|
||||
result.expect("Expected successful authorization");
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_check_permission_denied() {
|
||||
let (permission_dao, user_service) = generate_dependencies_mocks_permission(false, "hello");
|
||||
|
||||
let permission_service =
|
||||
PermissionServiceImpl::new(Arc::new(permission_dao), Arc::new(user_service));
|
||||
let result = permission_service.check_permission("hello").await;
|
||||
test_forbidden(&result);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_user_service_dev() {
|
||||
use service::UserService;
|
||||
let user_service = UserServiceDev;
|
||||
assert_eq!(
|
||||
"DEVUSER",
|
||||
user_service.current_user().await.unwrap().as_ref()
|
||||
);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_create_user() {
|
||||
let (mut permission_dao, user_service) = generate_dependencies_mocks_permission(true, "admin");
|
||||
permission_dao
|
||||
.expect_create_user()
|
||||
.with(
|
||||
eq(dao::UserEntity {
|
||||
name: "testuser".into(),
|
||||
}),
|
||||
eq("permission-service"),
|
||||
)
|
||||
.times(1)
|
||||
.returning(|_, _| Ok(()));
|
||||
|
||||
let permission_service =
|
||||
PermissionServiceImpl::new(Arc::new(permission_dao), Arc::new(user_service));
|
||||
permission_service
|
||||
.create_user("testuser")
|
||||
.await
|
||||
.expect("Extected successful user creation");
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_create_user_without_permission() {
|
||||
let (permission_dao, user_service) = generate_dependencies_mocks_permission(false, "admin");
|
||||
let permission_service =
|
||||
PermissionServiceImpl::new(Arc::new(permission_dao), Arc::new(user_service));
|
||||
test_forbidden(&permission_service.create_user("testuser").await);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_delete_user() {
|
||||
let (mut permission_dao, user_service) = generate_dependencies_mocks_permission(true, "admin");
|
||||
permission_dao
|
||||
.expect_delete_user()
|
||||
.with(eq("testuser"))
|
||||
.times(1)
|
||||
.returning(|_| Ok(()));
|
||||
|
||||
let permission_service =
|
||||
PermissionServiceImpl::new(Arc::new(permission_dao), Arc::new(user_service));
|
||||
|
||||
permission_service
|
||||
.delete_user("testuser")
|
||||
.await
|
||||
.expect("Expected successful delete");
|
||||
}
|
||||
#[tokio::test]
|
||||
async fn test_delete_user_without_permission() {
|
||||
let (permission_dao, user_service) = generate_dependencies_mocks_permission(false, "admin");
|
||||
let permission_service =
|
||||
PermissionServiceImpl::new(Arc::new(permission_dao), Arc::new(user_service));
|
||||
test_forbidden(&permission_service.delete_user("testuser").await);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_create_role() {
|
||||
let (mut permission_dao, user_service) = generate_dependencies_mocks_permission(true, "admin");
|
||||
permission_dao
|
||||
.expect_create_role()
|
||||
.with(
|
||||
eq(dao::RoleEntity {
|
||||
name: "testrole".into(),
|
||||
}),
|
||||
eq("permission-service"),
|
||||
)
|
||||
.times(1)
|
||||
.returning(|_, _| Ok(()));
|
||||
|
||||
let permission_service =
|
||||
PermissionServiceImpl::new(Arc::new(permission_dao), Arc::new(user_service));
|
||||
permission_service
|
||||
.create_role("testrole")
|
||||
.await
|
||||
.expect("Extected successful role creation");
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_create_role_without_permission() {
|
||||
let (permission_dao, user_service) = generate_dependencies_mocks_permission(false, "admin");
|
||||
let permission_service =
|
||||
PermissionServiceImpl::new(Arc::new(permission_dao), Arc::new(user_service));
|
||||
test_forbidden(&permission_service.create_role("testrole").await);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_delete_role() {
|
||||
let (mut permission_dao, user_service) = generate_dependencies_mocks_permission(true, "admin");
|
||||
permission_dao
|
||||
.expect_delete_role()
|
||||
.with(eq("testrole"))
|
||||
.times(1)
|
||||
.returning(|_| Ok(()));
|
||||
|
||||
let permission_service =
|
||||
PermissionServiceImpl::new(Arc::new(permission_dao), Arc::new(user_service));
|
||||
|
||||
permission_service
|
||||
.delete_role("testrole")
|
||||
.await
|
||||
.expect("Expected successful delete");
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_delete_role_without_permission() {
|
||||
let (permission_dao, user_service) = generate_dependencies_mocks_permission(false, "admin");
|
||||
let permission_service =
|
||||
PermissionServiceImpl::new(Arc::new(permission_dao), Arc::new(user_service));
|
||||
test_forbidden(&permission_service.delete_role("testrole").await);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_create_privilege() {
|
||||
let (mut permission_dao, user_service) = generate_dependencies_mocks_permission(true, "admin");
|
||||
permission_dao
|
||||
.expect_create_privilege()
|
||||
.with(
|
||||
eq(dao::PrivilegeEntity {
|
||||
name: "testprivilege".into(),
|
||||
}),
|
||||
eq("permission-service"),
|
||||
)
|
||||
.times(1)
|
||||
.returning(|_, _| Ok(()));
|
||||
|
||||
let permission_service =
|
||||
PermissionServiceImpl::new(Arc::new(permission_dao), Arc::new(user_service));
|
||||
|
||||
permission_service
|
||||
.create_privilege("testprivilege")
|
||||
.await
|
||||
.expect("Extected successful privilege creation");
|
||||
}
|
||||
#[tokio::test]
|
||||
async fn test_create_privilege_without_permission() {
|
||||
let (permission_dao, user_service) = generate_dependencies_mocks_permission(false, "admin");
|
||||
let permission_service =
|
||||
PermissionServiceImpl::new(Arc::new(permission_dao), Arc::new(user_service));
|
||||
test_forbidden(&permission_service.create_privilege("testprivilege").await);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_delete_privilege() {
|
||||
let (mut permission_dao, user_service) = generate_dependencies_mocks_permission(true, "admin");
|
||||
permission_dao
|
||||
.expect_delete_privilege()
|
||||
.with(eq("testprivilege"))
|
||||
.times(1)
|
||||
.returning(|_| Ok(()));
|
||||
|
||||
let permission_service =
|
||||
PermissionServiceImpl::new(Arc::new(permission_dao), Arc::new(user_service));
|
||||
|
||||
permission_service
|
||||
.delete_privilege("testprivilege")
|
||||
.await
|
||||
.expect("Expected successful delete");
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_delete_privilege_without_permission() {
|
||||
let (permission_dao, user_service) = generate_dependencies_mocks_permission(false, "admin");
|
||||
let permission_service =
|
||||
PermissionServiceImpl::new(Arc::new(permission_dao), Arc::new(user_service));
|
||||
test_forbidden(&permission_service.delete_privilege("testprivilege").await);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_add_user_role() {
|
||||
let (mut permission_dao, user_service) = generate_dependencies_mocks_permission(true, "admin");
|
||||
permission_dao
|
||||
.expect_add_user_role()
|
||||
.with(eq("testuser"), eq("testrole"), eq("permission-service"))
|
||||
.times(1)
|
||||
.returning(|_, _, _| Ok(()));
|
||||
|
||||
let permission_service =
|
||||
PermissionServiceImpl::new(Arc::new(permission_dao), Arc::new(user_service));
|
||||
|
||||
permission_service
|
||||
.add_user_role("testuser", "testrole")
|
||||
.await
|
||||
.expect("Extected successful user role creation");
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_add_user_role_without_permission() {
|
||||
let (permission_dao, user_service) = generate_dependencies_mocks_permission(false, "admin");
|
||||
let permission_service =
|
||||
PermissionServiceImpl::new(Arc::new(permission_dao), Arc::new(user_service));
|
||||
test_forbidden(
|
||||
&permission_service
|
||||
.add_user_role("testuser", "testrole")
|
||||
.await,
|
||||
);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_add_role_privilege() {
|
||||
let (mut permission_dao, user_service) = generate_dependencies_mocks_permission(true, "admin");
|
||||
permission_dao
|
||||
.expect_add_role_privilege()
|
||||
.with(
|
||||
eq("testrole"),
|
||||
eq("testprivilege"),
|
||||
eq("permission-service"),
|
||||
)
|
||||
.times(1)
|
||||
.returning(|_, _, _| Ok(()));
|
||||
|
||||
let permission_service =
|
||||
PermissionServiceImpl::new(Arc::new(permission_dao), Arc::new(user_service));
|
||||
|
||||
permission_service
|
||||
.add_role_privilege("testrole", "testprivilege")
|
||||
.await
|
||||
.expect("Extected successful role privilege creation");
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_add_role_privilege_without_permission() {
|
||||
let (permission_dao, user_service) = generate_dependencies_mocks_permission(false, "admin");
|
||||
let permission_service =
|
||||
PermissionServiceImpl::new(Arc::new(permission_dao), Arc::new(user_service));
|
||||
test_forbidden(
|
||||
&permission_service
|
||||
.add_role_privilege("testrole", "testprivilege")
|
||||
.await,
|
||||
);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_delete_role_privilege() {
|
||||
let (mut permission_dao, user_service) = generate_dependencies_mocks_permission(true, "admin");
|
||||
permission_dao
|
||||
.expect_delete_role_privilege()
|
||||
.with(eq("testrole"), eq("testprivilege"))
|
||||
.times(1)
|
||||
.returning(|_, _| Ok(()));
|
||||
|
||||
let permission_service =
|
||||
PermissionServiceImpl::new(Arc::new(permission_dao), Arc::new(user_service));
|
||||
|
||||
permission_service
|
||||
.delete_role_privilege("testrole", "testprivilege")
|
||||
.await
|
||||
.expect("Extected successful role privilege deletion");
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_delete_role_privilege_without_permission() {
|
||||
let (permission_dao, user_service) = generate_dependencies_mocks_permission(false, "admin");
|
||||
let permission_service =
|
||||
PermissionServiceImpl::new(Arc::new(permission_dao), Arc::new(user_service));
|
||||
test_forbidden(
|
||||
&permission_service
|
||||
.delete_role_privilege("testrole", "testprivilege")
|
||||
.await,
|
||||
);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_delete_user_role() {
|
||||
let (mut permission_dao, user_service) = generate_dependencies_mocks_permission(true, "admin");
|
||||
permission_dao
|
||||
.expect_delete_user_role()
|
||||
.with(eq("testuser"), eq("testrole"))
|
||||
.times(1)
|
||||
.returning(|_, _| Ok(()));
|
||||
|
||||
let permission_service =
|
||||
PermissionServiceImpl::new(Arc::new(permission_dao), Arc::new(user_service));
|
||||
|
||||
permission_service
|
||||
.delete_user_role("testuser", "testrole")
|
||||
.await
|
||||
.expect("Extected successful user role deletion");
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_delete_user_role_without_permission() {
|
||||
let (permission_dao, user_service) = generate_dependencies_mocks_permission(false, "admin");
|
||||
let permission_service =
|
||||
PermissionServiceImpl::new(Arc::new(permission_dao), Arc::new(user_service));
|
||||
test_forbidden(
|
||||
&permission_service
|
||||
.delete_user_role("testuser", "testrole")
|
||||
.await,
|
||||
);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_all_roles() {
|
||||
let (mut permission_dao, user_service) = generate_dependencies_mocks_permission(true, "admin");
|
||||
permission_dao.expect_all_roles().times(1).returning(|| {
|
||||
Ok(Arc::new([
|
||||
dao::RoleEntity {
|
||||
name: "testrole".into(),
|
||||
},
|
||||
dao::RoleEntity {
|
||||
name: "testrole2".into(),
|
||||
},
|
||||
]))
|
||||
});
|
||||
|
||||
let permission_service =
|
||||
PermissionServiceImpl::new(Arc::new(permission_dao), Arc::new(user_service));
|
||||
|
||||
let all_roles = permission_service
|
||||
.get_all_roles()
|
||||
.await
|
||||
.expect("Expected roles successfully");
|
||||
assert_eq!(all_roles.len(), 2);
|
||||
assert_eq!(all_roles[0].name.as_ref(), "testrole");
|
||||
assert_eq!(all_roles[1].name.as_ref(), "testrole2");
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_all_roles_without_permission() {
|
||||
let (permission_dao, user_service) = generate_dependencies_mocks_permission(false, "admin");
|
||||
let permission_service =
|
||||
PermissionServiceImpl::new(Arc::new(permission_dao), Arc::new(user_service));
|
||||
test_forbidden(&permission_service.get_all_roles().await);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_all_users() {
|
||||
let (mut permission_dao, user_service) = generate_dependencies_mocks_permission(true, "admin");
|
||||
permission_dao.expect_all_users().times(1).returning(|| {
|
||||
Ok(Arc::new([
|
||||
dao::UserEntity {
|
||||
name: "testuser".into(),
|
||||
},
|
||||
dao::UserEntity {
|
||||
name: "testuser2".into(),
|
||||
},
|
||||
]))
|
||||
});
|
||||
|
||||
let permission_service =
|
||||
PermissionServiceImpl::new(Arc::new(permission_dao), Arc::new(user_service));
|
||||
|
||||
let all_users = permission_service
|
||||
.get_all_users()
|
||||
.await
|
||||
.expect("Expected users successfully");
|
||||
|
||||
assert_eq!(all_users.len(), 2);
|
||||
assert_eq!(all_users[0].name.as_ref(), "testuser");
|
||||
assert_eq!(all_users[1].name.as_ref(), "testuser2");
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_all_users_without_permission() {
|
||||
let (permission_dao, user_service) = generate_dependencies_mocks_permission(false, "admin");
|
||||
let permission_service =
|
||||
PermissionServiceImpl::new(Arc::new(permission_dao), Arc::new(user_service));
|
||||
test_forbidden(&permission_service.get_all_users().await);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_all_privileges() {
|
||||
let (mut permission_dao, user_service) = generate_dependencies_mocks_permission(true, "admin");
|
||||
permission_dao
|
||||
.expect_all_privileges()
|
||||
.times(1)
|
||||
.returning(|| {
|
||||
Ok(Arc::new([
|
||||
dao::PrivilegeEntity {
|
||||
name: "testprivilege".into(),
|
||||
},
|
||||
dao::PrivilegeEntity {
|
||||
name: "testprivilege2".into(),
|
||||
},
|
||||
]))
|
||||
});
|
||||
|
||||
let permission_service =
|
||||
PermissionServiceImpl::new(Arc::new(permission_dao), Arc::new(user_service));
|
||||
|
||||
let all_privileges = permission_service
|
||||
.get_all_privileges()
|
||||
.await
|
||||
.expect("Expected privileges successfully");
|
||||
|
||||
assert_eq!(all_privileges.len(), 2);
|
||||
assert_eq!(all_privileges[0].name.as_ref(), "testprivilege");
|
||||
assert_eq!(all_privileges[1].name.as_ref(), "testprivilege2");
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_all_privileges_without_permission() {
|
||||
let (permission_dao, user_service) = generate_dependencies_mocks_permission(false, "admin");
|
||||
let permission_service =
|
||||
PermissionServiceImpl::new(Arc::new(permission_dao), Arc::new(user_service));
|
||||
test_forbidden(&permission_service.get_all_privileges().await);
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue