fix forgot password and add runscripts

This commit is contained in:
root
2026-05-17 23:25:03 -04:00
parent f30f6e9796
commit 7ac0098c7f
16 changed files with 211 additions and 3 deletions
+15
View File
@@ -167,6 +167,21 @@ docker compose -f traefik.yaml up -d
npm run docker:prod:up
```
Or use the new helper scripts if you want to start one production container at a time:
```bash
npm run docker:prod:start:traefik
npm run docker:prod:start:postgres
npm run docker:prod:start:redis
npm run docker:prod:start:api
npm run docker:prod:start:marketplace
npm run docker:prod:start:dashboard
npm run docker:prod:start:admin
npm run docker:prod:start:frontends
npm run docker:prod:start:pgmanage
npm run docker:prod:start:all
```
Docker will:
1. Build the monorepo image
2. Start all app services (`api`, `marketplace`, `dashboard`, `admin`, `pgmanage`)
+20 -1
View File
@@ -316,6 +316,22 @@ router.post('/auth/2fa/verify', requireAdminAuth, async (req, res, next) => {
const ADMIN_RESET_TOKEN_TTL_MINUTES = 60
function ensureAppBasePath(baseUrl: string, basePath: string) {
try {
const url = new URL(baseUrl)
const normalizedPathname = url.pathname.replace(/\/$/, '')
if (normalizedPathname === basePath || normalizedPathname.endsWith(basePath)) {
return url.toString().replace(/\/$/, '')
}
url.pathname = `${normalizedPathname}${basePath}` || basePath
return url.toString().replace(/\/$/, '')
} catch {
const trimmed = baseUrl.replace(/\/$/, '')
return trimmed.endsWith(basePath) ? trimmed : `${trimmed}${basePath}`
}
}
router.post('/auth/forgot-password', async (req, res, next) => {
try {
const { email } = z.object({ email: z.string().email().max(255).trim().toLowerCase() }).parse(req.body)
@@ -330,7 +346,10 @@ router.post('/auth/forgot-password', async (req, res, next) => {
data: { passwordResetToken: rawToken, passwordResetExpiresAt: expiresAt },
})
const adminUrl = process.env.ADMIN_URL ?? 'http://localhost:3002'
const adminUrl = ensureAppBasePath(
process.env.ADMIN_URL ?? process.env.NEXT_PUBLIC_ADMIN_URL ?? 'http://localhost:3002/admin',
'/admin',
)
const resetUrl = `${adminUrl}/reset-password?token=${rawToken}`
await sendTransactionalEmail({
+20 -1
View File
@@ -10,6 +10,22 @@ const router = Router()
const RESET_TOKEN_TTL_MINUTES = 60
function ensureAppBasePath(baseUrl: string, basePath: string) {
try {
const url = new URL(baseUrl)
const normalizedPathname = url.pathname.replace(/\/$/, '')
if (normalizedPathname === basePath || normalizedPathname.endsWith(basePath)) {
return url.toString().replace(/\/$/, '')
}
url.pathname = `${normalizedPathname}${basePath}` || basePath
return url.toString().replace(/\/$/, '')
} catch {
const trimmed = baseUrl.replace(/\/$/, '')
return trimmed.endsWith(basePath) ? trimmed : `${trimmed}${basePath}`
}
}
function signEmployeeToken(employeeId: string) {
return jwt.sign(
{ sub: employeeId, type: 'employee' },
@@ -150,7 +166,10 @@ router.post('/forgot-password', async (req, res, next) => {
data: { passwordResetToken: rawToken, passwordResetExpiresAt: expiresAt },
})
const dashboardUrl = process.env.DASHBOARD_URL ?? 'http://localhost:3001'
const dashboardUrl = ensureAppBasePath(
process.env.DASHBOARD_URL ?? process.env.NEXT_PUBLIC_DASHBOARD_URL ?? 'http://localhost:3001/dashboard',
'/dashboard',
)
const resetUrl = `${dashboardUrl}/reset-password?token=${rawToken}`
await sendTransactionalEmail({
+1 -1
View File
@@ -1,7 +1,7 @@
export const API_BASE =
typeof window === 'undefined'
? (process.env.API_INTERNAL_URL || 'http://localhost:4000/api/v1')
: (process.env.NEXT_PUBLIC_API_URL || 'http://localhost:4000/api/v1')
: (process.env.NEXT_PUBLIC_API_URL || '/dashboard/api/v1')
export const EMPLOYEE_TOKEN_KEY = 'employee_token'
export const EMPLOYEE_PROFILE_KEY = 'employee_profile'
+10
View File
@@ -11,6 +11,16 @@
"dev": "turbo dev",
"lint": "turbo lint",
"type-check": "turbo type-check",
"docker:prod:start:all": "bash scripts/docker-prod-up-all.sh",
"docker:prod:start:traefik": "bash scripts/docker-prod-up-traefik.sh",
"docker:prod:start:postgres": "bash scripts/docker-prod-up-postgres.sh",
"docker:prod:start:redis": "bash scripts/docker-prod-up-redis.sh",
"docker:prod:start:api": "bash scripts/docker-prod-up-api.sh",
"docker:prod:start:marketplace": "bash scripts/docker-prod-up-marketplace.sh",
"docker:prod:start:dashboard": "bash scripts/docker-prod-up-dashboard.sh",
"docker:prod:start:admin": "bash scripts/docker-prod-up-admin.sh",
"docker:prod:start:frontends": "bash scripts/docker-prod-up-frontends.sh",
"docker:prod:start:pgmanage": "bash scripts/docker-prod-up-pgmanage.sh",
"docker:prod:up": "docker compose -p rentaldrivego-prod --env-file .env.docker.production -f docker-compose.production.yml up --build -d",
"docker:prod:down": "docker compose -p rentaldrivego-prod --env-file .env.docker.production -f docker-compose.production.yml down",
"docker:prod:logs": "docker compose -p rentaldrivego-prod --env-file .env.docker.production -f docker-compose.production.yml logs -f",
+44
View File
@@ -0,0 +1,44 @@
#!/usr/bin/env bash
set -euo pipefail
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
PROD_COMPOSE_FILE="${ROOT_DIR}/docker-compose.production.yml"
TRAEFIK_COMPOSE_FILE="${ROOT_DIR}/traefik.yaml"
ENV_FILE="${ROOT_DIR}/.env.docker.production"
PROJECT_NAME="${DOCKER_PROD_PROJECT_NAME:-rentaldrivego-prod}"
TRAEFIK_NETWORK="${DOCKER_PROD_TRAEFIK_NETWORK:-traefik-proxy}"
ensure_env_file() {
if [[ ! -f "${ENV_FILE}" ]]; then
echo "Missing ${ENV_FILE}" >&2
echo "Create it from .env.docker.production.example before starting production containers." >&2
exit 1
fi
}
ensure_traefik_network() {
if ! docker network inspect "${TRAEFIK_NETWORK}" >/dev/null 2>&1; then
echo "Creating Docker network: ${TRAEFIK_NETWORK}"
docker network create "${TRAEFIK_NETWORK}" >/dev/null
fi
}
prod_compose() {
docker compose -p "${PROJECT_NAME}" --env-file "${ENV_FILE}" -f "${PROD_COMPOSE_FILE}" "$@"
}
traefik_compose() {
docker compose -f "${TRAEFIK_COMPOSE_FILE}" "$@"
}
start_prod_services() {
ensure_env_file
prod_compose up --build -d "$@"
}
start_traefik() {
ensure_env_file
ensure_traefik_network
traefik_compose up -d
}
+10
View File
@@ -0,0 +1,10 @@
#!/usr/bin/env bash
set -euo pipefail
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
source "${ROOT_DIR}/scripts/docker-prod-common.sh"
start_prod_services admin
echo "Admin is starting."
+11
View File
@@ -0,0 +1,11 @@
#!/usr/bin/env bash
set -euo pipefail
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
source "${ROOT_DIR}/scripts/docker-prod-common.sh"
start_traefik
start_prod_services
echo "Production stack is starting: traefik, postgres, redis, api, marketplace, dashboard, admin, pgmanage"
+10
View File
@@ -0,0 +1,10 @@
#!/usr/bin/env bash
set -euo pipefail
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
source "${ROOT_DIR}/scripts/docker-prod-common.sh"
start_prod_services api
echo "API is starting."
+10
View File
@@ -0,0 +1,10 @@
#!/usr/bin/env bash
set -euo pipefail
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
source "${ROOT_DIR}/scripts/docker-prod-common.sh"
start_prod_services dashboard
echo "Dashboard is starting."
+10
View File
@@ -0,0 +1,10 @@
#!/usr/bin/env bash
set -euo pipefail
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
source "${ROOT_DIR}/scripts/docker-prod-common.sh"
start_prod_services marketplace dashboard admin
echo "Frontend production services are starting: marketplace, dashboard, admin"
+10
View File
@@ -0,0 +1,10 @@
#!/usr/bin/env bash
set -euo pipefail
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
source "${ROOT_DIR}/scripts/docker-prod-common.sh"
start_prod_services marketplace
echo "Marketplace is starting."
+10
View File
@@ -0,0 +1,10 @@
#!/usr/bin/env bash
set -euo pipefail
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
source "${ROOT_DIR}/scripts/docker-prod-common.sh"
start_prod_services pgmanage
echo "pgManage is starting."
+10
View File
@@ -0,0 +1,10 @@
#!/usr/bin/env bash
set -euo pipefail
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
source "${ROOT_DIR}/scripts/docker-prod-common.sh"
start_prod_services postgres
echo "Postgres is starting."
+10
View File
@@ -0,0 +1,10 @@
#!/usr/bin/env bash
set -euo pipefail
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
source "${ROOT_DIR}/scripts/docker-prod-common.sh"
start_prod_services redis
echo "Redis is starting."
+10
View File
@@ -0,0 +1,10 @@
#!/usr/bin/env bash
set -euo pipefail
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
source "${ROOT_DIR}/scripts/docker-prod-common.sh"
start_traefik
echo "Traefik is starting."