fix stripe for production
Build & Push / Pipeline Tests (push) Successful in 1m51s
Test / Type Check (all packages) (push) Successful in 52s
Test / API Unit Tests (push) Successful in 1m10s
Test / Homepage Unit Tests (push) Successful in 48s
Test / Carplace Unit Tests (push) Successful in 44s
Test / Admin Unit Tests (push) Successful in 44s
Test / Dashboard Unit Tests (push) Successful in 44s
Test / API Integration Tests (push) Successful in 1m7s
Build & Push / Build & Push Docker Image (push) Failing after 41s

This commit is contained in:
root
2026-07-29 01:39:54 -04:00
parent 96d1d2d0d6
commit b944ff554c
8 changed files with 68 additions and 14 deletions
+3 -3
View File
@@ -36,8 +36,8 @@ CORS_ORIGINS=http://localhost:3000,http://localhost:3001,http://localhost:3002,h
# Stripe subscription checkout
# STRIPE_API_KEY must be a Stripe secret/restricted key (sk_ or rk_).
# STRIPE_WEBHOOK_SECRET must be a Stripe webhook signing secret (whsec_).
STRIPE_API_KEY=sk_test_51TvTsb9SpDRZn9yJyBAlUSXcTp9zpwQfhJYNKxfyYaZbqT6NN8W4pXu0zOUvpunrDPdtC0I6OZPzq0B5RRI1Ybub00OcYvj28K
STRIPE_WEBHOOK_SECRET=whsec_c5e0a6b2dd5e2f6ac804b428fe46f04e3af9b55c562f4124de20c52866f3c211
STRIPE_API_KEY=placeholder
STRIPE_WEBHOOK_SECRET=placeholder
# Email — Resend (primary) with SMTP fallback
# Get your API key at https://resend.com/api-keys
RESEND_API_KEY=re_PLACEHOLDER
@@ -48,7 +48,7 @@ MAIL_HOST=smtp.gmail.com
MAIL_PORT=587
MAIL_SCHEME=smtp
MAIL_USERNAME=rentaldrivego@gmail.com
MAIL_PASSWORD=kfahihfzbcvkczew
MAIL_PASSWORD=placeholder
MAIL_FROM_ADDRESS=rentaldrivego@gmail.com
MAIL_FROM_NAME=RentalDriveGo
MAIL_REPLY_TO_ADDRESS=rentaldrivego@gmail.com
+3 -3
View File
@@ -80,7 +80,7 @@ MAIL_HOST=smtp.gmail.com
MAIL_PORT=587
MAIL_SCHEME=smtp
MAIL_USERNAME=rentaldrivego@gmail.com
MAIL_PASSWORD=kfahihfzbcvkczew
MAIL_PASSWORD=placeholder
MAIL_FROM_ADDRESS=rentaldrivego@gmail.com
MAIL_FROM_NAME=RentalDriveGo
MAIL_REPLY_TO_ADDRESS=rentaldrivego@gmail.com
@@ -89,8 +89,8 @@ MAIL_REPLY_TO_NAME=RentalDriveGo
# Stripe subscription checkout
# STRIPE_API_KEY must be a Stripe secret/restricted key (sk_ or rk_).
# STRIPE_WEBHOOK_SECRET must be a Stripe webhook signing secret (whsec_).
STRIPE_API_KEY=sk_test_51TvTsb9SpDRZn9yJyBAlUSXcTp9zpwQfhJYNKxfyYaZbqT6NN8W4pXu0zOUvpunrDPdtC0I6OZPzq0B5RRI1Ybub00OcYvj28K
STRIPE_WEBHOOK_SECRET=whsec_c5e0a6b2dd5e2f6ac804b428fe46f04e3af9b55c562f4124de20c52866f3c211
STRIPE_API_KEY=placeholder
STRIPE_WEBHOOK_SECRET=placeholder
# ── Firebase push notifications (optional) ────────────────────────────────────
# FIREBASE_PROJECT_ID=your-firebase-project-id
+5
View File
@@ -49,6 +49,11 @@ PAYPAL_BASE_URL=https://api-m.paypal.com
# Use https://api-m.sandbox.paypal.com for sandbox
NEXT_PUBLIC_PAYPAL_CLIENT_ID=your-paypal-client-id
# ─── Stripe (subscription checkout) ────────────────────────────
# Prefer a restricted API key (rk_) with the minimum Billing/Checkout permissions.
STRIPE_API_KEY=placeholder
STRIPE_WEBHOOK_SECRET=placeholder
# ─── Cloudinary (Vehicle + brand photos) ──────────────────────
CLOUDINARY_CLOUD_NAME=your-cloud-name
CLOUDINARY_API_KEY=your-api-key
@@ -199,7 +199,7 @@ describe('menu.service', () => {
expect(result.items.find((item) => item.label === 'Reports')?.reasons.join(' ')).toContain('STARTER does not include this menu item')
})
it('returns the approved seven-item STARTER owner sidebar in order', async () => {
it('returns the approved STARTER owner sidebar in order', async () => {
vi.mocked(prisma.employee.findUniqueOrThrow).mockResolvedValue({
id: 'employee_1',
role: 'OWNER',
@@ -367,6 +367,7 @@ describe('menu.service', () => {
expect(result.items.map((menuItem) => menuItem.systemKey)).toEqual([
'dashboard',
'reservations',
'contracts',
'fleet',
'customers',
'reports',
+6 -5
View File
@@ -73,11 +73,12 @@ const ROLE_RANK: Record<EmployeeRole, number> = { OWNER: 3, MANAGER: 2, AGENT: 1
const BASELINE_EMPLOYEE_MENU_ITEMS = [
{ systemKey: 'dashboard', label: 'Dashboard', routeOrUrl: '/', icon: 'LayoutDashboard', displayOrder: 10, minRole: 'AGENT' },
{ systemKey: 'reservations', label: 'Reservations', routeOrUrl: '/reservations', icon: 'Calendar', displayOrder: 20, minRole: 'AGENT' },
{ systemKey: 'fleet', label: 'Fleet', routeOrUrl: '/fleet', icon: 'Car', displayOrder: 30, minRole: 'AGENT' },
{ systemKey: 'customers', label: 'Customers', routeOrUrl: '/customers', icon: 'Users', displayOrder: 40, minRole: 'AGENT' },
{ systemKey: 'reports', label: 'Reports', routeOrUrl: '/reports', icon: 'BarChart2', displayOrder: 50, minRole: 'MANAGER' },
{ systemKey: 'billing', label: 'Billing', routeOrUrl: '/billing', icon: 'CreditCard', displayOrder: 60, minRole: 'MANAGER' },
{ systemKey: 'settings', label: 'Settings', routeOrUrl: '/settings', icon: 'Settings', displayOrder: 70, minRole: 'OWNER' },
{ systemKey: 'contracts', label: 'Contracts', routeOrUrl: '/contracts', icon: 'FileText', displayOrder: 30, minRole: 'AGENT' },
{ systemKey: 'fleet', label: 'Fleet', routeOrUrl: '/fleet', icon: 'Car', displayOrder: 40, minRole: 'AGENT' },
{ systemKey: 'customers', label: 'Customers', routeOrUrl: '/customers', icon: 'Users', displayOrder: 50, minRole: 'AGENT' },
{ systemKey: 'reports', label: 'Reports', routeOrUrl: '/reports', icon: 'BarChart2', displayOrder: 60, minRole: 'MANAGER' },
{ systemKey: 'billing', label: 'Billing', routeOrUrl: '/billing', icon: 'CreditCard', displayOrder: 70, minRole: 'MANAGER' },
{ systemKey: 'settings', label: 'Settings', routeOrUrl: '/settings', icon: 'Settings', displayOrder: 80, minRole: 'OWNER' },
] as const
const MENU_RECOVERY_ROUTES = new Set(['/subscription', '/subscription/success', '/subscription/cancel'])
@@ -84,3 +84,8 @@ MAIL_FROM_ADDRESS=rentaldrivego@gmail.com
MAIL_FROM_NAME=RentalDriveGo
MAIL_REPLY_TO_ADDRESS=rentaldrivego@gmail.com
MAIL_REPLY_TO_NAME=RentalDriveGo
# Stripe subscription checkout
# Prefer a restricted API key (rk_) with the minimum Billing/Checkout permissions.
STRIPE_API_KEY=placeholder
STRIPE_WEBHOOK_SECRET=placeholder
+22 -1
View File
@@ -187,7 +187,7 @@ EOF
}
validate_prod_env_file() {
local acme_email api_domain public_site_domain cors_origins postgres_password redis_password jwt_secret
local acme_email api_domain public_site_domain cors_origins postgres_password redis_password jwt_secret stripe_api_key stripe_webhook_secret
acme_email="$(read_env_value ACME_EMAIL)"
api_domain="$(read_env_value API_DOMAIN)"
@@ -196,6 +196,8 @@ validate_prod_env_file() {
postgres_password="$(read_env_value POSTGRES_PASSWORD)"
redis_password="$(read_env_value REDIS_PASSWORD)"
jwt_secret="$(read_env_value JWT_SECRET)"
stripe_api_key="$(read_env_value STRIPE_API_KEY)"
stripe_webhook_secret="$(read_env_value STRIPE_WEBHOOK_SECRET)"
if [[ -z "${acme_email}" || "${acme_email}" != *@* || "${acme_email}" == *example.com* ]]; then
echo "Invalid ACME_EMAIL in ${ENV_FILE}. Set ACME_EMAIL=${DEFAULT_ACME_EMAIL} for Let's Encrypt." >&2
@@ -226,6 +228,25 @@ validate_prod_env_file() {
fi
done
if [[ -z "${stripe_api_key}" || "${stripe_api_key}" == placeholder || "${stripe_api_key}" == replace-with-* || "${stripe_api_key}" == *changeme* || "${stripe_api_key}" == *change-me* ]]; then
echo "Invalid STRIPE_API_KEY in ${ENV_FILE}. Set a real Stripe secret or restricted API key for production billing." >&2
exit 1
fi
if [[ "${stripe_api_key}" != sk_* && "${stripe_api_key}" != rk_* ]]; then
echo "Invalid STRIPE_API_KEY in ${ENV_FILE}. It must start with sk_ or rk_." >&2
exit 1
fi
if [[ -z "${stripe_webhook_secret}" || "${stripe_webhook_secret}" == placeholder || "${stripe_webhook_secret}" == replace-with-* || "${stripe_webhook_secret}" == *changeme* || "${stripe_webhook_secret}" == *change-me* ]]; then
echo "Invalid STRIPE_WEBHOOK_SECRET in ${ENV_FILE}. Set the Stripe webhook signing secret for /api/v1/subscriptions/webhooks/stripe." >&2
exit 1
fi
if [[ "${stripe_webhook_secret}" != whsec_* ]]; then
echo "Invalid STRIPE_WEBHOOK_SECRET in ${ENV_FILE}. It must start with whsec_." >&2
exit 1
fi
}
+22 -1
View File
@@ -181,7 +181,7 @@ EOF
}
validate_prod_env_file() {
local acme_email api_domain public_site_domain cors_origins portainer_domain postgres_password redis_password jwt_secret
local acme_email api_domain public_site_domain cors_origins portainer_domain postgres_password redis_password jwt_secret stripe_api_key stripe_webhook_secret
acme_email="$(read_env_value ACME_EMAIL)"
api_domain="$(read_env_value API_DOMAIN)"
@@ -191,6 +191,8 @@ validate_prod_env_file() {
postgres_password="$(read_env_value POSTGRES_PASSWORD)"
redis_password="$(read_env_value REDIS_PASSWORD)"
jwt_secret="$(read_env_value JWT_SECRET)"
stripe_api_key="$(read_env_value STRIPE_API_KEY)"
stripe_webhook_secret="$(read_env_value STRIPE_WEBHOOK_SECRET)"
if [[ -z "${acme_email}" || "${acme_email}" != *@* || "${acme_email}" == *example.com* ]]; then
echo "Invalid ACME_EMAIL in ${ENV_FILE}. Set it to a real contact email for Let's Encrypt, not example.com." >&2
@@ -221,6 +223,25 @@ validate_prod_env_file() {
fi
done
if [[ -z "${stripe_api_key}" || "${stripe_api_key}" == placeholder || "${stripe_api_key}" == replace-with-* || "${stripe_api_key}" == *changeme* || "${stripe_api_key}" == *change-me* ]]; then
echo "Invalid STRIPE_API_KEY in ${ENV_FILE}. Set a real Stripe secret or restricted API key for production billing." >&2
exit 1
fi
if [[ "${stripe_api_key}" != sk_* && "${stripe_api_key}" != rk_* ]]; then
echo "Invalid STRIPE_API_KEY in ${ENV_FILE}. It must start with sk_ or rk_." >&2
exit 1
fi
if [[ -z "${stripe_webhook_secret}" || "${stripe_webhook_secret}" == placeholder || "${stripe_webhook_secret}" == replace-with-* || "${stripe_webhook_secret}" == *changeme* || "${stripe_webhook_secret}" == *change-me* ]]; then
echo "Invalid STRIPE_WEBHOOK_SECRET in ${ENV_FILE}. Set the Stripe webhook signing secret for /api/v1/subscriptions/webhooks/stripe." >&2
exit 1
fi
if [[ "${stripe_webhook_secret}" != whsec_* ]]; then
echo "Invalid STRIPE_WEBHOOK_SECRET in ${ENV_FILE}. It must start with whsec_." >&2
exit 1
fi
if [[ -n "${portainer_domain}" && "${portainer_domain}" == *example.com* ]]; then
echo "Invalid PORTAINER_DOMAIN in ${ENV_FILE}. Set a real hostname or disable the portainer router." >&2