Return the username in a separate service

This allows us to use a service implementation which
returns a dummy user during development and the actual authenticated
user during production.  It also simplifies tests.
This commit is contained in:
Simon Goller 2024-04-26 22:41:44 +02:00
parent 789981ee92
commit 926ac006e7
3 changed files with 29 additions and 7 deletions

View file

@ -12,7 +12,15 @@ async fn main() {
let hello_dao = dao_impl::HelloDaoImpl::new(pool.clone());
let permission_dao = dao_impl::PermissionDaoImpl::new(pool);
let permission_service = service_impl::PermissionServiceImpl::new(permission_dao.into());
// Always authenticate with DEVUSER during development.
// This is used to test the permission service locally without a login service.
//
// TODO: Implement a proper authentication service when used in produciton. Maybe
// use differnet implementations on debug then on release. Or control it via a
// feature.
let user_service = service_impl::UserServiceDev;
let permission_service =
service_impl::PermissionServiceImpl::new(permission_dao.into(), user_service.into());
let hello_service =
service_impl::HelloServiceImpl::new(hello_dao.into(), permission_service.into());
rest::start_server(hello_service).await

View file

@ -19,6 +19,8 @@ pub trait PermissionService {
&self,
privilege: &str,
) -> impl Future<Output = Result<(), ServiceError>> + Send;
}
pub trait UserService {
fn current_user(&self) -> impl Future<Output = Result<Arc<str>, ServiceError>> + Send;
}

View file

@ -33,27 +33,35 @@ where
}
}
pub struct PermissionServiceImpl<PermissionDao>
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> PermissionServiceImpl<PermissionDao>
impl<PermissionDao, UserService> PermissionServiceImpl<PermissionDao, UserService>
where
PermissionDao: dao::PermissionDao + Send + Sync,
UserService: service::UserService + Send + Sync,
{
pub fn new(permission_dao: Arc<PermissionDao>) -> Self {
Self { permission_dao }
pub fn new(permission_dao: Arc<PermissionDao>, user_service: Arc<UserService>) -> Self {
Self {
permission_dao,
user_service,
}
}
}
impl<PermissionDao> service::PermissionService for PermissionServiceImpl<PermissionDao>
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.current_user().await?;
let current_user = self.user_service.current_user().await?;
if self
.permission_dao
.has_privilege(current_user.as_ref(), privilege)
@ -64,7 +72,11 @@ where
Err(service::ServiceError::Forbidden)
}
}
}
pub struct UserServiceDev;
impl service::UserService for UserServiceDev {
async fn current_user(&self) -> Result<Arc<str>, service::ServiceError> {
Ok("DEVUSER".into())
}