rustio_admin/lib.rs
1//! rustio-admin — Django Admin, but for Rust.
2//!
3//! This crate is the public face of the framework. Phase 2 ships the
4//! HTTP / router / server / ORM / migrations / templates core; later
5//! phases populate `auth` and `admin`.
6
7#![forbid(unsafe_code)]
8
9// public:
10pub mod admin;
11// public:
12pub mod auth;
13// public:
14pub mod background;
15// public:
16pub mod email;
17// public:
18pub mod error;
19// public:
20pub mod http;
21// public:
22pub mod middleware;
23// public:
24pub(crate) mod meta;
25pub mod migrations;
26pub(crate) mod multipart;
27// public:
28pub mod orm;
29// public:
30pub mod router;
31// public:
32pub mod server;
33// public:
34pub mod templates;
35// public:
36pub mod view_layer;
37
38// public:
39pub use crate::admin::{
40 register_admin_routes, Admin, AdminField, AdminModel, BulkAction, BulkActionContext,
41 BulkActionFailure, BulkActionResult, FieldType, FieldValidationError, Fieldset, Inline,
42 ModelAdmin,
43};
44// public:
45pub use crate::auth::{Identity, Role};
46// public:
47pub use crate::error::{Error, Result};
48// public:
49pub use crate::http::{FormData, Request, Response};
50// public:
51pub use crate::orm::{Db, DbOptions, Model, Row, Value};
52// public:
53pub use crate::router::{Next, Router};
54// public:
55pub use crate::server::Server;
56// public:
57pub use crate::templates::{embedded_template_names, embedded_template_source};
58
59// public:
60pub use rustio_admin_macros::RustioAdmin;
61
62// public: re-exported runtime dependencies.
63//
64// A downstream model crate depends on `rustio-admin` alone: the
65// `RustioAdmin` derive emits paths through these re-exports
66// (`::rustio_admin::chrono::…`, `::rustio_admin::rust_decimal::…`,
67// `::rustio_admin::uuid::…`), and a model's own field types resolve via
68// the bare type aliases below (`use rustio_admin::{Decimal, DateTime,
69// Utc, Uuid};`). This is what lets a scaffolded `Cargo.toml` drop its
70// direct `chrono` / `uuid` / `rust_decimal` / `sqlx` dependencies — the
71// framework already owns those versions, so re-exporting them keeps the
72// whole tree on one resolved copy and removes a class of version-skew
73// bugs. The crates are re-exported as modules (for the macro's
74// fully-qualified paths and for advanced handlers, e.g.
75// `rustio_admin::sqlx::query`); the type aliases are the ergonomic
76// surface model files actually name.
77pub use chrono;
78pub use rust_decimal;
79pub use sqlx;
80pub use uuid;
81// public: the field types a model declares, without a direct dep.
82pub use chrono::{DateTime, NaiveDate, NaiveTime, Utc};
83pub use rust_decimal::Decimal;
84pub use uuid::Uuid;
85
86// `RustioAdmin` emits `::rustio_admin::*` paths in its expansion. That
87// resolves cleanly for downstream consumers, but inside this crate's
88// own compilation unit `rustio_admin` isn't a known extern. Aliasing
89// the crate to itself under `cfg(test)` lets the macro be exercised
90// from this crate's own tests without changing any non-test build.
91#[cfg(test)]
92extern crate self as rustio_admin;
93
94// internal: test-only re-export surface, gated by integration-test feature
95/// Test-only re-exports for the integration-test suite under
96/// `tests/integration_*.rs`. NOT part of the public API — the
97/// module is `#[doc(hidden)]` and gated behind the
98/// `integration-test` Cargo feature, so a regular
99/// `cargo build` / `cargo test --workspace` cannot reach it.
100///
101/// Re-exports the otherwise-`pub(crate)` runtime surface of
102/// `auth::recovery_admin` so the integration tests can exercise
103/// `record_failed_login`, `admin_set_temp_password`, etc. without
104/// promoting the internal API to permanent `pub` visibility.
105///
106/// Plus a `fake_request()` builder for runtime fns that take
107/// `&Request` (currently `lock_user_account`,
108/// `unlock_user_account`, `admin_revoke_sessions`,
109/// `issue_admin_reset_token`, `admin_set_temp_password`). The
110/// fake request has no headers — `client_ip` and
111/// `correlation_id_from` both return `None`, which is the
112/// neutral state for the audit + logging layers.
113///
114/// See `DESIGN_R2_ORGANISATIONAL.md` §10.3 for the integration-
115/// test plan.
116#[doc(hidden)]
117#[cfg(feature = "integration-test")]
118pub mod __integration {
119 // internal: test-only re-export
120 pub use crate::auth::recovery_admin::{
121 admin_revoke_sessions, admin_set_temp_password, check_account_lockout,
122 check_session_elevated, issue_admin_reset_token, lock_user_account,
123 promote_session_elevated, record_failed_login, record_successful_login,
124 unlock_user_account, AdminActor, AdminIssueOutcome, AdminRevokeOutcome, AdminTempPwOutcome,
125 LockDuration, LockOutcome, LockState, ThrottleOutcome, UnlockOutcome,
126 };
127 // R3 MFA — runtime fns + outcomes + key type + pure helpers the
128 // integration suite needs to drive enrolment / verify /
129 // consume / disable / regenerate flows. The `auth::mfa` module
130 // is `pub(crate)`, so this is the only door under the
131 // `integration-test` feature. See `DESIGN_R3_MFA.md` §13.3.
132 // internal: test-only re-export
133 pub use crate::auth::mfa::{
134 confirm_enrolment, consume_backup_code, current_step, disable_mfa, generate_totp,
135 promote_session_to_mfa_verified, provision_secret, regenerate_backup_codes,
136 verify_totp_for_user, BackupConsumeOutcome, DisableOutcome, EnrolOutcome, MfaKey,
137 ProvisionedSecret, RegenOutcome, VerifyOutcome, BACKUP_CODE_COUNT,
138 };
139 // internal: test-only wrapper for the pub(crate) hash helper
140 /// R4 emergency-recovery test-only helper — forwards to the
141 /// `pub(crate)` `auth::sessions::hash_token_for_storage` so
142 /// the integration suite can verify that an
143 /// `emergency_access`-issued URL stores its token in the
144 /// exact same format R1's consume path will look up later.
145 /// Catches the hex-vs-base64 drift surfaced during commit #8
146 /// (which the unit-test gate could not have seen — only a
147 /// live-DB or testcontainers run can). Wrapped rather than
148 /// `pub use`'d because the inner helper is `pub(crate)` and
149 /// cannot be re-exported under a stricter visibility.
150 /// See `DESIGN_R4_EMERGENCY.md` §9.2.
151 pub fn hash_token_for_storage(token: &str) -> String {
152 crate::auth::sessions::hash_token_for_storage(token)
153 }
154
155 // internal: test-only re-export of the view-spec store
156 /// View-designer persistence (`admin::view_specs`) is `pub(crate)`;
157 /// these aliases let `tests/integration_view_specs.rs` exercise the
158 /// real Postgres round-trip (`ensure_table` → `save` → `load` →
159 /// `saved_models`) without promoting the store to permanent `pub`.
160 pub use crate::admin::view_specs::{
161 load as view_specs_load, save as view_specs_save, saved_models as view_specs_saved_models,
162 };
163
164 // internal: test-only request builder
165 /// Construct a minimal [`crate::http::Request`] for integration
166 /// tests. POST to `/test`, no headers, no body, no params.
167 /// Adequate for runtime fns that read only `client_ip` (None)
168 /// and `correlation_id_from` (None) from the request.
169 pub fn fake_request() -> crate::http::Request {
170 use std::collections::HashMap;
171 crate::http::Request::__integration_test_fake("/test".to_string(), HashMap::new())
172 }
173}