This commit is contained in:
2025-08-10 10:31:10 -04:00
commit db767dcabc
26 changed files with 8170 additions and 0 deletions

View File

@@ -0,0 +1,224 @@
# 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:**
```javascript
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:**
```javascript
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:**
```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.