Skip to content

add multiple user and multiple language and fix cve - #137

Open
burghy86 wants to merge 2 commits into
DumbWareio:mainfrom
burghy86:main
Open

add multiple user and multiple language and fix cve#137
burghy86 wants to merge 2 commits into
DumbWareio:mainfrom
burghy86:main

Conversation

@burghy86

@burghy86 burghy86 commented May 25, 2026

Copy link
Copy Markdown

Security (CVE / Path Traversal)

  • deleteAssetFileAsync: Added a path.resolve() check against DATA_DIR to prevent path traversal vulnerabilities.
  • /api/delete-file: Implemented the same protection; now returns a 403 Forbidden status code if the resolved path falls outside of DATA_DIR.

Internationalization (i18n)

  • public/i18n/translations.js: Created a complete EN/IT translation module exposing window.i18n and window.t().
  • HTML Integration: Included the script in index.html and login.html ensuring it loads before config.js.
  • DOM Elements: Added data-i18n and data-i18n-placeholder attributes to key elements.
  • UI Updates: Added a "Language" tab in the settings menu with 🇬🇧 English / 🇮🇹 Italiano toggle buttons.
  • Styling: Added dedicated CSS rules for language selectors (.lang-btn, .language-options).

Multi-user Support

  • /api/users: Endpoint added to fetch the user list (public, unauthenticated).
  • /api/whoami: Endpoint added to return the current session user (authenticated).
  • /verify-pin: Refactored to handle both single-user and multi-user modes (requiring username + PIN).
  • /pin-length: Updated to return multiUser: true when active.
  • Login Flow: Completely rewrote login.html to support a new multi-step flow: User Selection → PIN Input → Back Button.
  • Styling: Added custom CSS for .user-btn, .user-list, and .back-btn.
  • Routing: Updated publicPaths to allow access to /api/users and /i18n/.
  • UI Updates: The logged-in user's badge is now displayed in the footer when multi-user mode is active.

Bug Fixes

  • Search Reset: Fixed an issue where search queries were cleared; loadAssets() now caches the search term before fetching and reapplies it afterward.
  • CSV Export Quantity: Added the missing Quantity column to both CSV generators (full and simple exports).

High-level PR Summary

This PR introduces multi-user authentication support with username selection and individual PIN verification, adds internationalization (i18n) with English and Italian translations, and fixes a path traversal security vulnerability (CVE) in file deletion endpoints. The changes include a new translation module with data-i18n attributes throughout the UI, a completely rewritten multi-step login flow that handles both single-user and multi-user modes, security enhancements using path.resolve() checks to prevent directory traversal attacks, and several bug fixes including missing Quantity column in CSV exports and search query persistence issues.

⏱️ Estimated Review Time: 30-90 minutes

💡 Review Order Suggestion
Order File Path
1 server.js
2 public/i18n/translations.js
3 public/login.html
4 public/index.html
5 public/config.js
6 public/script.js
7 public/managers/settings.js
8 public/styles.css
9 package-lock.json
10 .replit
⚠️ Inconsistent Changes Detected
File Path Warning
.replit Adding Replit-specific deployment configuration appears unrelated to the main PR objectives of multi-user support, i18n, and security fixes. This is infrastructure/deployment configuration that doesn't align with the stated feature additions.

Need help? Join our Discord

Summary by CodeRabbit

  • New Features

    • Added internationalization support with English and Italian language options
    • Introduced multi-user PIN authentication with user selection on login
    • Added language selector in the settings interface
    • Added user identification display showing logged-in user information
    • Added Quantity column to CSV export functionality
  • Bug Fixes

    • Search queries are now preserved when refreshing the asset list
    • Enhanced security for file deletion operations

Review Change Stack

burghy added 2 commits May 25, 2026 11:58
Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 1d5a5e7a-1e52-4679-b44e-03e5db1b76d1
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Event-Id: 03fa99f7-c526-4a2e-ba94-35482042662f
Replit-Helium-Checkpoint-Created: true
Integrates internationalization with English and Italian translations, enhances the login process for multi-user environments, and includes security fixes.

Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 1d5a5e7a-1e52-4679-b44e-03e5db1b76d1
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Event-Id: 488d1972-701b-43b3-8ba1-c20a2ddc316f
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/0cfb949a-9516-4ec4-ac9a-15fbc70c2b2a/1d5a5e7a-1e52-4679-b44e-03e5db1b76d1/kfWRAC8
Replit-Helium-Checkpoint-Created: true
@coderabbitai

coderabbitai Bot commented May 25, 2026

Copy link
Copy Markdown

Walkthrough

This PR implements internationalization (English/Italian), multi-user PIN authentication, dashboard language switching, server-side user verification with IP lockout, path traversal protection for file deletion, and includes CSS styling, CSV export improvements, search persistence, and Replit configuration.

Changes

Multi-user authentication and internationalization infrastructure

