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

User

Struct User 

Source
pub struct User { /* private fields */ }
Expand description

User session object, returned after successful login

Represents an authenticated user with decrypted private keys loaded in memory. The User struct provides access to key management, tracked databases, and bootstrap approval operations.

Implementations§

Source§

impl User

Source

pub fn user_uuid(&self) -> &str

Get the internal user UUID (stable identifier)

Source

pub fn username(&self) -> &str

Get the username (login identifier)

Source

pub fn user_database(&self) -> &Database

Get a reference to the user’s database

Source

pub fn backend(&self) -> &Arc<dyn Backend>

Get a reference to the backend seam.

Source

pub fn user_info(&self) -> &UserInfo

Get a reference to the user info

Source

pub async fn is_admin(&self) -> Result<bool>

Whether this user is an instance admin.

“Instance admin” means the user’s default pubkey holds Admin in the _users system database’s auth_settings. The admin/admin user created during instance bootstrap is auto-promoted; subsequent users land as non-admins until promoted via InstanceAdmin::grant_instance_admin.

Returns false if the key resolution fails (key not in auth_settings, non-Admin permission, etc.). For the capability handle rather than a bool, use Self::admin.

Source

pub async fn admin(&self) -> Result<InstanceAdmin<'_>>

Obtain the instance-admin capability view.

Returns an InstanceAdmin only if this user’s default key holds Admin on the _users system database. All admin-gated operations (creating users, listing users, promoting admins) live on the returned view, so the privilege boundary is explicit at the call site and those operations need no further permission check of their own.

§Errors
Source

pub fn logout(self) -> Result<()>

Logout (consumes self and clears decrypted keys from memory)

After logout, all decrypted keys are zeroized and the session is ended. Keys are automatically cleared when the User is dropped.

Source

pub fn new_database(&mut self) -> DatabaseBuilder<'_>

Start building a new database via the chainable DatabaseBuilder API.

The builder collects settings, key policy, and store initializers, then produces a fully-initialized database in a single genesis entry when DatabaseBuilder::build is called.

For the lower-level direct constructor see Self::create_database.

Source

pub async fn create_database( &mut self, settings: Doc, key_id: &PublicKey, ) -> Result<Database>

Create a new database with explicit key selection.

This method requires you to specify which key should be used to create and manage the database, providing explicit control over key-database relationships.

§Arguments
  • settings - Initial database settings (metadata, name, etc.)
  • key_id - The ID of the key to use for this database (public key string)
§Returns

The created Database

§Errors
  • Returns an error if the specified key_id doesn’t exist
  • Returns an error if the key cannot be retrieved
§Example
// Get available keys
let keys = user.list_keys()?;
let key_id = &keys[1]; // Use the second key

// Create database with explicit key selection
let mut settings = Doc::new();
settings.set("name", "My Database");
let database = user.new_database(settings, key_id)?;
Source

pub async fn create_database_with_init<F>( &mut self, settings: Doc, key_id: &PublicKey, init: F, ) -> Result<Database>

Creates a new database with an initialization callback that runs inside the genesis transaction.

This is the underlying constructor used by Self::create_database and by Self::new_database (the builder API). The callback receives the genesis transaction after _settings and _root have been staged but before commit, allowing additional subtrees to be written into the same entry that establishes the database root. See Database::create_with_init for details on the atomicity guarantee.

After the genesis entry commits, this method performs the standard user-side tracking write (key-database mapping, TrackedDatabase entry) in a separate transaction on the user’s own system database.

Source

pub async fn open_database(&self, root_id: &ID) -> Result<Database>

Open an existing database by its root ID using this user’s keys.

This method automatically:

  1. Finds an appropriate key that has access to the database
  2. Retrieves the decrypted SigningKey from the UserKeyManager
  3. Gets the SigKey mapping for this database
  4. Creates a Database instance configured with the user’s key

The returned Database will use the user’s provided key for all operations, without requiring backend key lookups.

§Arguments
  • root_id - The root entry ID of the database
§Returns

The opened Database configured to use this user’s keys

§Errors
  • Returns an error if no key is found for the database
  • Returns an error if no SigKey mapping exists
  • Returns an error if the key is not in the UserKeyManager
Source

pub async fn open_database_with_key( &self, root_id: &ID, key_id: &PublicKey, ) -> Result<Database>

Open an existing database with an explicitly chosen key.

