fix: RateLimit graceful degradation on permission denied

Silence mkdir() with @ operator; guard file_put_contents with
is_writable() check. When storage/cache/rate_limit is not writable
by php-fpm, requests are allowed through instead of throwing
warnings that flood the nginx error log.
This commit is contained in:
Pontoporeia
2026-04-06 16:39:55 +02:00
parent 6a1b41ac93
commit 756ddb5765
4 changed files with 20 additions and 3 deletions

View File

@@ -11,6 +11,9 @@ Pending tasks have been split into topic files under [`todo/`](todo/README.md):
## Recently completed (this session) ## Recently completed (this session)
- [x] `RateLimit.php` — silence `mkdir()` with `@`; guard `file_put_contents` with `is_writable()` check so permission errors degrade gracefully (allow request, skip write) instead of spamming nginx error log
- [x] `scripts/deploy-server.sh` + `scripts/setup-server.sh` — add `mkdir -p storage/cache/rate_limit` + `chown`/`chmod 2775` so php-fpm has write access on fresh deploys
- [x] CSS cleanup — removed dark-mode `@media (prefers-color-scheme: dark)` block from `variables.css`; deleted dead `colors.css` reference file; added all missing semantic tokens to `variables.css` (`--header-*`, `--search-error-*`, `--sys-*` dark-terminal tokens, `--*-muted-bg/border/hover` alpha overlay tokens); replaced every hardcoded hex/rgba in `common.css`, `main.css`, `search.css`, `admin.css`, `system.css` with `var()` references; fixed `--border-color` typo → `--border-primary` in `search.css`; fixed `view-toggle__btn` active color to use `--accent-foreground`; updated `README.md`; admin and public now share identical token set with zero duplication - [x] CSS cleanup — removed dark-mode `@media (prefers-color-scheme: dark)` block from `variables.css`; deleted dead `colors.css` reference file; added all missing semantic tokens to `variables.css` (`--header-*`, `--search-error-*`, `--sys-*` dark-terminal tokens, `--*-muted-bg/border/hover` alpha overlay tokens); replaced every hardcoded hex/rgba in `common.css`, `main.css`, `search.css`, `admin.css`, `system.css` with `var()` references; fixed `--border-color` typo → `--border-primary` in `search.css`; fixed `view-toggle__btn` active color to use `--accent-foreground`; updated `README.md`; admin and public now share identical token set with zero duplication
- [x] `pages-edit.php` — replaced EasyMDE (333 KB: 320 KB JS + 13 KB CSS) with OverType (118 KB, single JS file, no CSS); removed `easymde.min.js` and `easymde.min.css` from `public/assets/`; vendored `overtype.min.js`; replaced `<textarea name="content">` + 60-line EasyMDE toolbar/SVG init block with `<input type="hidden" name="content">` + `<div id="editor">` mount target + 6-line OverType init; `onChange` callback keeps the hidden input in sync for form submission; net saving: ~215 KB, ~54 lines of JS - [x] `pages-edit.php` — replaced EasyMDE (333 KB: 320 KB JS + 13 KB CSS) with OverType (118 KB, single JS file, no CSS); removed `easymde.min.js` and `easymde.min.css` from `public/assets/`; vendored `overtype.min.js`; replaced `<textarea name="content">` + 60-line EasyMDE toolbar/SVG init block with `<input type="hidden" name="content">` + `<div id="editor">` mount target + 6-line OverType init; `onChange` callback keeps the hidden input in sync for form submission; net saving: ~215 KB, ~54 lines of JS

View File

@@ -42,6 +42,12 @@ if [ -d "/var/www/posterg/storage" ]; then
ok "Storage: 2775, databases: 660" ok "Storage: 2775, databases: 660"
fi fi
# Ensure writable cache subdirectories exist for php-fpm (www-data)
mkdir -p /var/www/posterg/storage/cache/rate_limit
chown -R www-data:posterg /var/www/posterg/storage/cache
chmod -R 2775 /var/www/posterg/storage/cache
ok "Cache dirs: created and owned by www-data:posterg"
# ── Step 2: Nginx config ────────────────────────────────────────────────────── # ── Step 2: Nginx config ──────────────────────────────────────────────────────
printf "\n📋 Step 2: Deploying nginx configuration...\n" printf "\n📋 Step 2: Deploying nginx configuration...\n"
printf "--------------------------------------------\n" printf "--------------------------------------------\n"

View File

@@ -82,6 +82,12 @@ if [ -d "$APP_DIR/storage" ]; then
ok "Storage: 2775, databases: 660" ok "Storage: 2775, databases: 660"
fi fi
# Ensure writable cache subdirectories exist for php-fpm (www-data)
mkdir -p "$APP_DIR/storage/cache/rate_limit"
chown -R "$WEB_USER:$APP_GROUP" "$APP_DIR/storage/cache"
chmod -R 2775 "$APP_DIR/storage/cache"
ok "Cache dirs: created and owned by $WEB_USER:$APP_GROUP"
printf "\n" printf "\n"
ok "Setup complete." ok "Setup complete."
printf "\nNext steps:\n" printf "\nNext steps:\n"

View File

@@ -22,7 +22,7 @@ class RateLimit {
// Create cache directory if it doesn't exist // Create cache directory if it doesn't exist
if (!is_dir($this->cacheDir)) { if (!is_dir($this->cacheDir)) {
mkdir($this->cacheDir, 0755, true); @mkdir($this->cacheDir, 0755, true);
} }
} }
@@ -79,8 +79,10 @@ class RateLimit {
// Add new request timestamp // Add new request timestamp
$data[] = $now; $data[] = $now;
// Save updated data // Save updated data (silently skip if directory is not writable)
if (is_dir($this->cacheDir) && is_writable($this->cacheDir)) {
file_put_contents($file, json_encode($data)); file_put_contents($file, json_encode($data));
}
return true; return true;
} }