Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions crates/cli/src/commands/manage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -390,9 +390,10 @@ impl Options {
info!("The following users can request admin privileges ({total} total):");
loop {
let page = repo.user().list(filter, cursor).await?;
for user in page.edges {
for edge in page.edges {
let user = edge.node;
info!(%user.id, username = %user.username);
cursor = cursor.after(user.id);
cursor = cursor.after(edge.cursor);
}

if !page.has_next_page {
Expand Down
3 changes: 2 additions & 1 deletion crates/cli/src/sync.rs
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,8 @@ pub async fn config_sync(
let mut existing_enabled_ids = BTreeSet::new();
let mut existing_disabled = BTreeMap::new();
// Process the existing providers
for provider in page.edges {
for edge in page.edges {
let provider = edge.node;
if provider.enabled() {
if config_ids.contains(&provider.id) {
existing_enabled_ids.insert(provider.id);
Expand Down
45 changes: 41 additions & 4 deletions crates/handlers/src/admin/response.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

#![allow(clippy::module_name_repetitions)]

use mas_storage::Pagination;
use mas_storage::{Pagination, pagination::Edge};
use schemars::JsonSchema;
use serde::Serialize;
use ulid::Ulid;
Expand Down Expand Up @@ -102,22 +102,26 @@ impl<T: Resource> PaginatedResponse<T> {
base,
current_pagination
.clear_before()
.after(page.edges.last().unwrap().id()),
.after(page.edges.last().unwrap().cursor),
)
}),
prev: if page.has_previous_page {
Some(url_with_pagination(
base,
current_pagination
.clear_after()
.before(page.edges.first().unwrap().id()),
.before(page.edges.first().unwrap().cursor),
))
} else {
None
},
};

let data = page.edges.into_iter().map(SingleResource::new).collect();
let data = page
.edges
.into_iter()
.map(SingleResource::from_edge)
.collect();

Self {
meta: PaginationMeta { count },
Expand All @@ -143,6 +147,31 @@ struct SingleResource<T> {

/// Related links
links: SelfLinks,

/// Metadata about the resource
#[serde(skip_serializing_if = "SingleResourceMeta::is_empty")]
meta: SingleResourceMeta,
}

/// Metadata associated with a resource
#[derive(Serialize, JsonSchema)]
struct SingleResourceMeta {
/// Information about the pagination of the resource
#[serde(skip_serializing_if = "Option::is_none")]
page: Option<SingleResourceMetaPage>,
}

impl SingleResourceMeta {
fn is_empty(&self) -> bool {
self.page.is_none()
}
}

/// Pagination metadata for a resource
#[derive(Serialize, JsonSchema)]
struct SingleResourceMetaPage {
/// The cursor of this resource in the paginated result
cursor: String,
}

impl<T: Resource> SingleResource<T> {
Expand All @@ -153,8 +182,16 @@ impl<T: Resource> SingleResource<T> {
id: resource.id(),
attributes: resource,
links: SelfLinks { self_ },
meta: SingleResourceMeta { page: None },
}
}

fn from_edge<C: ToString>(edge: Edge<T, C>) -> Self {
let cursor = edge.cursor.to_string();
let mut resource = Self::new(edge.node);
resource.meta.page = Some(SingleResourceMetaPage { cursor });
resource
}
}

/// Related links
Expand Down
33 changes: 32 additions & 1 deletion crates/handlers/src/admin/v1/compat_sessions/list.rs
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,13 @@ Use the `filter[status]` parameter to filter the sessions by their status and `p
let sessions = CompatSession::samples();
let pagination = mas_storage::Pagination::first(sessions.len());
let page = Page {
edges: sessions.into(),
edges: sessions
.into_iter()
.map(|node| mas_storage::pagination::Edge {
cursor: node.id(),
node,
})
.collect(),
has_next_page: true,
has_previous_page: false,
};
Expand Down Expand Up @@ -299,6 +305,11 @@ mod tests {
},
"links": {
"self": "/api/admin/v1/compat-sessions/01FSHNB530AAPR7PEV8KNBZD5Y"
},
"meta": {
"page": {
"cursor": "01FSHNB530AAPR7PEV8KNBZD5Y"
}
}
},
{
Expand All @@ -318,6 +329,11 @@ mod tests {
},
"links": {
"self": "/api/admin/v1/compat-sessions/01FSHNCZP0PPF7X0EVMJNECPZW"
},
"meta": {
"page": {
"cursor": "01FSHNCZP0PPF7X0EVMJNECPZW"
}
}
}
],
Expand Down Expand Up @@ -362,6 +378,11 @@ mod tests {
},
"links": {
"self": "/api/admin/v1/compat-sessions/01FSHNB530AAPR7PEV8KNBZD5Y"
},
"meta": {
"page": {
"cursor": "01FSHNB530AAPR7PEV8KNBZD5Y"
}
}
}
],
Expand Down Expand Up @@ -403,6 +424,11 @@ mod tests {
},
"links": {
"self": "/api/admin/v1/compat-sessions/01FSHNB530AAPR7PEV8KNBZD5Y"
},
"meta": {
"page": {
"cursor": "01FSHNB530AAPR7PEV8KNBZD5Y"
}
}
}
],
Expand Down Expand Up @@ -444,6 +470,11 @@ mod tests {
},
"links": {
"self": "/api/admin/v1/compat-sessions/01FSHNCZP0PPF7X0EVMJNECPZW"
},
"meta": {
"page": {
"cursor": "01FSHNCZP0PPF7X0EVMJNECPZW"
}
}
}
],
Expand Down
13 changes: 12 additions & 1 deletion crates/handlers/src/admin/v1/oauth2_sessions/list.rs
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,13 @@ Use the `filter[status]` parameter to filter the sessions by their status and `p
let sessions = OAuth2Session::samples();
let pagination = mas_storage::Pagination::first(sessions.len());
let page = Page {
edges: sessions.into(),
edges: sessions
.into_iter()
.map(|node| mas_storage::pagination::Edge {
cursor: node.id(),
node,
})
.collect(),
has_next_page: true,
has_previous_page: false,
};
Expand Down Expand Up @@ -354,6 +360,11 @@ mod tests {
},
"links": {
"self": "/api/admin/v1/oauth2-sessions/01FSHN9AG0MKGTBNZ16RDR3PVY"
},
"meta": {
"page": {
"cursor": "01FSHN9AG0MKGTBNZ16RDR3PVY"
}
}
}
],
Expand Down
64 changes: 55 additions & 9 deletions crates/handlers/src/admin/v1/upstream_oauth_links/list.rs
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,13 @@ pub fn doc(operation: TransformOperation) -> TransformOperation {
let links = UpstreamOAuthLink::samples();
let pagination = mas_storage::Pagination::first(links.len());
let page = Page {
edges: links.into(),
edges: links
.into_iter()
.map(|node| mas_storage::pagination::Edge {
cursor: node.id(),
node,
})
.collect(),
has_next_page: true,
has_previous_page: false,
};
Expand Down Expand Up @@ -296,7 +302,7 @@ mod tests {
let response = state.request(request).await;
response.assert_status(StatusCode::OK);
let body: serde_json::Value = response.json();
assert_json_snapshot!(body, @r###"
assert_json_snapshot!(body, @r#"
{
"meta": {
"count": 3
Expand All @@ -314,6 +320,11 @@ mod tests {
},
"links": {
"self": "/api/admin/v1/upstream-oauth-links/01FSHN9AG0AQZQP8DX40GD59PW"
},
"meta": {
"page": {
"cursor": "01FSHN9AG0AQZQP8DX40GD59PW"
}
}
},
{
Expand All @@ -328,6 +339,11 @@ mod tests {
},
"links": {
"self": "/api/admin/v1/upstream-oauth-links/01FSHN9AG0PJZ6DZNTAA1XKPT4"
},
"meta": {
"page": {
"cursor": "01FSHN9AG0PJZ6DZNTAA1XKPT4"
}
}
},
{
Expand All @@ -342,6 +358,11 @@ mod tests {
},
"links": {
"self": "/api/admin/v1/upstream-oauth-links/01FSHN9AG0QHEHKX2JNQ2A2D07"
},
"meta": {
"page": {
"cursor": "01FSHN9AG0QHEHKX2JNQ2A2D07"
}
}
}
],
Expand All @@ -351,7 +372,7 @@ mod tests {
"last": "/api/admin/v1/upstream-oauth-links?page[last]=10"
}
}
"###);
"#);

// Filter by user ID
let request = Request::get(format!(
Expand All @@ -364,7 +385,7 @@ mod tests {
let response = state.request(request).await;
response.assert_status(StatusCode::OK);
let body: serde_json::Value = response.json();
assert_json_snapshot!(body, @r###"
assert_json_snapshot!(body, @r#"
{
"meta": {
"count": 2
Expand All @@ -382,6 +403,11 @@ mod tests {
},
"links": {
"self": "/api/admin/v1/upstream-oauth-links/01FSHN9AG0AQZQP8DX40GD59PW"
},
"meta": {
"page": {
"cursor": "01FSHN9AG0AQZQP8DX40GD59PW"
}
}
},
{
Expand All @@ -396,6 +422,11 @@ mod tests {
},
"links": {
"self": "/api/admin/v1/upstream-oauth-links/01FSHN9AG0QHEHKX2JNQ2A2D07"
},
"meta": {
"page": {
"cursor": "01FSHN9AG0QHEHKX2JNQ2A2D07"
}
}
}
],
Expand All @@ -405,7 +436,7 @@ mod tests {
"last": "/api/admin/v1/upstream-oauth-links?filter[user]=01FSHN9AG0MZAA6S4AF7CTV32E&page[last]=10"
}
}
"###);
"#);

// Filter by provider
let request = Request::get(format!(
Expand All @@ -418,7 +449,7 @@ mod tests {
let response = state.request(request).await;
response.assert_status(StatusCode::OK);
let body: serde_json::Value = response.json();
assert_json_snapshot!(body, @r###"
assert_json_snapshot!(body, @r#"
{
"meta": {
"count": 2
Expand All @@ -436,6 +467,11 @@ mod tests {
},
"links": {
"self": "/api/admin/v1/upstream-oauth-links/01FSHN9AG0AQZQP8DX40GD59PW"
},
"meta": {
"page": {
"cursor": "01FSHN9AG0AQZQP8DX40GD59PW"
}
}
},
{
Expand All @@ -450,6 +486,11 @@ mod tests {
},
"links": {
"self": "/api/admin/v1/upstream-oauth-links/01FSHN9AG0PJZ6DZNTAA1XKPT4"
},
"meta": {
"page": {
"cursor": "01FSHN9AG0PJZ6DZNTAA1XKPT4"
}
}
}
],
Expand All @@ -459,7 +500,7 @@ mod tests {
"last": "/api/admin/v1/upstream-oauth-links?filter[provider]=01FSHN9AG09NMZYX8MFYH578R9&page[last]=10"
}
}
"###);
"#);

// Filter by subject
let request = Request::get(format!(
Expand All @@ -472,7 +513,7 @@ mod tests {
let response = state.request(request).await;
response.assert_status(StatusCode::OK);
let body: serde_json::Value = response.json();
assert_json_snapshot!(body, @r###"
assert_json_snapshot!(body, @r#"
{
"meta": {
"count": 1
Expand All @@ -490,6 +531,11 @@ mod tests {
},
"links": {
"self": "/api/admin/v1/upstream-oauth-links/01FSHN9AG0AQZQP8DX40GD59PW"
},
"meta": {
"page": {
"cursor": "01FSHN9AG0AQZQP8DX40GD59PW"
}
}
}
],
Expand All @@ -499,6 +545,6 @@ mod tests {
"last": "/api/admin/v1/upstream-oauth-links?filter[subject]=subject1&page[last]=10"
}
}
"###);
"#);
}
}
Loading
Loading