diff --git a/schema.graphql b/schema.graphql index ec40c5c..d41d6e7 100644 --- a/schema.graphql +++ b/schema.graphql @@ -47,6 +47,7 @@ type Query { user(userId: String!): User! users(filters: RequestFilter): [User!]! groups: [Group!]! + group(groupId: Int!): Group! } "The details required to create a user." diff --git a/server/src/domain/handler.rs b/server/src/domain/handler.rs index 02d841a..1f09153 100644 --- a/server/src/domain/handler.rs +++ b/server/src/domain/handler.rs @@ -88,7 +88,7 @@ pub trait LoginHandler: Clone + Send { #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)] pub struct GroupId(pub i32); -#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)] +#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, sqlx::FromRow)] pub struct GroupIdAndName(pub GroupId, pub String); #[async_trait] @@ -96,6 +96,7 @@ pub trait BackendHandler: Clone + Send { async fn list_users(&self, filters: Option) -> Result>; async fn list_groups(&self) -> Result>; async fn get_user_details(&self, user_id: &str) -> Result; + async fn get_group_details(&self, group_id: GroupId) -> Result; async fn create_user(&self, request: CreateUserRequest) -> Result<()>; async fn update_user(&self, request: UpdateUserRequest) -> Result<()>; async fn update_group(&self, request: UpdateGroupRequest) -> Result<()>; @@ -118,6 +119,7 @@ mockall::mock! { async fn list_users(&self, filters: Option) -> Result>; async fn list_groups(&self) -> Result>; async fn get_user_details(&self, user_id: &str) -> Result; + async fn get_group_details(&self, group_id: GroupId) -> Result; async fn create_user(&self, request: CreateUserRequest) -> Result<()>; async fn update_user(&self, request: UpdateUserRequest) -> Result<()>; async fn update_group(&self, request: UpdateGroupRequest) -> Result<()>; diff --git a/server/src/domain/sql_backend_handler.rs b/server/src/domain/sql_backend_handler.rs index 89e0893..23a76c8 100644 --- a/server/src/domain/sql_backend_handler.rs +++ b/server/src/domain/sql_backend_handler.rs @@ -186,6 +186,19 @@ impl BackendHandler for SqlBackendHandler { .await?) } + async fn get_group_details(&self, group_id: GroupId) -> Result { + let query = Query::select() + .column(Groups::GroupId) + .column(Groups::DisplayName) + .from(Groups::Table) + .and_where(Expr::col(Groups::GroupId).eq(group_id)) + .to_string(DbQueryBuilder {}); + + Ok(sqlx::query_as::<_, GroupIdAndName>(&query) + .fetch_one(&self.sql_pool) + .await?) + } + async fn get_user_groups(&self, user: &str) -> Result> { if user == self.config.ldap_user_dn { let mut groups = HashSet::new(); diff --git a/server/src/infra/graphql/query.rs b/server/src/infra/graphql/query.rs index 203c8d4..6c999c0 100644 --- a/server/src/infra/graphql/query.rs +++ b/server/src/infra/graphql/query.rs @@ -139,6 +139,17 @@ impl Query { .await .map(|v| v.into_iter().map(Into::into).collect())?) } + + async fn group(context: &Context, group_id: i32) -> FieldResult> { + if !context.validation_result.is_admin { + return Err("Unauthorized access to group data".into()); + } + Ok(context + .handler + .get_group_details(GroupId(group_id)) + .await + .map(Into::into)?) + } } #[derive(PartialEq, Eq, Debug, Serialize, Deserialize)] diff --git a/server/src/infra/tcp_backend_handler.rs b/server/src/infra/tcp_backend_handler.rs index 4025d1b..194001e 100644 --- a/server/src/infra/tcp_backend_handler.rs +++ b/server/src/infra/tcp_backend_handler.rs @@ -29,6 +29,7 @@ mockall::mock! { async fn list_users(&self, filters: Option) -> DomainResult>; async fn list_groups(&self) -> DomainResult>; async fn get_user_details(&self, user_id: &str) -> DomainResult; + async fn get_group_details(&self, group_id: GroupId) -> DomainResult; async fn get_user_groups(&self, user: &str) -> DomainResult>; async fn create_user(&self, request: CreateUserRequest) -> DomainResult<()>; async fn update_user(&self, request: UpdateUserRequest) -> DomainResult<()>;