Skip to content

[Bug]: Server Crashes on Password Reset Function (ENOENT: password_reset_email_subject.txt) #1750

Open
@Arny80Hexa

Description

@Arny80Hexa

Issue Description

When attempting to use the "Forgot Password" function, the OpenSign server container unexpectedly crashes. The server logs indicate an ENOENT (Error NO ENTry) error, meaning a required file for sending the password reset email cannot be found.

I'm using a custom docker-compose.yml, because for SSL I'm using an nginx reverse proxy on the host:

services:
  server:
    image: opensign/opensignserver:main
    container_name: stage.sign.example.com_server
    volumes:
      - ./opensign-stage-files:/usr/src/app/files:Z
    ports:
      - "4009:8080"
    depends_on:
      - mongo
    env_file: .env.stage
    environment:
      - NODE_ENV=production
      - SERVER_URL=http://stage.sign.example.com_server:8080/app
      - PUBLIC_URL=${HOST_URL}
    networks:
      - opensign-stage-network

  mongo:
    image: mongo:latest
    container_name: stage.sign.example.com_mongo
    volumes:
      - ./opensign-stage-mongo-data:/data/db:Z
    networks:
      - opensign-stage-network

  client:
    image: opensign/opensign:main
    container_name: stage.sign.example.com_client
    depends_on:
      - server
    env_file: .env.stage
    ports:
      - "4008:3000"
    networks:
      - opensign-stage-network

networks:
  opensign-stage-network:
    driver: bridge

volumes:
  opensign-stage-mongo-data:
  opensign-stage-files:

The .env.stage:

PUBLIC_URL=https://stage.sign.example.com
GENERATE_SOURCEMAP=false
REACT_APP_APPID=opensign
REACT_APP_SERVERURL=https://stage.sign.example.com/api/app
appName=open_sign_server_stage
MASTER_KEY=XnAadwKxxByMr # Consider generating a new, strong key for production
MONGODB_URI=mongodb://stage.sign.example.com_mongo:27017/OpenSignDB
PARSE_MOUNT=/app
SERVER_URL=http://stage.sign.example.com_server:8080/app
HOST_URL=https://stage.sign.example.com
DO_SPACE=DOSPACENAME # Replace with your actual Digital Ocean Space or S3 bucket name
DO_ENDPOINT=ams3.digitaloceanspaces.com # Replace with your actual endpoint
DO_BASEURL=https://DOSPACENAME.ams3.digitaloceanspaces.com # Replace with your actual base URL
DO_ACCESS_KEY_ID= # Replace with your actual key
DO_SECRET_ACCESS_KEY= # Replace with your actual key
DO_REGION=us-west # Replace with your actual region
USE_LOCAL=true # Set to false if you want to use Digital Ocean Spaces/S3
MAILGUN_API_KEY= # Replace with your Mailgun API Key
MAILGUN_DOMAIN=mail.yourdomain.com # Replace with your Mailgun Domain
[email protected] # Replace with your Mailgun Sender
SMTP_ENABLE=true
SMTP_HOST=exchange.example.de # Replace with your SMTP Host
SMTP_PORT=587 # Replace with your SMTP Port
[email protected] # Replace with your SMTP User Email
SMTP_PASS=super_secret_passwort # Replace with your SMTP Password. If your password includes spaces then write password in single quotes ('asdf pasd asdf bgds').
PFX_BASE64='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
3pXAXxZuvVvv9tsb4bdrBAhyb+KCIjp/gAICCAA='
PASS_PHRASE=opensign # Replace with your actual passphrase
APP_ID=opensign

nginx vhost config:

server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;
    server_name stage.sign.example.com;
    server_tokens off;
    ssl_certificate /etc/ssl/certs/sign.example.com.temp-selfsigned.pem;
    ssl_certificate_key /etc/ssl/private/sign.example.com.temp-selfsigned.key;