Equivalent to open_database, but selects the user’s signing key by public key instead of relying on find_key’s iteration order. Use this when the user holds multiple authorized keys for a database and you need writes signed by a specific one (e.g. agent-as-signer scenarios where cryptographic provenance matters, not just authorization).

The key_id is purely a selector into this user’s UserKeyManager; no crypto material is passed in.

§Arguments
  • root_id - The root entry ID of the database
  • key_id - Public key of the user-held key to sign with
§Returns

The opened Database configured to use the specified key

§Errors
  • Returns an error if the root entry does not exist
  • Returns an error if the user does not hold a key with that pubkey
  • Returns an error if the key has no SigKey mapping for this database
Source

pub async fn find_database( &self, name: impl AsRef<str>, ) -> Result<Vec<Database>>

Find databases by name among the user’s tracked databases.

Searches only the databases this user has tracked for those matching the given name.

§Arguments
  • name - Database name to search for
§Returns

Vector of matching databases from the user’s tracked list

Source

pub fn find_key(&self, database_id: &ID) -> Result<Option<PublicKey>>

Find which key can access a database.

Searches this user’s keys to find one that can access the specified database. Considers the SigKey mappings stored in user key metadata.

Returns the key_id of a suitable key, preferring keys with mappings for this database.

§Arguments
  • database_id - The ID of the database
§Returns

Some(key_id) if a suitable key is found, None if no keys can access this database

Source

pub fn key_mapping( &self, key_id: &PublicKey, database_id: &ID, ) -> Result<Option<SigKey>>

Get the resolved SigKey mapping for a key in a specific database.

Users map their private keys to SigKey identifiers on a per-database basis. This retrieves the resolved SigKey that a specific key uses in a specific database’s authentication settings.

Internally, None in the stored mapping means “default pubkey identity”, which this method resolves to the concrete SigKey::from_pubkey(...) value.

§Arguments
  • key_id - The user’s key identifier
  • database_id - The database ID
§Returns

Ok(Some(sigkey)) if a mapping exists (resolved to concrete SigKey), Ok(None) if no mapping is configured for this database

§Errors

Returns an error if the key_id doesn’t exist in the UserKeyManager

Source

pub async fn map_key( &mut self, key_id: &PublicKey, database_id: &ID, sigkey: SigKey, ) -> Result<()>

Map a key to a SigKey identity for a specific database.

Registers that this user’s key should be used with a specific SigKey identity when interacting with a database. This is typically used when a user has been granted access to a database and needs to configure their local key to work with it.

If the provided SigKey matches the default pubkey identity for this key, it is normalized to None internally (compact storage for the common case).

§Multi-Key Support

Note: A database may have mappings to multiple keys. This is useful for multi-device scenarios where the same user wants to access a database from different devices, each with their own key.

§Arguments
  • key_id - The user’s key identifier (public key)
  • database_id - The database ID
  • sigkey - The SigKey identity to use for this database
§Errors

Returns an error if the key_id doesn’t exist in the user database

Source

pub async fn add_private_key( &mut self, display_name: Option<&str>, ) -> Result<PublicKey>

Add a new private key to this user’s keyring.

Generates a new Ed25519 keypair, encrypts it (for password-protected users) or stores it unencrypted (for passwordless users), and adds it to the user’s key database.

§Arguments
  • display_name - Optional display name for the key
§Returns

The key ID (public key string)

Source

pub fn list_keys(&self) -> Result<Vec<PublicKey>>

List all key IDs owned by this user.

Keys are returned sorted by creation timestamp (oldest first), making the first key in the list the “default” key created when the user was set up.

§Returns

Vector of PublicKeys sorted by creation time

Source

pub fn get_default_key(&self) -> Result<PublicKey>

Get the default key.

Returns the key marked as is_default=true, or falls back to the oldest key by creation timestamp if no default is explicitly set.

§Returns

The PublicKey of the default key

§Errors

Returns an error if no keys exist

Source

pub fn key_display_name(&self, key_id: &PublicKey) -> Option<&str>

Get the display name set for a key.

Display names are caller-supplied human-readable labels passed to add_private_key. They have no cryptographic significance and are not unique across keys. Returns None if the user does not hold a key with this pubkey, or if it was added without a display name.

§Arguments
  • key_id - Public key of a key held by this user
Source

pub fn find_keys_by_display_name(&self, name: &str) -> Vec<PublicKey>

