Development Documentation (main branch) - For stable release docs, see docs.rs/eidetica
Skip to main content

eidetica/instance/
new_user.rs

1//! Inputs for creating a user.
2//!
3//! [`NewUser`] is the request shape for "create a user with these settings",
4//! used in two places:
5//!
6//! - [`Instance::create_backend`](super::Instance::create_backend) and
7//!   [`Instance::connect_or_create`](super::Instance::connect_or_create) — the
8//!   initial user who bootstraps a fresh instance, automatically granted
9//!   Admin on the system databases by virtue of being the first user.
10//! - [`InstanceAdmin::create_user`](crate::user::InstanceAdmin::create_user) —
11//!   every subsequent user created by an existing admin.
12//!
13//! There is no separate "initial user" concept: the entity that creates the
14//! instance is just the first `NewUser`, and from that point on additional
15//! users are created through the admin path. This eliminates the prior
16//! hardcoded `admin/admin` bootstrap.
17
18/// Inputs needed to create a user account.
19///
20/// Use the [`passwordless`](Self::passwordless) constructor for embedded or
21/// single-user applications where login latency matters and the surrounding
22/// process is already trusted; use [`with_password`](Self::with_password) for
23/// multi-user deployments where the root key must be encrypted at rest.
24///
25/// The struct is marked `#[non_exhaustive]` so we can add fields
26/// (key algorithm, locale, initial roles, etc.) without a breaking API
27/// change. Construct it through the provided helpers rather than struct
28/// literal syntax.
29#[derive(Debug, Clone)]
30#[non_exhaustive]
31pub struct NewUser {
32    /// Login identifier for the user. Must be unique within the instance.
33    pub username: String,
34    /// Optional password. `None` produces a passwordless user whose root key
35    /// is stored unencrypted (fine for embedded apps where the host process
36    /// is the trust boundary); `Some(_)` produces an Argon2id-derived
37    /// encryption key under which the root signing key is AES-256-GCM
38    /// encrypted at rest.
39    pub password: Option<String>,
40}
41
42impl NewUser {
43    /// Create a passwordless user. The root signing key will be stored
44    /// unencrypted in the user's credentials.
45    pub fn passwordless(name: impl Into<String>) -> Self {
46        Self {
47            username: name.into(),
48            password: None,
49        }
50    }
51
52    /// Create a password-protected user. The root signing key will be
53    /// encrypted with an Argon2id-derived key at rest; the password is
54    /// required for every login.
55    pub fn with_password(name: impl Into<String>, password: impl Into<String>) -> Self {
56        Self {
57            username: name.into(),
58            password: Some(password.into()),
59        }
60    }
61}