Skip to content

Admin Guide

Last updated: 2025-09-19

This secure notes application is designed with end-to-end encryption where each user manages their own encrypted workspace. This guide explains how to manage users, configure admin access, and maintain the system while respecting the zero-knowledge architecture.

The application uses:

  • Zero-knowledge encryption: Server never sees plaintext data
  • User workspaces: Each user has their own encrypted workspace
  • Note-level permissions: Users can share notes with read, write, or admin permissions
  • PostgreSQL database: User data stored in encrypted format
  1. Get your user ID (UUID):

    • Log in, then open browser DevTools → Application → Local Storage → find current_user_id
    • Or decode the JWT stored in secure_token:
      JSON.parse(atob(localStorage.getItem('secure_token').split('.')[1])).user_id
  2. Add to environment variables:

    • Add your UUID to .env: ADMIN_USER_IDS=<your-uuid-here>
    • Multiple admins: ADMIN_USER_IDS=<uuid-1>,<uuid-2>
  3. Restart the application:

    Terminal window
    make down && make up
-- Connect to PostgreSQL database
psql -U postgres -d notes
-- Add admin role column
ALTER TABLE users ADD COLUMN is_admin BOOLEAN DEFAULT false;
-- Create index for faster admin queries
CREATE INDEX idx_users_is_admin ON users(is_admin);
-- Grant admin access by email
UPDATE users
SET is_admin = true
WHERE email = 'admin@example.com';
-- Or by user ID
UPDATE users
SET is_admin = true
WHERE id = 'your-user-uuid-here';
-- Revoke admin access
UPDATE users
SET is_admin = false
WHERE email = 'user@example.com';
  • In builds: Set VITE_ENABLE_ADMIN_PANEL=true for the frontend
  • Local development:
    Terminal window
    export VITE_ENABLE_ADMIN_PANEL=true && docker compose up -d --build
  1. Log in as an admin user
  2. Click the shield icon in the app header
  3. The Admin Panel allows you to:
    • Toggle user’s built-in is_admin flag
    • Assign or remove RBAC roles (moderator, auditor)
    • Load current roles for users
    • Enable/disable user registration
-- List all users with basic info
SELECT
id,
email,
COALESCE(is_admin, false) as is_admin,
created_at,
last_login,
failed_attempts
FROM users
ORDER BY created_at DESC;
-- List all admin users
SELECT
id,
email,
created_at,
last_login
FROM users
WHERE is_admin = true;
-- Find inactive users (haven't logged in recently)
SELECT
id,
email,
created_at,
last_login,
(NOW() - last_login) as inactive_period
FROM users
WHERE last_login < NOW() - INTERVAL '30 days'
OR last_login IS NULL;
-- Check users with too many failed attempts
SELECT
id,
email,
failed_attempts,
locked_until
FROM users
WHERE failed_attempts > 5;
-- Unlock a locked user account
UPDATE users
SET failed_attempts = 0,
locked_until = NULL
WHERE email = 'user@example.com';
-- Count total users
SELECT COUNT(*) as total_users FROM users;
-- Count active users (logged in last 30 days)
SELECT COUNT(*) as active_users
FROM users
WHERE last_login > NOW() - INTERVAL '30 days';
-- Count notes per user
SELECT
u.email,
COUNT(n.id) as note_count
FROM users u
LEFT JOIN workspaces w ON u.id = w.owner_id
LEFT JOIN notes n ON w.id = n.workspace_id
WHERE n.deleted_at IS NULL
GROUP BY u.id, u.email
ORDER BY note_count DESC;

Safe admin operations that preserve encryption:

  • ✅ View user list and metadata
  • ✅ Monitor login attempts and security events
  • ✅ Disable/enable user accounts
  • ✅ View system statistics and usage
  • ✅ Manage system-wide settings
  • ❌ Read user notes or content
  • ❌ Reset passwords without user involvement
Terminal window
# Using PostgreSQL command line
export PGPASSWORD="your-postgres-password"
psql -h localhost -U postgres -d notes
# Or connect via URL
# postgresql://postgres:password@localhost:5432/notes

Before making changes, always backup:

Terminal window
# Backup users table
pg_dump -h localhost -U postgres -d notes -t users > users_backup.sql
# Full database backup
pg_dump -h localhost -U postgres -d notes > full_backup.sql
-- After first user registers, make them admin
UPDATE users
SET is_admin = true
WHERE email = (
SELECT email FROM users
ORDER BY created_at ASC
LIMIT 1
);
-- If admin is locked out, unlock manually
UPDATE users
SET failed_attempts = 0,
locked_until = NULL
WHERE is_admin = true;
-- Clean up old deleted notes (after 30 days)
DELETE FROM notes
WHERE deleted_at IS NOT NULL
AND deleted_at < NOW() - INTERVAL '30 days';

For production admin management:

  1. Enable PostgreSQL logging for audit trails
  2. Monitor authentication failures for security
  3. Set up alerts for suspicious activity
  4. Regular backups of user data

For admin-related questions, contact contact@leaflock.app.