mirror of
https://github.com/DumbWareio/DumbDrop.git
synced 2025-11-03 05:23:39 +00:00
Add helmet config and deprecate previous ALLOWED_IFRAME_ORIGINS
This commit is contained in:
@@ -13,9 +13,10 @@ BASE_URL=http://localhost:3000/
|
|||||||
# (default: '*' if empty, add your base_url if you want to restrict only to base_url)
|
# (default: '*' if empty, add your base_url if you want to restrict only to base_url)
|
||||||
# When adding multiple origins, base_url will be included by default
|
# When adding multiple origins, base_url will be included by default
|
||||||
# ALLOWED_ORIGINS: http://internalip:port,https://subdomain.example.com
|
# ALLOWED_ORIGINS: http://internalip:port,https://subdomain.example.com
|
||||||
ALLOWED_ORIGINS=*
|
ALLOWED_ORIGINS=
|
||||||
|
|
||||||
# Node environment (default: production)
|
# Node environment (default: production)
|
||||||
|
# When set to 'development', ALLOWED_ORIGINS will default to '*'
|
||||||
NODE_ENV=production
|
NODE_ENV=production
|
||||||
|
|
||||||
#########################################
|
#########################################
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
# Base stage for shared configurations
|
# Base stage for shared configurations
|
||||||
FROM node:20-alpine as base
|
FROM node:22-alpine as base
|
||||||
|
|
||||||
# Install python and create virtual environment with minimal dependencies
|
# Install python and create virtual environment with minimal dependencies
|
||||||
RUN apk add --no-cache python3 py3-pip && \
|
RUN apk add --no-cache python3 py3-pip && \
|
||||||
|
|||||||
120
README.md
120
README.md
@@ -7,6 +7,7 @@ A stupid simple file upload application that provides a clean, modern interface
|
|||||||
No auth (unless you want it now!), no storage, no nothing. Just a simple file uploader to drop dumb files into a dumb folder.
|
No auth (unless you want it now!), no storage, no nothing. Just a simple file uploader to drop dumb files into a dumb folder.
|
||||||
|
|
||||||
## Table of Contents
|
## Table of Contents
|
||||||
|
|
||||||
- [Quick Start](#quick-start)
|
- [Quick Start](#quick-start)
|
||||||
- [Production Deployment with Docker](#production-deployment-with-docker)
|
- [Production Deployment with Docker](#production-deployment-with-docker)
|
||||||
- [Local Development (Recommended Quick Start)](LOCAL_DEVELOPMENT.md)
|
- [Local Development (Recommended Quick Start)](LOCAL_DEVELOPMENT.md)
|
||||||
@@ -21,44 +22,51 @@ No auth (unless you want it now!), no storage, no nothing. Just a simple file up
|
|||||||
## Quick Start
|
## Quick Start
|
||||||
|
|
||||||
### Option 1: Docker (For Dummies)
|
### Option 1: Docker (For Dummies)
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Pull and run with one command
|
# Pull and run with one command
|
||||||
docker run -p 3000:3000 -v ./uploads:/app/uploads dumbwareio/dumbdrop:latest
|
docker run -p 3000:3000 -v ./uploads:/app/uploads dumbwareio/dumbdrop:latest
|
||||||
```
|
```
|
||||||
|
|
||||||
1. Go to http://localhost:3000
|
1. Go to http://localhost:3000
|
||||||
2. Upload a File - It'll show up in ./uploads
|
2. Upload a File - It'll show up in ./uploads
|
||||||
3. Celebrate on how dumb easy this was
|
3. Celebrate on how dumb easy this was
|
||||||
|
|
||||||
### Option 2: Docker Compose (For Dummies who like customizing)
|
### Option 2: Docker Compose (For Dummies who like customizing)
|
||||||
|
|
||||||
Create a `docker-compose.yml` file:
|
Create a `docker-compose.yml` file:
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
services:
|
services:
|
||||||
dumbdrop:
|
dumbdrop:
|
||||||
image: dumbwareio/dumbdrop:latest
|
image: dumbwareio/dumbdrop:latest
|
||||||
ports:
|
ports:
|
||||||
- 3000:3000
|
- 3000:3000
|
||||||
volumes:
|
volumes:
|
||||||
# Where your uploaded files will land
|
# Where your uploaded files will land
|
||||||
- ./uploads:/app/uploads
|
- ./uploads:/app/uploads
|
||||||
environment:
|
environment:
|
||||||
# Explicitly set upload directory inside the container
|
# Explicitly set upload directory inside the container
|
||||||
UPLOAD_DIR: /app/uploads
|
UPLOAD_DIR: /app/uploads
|
||||||
# The title shown in the web interface
|
# The title shown in the web interface
|
||||||
DUMBDROP_TITLE: DumbDrop
|
DUMBDROP_TITLE: DumbDrop
|
||||||
# Maximum file size in MB
|
# Maximum file size in MB
|
||||||
MAX_FILE_SIZE: 1024
|
MAX_FILE_SIZE: 1024
|
||||||
# Optional PIN protection (leave empty to disable)
|
# Optional PIN protection (leave empty to disable)
|
||||||
DUMBDROP_PIN: 123456
|
DUMBDROP_PIN: 123456
|
||||||
# Upload without clicking button
|
# Upload without clicking button
|
||||||
AUTO_UPLOAD: false
|
AUTO_UPLOAD: false
|
||||||
# The base URL for the application
|
# The base URL for the application
|
||||||
# You must update this to the url you use to access your site
|
# You must update this to the url you use to access your site
|
||||||
BASE_URL: http://localhost:3000
|
BASE_URL: http://localhost:3000
|
||||||
```
|
```
|
||||||
|
|
||||||
Then run:
|
Then run:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
docker compose up -d
|
docker compose up -d
|
||||||
```
|
```
|
||||||
|
|
||||||
1. Go to http://localhost:3000
|
1. Go to http://localhost:3000
|
||||||
2. Upload a File - It'll show up in ./uploads
|
2. Upload a File - It'll show up in ./uploads
|
||||||
3. Rejoice in the glory of your dumb uploads
|
3. Rejoice in the glory of your dumb uploads
|
||||||
@@ -90,21 +98,22 @@ For local development setup, troubleshooting, and advanced usage, see the dedica
|
|||||||
|
|
||||||
### Environment Variables
|
### Environment Variables
|
||||||
|
|
||||||
| Variable | Description | Default | Required |
|
| Variable | Description | Default | Required |
|
||||||
|------------------------|------------------------------------------------------------------|-----------------------------------------|----------|
|
| -------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------- | -------- |
|
||||||
| PORT | Server port | 3000 | No |
|
| PORT | Server port | 3000 | No |
|
||||||
| BASE_URL | Base URL for the application | http://localhost:PORT | No |
|
| BASE_URL | Base URL for the application | http://localhost:PORT | No |
|
||||||
| MAX_FILE_SIZE | Maximum file size in MB | 1024 | No |
|
| MAX_FILE_SIZE | Maximum file size in MB | 1024 | No |
|
||||||
| DUMBDROP_PIN | PIN protection (4-10 digits) | None | No |
|
| DUMBDROP_PIN | PIN protection (4-10 digits) | None | No |
|
||||||
| DUMBDROP_TITLE | Site title displayed in header | DumbDrop | No |
|
| DUMBDROP_TITLE | Site title displayed in header | DumbDrop | No |
|
||||||
| APPRISE_URL | Apprise URL for notifications | None | No |
|
| APPRISE_URL | Apprise URL for notifications | None | No |
|
||||||
| APPRISE_MESSAGE | Notification message template | New file uploaded {filename} ({size}), Storage used {storage} | No |
|
| APPRISE_MESSAGE | Notification message template | New file uploaded {filename} ({size}), Storage used {storage} | No |
|
||||||
| APPRISE_SIZE_UNIT | Size unit for notifications (B, KB, MB, GB, TB, or Auto) | Auto | No |
|
| APPRISE_SIZE_UNIT | Size unit for notifications (B, KB, MB, GB, TB, or Auto) | Auto | No |
|
||||||
| AUTO_UPLOAD | Enable automatic upload on file selection | false | No |
|
| AUTO_UPLOAD | Enable automatic upload on file selection | false | No |
|
||||||
| ALLOWED_EXTENSIONS | Comma-separated list of allowed file extensions | None | No |
|
| ALLOWED_EXTENSIONS | Comma-separated list of allowed file extensions | None | No |
|
||||||
| ALLOWED_IFRAME_ORIGINS | Comma-separated list of origins allowed to embed the app in an iframe | None | No |
|
| ALLOWED_IFRAME_ORIGINS (deprecated: see ALLOWED_ORIGINS) | Comma-separated list of origins allowed to embed the app in an iframe | None | No |
|
||||||
| UPLOAD_DIR | Directory for uploads (Docker/production; should be `/app/uploads` in container) | None (see LOCAL_UPLOAD_DIR fallback) | No |
|
| ALLOWED_ORIGINS | You can restrict CORS to your BASE_URL or a comma-separated list of specified origins, which will automatically include your base_url | '\*' | No |
|
||||||
| LOCAL_UPLOAD_DIR | Directory for uploads (local dev, fallback: './local_uploads') | ./local_uploads | No |
|
| UPLOAD_DIR | Directory for uploads (Docker/production; should be `/app/uploads` in container) | None (see LOCAL_UPLOAD_DIR fallback) | No |
|
||||||
|
| LOCAL_UPLOAD_DIR | Directory for uploads (local dev, fallback: './local_uploads') | ./local_uploads | No |
|
||||||
|
|
||||||
- **UPLOAD_DIR** is used in Docker/production. If not set, LOCAL_UPLOAD_DIR is used for local development. If neither is set, the default is `./local_uploads`.
|
- **UPLOAD_DIR** is used in Docker/production. If not set, LOCAL_UPLOAD_DIR is used for local development. If neither is set, the default is `./local_uploads`.
|
||||||
- **Docker Note:** The Dockerfile now only creates the `uploads` directory inside the container. The host's `./local_uploads` is mounted to `/app/uploads` and should be managed on the host system.
|
- **Docker Note:** The Dockerfile now only creates the `uploads` directory inside the container. The host's `./local_uploads` is mounted to `/app/uploads` and should be managed on the host system.
|
||||||
@@ -114,50 +123,72 @@ For local development setup, troubleshooting, and advanced usage, see the dedica
|
|||||||
See `.env.example` for a template and more details.
|
See `.env.example` for a template and more details.
|
||||||
|
|
||||||
<details>
|
<details>
|
||||||
<summary>ALLOWED_IFRAME_ORIGINS</summary>
|
<summary>ALLOWED_IFRAME_ORIGINS (DEPRECATED: see ALLOWED_ORIGINS)</summary>
|
||||||
|
|
||||||
To allow this app to be embedded in an iframe on specific origins (such as Organizr), set the `ALLOWED_IFRAME_ORIGINS` environment variable. For example:
|
~~To allow this app to be embedded in an iframe on specific origins (such as Organizr), set the `ALLOWED_IFRAME_ORIGINS` environment variable. For example:~~
|
||||||
|
|
||||||
```env
|
```env
|
||||||
ALLOWED_IFRAME_ORIGINS=https://organizr.example.com,https://myportal.com
|
ALLOWED_IFRAME_ORIGINS=https://organizr.example.com,https://myportal.com
|
||||||
```
|
```
|
||||||
|
|
||||||
- If not set, the app will only allow itself to be embedded in an iframe on the same origin (default security).
|
- ~~If not set, the app will only allow itself to be embedded in an iframe on the same origin (default security).~~
|
||||||
- If set, the app will allow embedding in iframes on the specified origins and itself.
|
- ~~If set, the app will allow embedding in iframes on the specified origins and itself.~~
|
||||||
- **Security Note:** Only add trusted origins. Allowing arbitrary origins can expose your app to clickjacking and other attacks.
|
- ~~**Security Note:** Only add trusted origins. Allowing arbitrary origins can expose your app to clickjacking and other attacks.~~
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>ALLOWED_ORIGINS</summary>
|
||||||
|
|
||||||
|
By default `ALLOWED_ORIGINS` is set to '\*'
|
||||||
|
|
||||||
|
```env
|
||||||
|
ALLOWED_ORIGINS=https://organizr.example.com,https://myportal.com,http://internalip:port
|
||||||
|
```
|
||||||
|
|
||||||
|
- If you would like to restrict CORS to your BASE_URL, you can set it like this: `ALLOWED_ORIGINS=http://localhost:3000`
|
||||||
|
- If you would like to allow multiple origins, you can set it like this: `ALLOWED_ORIGINS=http://internalip:port,https://subdomain.domain.tld`
|
||||||
|
- This will automatically include your BASE_URL in the list of allowed origins.
|
||||||
|
</details>
|
||||||
|
|
||||||
<details>
|
<details>
|
||||||
<summary>File Extension Filtering</summary>
|
<summary>File Extension Filtering</summary>
|
||||||
|
|
||||||
To restrict which file types can be uploaded, set the `ALLOWED_EXTENSIONS` environment variable. For example:
|
To restrict which file types can be uploaded, set the `ALLOWED_EXTENSIONS` environment variable. For example:
|
||||||
|
|
||||||
```env
|
```env
|
||||||
ALLOWED_EXTENSIONS=.jpg,.jpeg,.png,.pdf,.doc,.docx,.txt
|
ALLOWED_EXTENSIONS=.jpg,.jpeg,.png,.pdf,.doc,.docx,.txt
|
||||||
```
|
```
|
||||||
|
|
||||||
If not set, all file extensions will be allowed.
|
If not set, all file extensions will be allowed.
|
||||||
|
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
<details>
|
<details>
|
||||||
<summary>Notification Setup</summary>
|
<summary>Notification Setup</summary>
|
||||||
|
|
||||||
#### Message Templates
|
#### Message Templates
|
||||||
|
|
||||||
The notification message supports the following placeholders:
|
The notification message supports the following placeholders:
|
||||||
|
|
||||||
- `{filename}`: Name of the uploaded file
|
- `{filename}`: Name of the uploaded file
|
||||||
- `{size}`: Size of the file (formatted according to APPRISE_SIZE_UNIT)
|
- `{size}`: Size of the file (formatted according to APPRISE_SIZE_UNIT)
|
||||||
- `{storage}`: Total size of all files in upload directory
|
- `{storage}`: Total size of all files in upload directory
|
||||||
|
|
||||||
Example message template:
|
Example message template:
|
||||||
|
|
||||||
```env
|
```env
|
||||||
APPRISE_MESSAGE: New file uploaded {filename} ({size}), Storage used {storage}
|
APPRISE_MESSAGE: New file uploaded {filename} ({size}), Storage used {storage}
|
||||||
```
|
```
|
||||||
|
|
||||||
Size formatting examples:
|
Size formatting examples:
|
||||||
|
|
||||||
- Auto (default): Chooses nearest unit (e.g., "1.44MB", "256KB")
|
- Auto (default): Chooses nearest unit (e.g., "1.44MB", "256KB")
|
||||||
- Fixed unit: Set APPRISE_SIZE_UNIT to B, KB, MB, GB, or TB
|
- Fixed unit: Set APPRISE_SIZE_UNIT to B, KB, MB, GB, or TB
|
||||||
|
|
||||||
Both {size} and {storage} use the same formatting rules based on APPRISE_SIZE_UNIT.
|
Both {size} and {storage} use the same formatting rules based on APPRISE_SIZE_UNIT.
|
||||||
|
|
||||||
#### Notification Support
|
#### Notification Support
|
||||||
|
|
||||||
- Integration with [Apprise](https://github.com/caronc/apprise?tab=readme-ov-file#supported-notifications) for flexible notifications
|
- Integration with [Apprise](https://github.com/caronc/apprise?tab=readme-ov-file#supported-notifications) for flexible notifications
|
||||||
- Support for all Apprise notification services
|
- Support for all Apprise notification services
|
||||||
- Customizable notification messages with filename templating
|
- Customizable notification messages with filename templating
|
||||||
@@ -167,6 +198,7 @@ Both {size} and {storage} use the same formatting rules based on APPRISE_SIZE_UN
|
|||||||
## Security
|
## Security
|
||||||
|
|
||||||
### Features
|
### Features
|
||||||
|
|
||||||
- Variable-length PIN support (4-10 digits)
|
- Variable-length PIN support (4-10 digits)
|
||||||
- Constant-time PIN comparison
|
- Constant-time PIN comparison
|
||||||
- Input sanitization
|
- Input sanitization
|
||||||
@@ -178,6 +210,7 @@ Both {size} and {storage} use the same formatting rules based on APPRISE_SIZE_UN
|
|||||||
## Technical Details
|
## Technical Details
|
||||||
|
|
||||||
### Stack
|
### Stack
|
||||||
|
|
||||||
- **Backend**: Node.js (>=20.0.0) with Express
|
- **Backend**: Node.js (>=20.0.0) with Express
|
||||||
- **Frontend**: Vanilla JavaScript (ES6+)
|
- **Frontend**: Vanilla JavaScript (ES6+)
|
||||||
- **Container**: Docker with multi-stage builds
|
- **Container**: Docker with multi-stage builds
|
||||||
@@ -186,6 +219,7 @@ Both {size} and {storage} use the same formatting rules based on APPRISE_SIZE_UN
|
|||||||
- **Notifications**: Apprise integration
|
- **Notifications**: Apprise integration
|
||||||
|
|
||||||
### Dependencies
|
### Dependencies
|
||||||
|
|
||||||
- express: Web framework
|
- express: Web framework
|
||||||
- multer: File upload handling
|
- multer: File upload handling
|
||||||
- apprise: Notification system
|
- apprise: Notification system
|
||||||
@@ -210,8 +244,10 @@ See [Local Development (Recommended Quick Start)](LOCAL_DEVELOPMENT.md) for loca
|
|||||||
</a>
|
</a>
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
Made with ❤️ by [DumbWare.io](https://dumbware.io)
|
Made with ❤️ by [DumbWare.io](https://dumbware.io)
|
||||||
|
|
||||||
## Future Features
|
## Future Features
|
||||||
|
|
||||||
- Camera Upload for Mobile
|
- Camera Upload for Mobile
|
||||||
> Got an idea? [Open an issue](https://github.com/dumbwareio/dumbdrop/issues) or [submit a PR](https://github.com/dumbwareio/dumbdrop/pulls)
|
> Got an idea? [Open an issue](https://github.com/dumbwareio/dumbdrop/issues) or [submit a PR](https://github.com/dumbwareio/dumbdrop/pulls)
|
||||||
|
|||||||
@@ -16,8 +16,8 @@ services:
|
|||||||
BASE_URL: http://localhost:3000 # The base URL for the application, You must update this to the url you use to access your site
|
BASE_URL: http://localhost:3000 # The base URL for the application, You must update this to the url you use to access your site
|
||||||
|
|
||||||
# Comma-separated list of allowed origins for CORS
|
# Comma-separated list of allowed origins for CORS
|
||||||
# (default: '*' if empty, add your base_url if you want to restrict only to base_url)
|
# (default: '*' if empty, replace with your base_url if you want to restrict only to base_url)
|
||||||
# When adding multiple origins, base_url will be included by default
|
# When adding multiple origins, base_url will be included by default and does not need to the list
|
||||||
# ALLOWED_ORIGINS: http://internalip:port,https://subdomain.example.com
|
# ALLOWED_ORIGINS: http://internalip:port,https://subdomain.example.com
|
||||||
|
|
||||||
# Additional available environment variables (commented out with defaults)
|
# Additional available environment variables (commented out with defaults)
|
||||||
|
|||||||
10
package-lock.json
generated
10
package-lock.json
generated
@@ -15,6 +15,7 @@
|
|||||||
"dotenv": "^16.0.3",
|
"dotenv": "^16.0.3",
|
||||||
"express": "^4.18.2",
|
"express": "^4.18.2",
|
||||||
"express-rate-limit": "^7.1.5",
|
"express-rate-limit": "^7.1.5",
|
||||||
|
"helmet": "^8.1.0",
|
||||||
"multer": "^1.4.5-lts.1",
|
"multer": "^1.4.5-lts.1",
|
||||||
"toastify-js": "^1.12.0"
|
"toastify-js": "^1.12.0"
|
||||||
},
|
},
|
||||||
@@ -1424,6 +1425,15 @@
|
|||||||
"node": ">= 0.4"
|
"node": ">= 0.4"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/helmet": {
|
||||||
|
"version": "8.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/helmet/-/helmet-8.1.0.tgz",
|
||||||
|
"integrity": "sha512-jOiHyAZsmnr8LqoPGmCjYAaiuWwjAPLgY8ZX2XrmHawt99/u1y6RgrZMTeoPfpUbV96HOalYgz1qzkRbw54Pmg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/http-errors": {
|
"node_modules/http-errors": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz",
|
||||||
|
|||||||
@@ -21,6 +21,7 @@
|
|||||||
"dotenv": "^16.0.3",
|
"dotenv": "^16.0.3",
|
||||||
"express": "^4.18.2",
|
"express": "^4.18.2",
|
||||||
"express-rate-limit": "^7.1.5",
|
"express-rate-limit": "^7.1.5",
|
||||||
|
"helmet": "^8.1.0",
|
||||||
"multer": "^1.4.5-lts.1",
|
"multer": "^1.4.5-lts.1",
|
||||||
"toastify-js": "^1.12.0"
|
"toastify-js": "^1.12.0"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
|
|
||||||
const express = require('express');
|
const express = require('express');
|
||||||
const cors = require('cors');
|
const cors = require('cors');
|
||||||
|
const helmet = require('helmet');
|
||||||
const cookieParser = require('cookie-parser');
|
const cookieParser = require('cookie-parser');
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
@@ -14,7 +15,7 @@ const fsPromises = require('fs').promises;
|
|||||||
const { config, validateConfig } = require('./config');
|
const { config, validateConfig } = require('./config');
|
||||||
const logger = require('./utils/logger');
|
const logger = require('./utils/logger');
|
||||||
const { ensureDirectoryExists } = require('./utils/fileUtils');
|
const { ensureDirectoryExists } = require('./utils/fileUtils');
|
||||||
const { requirePin } = require('./middleware/security');
|
const { getHelmetConfig, requirePin } = require('./middleware/security');
|
||||||
const { safeCompare } = require('./utils/security');
|
const { safeCompare } = require('./utils/security');
|
||||||
const { initUploadLimiter, pinVerifyLimiter, downloadLimiter } = require('./middleware/rateLimiter');
|
const { initUploadLimiter, pinVerifyLimiter, downloadLimiter } = require('./middleware/rateLimiter');
|
||||||
const { injectDemoBanner, demoMiddleware } = require('./utils/demoMode');
|
const { injectDemoBanner, demoMiddleware } = require('./utils/demoMode');
|
||||||
@@ -32,6 +33,8 @@ app.set('trust proxy', 1);
|
|||||||
app.use(cors(getCorsOptions(BASE_URL)));
|
app.use(cors(getCorsOptions(BASE_URL)));
|
||||||
app.use(cookieParser());
|
app.use(cookieParser());
|
||||||
app.use(express.json());
|
app.use(express.json());
|
||||||
|
app.use(helmet(getHelmetConfig()));
|
||||||
|
|
||||||
// --- AUTHENTICATION MIDDLEWARE FOR ALL PROTECTED ROUTES ---
|
// --- AUTHENTICATION MIDDLEWARE FOR ALL PROTECTED ROUTES ---
|
||||||
app.use((req, res, next) => {
|
app.use((req, res, next) => {
|
||||||
// List of paths that should be publicly accessible
|
// List of paths that should be publicly accessible
|
||||||
|
|||||||
@@ -79,7 +79,7 @@ function determineUploadDirectory() {
|
|||||||
* Returns true if NODE_ENV is not 'production' and UPLOAD_DIR is not set (i.e., not Docker)
|
* Returns true if NODE_ENV is not 'production' and UPLOAD_DIR is not set (i.e., not Docker)
|
||||||
*/
|
*/
|
||||||
function isLocalDevelopment() {
|
function isLocalDevelopment() {
|
||||||
return process.env.NODE_ENV !== 'production' && !process.env.UPLOAD_DIR;
|
return process.env.NODE_ENV !== 'production';
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -119,10 +119,10 @@ const config = {
|
|||||||
*/
|
*/
|
||||||
port: process.env.PORT,
|
port: process.env.PORT,
|
||||||
/**
|
/**
|
||||||
* Node environment (default: 'development')
|
* Node environment (default: 'production')
|
||||||
* Set via NODE_ENV in .env
|
* Set via NODE_ENV in .env
|
||||||
*/
|
*/
|
||||||
nodeEnv: process.env.NODE_ENV || 'production',
|
nodeEnv: process.env.NODE_ENV,
|
||||||
/**
|
/**
|
||||||
* Base URL for the app (default: http://localhost:${PORT})
|
* Base URL for the app (default: http://localhost:${PORT})
|
||||||
* Set via BASE_URL in .env
|
* Set via BASE_URL in .env
|
||||||
|
|||||||
@@ -9,11 +9,11 @@ const logger = require('../utils/logger');
|
|||||||
const PORT = process.env.PORT || 3000;
|
const PORT = process.env.PORT || 3000;
|
||||||
const NODE_ENV = process.env.NODE_ENV || 'production';
|
const NODE_ENV = process.env.NODE_ENV || 'production';
|
||||||
const BASE_URL = process.env.BASE_URL || `http://localhost:${PORT}`;
|
const BASE_URL = process.env.BASE_URL || `http://localhost:${PORT}`;
|
||||||
// const { config } = require('../config');
|
|
||||||
|
|
||||||
|
// const { config } = require('../config');
|
||||||
/**
|
/**
|
||||||
* Security headers middleware
|
* Security headers middleware
|
||||||
* DEPRECATED
|
* DEPRECATED: Use helmet middleware instead for security headers
|
||||||
*/
|
*/
|
||||||
// function securityHeaders(req, res, next) {
|
// function securityHeaders(req, res, next) {
|
||||||
// // Content Security Policy
|
// // Content Security Policy
|
||||||
@@ -47,6 +47,25 @@ const BASE_URL = process.env.BASE_URL || `http://localhost:${PORT}`;
|
|||||||
// next();
|
// next();
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
function getHelmetConfig() {
|
||||||
|
return {
|
||||||
|
noSniff: true, // Prevent MIME type sniffing
|
||||||
|
frameguard: { action: 'deny' }, // Prevent clickjacking
|
||||||
|
hsts: { maxAge: 31536000, includeSubDomains: true }, // Enforce HTTPS for one year
|
||||||
|
crossOriginEmbedderPolicy: true,
|
||||||
|
crossOriginOpenerPolicy: { policy: 'same-origin-allow-popups' },
|
||||||
|
crossOriginResourcePolicy: { policy: 'same-origin' },
|
||||||
|
referrerPolicy: { policy: 'no-referrer-when-downgrade' }, // Set referrer policy
|
||||||
|
ieNoOpen: true, // Prevent IE from executing downloads
|
||||||
|
// Disabled Helmet middlewares:
|
||||||
|
contentSecurityPolicy: false, // Disable CSP for now
|
||||||
|
dnsPrefetchControl: true, // Disable DNS prefetching
|
||||||
|
permittedCrossDomainPolicies: false,
|
||||||
|
originAgentCluster: false,
|
||||||
|
xssFilter: false,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* PIN protection middleware
|
* PIN protection middleware
|
||||||
* @param {string} PIN - Valid PIN for comparison
|
* @param {string} PIN - Valid PIN for comparison
|
||||||
@@ -86,6 +105,7 @@ function requirePin(PIN) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
// securityHeaders,
|
// securityHeaders, // Deprecated, use helmet instead
|
||||||
|
getHelmetConfig,
|
||||||
requirePin
|
requirePin
|
||||||
};
|
};
|
||||||
Reference in New Issue
Block a user