2 releases

new 0.1.1 Dec 4, 2024
0.1.0 Nov 24, 2024

#951 in Web programming

Download history 115/week @ 2024-11-18 31/week @ 2024-11-25

146 downloads per month

GPL-3.0-or-later

690KB
16K SLoC

xapi-rs

This project is an attempt at implementing a conformant IEEE Std 9274.1.1, IEEE Standard for Learning Technology— JavaScript Object Notation (JSON) Data Model Format and Representational State Transfer (RESTful) Web Service for Learner Experience Data Tracking and Access 2.0.0 LRS.

There are 3 main modules in this project that cover:

  1. data – the data structures involved,
  2. db – their Data Access Objects for storing in, and fetching them from a database, and finally
  3. lrs – a Web server to handle the LRS calls proper.

Changes are tracked in ChangeLog.

Prerequisites

Users of this project, at this stage, are expected to be mostly developers or system administrators planning on setting up an LRS to integrate with an LMS (Learning Management System) or other learning experience related systems --see here for various examples and definitions. The jargon i'll use here then is for those user profiles.

The main software components required to make use of this project are:

  1. Rust

    The produced binaries (debug and release versions) can run directly on their own. However b/c this is a Web Server that stores users' data locally, produces logs, etc... deployment is not as straightforward as installing and using a command line utility. A good guide on how to do that I would suggest is Rocket Guide - Deploying.

    In addition if you plan on contributing to the project, and locally testing changes etc... including passing conformance tests you'll need to install Rust.

  2. PostgreSQL

    As mentioned in the documentation, this project relies on an installed PostgreSQL database system. FWIW, as of the last edit date of this document, the version of PostgreSQL was 16.3.

    You will need to configure a user w/ enough permissions to create databases and tables on the node where the RDBMS is running.

  3. Node.js

    To locally run the CTS you'll need to install Node.js and configure LaRS to be efficiently used for this use-case --see the Conformance Tests section later in this document.

  4. nginx (or another HTTP Proxy server)

    I developed and tested this project running it behind an nginx proxy in turn behind a firewall. This setup delegates the security, TLS handshakes + Certificates handling, and outside access to the nginx proxy server, which then allows running LaRS in HTTP mode securely.

    Of course other proxy servers can be used such as Apache httpd but nowadays, nginx is my preferred goto for these use-cases.

Templates

You should copy the two .env.template and Rocket.toml.template files and rename them removing the .template suffix.

These files are expected to contain sensitive information particular to your environment. They should be already included in the .gitignore file but it's a good idea to double-check.

You should also carefully inspect and set the variables in those files to accurately reflect your setup + environment. Hopefully the comments in .env.template should make this easy. The Rocket.toml as its name implies is a Rocket specific configuration file. It is documented here.

The static and logs folders

When you run LaRS for the first time it will create two folders named static and logs under the project's home-dir —which in development is the CARGO_MANIFEST_DIR.

The static folder will contain files that store xAPI Attachments, Statements, and JWS Signatures received by way of PUT and POST HTTP Requests having multipart/mixed content type.

The logs folder will contain log files that capture the tracing output of the server.

Conformance Tests

This project passes the LRS Conformance Tests Suite (CTS) found here w/ caveats. Here's the output of the first time it did:

{
    "name": "console",
    "owner": null,
    "flags": {
        "endpoint": "http://localhost:9000"
    },
    "options": {},
    "rollupRule": "mustPassAll",
    "uuid": "101cae0f-785d-4cbe-9de0-30b29f973647",
    "startTime": 1732158267726,
    "endTime": 1732158306773,
    "duration": 39047,
    "state": "finished",
    "summary": {
        "total": 1442,
        "passed": 1442,
        "failed": 0,
        "version": "2.0.0"
    }
}

The CTS when run locally requires the following patch (to the helper.js file) and adjustment to the server's configuration. The patch for the helper.js eliminates the TIME_MARGIN constraint.

The server configuration adjustments deal with modifying the .env parameters to run the server locally. These modifications are:

DB_STATEMENTS_PAGE_LEN = 2
LRS_EXTERNAL_URL="http://localhost:9000/"
RUST_LOG="info,xapi_rs=debug"

The first limits the number of Statements to include in a StatementResult to only 2. Given that the tests rely on a setup preamble of one or two known Statements the limit of 2 for DB_STATEMENTS_PAGE_LEN ensures that no more than 2 calls are made to LaRS before the test receives the expected result.

The second is used by LaRS for populating the more property of a StatementResult which the test may invoke when an earlier response did not contain the expected Statement.

The last parameter ensures maximum verbosity in the logs which should help tracking what LaRS is emitting in response to CTS requests.

Finally to run the CTS, on LaRS side, open a command line console and enter:

$ sqlx db drop ↵
Drop database at <DB_SERVER_URL/DB_NAME>? (y/n): y ↵
$ sqlx db create ↵
$ cargo run --release

And on the CTS side, enter:

$ node bin/console_runner.js -e <LRS_EXTERNAL_URL> -x 2.0.0 -z

The DB_SERVER_URL, DB_NAME, and LRS_EXTERNAL_URL should be the same as set in .env.

TODO

In no particular order...

  • Pass the conformance tests. Done 2024-11-21.
  • Remove speedate and re-write using chrono.
  • If the JWS header (of a signed Statement) includes an X.509 certificate, we should validate the signature against that certificate as defined in JWS. We don't do that yet.
  • Clean up residual temporary files that are created while processing multipart requests for Statements and Attachments which end up being rejected.
  • Implement a Job scheduler to clean temporary database Views created when a GET request leads to more results that can fit into a page.
  • Introduce a configuration option to allow setting either a time or size limits on assets stored in static.
  • Optimize Pg SQL queries --may be using CTEs.
  • Minimize memory allocation by reducing the use of String types especially in custom deserializer implementations --e.g. consider using DeserializeSeed.
  • Add support for Authentication.
  • Add support for Authorization.

License

This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program. If not, see https://www.gnu.org/licenses/.

Dependencies

~62–95MB
~2M SLoC