Layer / File(s) Summary
i18n translation engine and DOM integration
public/i18n/translations.js, public/config.js
Introduces TRANSLATIONS catalog for English and Italian, detects active language from localStorage or browser, exposes window.i18n API with t(), setLanguage(), getLanguage(), applyTranslations(), and wires DOM translation on DOMContentLoaded using data-i18n attributes.
Login page multi-user and single-user flows
public/login.html
Refactors login to detect single vs. multi-user mode via /pin-length endpoint, renders conditional UI for user selection or direct PIN entry, implements buildPinInputs helper for digit input management, verifies via verify-pin with {username, pin} or {pin}, handles lockout/redirect messages with i18n labels.
Server multi-user authentication endpoints and middleware
server.js
Parses DUMBASSETS_USERS into USERS array, adds /api/users and /api/whoami endpoints, refactors authMiddleware to handle multi-user sessions, extends pin-length/verify-pin to validate {username, pin} with IP-based brute-force lockout (429), and preserves single-user behavior when multi-user is disabled.

Dashboard UI integration, styling, and hardening

Layer / File(s) Summary
Dashboard language support and settings tab
public/index.html
Loads translations.js, applies i18n to sidebar search, "Add Asset" button, and Settings modal tabs, introduces Language/Lingua tab with language buttons, and internationalizes Save/Cancel/Test action buttons.
User badge and language sync
public/index.html (script section)
Adds hidden user badge element, wires language button clicks to setLanguage(), syncs active button with current language, listens for languageChanged events, and fetches /api/whoami to display logged-in username.
Login and dashboard UI styling
public/styles.css
Adds CSS for language selector buttons (.language-options, .lang-btn), multi-user user list (.user-list, .user-btn), and back button (.back-btn) with hover/active state styling.
File deletion security and minor features
server.js (path checks), public/managers/settings.js, public/script.js
Hardens asset file deletion and /api/delete-file with path traversal boundary checks. Extends CSV exports to include Quantity field with 1 as default. Updates loadAssets() to preserve active search query on re-render.
Replit environment configuration
.replit
Defines Replit environment with Node.js modules, expertMode agent settings, Nix stable-25_05 channel, server startup workflow (port 5000), port mappings, and VM deployment run command.

🌍🔐 Multi-users now log in with their own PINs,
While languages dance between English and Italian spins,
Path traversal blocked with security gains,
Dashboard glows with i18n's refrains,
CSV counts quantities as the flow begins. 🎯


🎯 3 (Moderate) | ⏱️ ~25 minutes

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 25.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The PR title mentions the main features added (multiple users, multiple languages) but is vague about the CVE fix and lacks specificity about what changes were made. Consider being more specific, such as: 'Add multi-user and i18n support with path traversal security fix' to better convey the scope and main objectives.
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

ESLint skipped: no ESLint configuration detected in root package.json. To enable, add eslint to devDependencies.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
server.js (1)

351-355: ⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

Multi-user login is bypassed when DUMBASSETS_PIN is unset.

This branch redirects from /login whenever PIN is empty, which breaks multi-user auth flow (and can cause redirect loops) because multi-user mode doesn’t require DUMBASSETS_PIN.

