Skip to content

User Management

This guide covers everything you need to know about managing users in LeafLock, from setting up admin accounts to troubleshooting user issues.

LeafLock automatically creates an admin account when starting up with an empty database. This makes initial setup simple and secure.

🔧 Auto-Admin Creation

When it happens:

  • ✅ Application starts up
  • ✅ Database is empty (no existing users)
  • ENABLE_DEFAULT_ADMIN=true (default setting)

What you get:

  • Fully configured admin account
  • Secure default permissions
  • Ready to use immediately
Terminal window
# Enable automatic admin creation
ENABLE_DEFAULT_ADMIN=true
# Admin login credentials
DEFAULT_ADMIN_EMAIL=admin@leaflock.app
DEFAULT_ADMIN_PASSWORD=YourSecurePassword123!
-- Quick user overview
SELECT
id,
email_search_hash,
is_admin,
mfa_enabled,
failed_attempts,
locked_until,
created_at,
last_login
FROM users
ORDER BY created_at DESC;

📊 User Counts

-- Total users
SELECT COUNT(*) as total_users FROM users;
-- Admin users
SELECT COUNT(*) as admin_users
FROM users WHERE is_admin = true;
-- Locked accounts
SELECT COUNT(*) as locked_accounts
FROM users WHERE locked_until > NOW();

💾 Storage Usage

-- Storage by user
SELECT
id,
storage_used,
storage_limit,
ROUND((storage_used::float / storage_limit * 100), 2) as usage_percent
FROM users
WHERE storage_used > 0
ORDER BY usage_percent DESC;
-- Make user an admin
UPDATE users
SET is_admin = true
WHERE id = 'user-uuid-here';
Terminal window
# Via API
curl -X PATCH http://localhost:8080/api/v1/admin/users/user-id \
-H "Authorization: Bearer admin-token" \
-H "Content-Type: application/json" \
-d '{"is_admin": true}'

🔓 Unlock Locked Accounts

Single user:

UPDATE users
SET failed_attempts = 0,
locked_until = NULL
WHERE id = 'user-uuid-here';

All locked users:

UPDATE users
SET failed_attempts = 0,
locked_until = NULL
WHERE locked_until IS NOT NULL;
-- Update storage limit (10MB example)
UPDATE users
SET storage_limit = 10485760
WHERE id = 'user-uuid-here';
-- Check users near storage limit
SELECT id, email_search_hash,
storage_used, storage_limit,
ROUND((storage_used::float / storage_limit * 100), 1) as usage_percent
FROM users
WHERE (storage_used::float / storage_limit) > 0.8
ORDER BY usage_percent DESC;

📝 New User Registration

Terminal window
curl -X POST http://localhost:8080/api/v1/auth/register \
-H "Content-Type: application/json" \
-d '{
"email": "newuser@example.com",
"password": "SecurePassword123!"
}'

Requirements:

  • Valid email format
  • Password: 8+ chars, mixed case, numbers, special chars
  • Unique email address
  • Registration enabled (ENABLE_REGISTRATION=true - defaults to false for security)

🚫 Cannot Login

Check account status:

SELECT id, failed_attempts, locked_until, is_admin
FROM users
WHERE email_search_hash = encode(
sha256(lower('user@example.com')::bytea),
'hex'
)::bytea;

Fix locked account:

UPDATE users
SET failed_attempts = 0, locked_until = NULL
WHERE id = 'user-id';

🔑 Lost Admin Access

Promote existing user:

UPDATE users
SET is_admin = true
WHERE id = 'trusted-user-id';

Or create emergency admin:

Terminal window
# In .env file
ENABLE_DEFAULT_ADMIN=true
DEFAULT_ADMIN_EMAIL=recovery@yourdomain.com
DEFAULT_ADMIN_PASSWORD=TempRecovery123!
# Restart application
docker compose restart

Since emails are encrypted, you need to use the search hash:

-- Find user by email (requires the actual email)
SELECT id, is_admin, created_at, last_login
FROM users
WHERE email_search_hash = encode(
sha256(lower('user@example.com')::bytea),
'hex'
)::bytea;

👥 User Management

  • View all registered users
  • Modify user permissions (admin/regular)
  • Lock/unlock user accounts
  • Reset password tokens
  • Monitor user activity

⚙️ System Settings

  • Global application configuration
  • User registration settings
  • Security policy management
  • System announcements

📋 Audit Logs

  • User login attempts
  • Permission changes
  • Security events
  • Data access patterns
  • Authentication: Must be logged in
  • Authorization: is_admin = true in database
  • Endpoints: All admin functions at /api/v1/admin/*

🔒 Zero-Knowledge Architecture

User data protection:

  • All emails encrypted at rest
  • Password hashing with Argon2id (64MB memory, 3 iterations)
  • User master keys encrypted with user passwords
  • Server never sees plaintext notes or sensitive data

Session security:

  • JWT tokens with Redis-backed refresh rotation
  • Secure cookie settings (HttpOnly, Secure, SameSite)
  • Automatic session expiry and cleanup

When backing up user data, ensure you preserve:

  • ✅ Database encryption keys
  • ✅ JWT signing secrets
  • ✅ User master keys (encrypted)
  • ✅ Server encryption keys
  • ✅ Redis session data (for active sessions)

Critical Backup Note

Without the proper encryption keys, backed up user data cannot be decrypted or restored. Keep encryption keys secure and separate from data backups.

  1. Strong Authentication

    • Use complex passwords with special characters
    • Enable MFA on all admin accounts
    • Regularly rotate admin passwords
  2. Access Control

    • Limit number of admin users
    • Use principle of least privilege
    • Monitor admin activity through audit logs
  3. Operational Security

    • Keep admin credentials secure
    • Use dedicated admin accounts (don’t use for regular notes)
    • Regularly review admin permissions
  • Never log or store plaintext passwords
  • Minimize data collection to essential fields only
  • Respect user deletion requests completely
  • Audit access to user data regularly

This guide covers the essential user management operations for LeafLock. For additional security features or enterprise deployment considerations, consult the deployment guides.