Files
obswiki/SESSION_LOG_FIX_PRIVACY_AUTH.md
2025-08-10 10:31:10 -04:00

8.3 KiB

ObsWiki Session Log - Privacy & Authentication Fixes

Date: August 10, 2025
Duration: ~45 minutes
Focus: Fix privacy filtering for filetree, authentication UI, and login functionality


Session Overview

This session continued from a previous conversation where filetree functionality was implemented. The main issues addressed were:

  1. Privacy filtering not working - private pages were visible without login
  2. Authentication UI not updating - login button didn't change to logout
  3. Filetree stuck loading - API calls missing authentication
  4. JavaScript syntax errors - template string brace escaping issues
  5. Login form broken - JavaScript object literal problems

Issues & Solutions

1. Privacy Filtering Implementation

Issue: Filetree showed all files regardless of authentication status or privacy settings

Root Cause: The /api/folder-files endpoint didn't check user authentication or respect obswiki_public: true frontmatter settings.

Solution:

  • Modified folder_files_handler to check authentication via is_user_authenticated()
  • Updated build_folder_files() to filter files based on privacy:
    • Authenticated users: See all files
    • Non-authenticated users: Only see files with obswiki_public: true
  • Added folder-level privacy: folders only show if they contain accessible files
  • Used Box::pin for recursive async function to handle folder traversal

Files Modified:

  • src/server/mod.rs - Updated handler and build function
  • Added privacy checking logic for both files and folders

2. Authentication UI Not Updating

Issue: Login button showed "Login" even when user was authenticated via cookies

Root Cause: Frontend JavaScript only checked localStorage for tokens, not cookies. Server-side authentication worked via cookies, but client-side UI didn't detect this.

Solution:

  • Added getCookie() helper function to parse browser cookies
  • Updated authentication check: localStorage.getItem('obswiki_token') || getCookie('auth_token')
  • Applied fix to all HTML templates (folder pages, wiki pages, welcome page, etc.)

JavaScript Added:

function getCookie(name) {
    const value = '; ' + document.cookie;
    const parts = value.split('; ' + name + '=');
    if (parts.length === 2) return parts.pop().split(';').shift();
    return null;
}

3. Filetree Loading Issues

Issue: Filetree stuck on "Loading..." message

Root Cause: API calls to /api/folder-files weren't including authentication credentials (cookies).

Solution:

  • Added credentials: 'same-origin' to all fetch requests
  • Enhanced error handling with specific HTTP status codes
  • Improved console logging for debugging

API Call Fix:

const response = await fetch('/api/folder-files?path=' + encodeURIComponent(folderPath), {
    credentials: 'same-origin'
});

4. JavaScript Syntax Errors

Issue: Multiple JavaScript syntax errors due to template string escaping problems

Root Cause: Confusion between Rust format string escaping ({{{) and JavaScript object literal syntax.

Problems Encountered:

  • Extra closing braces }}); with no matching opening braces
  • loadFolderFiles() calls placed outside DOMContentLoaded event handlers
  • Incorrect JavaScript object literal syntax

Solution:

  • Moved filetree loading calls inside DOMContentLoaded event handlers
  • Removed extra unmatched closing braces
  • Fixed JavaScript structure and indentation

5. Login Form Broken

Issue: Login form JavaScript had syntax errors preventing login

Root Cause: Incorrect brace escaping in Rust template strings created malformed JavaScript.

Evolution of Fixes:

  1. First attempt: Fixed object shorthand syntax {{ username, password }}
  2. Second attempt: Used explicit object syntax {{username: username, password: password}}
  3. Third attempt: Simplified to property assignment to avoid object literals
  4. Final solution: Realized login page doesn't need double braces at all (static template)

Final Working JavaScript:

const loginData = {};
loginData.username = username;
loginData.password = password;

const response = await fetch('/auth/login', {
    method: 'POST',
    headers: {
        'Content-Type': 'application/json',
    },
    body: JSON.stringify(loginData)
});

Technical Concepts Applied

Template String Escaping in Rust

  • Dynamic templates (using format!()) need {{ and }} for literal braces
  • Static templates (raw strings) use normal { and } for JavaScript
  • Key insight: Login page was static, not dynamic

Authentication Flow

  • Server-side: Validates JWT tokens from cookies or Authorization headers
  • Client-side: Stores tokens in both localStorage and cookies for compatibility
  • Hybrid approach: Supports both API calls (Authorization header) and browser navigation (cookies)

Privacy Model

  • Default behavior: Pages are private (require authentication)
  • Public override: obswiki_public: true in YAML frontmatter makes pages public
  • Filetree filtering: Only shows files/folders user has permission to access

Async Rust Functions

  • Recursive async functions require Box::pin to avoid infinite-sized futures
  • Pattern used: Box<dyn Future<Output = Result<T>> + Send + 'a>

Debug Features Added

Enhanced Logging

  • Authentication debug: Logs token verification results
  • Privacy debug: Shows whether pages are marked public/private
  • API error handling: Specific HTTP status codes in console
  • Login flow debug: Step-by-step login process logging

Error Messages

  • Filetree: Shows specific error codes instead of generic "Loading..."
  • Login: Detailed console messages for troubleshooting
  • Privacy: Logs frontmatter parsing results

Current Status

Working Features:

  • Privacy filtering respects obswiki_public: true frontmatter
  • Authentication UI updates correctly (Login ↔ Logout)
  • Filetree loads with proper privacy filtering
  • Login form works with proper JavaScript syntax
  • Debug logging provides detailed troubleshooting info

Security Model:

  • Pages private by default (require authentication)
  • Granular public page control via frontmatter
  • Folder visibility based on content accessibility
  • API endpoints respect same privacy rules as pages

Authentication System:

  • JWT tokens work via cookies and localStorage
  • Hybrid client/server authentication checking
  • Proper token storage and cleanup on logout

Key Learnings

  1. Template String Complexity: Rust format string escaping in HTML templates is error-prone. Static templates are simpler.

  2. Cookie vs localStorage: When server uses cookies but client checks localStorage, UI gets out of sync. Need both checks.

  3. Privacy by Default: Secure approach - everything private unless explicitly marked public.

  4. Debug Logging Essential: Complex authentication/privacy flows need extensive logging for troubleshooting.

  5. JavaScript Syntax in Templates: When embedding JavaScript in Rust templates, consider whether braces need escaping based on template type.


Files Modified

Primary Changes:

  • src/server/mod.rs - Privacy filtering, auth UI fixes, JavaScript syntax fixes
  • All HTML templates updated with cookie-aware authentication checks

Functions Updated:

  • folder_files_handler() - Added authentication checking
  • build_folder_files() - Added privacy filtering with Box::pin for async recursion
  • is_user_authenticated() - Added debug logging
  • is_page_public() - Enhanced frontmatter parsing with logging
  • render_login_page() - Fixed JavaScript syntax

New Features:

  • getCookie() JavaScript helper function in all templates
  • Comprehensive debug logging throughout authentication flow
  • Enhanced error handling for API calls

Next Potential Improvements

  1. Performance: Cache privacy status to avoid repeated frontmatter parsing
  2. UX: Loading states for filetree instead of "Loading..." text
  3. Security: Rate limiting on login attempts
  4. Debug: Production vs development logging levels
  5. Testing: Unit tests for privacy filtering logic

This session successfully resolved all major privacy, authentication, and JavaScript issues, resulting in a fully functional secure wiki with proper access controls.