#    ssl_certificate /etc/ssl/certs/sign.example.com.pem;
#    ssl_certificate_key /etc/ssl/private/sign.example.com.key;
    ssl_session_timeout 1d;
    ssl_session_cache shared:MozSSL:10m;
    ssl_session_tickets off;
    ssl_dhparam /etc/ssl/dhparams.pem;
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-CHACHA20-POLY1305;
    ssl_prefer_server_ciphers off;
    add_header Strict-Transport-Security "max-age=63072000" always;
    ssl_stapling on;
    ssl_stapling_verify on;
    resolver 8.8.8.8 8.8.4.4 valid=300s; # DNS-Resolver für OCSP-Stapling
    resolver_timeout 5s;
    access_log /var/log/nginx/stage.example.com-access.log;
    error_log /var/log/nginx/stage.example.com-error.log warn;
    client_max_body_size 0;
    proxy_request_buffering off;
    proxy_buffer_size 128k;
    proxy_buffers 4 256k;
    proxy_busy_buffers_size 256k;
    proxy_max_temp_file_size 0;

    # Proxy-Pass für den Frontend (Client-Container)
    location / {
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_hide_header Upgrade;
        proxy_pass http://127.0.0.1:4008; # Angepasster Port für den Client
    }

    # Proxy-Pass für die Backend-API (Server-Container)
    location /api/app {
        # Entfernt NUR den /api-Präfix, um den /app-Pfad für den Backend-Server beizubehalten
        rewrite ^/api/(.*)$ /$1 break;
        proxy_set_header Host $host; # Angepasst: Host-Header sollte den öffentlichen Hostnamen widerspiegeln
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        # Hinzugefügt für WebSocket-Unterstützung
        proxy_set_header Connection "upgrade";
        proxy_set_header Upgrade $http_upgrade;
        proxy_pass http://127.0.0.1:4009; # Angepasster Port für den Server
        proxy_redirect off; # Wichtig für korrekte Weiterleitungen vom Backend
    }

    # Spezifischer Proxy-Pass für /getlogobydomain, da es nicht unter /api/app aufgerufen wird
    # Dies leitet die Anfrage intern an den korrekten Backend-Pfad um.
    location = /getlogobydomain {
        # Umschreibung auf den vollen Parse Cloud Function Pfad
        rewrite ^/getlogobydomain$ /app/functions/getlogobydomain break;
        proxy_set_header Host $host; # Angepasst: Host-Header sollte den öffentlichen Hostnamen widerspiegeln
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        # Hinzugefügt für WebSocket-Unterstützung
        proxy_set_header Connection "upgrade";
        proxy_set_header Upgrade $http_upgrade;
        proxy_pass http://127.0.0.1:4009; # Angepasster Port für den Server
        proxy_redirect off; # Wichtig für korrekte Weiterleitungen vom Backend
    }
}

It was a long way, to get everything working until this point. I had a lot of trouble with the locations but this works for me (except "forget password").

And the error from the server-container-log, when using Forget Password function:

An uncaught exception occurred: ENOENT: no such file or directory, open './files/password_reset_email_subject.txt'Stack Trace:
Error: ENOENT: no such file or directory, open './files/password_reset_email_subject.txt'
    at async open (node:internal/fs/promises:638:25)
    at async Object.readFile (node:internal/fs/promises:1242:14)
    at async ApiMailAdapter._loadFile (/usr/src/app/node_modules/parse-server-api-mail-adapter/lib/ApiMailAdapter.js:333:18)
    at async ApiMailAdapter._createApiData (/usr/src/app/node_modules/parse-server-api-mail-adapter/lib/ApiMailAdapter.js:251:41)
    at async ApiMailAdapter._sendMail (/usr/src/app/node_modules/parse-server-api-mail-adapter/lib/ApiMailAdapter.js:195:21)npm notice
npm notice New major version of npm available! 10.9.2 -> 11.4.1
npm notice Changelog: https://github.com/npm/cli/releases/tag/v11.4.1
npm notice To update run: npm install -g [email protected]
npm notice

Expected Behavior

The "Forgot Password" function should successfully process the request and send a password reset email to the provided address without the server crashing.

Current Behavior

The server container crashes immediately after attempting to use the "Forgot Password" function, due to the missing email template file.

Steps to reproduce

  1. Start the OpenSign server container.
  2. Navigate to the login page of the OpenSign frontend.
  3. Click on the "Forgot Password" link (or similar UI element).
  4. Enter a valid email address into the input field and confirm the request (e.g., by clicking "Send" or "Reset Password").
  5. Observe that the server container crashes.

Screenshots of the issue(optional)

No response

Operating System [e.g. MacOS Sonoma 14.1, Windows 11]

AlmaLinux 9.4

What browsers are you seeing the problem on?

Chrome, Firefox

What version of OpenSign™ are you seeing this issue on? [e.g. 1.0.6]

latest

What environment are you seeing the problem on?

Hosted (app.yourdomain.com)

Please check the boxes that apply to this issue report.

  • I have searched the existing issues & discussions to make sure that this is not a duplicate.

Code of Conduct

  • I agree to follow this project's Code of Conduct
  • I have searched the existing issues & discussions to make sure that this is not a duplicate.

Metadata

Metadata

Labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions