use async_graphql::{
connection::{query, Connection, Edge, OpaqueCursor},
Context, Object, ID,
};
use mas_storage::{upstream_oauth2::UpstreamOAuthProviderFilter, Pagination, RepositoryAccess};
use crate::graphql::{
model::{
Cursor, NodeCursor, NodeType, PreloadedTotalCount, UpstreamOAuth2Link,
UpstreamOAuth2Provider,
},
state::ContextExt,
};
#[derive(Default)]
pub struct UpstreamOAuthQuery;
#[Object]
impl UpstreamOAuthQuery {
pub async fn upstream_oauth2_link(
&self,
ctx: &Context<'_>,
id: ID,
) -> Result<Option<UpstreamOAuth2Link>, async_graphql::Error> {
let state = ctx.state();
let id = NodeType::UpstreamOAuth2Link.extract_ulid(&id)?;
let requester = ctx.requester();
let mut repo = state.repository().await?;
let link = repo.upstream_oauth_link().lookup(id).await?;
repo.cancel().await?;
let Some(link) = link else {
return Ok(None);
};
if !requester.is_owner_or_admin(&link) {
return Ok(None);
}
Ok(Some(UpstreamOAuth2Link::new(link)))
}
pub async fn upstream_oauth2_provider(
&self,
ctx: &Context<'_>,
id: ID,
) -> Result<Option<UpstreamOAuth2Provider>, async_graphql::Error> {
let state = ctx.state();
let id = NodeType::UpstreamOAuth2Provider.extract_ulid(&id)?;
let mut repo = state.repository().await?;
let provider = repo.upstream_oauth_provider().lookup(id).await?;
repo.cancel().await?;
let Some(provider) = provider else {
return Ok(None);
};
if !provider.enabled() {
return Ok(None);
}
Ok(Some(UpstreamOAuth2Provider::new(provider)))
}
async fn upstream_oauth2_providers(
&self,
ctx: &Context<'_>,
#[graphql(desc = "Returns the elements in the list that come after the cursor.")]
after: Option<String>,
#[graphql(desc = "Returns the elements in the list that come before the cursor.")]
before: Option<String>,
#[graphql(desc = "Returns the first *n* elements from the list.")] first: Option<i32>,
#[graphql(desc = "Returns the last *n* elements from the list.")] last: Option<i32>,
) -> Result<Connection<Cursor, UpstreamOAuth2Provider, PreloadedTotalCount>, async_graphql::Error>
{
let state = ctx.state();
let mut repo = state.repository().await?;
query(
after,
before,
first,
last,
|after, before, first, last| async move {
let after_id = after
.map(|x: OpaqueCursor<NodeCursor>| {
x.extract_for_type(NodeType::UpstreamOAuth2Provider)
})
.transpose()?;
let before_id = before
.map(|x: OpaqueCursor<NodeCursor>| {
x.extract_for_type(NodeType::UpstreamOAuth2Provider)
})
.transpose()?;
let pagination = Pagination::try_new(before_id, after_id, first, last)?;
let filter = UpstreamOAuthProviderFilter::new().enabled_only();
let page = repo
.upstream_oauth_provider()
.list(filter, pagination)
.await?;
let count = if ctx.look_ahead().field("totalCount").exists() {
Some(repo.upstream_oauth_provider().count(filter).await?)
} else {
None
};
repo.cancel().await?;
let mut connection = Connection::with_additional_fields(
page.has_previous_page,
page.has_next_page,
PreloadedTotalCount(count),
);
connection.edges.extend(page.edges.into_iter().map(|p| {
Edge::new(
OpaqueCursor(NodeCursor(NodeType::UpstreamOAuth2Provider, p.id)),
UpstreamOAuth2Provider::new(p),
)
}));
Ok::<_, async_graphql::Error>(connection)
},
)
.await
}
}