From 39cd05378d8111ed43caba19da7e19202c10516e Mon Sep 17 00:00:00 2001 From: henry Date: Mon, 16 Dec 2024 08:45:14 +0900 Subject: [PATCH] Add `updateTrustedDomain` GraphQL API Closes #2 --- CHANGELOG.md | 5 ++ src/graphql.rs | 1 + src/graphql/trusted_domain.rs | 88 ++++++++++++++++++++++++++++++++++- 3 files changed, 92 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5203fe2..cd3fcc8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,11 @@ Versioning](https://semver.org/spec/v2.0.0.html). ## [Unreleased] +### Added + +- Added the `updateTrustedDomain` GraphQL API, allowing users to modify a + trusted domain. + ### Changed - The paginated GraphQL queries use different representations for cursors. The diff --git a/src/graphql.rs b/src/graphql.rs index 0023758..6f02330 100644 --- a/src/graphql.rs +++ b/src/graphql.rs @@ -710,6 +710,7 @@ mod tests { #[tokio::test] async fn unimplemented_agent_manager() { let agent_manager = super::MockAgentManager {}; + assert!(agent_manager.broadcast_trusted_domains().await.is_ok()); assert!(agent_manager .broadcast_trusted_user_agent_list(&[]) .await diff --git a/src/graphql/trusted_domain.rs b/src/graphql/trusted_domain.rs index e787173..86b5c08 100644 --- a/src/graphql/trusted_domain.rs +++ b/src/graphql/trusted_domain.rs @@ -1,7 +1,7 @@ use async_graphql::connection::OpaqueCursor; use async_graphql::{ connection::{Connection, EmptyFields}, - Context, Object, Result, SimpleObject, + Context, InputObject, Object, Result, SimpleObject, }; use super::{AgentManager, BoxedAgentManager, Role, RoleGuard}; @@ -63,6 +63,29 @@ impl TrustedDomainMutation { Ok(name) } + /// Updates a trusted domain, returning the new value. + #[graphql(guard = "RoleGuard::new(Role::SystemAdministrator) + .or(RoleGuard::new(Role::SecurityAdministrator))")] + async fn update_trusted_domain( + &self, + ctx: &Context<'_>, + old: TrustedDomainInput, + new: TrustedDomainInput, + ) -> Result { + let name = { + let store = crate::graphql::get_store(ctx).await?; + let map = store.trusted_domain_map(); + let old = review_database::TrustedDomain::from(old); + let new = review_database::TrustedDomain::from(new); + map.update(&old, &new)?; + new.name + }; + + let agent_manager = ctx.data::()?; + agent_manager.broadcast_trusted_domains().await?; + Ok(name) + } + /// Removes a trusted domain, returning the old value if it existed. #[graphql( guard = "RoleGuard::new(Role::SystemAdministrator).or(RoleGuard::new(Role::SecurityAdministrator))" @@ -95,6 +118,21 @@ impl From for TrustedDomain { } } +#[derive(InputObject)] +pub(super) struct TrustedDomainInput { + name: String, + remarks: String, +} + +impl From for review_database::TrustedDomain { + fn from(input: TrustedDomainInput) -> Self { + Self { + name: input.name, + remarks: input.remarks, + } + } +} + async fn load( ctx: &Context<'_>, after: Option>>, @@ -109,7 +147,9 @@ async fn load( #[cfg(test)] mod tests { - use crate::graphql::TestSchema; + use std::net::SocketAddr; + + use crate::graphql::{BoxedAgentManager, MockAgentManager, TestSchema}; #[tokio::test] async fn trusted_domain_list() { @@ -158,4 +198,48 @@ mod tests { r#"{trustedDomainList: {edges: [{node: {name: "example2.org"}}]}}"# ); } + + #[tokio::test] + async fn update_trusted_domain() { + let agent_manager: BoxedAgentManager = Box::new(MockAgentManager {}); + let test_addr: SocketAddr = "127.0.0.1:8080".parse().unwrap(); + let schema = TestSchema::new_with(agent_manager, Some(test_addr)).await; + let insert_query = r#" + mutation { + insertTrustedDomain( + name: "test.com" + remarks: "origin_remarks" + ) + } + "#; + let update_query = r#" + mutation { + updateTrustedDomain( + old: { + name: "test.com" + remarks: "origin_remarks" + } + new: { + name: "test2.com" + remarks: "updated_remarks" + } + ) + } + "#; + + let res = schema.execute(update_query).await; + assert_eq!( + res.errors.first().unwrap().message, + "no such entry".to_string() + ); + + let res = schema.execute(insert_query).await; + assert_eq!(res.data.to_string(), r#"{insertTrustedDomain: "test.com"}"#); + + let res = schema.execute(update_query).await; + assert_eq!( + res.data.to_string(), + r#"{updateTrustedDomain: "test2.com"}"# + ); + } }