Skip to main content

xapi_rs/lrs/resources/
agents.rs

1// SPDX-License-Identifier: GPL-3.0-or-later
2
3//! Agents Resource (/agents)
4//! --------------------------
5//! Provides a method to retrieve a [Person] Object with combined information
6//! about an [Agent] derived from an outside service, such as a directory
7//! service. This object is called a "Person Object". This [Person] Object is
8//! very similar to an [Agent] Object, but instead of each attribute having a
9//! single value, each attribute has an array value. In addition it's legal
10//! to include multiple identifying properties.
11//!
12//! Any deviation from section [4.1.6.3 Agents Resource (/activities/state)][1]
13//! of the xAPI specification is a bug.
14//!
15//! [1]: https://opensource.ieee.org/xapi/xapi-base-standard-documentation/-/blob/main/9274.1.1%20xAPI%20Base%20Standard%20for%20LRSs.md#4163-agents-resource-agents
16
17use crate::{
18    data::{Agent, Person},
19    db::actor::find_person,
20    emit_response,
21    lrs::{headers::Headers, resources::WithResource, User, DB},
22    MyError,
23};
24use rocket::{get, http::Status, routes, State};
25use sqlx::PgPool;
26use std::str::FromStr;
27use tracing::{debug, info};
28
29#[doc(hidden)]
30pub fn routes() -> Vec<rocket::Route> {
31    routes![get]
32}
33
34#[get("/?<agent>")]
35async fn get(
36    c: Headers,
37    agent: &str,
38    db: &State<DB>,
39    user: User,
40) -> Result<WithResource<Person>, MyError> {
41    debug!("----- get ----- {}", user);
42    user.can_use_xapi()?;
43
44    let agent =
45        Agent::from_str(agent).map_err(|x| MyError::Data(x).with_status(Status::BadRequest))?;
46    debug!("agent = {}", agent);
47    let resource = get_resource(db.pool(), &agent).await?;
48    debug!("resource = {}", resource);
49    emit_response!(c, resource => Person)
50}
51
52async fn get_resource(conn: &PgPool, agent: &Agent) -> Result<Person, MyError> {
53    let x = find_person(conn, agent).await?;
54    match x {
55        None => {
56            // NOTE (rsn) 20241103 - CTS expects a Person object even when none
57            // was found.  the spec only states "Returns: 200 OK, Person Object"
58            // how clear is that :/
59            info!("No known Person");
60            Ok(Person::unknown())
61        }
62        Some(x) => Ok(x),
63    }
64}