lenso-module-auth 0.2.3

First-party auth anchor module for the Lenso backend framework.
Documentation
use axum::Json;
use axum::http::{HeaderMap, HeaderValue, header};
use platform_http::{ApiOpenApiRouter, OpenApiRouter, routes};
use serde_json::{Value, json};
use sha2::{Digest as _, Sha256};

pub const AUTH_CONSOLE_ARTIFACT_PATH: &str = "/v1/auth/console/artifact";
pub const AUTH_CONSOLE_RELEASE_PATH: &str = "/v1/auth/console/release";
pub const AUTH_CONSOLE_RELEASE_PROTOCOL: &str = "lenso.console-artifact-template.v1";

const AUTH_CONSOLE_ARTIFACT: &[u8] = include_bytes!("../artifacts/auth-console.tgz");
const AUTH_CONTRACT_DOCUMENT: &str = include_str!("../artifacts/auth-business-api.v1.json");

pub fn router() -> ApiOpenApiRouter {
    OpenApiRouter::new()
        .routes(routes!(get_console_artifact))
        .routes(routes!(get_console_release))
}

#[utoipa::path(
    get,
    path = "/v1/auth/console/artifact",
    operation_id = "auth_console_artifact",
    tag = "auth-console",
    responses((status = 200, description = "Exact Auth Console ESM artifact", content_type = "application/gzip"))
)]
async fn get_console_artifact() -> (HeaderMap, &'static [u8]) {
    let mut headers = HeaderMap::new();
    headers.insert(
        header::CONTENT_TYPE,
        HeaderValue::from_static("application/gzip"),
    );
    headers.insert(
        header::CACHE_CONTROL,
        HeaderValue::from_static("public, max-age=31536000, immutable"),
    );
    (headers, AUTH_CONSOLE_ARTIFACT)
}

#[utoipa::path(
    get,
    path = "/v1/auth/console/release",
    operation_id = "auth_console_release",
    tag = "auth-console",
    responses((status = 200, description = "Auth Module-owned Console artifact release template", body = serde_json::Value, content_type = "application/json"))
)]
async fn get_console_release() -> Json<Value> {
    Json(console_release_template())
}

#[must_use]
pub fn console_release_template() -> Value {
    let manifest = crate::module::manifest();
    let console_manifest = manifest.console_module_manifest("^2.1.0", "^2.0.0");
    json!({
        "protocol": AUTH_CONSOLE_RELEASE_PROTOCOL,
        "moduleId": manifest.module_id,
        "version": env!("CARGO_PKG_VERSION"),
        "manifest": manifest,
        "artifactPath": AUTH_CONSOLE_ARTIFACT_PATH,
        "artifact": {
            "digest": artifact_digest(),
            "format": "console_ui_esm",
            "protocolMajor": 1,
            "entry": "index.js",
            "entries": [
                { "name": "module", "path": "index.js" },
                { "name": "sessions", "path": "index.js?surface=sessions" },
                { "name": "users", "path": "index.js?surface=users" },
                { "name": "style", "path": "assets/stylex.css" }
            ],
            "styleAssets": [
                { "path": "assets/stylex.css", "order": 0 }
            ],
            "manifest": console_manifest,
            "requestedPermissions": []
        },
        "delivery": {
            "kind": "linked",
            "package": "lenso-module-auth",
            "crateVersion": env!("CARGO_PKG_VERSION"),
            "defaultFeatures": false,
            "features": ["redis"],
            "binding": "auth"
        },
        "compatibility": {
            "lensoRequirement": "^0.3.0",
            "hostApiRequirement": "^2.1.0",
            "consoleUiRequirement": "^2.0.0",
            "rustRequirement": ">=1.94"
        },
        "surfaceApi": {
            "contractDigest": crate::console_api::AUTH_CONTRACT_DIGEST,
            "operationIds": [
                crate::console_api::LIST_SESSIONS_OPERATION,
                crate::console_api::LIST_USERS_OPERATION,
                crate::console_api::REVOKE_SESSION_OPERATION,
                crate::console_api::DISABLE_USER_OPERATION,
                crate::console_api::ENABLE_USER_OPERATION
            ],
            "contractArtifact": {
                "format": "openapi_3_1_json",
                "document": AUTH_CONTRACT_DOCUMENT
            }
        }
    })
}

fn artifact_digest() -> String {
    let hex = Sha256::digest(AUTH_CONSOLE_ARTIFACT)
        .iter()
        .map(|byte| format!("{byte:02x}"))
        .collect::<String>();
    format!("sha256:{hex}")
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn release_template_binds_the_current_module_and_surface_contract() {
        let release = console_release_template();
        assert_eq!(release["moduleId"], "lenso/auth");
        assert_eq!(release["version"], env!("CARGO_PKG_VERSION"));
        assert_eq!(
            release["artifact"]["digest"],
            "sha256:01d607ec71232d7973cbce6787f4cd713f49eefb18002bf5764d65656708cf89"
        );
        assert_eq!(
            release["surfaceApi"]["contractDigest"],
            crate::console_api::AUTH_CONTRACT_DIGEST
        );
        assert_eq!(
            release["artifact"]["manifest"],
            serde_json::to_value(
                crate::module::manifest().console_module_manifest("^2.1.0", "^2.0.0")
            )
            .unwrap()
        );
    }
}