Skip to content

Commit d516b3d

Browse files
committed
Add scope filter to personal sessions list
1 parent cc57e33 commit d516b3d

File tree

1 file changed

+35
-9
lines changed
  • crates/handlers/src/admin/v1/personal_sessions

1 file changed

+35
-9
lines changed

crates/handlers/src/admin/v1/personal_sessions/list.rs

Lines changed: 35 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,17 @@
33
// SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
44
// Please see LICENSE files in the repository root for full details.
55

6+
use std::str::FromStr as _;
7+
68
use aide::{OperationIo, transform::TransformOperation};
7-
use axum::{
8-
Json,
9-
extract::{Query, rejection::QueryRejection},
10-
response::IntoResponse,
11-
};
9+
use axum::{Json, response::IntoResponse};
10+
use axum_extra::extract::{Query, QueryRejection};
1211
use axum_macros::FromRequestParts;
1312
use chrono::{DateTime, Utc};
1413
use hyper::StatusCode;
1514
use mas_axum_utils::record_error;
1615
use mas_storage::personal::PersonalSessionFilter;
16+
use oauth2_types::scope::{Scope, ScopeToken};
1717
use schemars::JsonSchema;
1818
use serde::Deserialize;
1919
use ulid::Ulid;
@@ -64,6 +64,10 @@ pub struct FilterParams {
6464
#[schemars(with = "Option<crate::admin::schema::Ulid>")]
6565
actor_user: Option<Ulid>,
6666

67+
/// Retrieve the items with the given scope
68+
#[serde(default, rename = "filter[scope]")]
69+
scope: Vec<String>,
70+
6771
/// Filter by session status
6872
#[serde(rename = "filter[status]")]
6973
status: Option<PersonalSessionStatus>,
@@ -97,6 +101,10 @@ impl std::fmt::Display for FilterParams {
97101
write!(f, "{sep}filter[actor_user]={actor_user}")?;
98102
sep = '&';
99103
}
104+
for scope in &self.scope {
105+
write!(f, "{sep}filter[scope]={scope}")?;
106+
sep = '&';
107+
}
100108
if let Some(status) = self.status {
101109
write!(f, "{sep}filter[status]={status}")?;
102110
sep = '&';
@@ -141,6 +149,9 @@ pub enum RouteError {
141149

142150
#[error("Invalid filter parameters")]
143151
InvalidFilter(#[from] QueryRejection),
152+
153+
#[error("Invalid scope {0:?} in filter parameters")]
154+
InvalidScope(String),
144155
}
145156

146157
impl_from_error_for_route!(mas_storage::RepositoryError);
@@ -153,7 +164,7 @@ impl IntoResponse for RouteError {
153164
let status = match self {
154165
Self::Internal(_) => StatusCode::INTERNAL_SERVER_ERROR,
155166
Self::UserNotFound(_) | Self::ClientNotFound(_) => StatusCode::NOT_FOUND,
156-
Self::InvalidFilter(_) => StatusCode::BAD_REQUEST,
167+
Self::InvalidScope(_) | Self::InvalidFilter(_) => StatusCode::BAD_REQUEST,
157168
};
158169
(status, sentry_event_id, Json(error)).into_response()
159170
}
@@ -259,7 +270,18 @@ pub async fn handler(
259270
None => filter,
260271
};
261272

262-
// Apply status filter
273+
let scope: Scope = params
274+
.scope
275+
.into_iter()
276+
.map(|s| ScopeToken::from_str(&s).map_err(|_| RouteError::InvalidScope(s)))
277+
.collect::<Result<_, _>>()?;
278+
279+
let filter = if scope.is_empty() {
280+
filter
281+
} else {
282+
filter.with_scope(&scope)
283+
};
284+
263285
let filter = match params.status {
264286
Some(PersonalSessionStatus::Active) => filter.active_only(),
265287
Some(PersonalSessionStatus::Revoked) => filter.finished_only(),
@@ -402,7 +424,7 @@ mod tests {
402424
PersonalSessionOwner::from(&user),
403425
&user,
404426
"Another test session".to_owned(),
405-
Scope::from_iter([OPENID]),
427+
Scope::from_iter([OPENID, "urn:mas:admin".parse().unwrap()]),
406428
)
407429
.await
408430
.unwrap();
@@ -490,7 +512,7 @@ mod tests {
490512
"owner_client_id": null,
491513
"actor_user_id": "01FSHN9AG09FE39KETP6F390F8",
492514
"human_name": "Another test session",
493-
"scope": "openid",
515+
"scope": "openid urn:mas:admin",
494516
"last_active_at": null,
495517
"last_active_ip": null,
496518
"expires_at": "2022-02-01T14:40:00Z"
@@ -533,6 +555,10 @@ mod tests {
533555
&["01FSHN9AG0YQYAR04VCYTHJ8SK", "01FSPT2RG08Y11Y5BM4VZ4CN8K"],
534556
),
535557
("filter[expires]=false", &["01FSM7P1G0VBGAMK9D9QMGQ5MY"]),
558+
(
559+
"filter[scope]=urn:mas:admin",
560+
&["01FSPT2RG08Y11Y5BM4VZ4CN8K"],
561+
),
536562
];
537563

538564
for (filter, expected_ids) in filters_and_expected {

0 commit comments

Comments
 (0)