update
This commit is contained in:
@@ -14,13 +14,13 @@ const fs = require('fs');
|
||||
const path = require('path');
|
||||
const bcrypt = require('bcryptjs');
|
||||
|
||||
// APP_TYPE validation — host mode requires HOST_DOMAIN and HOST_ADMIN_KEY.
|
||||
// If either is missing, fall back to selfhost and warn rather than silently
|
||||
// APP_TYPE validation — host mode requires APP_DOMAIN, HOST_SLUG, and HOST_ADMIN_KEY.
|
||||
// If any are missing, fall back to selfhost and warn rather than silently
|
||||
// exposing a broken or insecure host control plane.
|
||||
let APP_TYPE = (process.env.APP_TYPE || 'selfhost').toLowerCase().trim();
|
||||
if (APP_TYPE === 'host') {
|
||||
if (!process.env.HOST_DOMAIN || !process.env.HOST_ADMIN_KEY) {
|
||||
console.warn('[DB] WARNING: APP_TYPE=host requires HOST_DOMAIN and HOST_ADMIN_KEY to be set.');
|
||||
if (!process.env.APP_DOMAIN || !process.env.HOST_SLUG || !process.env.HOST_ADMIN_KEY) {
|
||||
console.warn('[DB] WARNING: APP_TYPE=host requires APP_DOMAIN, HOST_SLUG, and HOST_ADMIN_KEY to be set.');
|
||||
console.warn('[DB] WARNING: Falling back to APP_TYPE=selfhost for safety.');
|
||||
APP_TYPE = 'selfhost';
|
||||
}
|
||||
@@ -52,12 +52,17 @@ function resolveSchema(req) {
|
||||
if (APP_TYPE === 'selfhost') return 'public';
|
||||
|
||||
const host = (req.headers.host || '').toLowerCase().split(':')[0];
|
||||
const baseDomain = (process.env.HOST_DOMAIN || 'rosterchirp.com').toLowerCase();
|
||||
const baseDomain = (process.env.APP_DOMAIN || 'rosterchirp.com').toLowerCase();
|
||||
const hostSlug = (process.env.HOST_SLUG || 'host').toLowerCase();
|
||||
const hostControlDomain = `${hostSlug}.${baseDomain}`;
|
||||
|
||||
// Internal requests (Docker health checks, localhost) → public schema
|
||||
if (host === 'localhost' || host === '127.0.0.1' || host === '::1') return 'public';
|
||||
|
||||
// Subdomain: team1.rosterchirp.com → tenant_team1
|
||||
// Host control panel subdomain: chathost.example.com → public schema
|
||||
if (host === hostControlDomain) return 'public';
|
||||
|
||||
// Tenant subdomain: mychat.example.com → tenant_mychat
|
||||
if (host.endsWith(`.${baseDomain}`)) {
|
||||
const slug = host.slice(0, -(baseDomain.length + 1));
|
||||
if (!slug || slug === 'www') throw new Error(`Invalid tenant slug: ${slug}`);
|
||||
@@ -67,9 +72,6 @@ function resolveSchema(req) {
|
||||
// Custom domain lookup (populated from host admin DB)
|
||||
if (tenantDomainCache.has(host)) return tenantDomainCache.get(host);
|
||||
|
||||
// Base domain → public schema (host admin panel)
|
||||
if (host === baseDomain || host === `www.${baseDomain}`) return 'public';
|
||||
|
||||
throw new Error(`Unknown tenant for host: ${host}`);
|
||||
}
|
||||
|
||||
|
||||
@@ -162,7 +162,7 @@ router.post('/tenants', async (req, res) => {
|
||||
// 7. Reload domain cache
|
||||
await reloadTenantCache();
|
||||
|
||||
const baseDomain = process.env.HOST_DOMAIN || 'rosterchirp.com';
|
||||
const baseDomain = process.env.APP_DOMAIN || 'rosterchirp.com';
|
||||
const tenant = tr.rows[0];
|
||||
tenant.url = `https://${slug}.${baseDomain}`;
|
||||
|
||||
@@ -320,7 +320,7 @@ router.get('/status', async (req, res) => {
|
||||
try {
|
||||
const tenantCount = await queryOne('public', 'SELECT COUNT(*) AS count FROM tenants');
|
||||
const active = await queryOne('public', "SELECT COUNT(*) AS count FROM tenants WHERE status='active'");
|
||||
const baseDomain = process.env.HOST_DOMAIN || 'rosterchirp.com';
|
||||
const baseDomain = process.env.APP_DOMAIN || 'rosterchirp.com';
|
||||
res.json({
|
||||
ok: true,
|
||||
appType: process.env.APP_TYPE || 'selfhost',
|
||||
|
||||
@@ -39,14 +39,16 @@ router.get('/', async (req, res) => {
|
||||
if (admin) obj.admin_email = admin.email;
|
||||
obj.app_version = process.env.ROSTERCHIRP_VERSION || 'dev';
|
||||
obj.user_pass = process.env.USER_PASS || 'user@1234';
|
||||
// Tell the frontend whether this request came from the HOST_DOMAIN.
|
||||
// Used to show/hide the Control Panel menu item — only visible on the host's own domain.
|
||||
// Tell the frontend whether this request came from the host control panel subdomain.
|
||||
// Used to show/hide the Control Panel menu item — only visible on the host's own subdomain.
|
||||
const reqHost = (req.headers.host || '').toLowerCase().split(':')[0];
|
||||
const hostDomain = (process.env.HOST_DOMAIN || '').toLowerCase();
|
||||
const appDomain = (process.env.APP_DOMAIN || '').toLowerCase();
|
||||
const hostSlug = (process.env.HOST_SLUG || 'host').toLowerCase();
|
||||
const hostControlDomain = appDomain ? `${hostSlug}.${appDomain}` : '';
|
||||
obj.is_host_domain = (
|
||||
process.env.APP_TYPE === 'host' &&
|
||||
!!hostDomain &&
|
||||
(reqHost === hostDomain || reqHost === `www.${hostDomain}` || reqHost === 'localhost')
|
||||
!!hostControlDomain &&
|
||||
(reqHost === hostControlDomain || reqHost === 'localhost')
|
||||
) ? 'true' : 'false';
|
||||
res.json({ settings: obj });
|
||||
} catch (e) { res.status(500).json({ error: e.message }); }
|
||||
|
||||
Reference in New Issue
Block a user