Find user-held keys whose display name matches name.

Display names are not unique, so this returns every key whose display_name exactly matches the provided string. Keys without a display name are never returned. Returns an empty Vec when there are no matches.

§Arguments
  • name - Exact display name to match
Source

pub fn get_signing_key(&self, key_id: &PublicKey) -> Result<PrivateKey>

Get a signing key by its ID.

§Arguments
  • key_id - The public key identifier
§Returns

The PrivateKey if found

Source

pub async fn pending_bootstrap_requests( &self, sync: &Sync, ) -> Result<Vec<(String, BootstrapRequest)>>

Get all pending bootstrap requests from the sync system.

This is a convenience method that requires the Instance’s Sync to be initialized.

§Arguments
  • sync - Reference to the Instance’s Sync object
§Returns

A vector of (request_id, bootstrap_request) pairs for pending requests

Source

pub async fn approve_bootstrap_request( &self, sync: &Sync, request_id: &str, approving_key_id: &PublicKey, ) -> Result<()>

Approve a bootstrap request and add the requesting key to the target database.

The approving key must have Admin permission on the target database.

§Arguments
  • sync - Mutable reference to the Instance’s Sync object
  • request_id - The unique identifier of the request to approve
  • approving_key_id - The ID of this user’s key to use for approval (must have Admin permission)
§Returns

Result indicating success or failure of the approval operation

§Errors
  • Returns an error if the user doesn’t own the specified approving key
  • Returns an error if the approving key doesn’t have Admin permission on the target database
  • Returns an error if the request doesn’t exist or isn’t pending
  • Returns an error if the key addition to the database fails
Source

pub async fn reject_bootstrap_request( &self, sync: &Sync, request_id: &str, rejecting_key_id: &PublicKey, ) -> Result<()>

Reject a bootstrap request.

This method marks the request as rejected. The requesting device will not be granted access to the target database. Requires Admin permission on the target database to prevent unauthorized users from disrupting the bootstrap protocol.

§Arguments
  • sync - Mutable reference to the Instance’s Sync object
  • request_id - The unique identifier of the request to reject
  • rejecting_key_id - The ID of this user’s key (for permission validation and audit trail)
§Returns

Result indicating success or failure of the rejection operation

§Errors
  • Returns an error if the user doesn’t own the specified rejecting key
  • Returns an error if the request doesn’t exist or isn’t pending
  • Returns an error if the rejecting key lacks Admin permission on the target database
Source

pub async fn request_database_access( &self, sync: &Sync, ticket: &DatabaseTicket, key_id: &PublicKey, requested_permission: Permission, ) -> Result<()>

Request access to a database from a peer (bootstrap sync).

This convenience method initiates a bootstrap sync request to access a database that this user doesn’t have locally yet. The user’s key will be sent to the peer to request the specified permission level.

This is useful for multi-device scenarios where a user wants to access their existing database from a new device, or when requesting access to a database shared by another user.

§Arguments
  • sync - Reference to the Instance’s Sync object
  • ticket - A ticket containing the database ID and address hints
  • key_id - The ID of this user’s key to use for the request
  • requested_permission - The permission level being requested
§Returns

Result indicating success or failure of the bootstrap request

§Errors
  • Returns an error if the user doesn’t own the specified key
  • Returns an error if all addresses in the ticket fail
  • Returns an error if the bootstrap sync fails
§Example
// Request write access to a shared database
let user_key_id = user.get_default_key()?;
let ticket: DatabaseTicket = "eidetica:?db=sha256:abc...&pr=http:192.168.1.1:8080".parse()?;
user.request_database_access(
    &sync,
    &ticket,
    &user_key_id,
    Permission::Write(5),
).await?;

// After approval, the database can be opened
let database = user.open_database(ticket.database_id())?;
Source

pub async fn track_database( &mut self, database_id: impl Into<ID>, key_id: &PublicKey, sync_settings: SyncSettings, ) -> Result<()>

Track a database, adding it to this user’s list with auto-discovery of SigKeys.

This method adds an existing database to your tracked list, or updates it if already tracked (upsert behavior).

When tracking:

  1. Uses Database::find_sigkeys() to discover which SigKey the user can use
  2. Automatically selects the SigKey with highest permission
  3. Stores the key mapping and sync settings

