The Feature Access system provides role-based access control (RBAC) for various features and services in LogseqSpringThing. It manages user permissions, feature flags, and API access through environment variables and dynamic registration.
The feature access system is implemented in src/config/feature_access.rs and provides:
- Public Key Based Authentication: Users are identified by their Nostr public keys
- Feature Flags: Enable/disable specific features per user
- Role-Based Access: Special privileges for power users
- Dynamic Registration: New users can be registered with default features
pub struct FeatureAccess {
// Base access control
pub approved_pubkeys: Vec<String>,
// Feature-specific access
pub perplexity_enabled: Vec<String>,
pub openai_enabled: Vec<String>,
pub ragflow_enabled: Vec<String>,
// Role-based access control
pub power_users: Vec<String>,
pub settings_sync_enabled: Vec<String>,
}The system reads configuration from environment variables:
APPROVED_PUBKEYS- Comma-separated list of approved public keysPERPLEXITY_ENABLED_PUBKEYS- Users with Perplexity AI accessOPENAI_ENABLED_PUBKEYS- Users with OpenAI (Kokoro) accessRAGFLOW_ENABLED_PUBKEYS- Users with RAGFlow chat accessPOWER_USER_PUBKEYS- Users with administrative privilegesSETTINGS_SYNC_ENABLED_PUBKEYS- Users who can sync settings across devices
Example .env configuration:
APPROVED_PUBKEYS=pubkey1,pubkey2,pubkey3
PERPLEXITY_ENABLED_PUBKEYS=pubkey1,pubkey2
OPENAI_ENABLED_PUBKEYS=pubkey1,pubkey2,pubkey3
RAGFLOW_ENABLED_PUBKEYS=pubkey1,pubkey2,pubkey3
POWER_USER_PUBKEYS=pubkey1
SETTINGS_SYNC_ENABLED_PUBKEYS=pubkey1,pubkey2- Controlled by:
APPROVED_PUBKEYS - Provides: Basic application access
- Required for: All other features
- Controlled by:
PERPLEXITY_ENABLED_PUBKEYS - Provides: Access to Perplexity AI for advanced queries
- Endpoint:
/api/perplexity
- Controlled by:
OPENAI_ENABLED_PUBKEYS - Provides: Access to Kokoro text-to-speech service
- Features: Voice synthesis, speech options
- Default for: New users (auto-granted on registration)
- Controlled by:
RAGFLOW_ENABLED_PUBKEYS - Provides: Access to RAGFlow document-based chat
- Features: Contextual chat, document retrieval
- Default for: New users (auto-granted on registration)
- Controlled by:
SETTINGS_SYNC_ENABLED_PUBKEYS - Provides: Cross-device settings synchronization
- Auto-granted to: Power users
- Endpoints:
/api/user-settings/sync
- Controlled by:
POWER_USER_PUBKEYS - Provides:
- All feature access
- Administrative functions
- Cache management (
/api/admin/settings/clear-all-cache) - System monitoring
- Priority support
All protected endpoints require the Nostr public key in headers:
X-Nostr-Pubkey: <user_public_key>
GET /api/auth/nostr/power-user-status
Headers: X-Nostr-Pubkey: <pubkey>
Response:
{
"is_power_user": true
}GET /api/auth/nostr/features
Headers: X-Nostr-Pubkey: <pubkey>
Response:
{
"features": ["perplexity", "openai", "ragflow", "settings_sync", "power_user"]
}GET /api/auth/nostr/features/{feature}
Headers: X-Nostr-Pubkey: <pubkey>
Response:
{
"feature": "perplexity",
"has_access": true
}New users can be registered dynamically with default features:
pub fn register_new_user(&mut self, pubkey: &str) -> bool {
// Adds user to approved_pubkeys
// Grants RAGFlow access by default
// Grants OpenAI (Kokoros) access by default
// Updates the .env file
}- Basic application access
- RAGFlow chat access
- OpenAI/Kokoro voice service access
- User attempts to authenticate with Nostr
- If pubkey not in
APPROVED_PUBKEYS, registration is triggered - User is added with default features
.envfile is updated to persist changes
// Check basic access
if feature_access.has_access(&pubkey) {
// User has basic access
}
// Check specific feature
if feature_access.has_perplexity_access(&pubkey) {
// User can use Perplexity AI
}
// Check multiple features
let features = feature_access.get_available_features(&pubkey);The system automatically updates the .env file when:
- New users are registered
- Features are granted/revoked programmatically
- This ensures persistence across server restarts
Example from the settings handler:
async fn clear_all_settings_cache(
req: HttpRequest,
feature_access: web::Data<FeatureAccess>
) -> Result<HttpResponse, Error> {
let pubkey = req.headers()
.get("X-Nostr-Pubkey")
.and_then(|h| h.to_str().ok())
.unwrap_or("");
if !feature_access.is_power_user(&pubkey) {
return Ok(HttpResponse::Forbidden()
.body("Only power users can clear all settings caches"));
}
// Proceed with cache clearing...
}- Public Key Validation: Always validate public key format
- Header Injection: Sanitize header values
- Privilege Escalation: Power user status cannot be self-assigned
- Environment Security: Protect
.envfile with appropriate permissions - Audit Trail: Log all access attempts and feature usage
- Principle of Least Privilege: Grant only necessary features
- Regular Audits: Review user permissions periodically
- Feature Grouping: Consider creating feature bundles for common use cases
- Documentation: Keep feature access documentation up-to-date
- Monitoring: Track feature usage for optimization
- Dynamic Feature Management: Web UI for managing user permissions
- Feature Expiration: Time-limited feature access
- Usage Quotas: Rate limiting per feature
- Feature Dependencies: Automatic dependency resolution
- Audit Logging: Comprehensive access logs
- Multi-tenant Support: Organization-based access control