Skip to main content

alibi_plugins/multi_session/
endpoint.rs

1use super::{MultiSessionPlugin, SessionTokenRequest};
2use crate::authentication_helpers::RequestBody;
3use crate::endpoint::{definition, validate_fields, validation};
4use alibi_core::endpoint::{EndpointCall, EndpointDefinition, EndpointInput, ServerEndpoint};
5use alibi_core::{AuthResult, HttpMethod};
6use serde::Deserialize;
7
8/// An active account selected by the caller's signed device-session proofs.
9#[derive(Debug, Deserialize)]
10pub struct DeviceSession {
11    pub user: Box<alibi_core::UserView>,
12    pub session: Box<alibi_core::wire::SessionView>,
13}
14
15/// A selected device session was revoked and its browser proof retired.
16#[derive(Debug, Deserialize)]
17pub struct DeviceSessionRevoked {
18    pub status: bool,
19}
20
21pub(super) fn definitions() -> Vec<EndpointDefinition> {
22    vec![
23        definition(
24            "revokeDeviceSession",
25            "revokeDeviceSession",
26            Some("/multi-session/revoke"),
27            HttpMethod::Post,
28        ),
29        definition(
30            "listDeviceSessions",
31            "listDeviceSessions",
32            Some("/multi-session/list-device-sessions"),
33            HttpMethod::Get,
34        ),
35        definition(
36            "setActiveSession",
37            "setActiveSession",
38            Some("/multi-session/set-active"),
39            HttpMethod::Post,
40        ),
41    ]
42}
43
44pub(super) fn validate(call: &EndpointCall) -> AuthResult<EndpointInput> {
45    let body = if matches!(
46        call.operation_id(),
47        "setActiveSession" | "revokeDeviceSession"
48    ) {
49        Some(validate_fields(
50            call.body(),
51            "body",
52            SessionTokenRequest::FIELDS,
53        )?)
54    } else {
55        call.body().cloned()
56    };
57    if call.headers().is_none() {
58        return Err(validation("Headers is required"));
59    }
60    Ok(EndpointInput {
61        body,
62        query: call.query().cloned(),
63    })
64}
65
66impl MultiSessionPlugin {
67    /// Revoke a device proof under the caller's authenticated session.
68    #[must_use]
69    pub fn revoke_device_session_endpoint(
70        session_token: impl Into<String>,
71    ) -> ServerEndpoint<DeviceSessionRevoked> {
72        ServerEndpoint::new("multi-session", "revokeDeviceSession").with_body_value(
73            alibi_core::utils::json::JsValue::Object(
74                [(
75                    "sessionToken".into(),
76                    alibi_core::utils::json::JsValue::String(session_token.into()),
77                )]
78                .into_iter()
79                .collect(),
80            ),
81        )
82    }
83
84    /// Select an account using its genuine signed device proof.
85    #[must_use]
86    pub fn set_active_session_endpoint(
87        session_token: impl Into<String>,
88    ) -> ServerEndpoint<DeviceSession> {
89        ServerEndpoint::new("multi-session", "setActiveSession").with_body_value(
90            alibi_core::utils::json::JsValue::Object(
91                [(
92                    "sessionToken".into(),
93                    alibi_core::utils::json::JsValue::String(session_token.into()),
94                )]
95                .into_iter()
96                .collect(),
97            ),
98        )
99    }
100
101    /// List active distinct accounts from genuine signed browser proofs.
102    #[must_use]
103    pub const fn list_device_sessions_endpoint() -> ServerEndpoint<Vec<DeviceSession>> {
104        ServerEndpoint::new("multi-session", "listDeviceSessions")
105    }
106}