The sync_settings indicate your sync preferences, but do not automatically configure sync. Use the Sync module’s peer and tree methods to set up actual sync relationships.

§Arguments
  • database_id - ID of the database to track
  • key_id - Which user key to use for this database
  • sync_settings - Sync preferences for this database
§Returns

Result indicating success or failure

§Errors
  • Returns NoSigKeyFound if no SigKey can be found for the specified key
  • Returns KeyNotFound if the specified key_id doesn’t exist
Source

pub async fn databases(&self) -> Result<Vec<TrackedDatabase>>

List all tracked databases.

Returns all databases this user has added to their tracked list.

§Returns

Vector of TrackedDatabase entries

Source

pub async fn database(&self, database_id: &ID) -> Result<TrackedDatabase>

Get a specific tracked database by ID.

§Arguments
  • database_id - The ID of the database
§Returns

The TrackedDatabase if it’s in the user’s tracked list

§Errors

Returns DatabaseNotTracked if the database is not in the user’s list

Source

pub async fn enable_sync(&mut self, database_id: &ID) -> Result<()>

Enable sync for a tracked database.

Sets sync_enabled = true on the user’s preference for this database, preserving sync_on_commit, interval_seconds, and properties. Propagates the change to the host-level combined sync state by calling Sync::sync_user if sync is attached to the instance.

No-op if already enabled.

§Errors

Returns DatabaseNotTracked if the database is not in the user’s list.

Source

pub async fn disable_sync(&mut self, database_id: &ID) -> Result<()>

Disable sync for a tracked database.

Sets sync_enabled = false on the user’s preference for this database, preserving other sync settings. Propagates to the host via Sync::sync_user if sync is attached.

The host-level combined state is OR’d across all users on the instance, so another user with sync enabled for the same database will keep the host serving it.

No-op if already disabled.

§Errors

Returns DatabaseNotTracked if the database is not in the user’s list.

Source

pub async fn share(&mut self, database_id: &ID) -> Result<DatabaseTicket>

Enable sync for a tracked database and return a DatabaseTicket for handoff.

Equivalent to building a ticket via Sync::create_ticket and then calling Self::enable_sync, in a single call. The ticket carries the database ID plus any peer addresses that the instance’s sync transports are currently advertising; a peer that imports the ticket via Sync::sync_with_ticket will be able to fetch the database immediately.

All preconditions (sync attached, transport registered) are checked before any user state is mutated, so a failed share() leaves the user’s sync preference unchanged.

§Errors
Source

pub async fn is_sync_enabled(&self, database_id: &ID) -> Result<bool>

Check whether this user has sync enabled for a tracked database.

Returns this user’s own preference, not the host’s combined state. A false result means this user is not personally sharing the database; another user on the same instance may still have sync enabled for it.

Returns Ok(false) for databases not tracked by this user.

Source

pub async fn untrack_database(&mut self, database_id: &ID) -> Result<()>

Stop tracking a database.

This removes the database from the user’s tracked list. It does not delete the database itself, remove key mappings, or delete any data.

§Arguments
  • database_id - The ID of the database to stop tracking
§Errors

Returns DatabaseNotTracked if the database is not in the user’s list

Trait Implementations§

Source§

impl Debug for User

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

§

impl Freeze for User

§

impl !RefUnwindSafe for User

§

impl Send for User

§

impl Sync for User

§

impl Unpin for User

§

impl UnsafeUnpin for User

§

impl !UnwindSafe for User

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
§

impl<T> CompatExt for T

§

fn compat(self) -> Compat<T>

Applies the [Compat] adapter by value. Read more
§

fn compat_ref(&self) -> Compat<&T>

Applies the [Compat] adapter by shared reference. Read more
§

fn compat_mut(&mut self) -> Compat<&mut T>

Applies the [Compat] adapter by mutable reference. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
§

impl<T> Pointable for T

§

const ALIGN: usize

The alignment of pointer.
§

type Init = T

The type for initializers.
§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
§

impl<T> PolicyExt for T
where T: ?Sized,

§

fn and<P, B, E>(self, other: P) -> And<T, P>
where T: Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns [Action::Follow] only if self and other return Action::Follow. Read more
§

fn or<P, B, E>(self, other: P) -> Or<T, P>
where T: Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns [Action::Follow] if either self or other returns Action::Follow. Read more
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

§

fn vzip(self) -> V

§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a [WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a [WithDispatch] wrapper. Read more