Suggested fix
-    if (!PIN || PIN.trim() === '') {
+    if (!MULTI_USER_MODE && (!PIN || PIN.trim() === '')) {
         const returnTo = req.query.returnTo || (BASE_PATH + '/');
         debugLog('No PIN set, redirecting to:', returnTo);
         return res.redirect(returnTo);
     }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@server.js` around lines 351 - 355, The redirect that runs when PIN is empty
improperly triggers in multi-user deployments; update the condition around PIN
so it only redirects for single-user mode: replace the current if (!PIN ||
PIN.trim() === '') check with a guard that also verifies the app is not running
in multi-user mode (e.g., check your existing multi-user flag/function instead
of PIN alone), and only then compute returnTo and call res.redirect(returnTo);
keep references to PIN, req.query.returnTo, BASE_PATH and res.redirect to locate
the code to change.
🧹 Nitpick comments (2)
public/managers/settings.js (1)

648-649: ⚡ Quick win

Don’t bother swapping quantity || 1 to quantity ?? 1 in public/managers/settings.js0 is already turned into 1 upstream (stupidly)

  • The quantity inputs enforce min="1" (public/index.html).
  • Client form parsing also forces 1 via parseInt(...) || 1 (public/managers/modalManager.js).
  • Server import + GET/back-compat normalization coerce 0 to 1 (parseInt(get('quantity')) || 1 and quantity: asset.quantity || 1 / subAsset.quantity || 1 in server.js).
  • So the CSV export rows won’t contain real 0 anyway; doing it only in the export is pointless—if you care about 0, fix the upstream coercion.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@public/managers/settings.js` around lines 648 - 649, Leave the export
expression asset.quantity || 1 as-is (do not change it to asset.quantity ?? 1);
the current upstream inputs and parsing coerce 0 to 1, so changing this line
alone is pointless—if you need true-0 support, update the upstream coercion
points instead (e.g., the client parsing in modalManager.js, server-side
normalization in server.js, and the quantity input constraint).
public/i18n/translations.js (1)

464-513: ⚡ Quick win

Add JSDoc to the public i18n API methods.

t, setLanguage, getLanguage, and applyTranslations are exposed publicly via window.i18n, but they currently lack API-level JSDoc.

As per coding guidelines, "JSDoc comments must be present for public functions and APIs."

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@public/i18n/translations.js` around lines 464 - 513, Add JSDoc comments for
the public i18n API functions exported on window: t, setLanguage, getLanguage,
and applyTranslations (also mention window.t). For each function add a short
description, `@param` tags (e.g., t(key: string, fallback?: string),
setLanguage(lang: string)), and `@returns` tags where applicable (t returns
string, getLanguage returns string) and include `@public/`@exports or similar tag
per project style; place the comments immediately above the function
declarations for detectability by documentation tooling.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@server.js`:
- Around line 380-383: The /api/whoami route is registered at the root instead
of being mounted under BASE_PATH causing inconsistent routing; change the
registration from app.get('/api/whoami', ...) to use the BASE_PATH prefix (e.g.
app.get(`${BASE_PATH}/api/whoami`, ...)) so it matches other auth/login routes,
keeping the same auth check (req.session.authenticated) and response logic
(username and MULTI_USER_MODE); after changing the route, update any
client/dashboard code that fetches the endpoint to use window.appConfig.basePath
or BASE_PATH (e.g. `${window.appConfig.basePath}/api/whoami`) so calls align
with the new mount point.

---

Outside diff comments:
In `@server.js`:
- Around line 351-355: The redirect that runs when PIN is empty improperly
triggers in multi-user deployments; update the condition around PIN so it only
redirects for single-user mode: replace the current if (!PIN || PIN.trim() ===
'') check with a guard that also verifies the app is not running in multi-user
mode (e.g., check your existing multi-user flag/function instead of PIN alone),
and only then compute returnTo and call res.redirect(returnTo); keep references
to PIN, req.query.returnTo, BASE_PATH and res.redirect to locate the code to
change.

---

Nitpick comments:
In `@public/i18n/translations.js`:
- Around line 464-513: Add JSDoc comments for the public i18n API functions
exported on window: t, setLanguage, getLanguage, and applyTranslations (also
mention window.t). For each function add a short description, `@param` tags (e.g.,
t(key: string, fallback?: string), setLanguage(lang: string)), and `@returns` tags
where applicable (t returns string, getLanguage returns string) and include
`@public/`@exports or similar tag per project style; place the comments
immediately above the function declarations for detectability by documentation
tooling.

In `@public/managers/settings.js`:
- Around line 648-649: Leave the export expression asset.quantity || 1 as-is (do
not change it to asset.quantity ?? 1); the current upstream inputs and parsing
coerce 0 to 1, so changing this line alone is pointless—if you need true-0
support, update the upstream coercion points instead (e.g., the client parsing
in modalManager.js, server-side normalization in server.js, and the quantity
input constraint).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 7fc699a1-10e0-43ac-a299-be30e509372e

📥 Commits

Reviewing files that changed from the base of the PR and between 2bacca1 and b4dceea.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (9)
  • .replit
  • public/config.js
  • public/i18n/translations.js
  • public/index.html
  • public/login.html
  • public/managers/settings.js
  • public/script.js
  • public/styles.css
  • server.js

Comment thread server.js
Comment on lines +380 to +383
app.get('/api/whoami', (req, res) => {
if (!req.session.authenticated) return res.status(401).json({ error: 'Not authenticated' });
res.json({ username: req.session.username || null, multiUser: MULTI_USER_MODE });
});

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

/api/whoami is mounted outside BASE_PATH.

All auth/login routes are BASE_PATH-aware, but this endpoint is root-mounted. That causes inconsistent routing in subpath deployments and complicates client calls.

Suggested fix
-app.get('/api/whoami', (req, res) => {
+app.get(BASE_PATH + '/api/whoami', (req, res) => {
     if (!req.session.authenticated) return res.status(401).json({ error: 'Not authenticated' });
     res.json({ username: req.session.username || null, multiUser: MULTI_USER_MODE });
 });

Downstream impact: update the dashboard fetch call to use ${window.appConfig.basePath}/api/whoami.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
app.get('/api/whoami', (req, res) => {
if (!req.session.authenticated) return res.status(401).json({ error: 'Not authenticated' });
res.json({ username: req.session.username || null, multiUser: MULTI_USER_MODE });
});
app.get(BASE_PATH + '/api/whoami', (req, res) => {
if (!req.session.authenticated) return res.status(401).json({ error: 'Not authenticated' });
res.json({ username: req.session.username || null, multiUser: MULTI_USER_MODE });
});
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@server.js` around lines 380 - 383, The /api/whoami route is registered at the
root instead of being mounted under BASE_PATH causing inconsistent routing;
change the registration from app.get('/api/whoami', ...) to use the BASE_PATH
prefix (e.g. app.get(`${BASE_PATH}/api/whoami`, ...)) so it matches other
auth/login routes, keeping the same auth check (req.session.authenticated) and
response logic (username and MULTI_USER_MODE); after changing the route, update
any client/dashboard code that fetches the endpoint to use
window.appConfig.basePath or BASE_PATH (e.g.
`${window.appConfig.basePath}/api/whoami`) so calls align with the new mount
point.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant