mirror of
https://github.com/lobehub/lobehub.git
synced 2026-03-27 13:29:15 +07:00
* 🐛 fix(email): use || instead of ?? to handle empty string from Dockerfile Dockerfile sets empty string defaults for email env vars (SMTP_FROM, SMTP_HOST, etc). The ?? operator doesn't treat empty strings as nullish, causing email sending to fail with "Mail Account:" being empty. Fixes #11757 * ✨ feat(workflow): add Claude migration support workflow Add automated support for migration feedback issues (#11757, #11707): - Auto-respond to new comments on migration issues - Check for sensitive information leaks and warn users - Read latest docs before responding - Validate required information from issue description - Match issues against documented FAQ solutions * 🐛 fix(auth): add APP_URL trailing slash check Detect and warn when APP_URL ends with a trailing slash, which causes double slashes in redirect URLs (e.g., https://example.com//). * ✨ feat(workflow): add Claude migration support workflow Add automated support for migration feedback issues (#11757, #11707): - Auto-respond to new comments on migration issues - Check for sensitive information leaks and warn users - Read latest docs before responding - Validate required information from issue description - Match issues against documented FAQ solutions - Minimize resolved/success feedback comments * 📝 docs: add browser cache clearing guide and improve migration workflow - Add troubleshooting section for clearing browser site data after migration - Exclude maintainers (tjx666, arvinxx) from auto-reply workflow - Add references to auth.mdx and checkDeprecatedAuth.js in workflow * 📝 docs: add migration internals technical documentation - Explain users table vs accounts table relationship - Document simple vs full migration principles - Add troubleshooting guide with SQL examples - Link from migration guides to new doc
212 lines
7.2 KiB
JavaScript
212 lines
7.2 KiB
JavaScript
/**
|
|
* Shared utility to check for deprecated authentication environment variables.
|
|
* Used by both prebuild.mts (build time) and startServer.js (Docker runtime).
|
|
*
|
|
* IMPORTANT: Keep this file as CommonJS (.js) for compatibility with startServer.js
|
|
*/
|
|
|
|
const MIGRATION_DOC_BASE = 'https://lobehub.com/docs/self-hosting/advanced/auth';
|
|
|
|
/**
|
|
* Deprecated environment variable checks configuration
|
|
* @type {Array<{
|
|
* name: string;
|
|
* getVars: () => string[];
|
|
* message: string;
|
|
* docUrl?: string;
|
|
* formatVar?: (envVar: string) => string;
|
|
* }>}
|
|
*/
|
|
const DEPRECATED_CHECKS = [
|
|
{
|
|
docUrl: `${MIGRATION_DOC_BASE}/nextauth-to-betterauth`,
|
|
getVars: () =>
|
|
Object.keys(process.env).filter(
|
|
(key) => key.startsWith('NEXT_AUTH') || key.startsWith('NEXTAUTH'),
|
|
),
|
|
message: 'NextAuth has been removed from LobeChat. Please migrate to Better Auth.',
|
|
name: 'NextAuth',
|
|
},
|
|
{
|
|
docUrl: `${MIGRATION_DOC_BASE}/clerk-to-betterauth`,
|
|
getVars: () =>
|
|
['NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY', 'CLERK_SECRET_KEY', 'CLERK_WEBHOOK_SECRET'].filter(
|
|
(key) => process.env[key],
|
|
),
|
|
message: 'Clerk has been removed from LobeChat. Please migrate to Better Auth.',
|
|
name: 'Clerk',
|
|
},
|
|
{
|
|
formatVar: (envVar) => {
|
|
const mapping = {
|
|
ENABLE_MAGIC_LINK: 'AUTH_ENABLE_MAGIC_LINK',
|
|
NEXT_PUBLIC_AUTH_EMAIL_VERIFICATION: 'AUTH_EMAIL_VERIFICATION',
|
|
NEXT_PUBLIC_ENABLE_MAGIC_LINK: 'AUTH_ENABLE_MAGIC_LINK',
|
|
};
|
|
return `${envVar} → Please use ${mapping[envVar]} instead`;
|
|
},
|
|
getVars: () =>
|
|
[
|
|
'ENABLE_MAGIC_LINK',
|
|
'NEXT_PUBLIC_AUTH_EMAIL_VERIFICATION',
|
|
'NEXT_PUBLIC_ENABLE_MAGIC_LINK',
|
|
].filter((key) => process.env[key]),
|
|
message: 'Please update to the new environment variable names.',
|
|
name: 'Deprecated Auth',
|
|
},
|
|
{
|
|
getVars: () => (process.env['NEXT_PUBLIC_SERVICE_MODE'] ? ['NEXT_PUBLIC_SERVICE_MODE'] : []),
|
|
message:
|
|
'LobeChat 2.0 no longer supports client-side database mode. This environment variable is now obsolete and can be removed.',
|
|
name: 'Service Mode',
|
|
},
|
|
{
|
|
getVars: () => (process.env['ACCESS_CODE'] ? ['ACCESS_CODE'] : []),
|
|
message:
|
|
'ACCESS_CODE is no longer supported in LobeChat 2.0. Please use Better Auth authentication system instead.',
|
|
name: 'Access Code',
|
|
},
|
|
{
|
|
getVars: () =>
|
|
process.env['NEXT_PUBLIC_ENABLE_BETTER_AUTH'] ? ['NEXT_PUBLIC_ENABLE_BETTER_AUTH'] : [],
|
|
message:
|
|
'NEXT_PUBLIC_ENABLE_BETTER_AUTH is no longer needed. Better Auth is now automatically detected via AUTH_SECRET presence.',
|
|
name: 'Better Auth Flag',
|
|
},
|
|
{
|
|
getVars: () => ['NEXT_PUBLIC_AUTH_URL', 'AUTH_URL'].filter((key) => process.env[key]),
|
|
message:
|
|
'AUTH_URL is no longer needed. The authentication URL is now automatically detected from request headers.',
|
|
name: 'Auth URL',
|
|
},
|
|
{
|
|
docUrl: `${MIGRATION_DOC_BASE}/nextauth-to-betterauth`,
|
|
formatVar: (envVar) => {
|
|
const mapping = {
|
|
AUTH_AZURE_AD_ID: 'AUTH_MICROSOFT_ID',
|
|
AUTH_AZURE_AD_SECRET: 'AUTH_MICROSOFT_SECRET',
|
|
AUTH_AZURE_AD_TENANT_ID: 'No longer needed',
|
|
AZURE_AD_CLIENT_ID: 'AUTH_MICROSOFT_ID',
|
|
AZURE_AD_CLIENT_SECRET: 'AUTH_MICROSOFT_SECRET',
|
|
AZURE_AD_TENANT_ID: 'No longer needed',
|
|
};
|
|
return `${envVar} → ${mapping[envVar]}`;
|
|
},
|
|
getVars: () =>
|
|
[
|
|
'AZURE_AD_CLIENT_ID',
|
|
'AZURE_AD_CLIENT_SECRET',
|
|
'AZURE_AD_TENANT_ID',
|
|
'AUTH_AZURE_AD_ID',
|
|
'AUTH_AZURE_AD_SECRET',
|
|
'AUTH_AZURE_AD_TENANT_ID',
|
|
].filter((key) => process.env[key]),
|
|
message:
|
|
'Azure AD provider has been renamed to Microsoft. Please update your environment variables.',
|
|
name: 'Azure AD',
|
|
},
|
|
{
|
|
formatVar: (envVar) => {
|
|
const mapping = {
|
|
ZITADEL_CLIENT_ID: 'AUTH_ZITADEL_ID',
|
|
ZITADEL_CLIENT_SECRET: 'AUTH_ZITADEL_SECRET',
|
|
ZITADEL_ISSUER: 'AUTH_ZITADEL_ISSUER',
|
|
};
|
|
return `${envVar} → Please use ${mapping[envVar]} instead`;
|
|
},
|
|
getVars: () =>
|
|
['ZITADEL_CLIENT_ID', 'ZITADEL_CLIENT_SECRET', 'ZITADEL_ISSUER'].filter(
|
|
(key) => process.env[key],
|
|
),
|
|
message: 'ZITADEL environment variables have been renamed.',
|
|
name: 'ZITADEL',
|
|
},
|
|
{
|
|
formatVar: () => 'OIDC_JWKS_KEY → Please use JWKS_KEY instead',
|
|
getVars: () => (process.env['OIDC_JWKS_KEY'] ? ['OIDC_JWKS_KEY'] : []),
|
|
message: 'OIDC_JWKS_KEY has been renamed to JWKS_KEY.',
|
|
name: 'OIDC JWKS',
|
|
},
|
|
{
|
|
formatVar: () => 'APP_URL should not end with a trailing slash',
|
|
getVars: () => (process.env['APP_URL']?.endsWith('/') ? ['APP_URL'] : []),
|
|
message:
|
|
'APP_URL ends with a trailing slash which causes double slashes in redirect URLs (e.g., https://example.com//). Please remove the trailing slash.',
|
|
name: 'APP_URL Trailing Slash',
|
|
},
|
|
{
|
|
docUrl: `${MIGRATION_DOC_BASE}/nextauth-to-betterauth`,
|
|
formatVar: (envVar) => {
|
|
const mapping = {
|
|
AUTH_MICROSOFT_ENTRA_ID_BASE_URL: 'No longer needed',
|
|
AUTH_MICROSOFT_ENTRA_ID_ID: 'AUTH_MICROSOFT_ID',
|
|
AUTH_MICROSOFT_ENTRA_ID_SECRET: 'AUTH_MICROSOFT_SECRET',
|
|
AUTH_MICROSOFT_ENTRA_ID_TENANT_ID: 'No longer needed',
|
|
};
|
|
return `${envVar} → ${mapping[envVar]}`;
|
|
},
|
|
getVars: () =>
|
|
[
|
|
'AUTH_MICROSOFT_ENTRA_ID_ID',
|
|
'AUTH_MICROSOFT_ENTRA_ID_SECRET',
|
|
'AUTH_MICROSOFT_ENTRA_ID_TENANT_ID',
|
|
'AUTH_MICROSOFT_ENTRA_ID_BASE_URL',
|
|
].filter((key) => process.env[key]),
|
|
message:
|
|
'Microsoft Entra ID provider has been renamed to Microsoft. Please update your environment variables.',
|
|
name: 'Microsoft Entra ID',
|
|
},
|
|
];
|
|
|
|
/**
|
|
* Print a single deprecation error block
|
|
*/
|
|
function printErrorBlock(name, vars, message, docUrl, formatVar) {
|
|
console.error(`\n❌ ${name}`);
|
|
console.error('─'.repeat(50));
|
|
console.error('Detected deprecated environment variables:');
|
|
for (const envVar of vars) {
|
|
console.error(` • ${formatVar ? formatVar(envVar) : envVar}`);
|
|
}
|
|
console.error(`\n${message}`);
|
|
if (docUrl) {
|
|
console.error(`📖 Migration guide: ${docUrl}`);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Check for deprecated authentication environment variables and exit if found
|
|
* @param {object} options
|
|
* @param {string} [options.action='redeploy'] - Action hint in error message ('redeploy' or 'restart')
|
|
*/
|
|
function checkDeprecatedAuth(options = {}) {
|
|
const { action = 'redeploy' } = options;
|
|
|
|
const foundIssues = [];
|
|
for (const check of DEPRECATED_CHECKS) {
|
|
const foundVars = check.getVars();
|
|
if (foundVars.length > 0) {
|
|
foundIssues.push({ ...check, foundVars });
|
|
}
|
|
}
|
|
|
|
if (foundIssues.length > 0) {
|
|
console.error('\n' + '═'.repeat(70));
|
|
console.error(
|
|
`❌ ERROR: Found ${foundIssues.length} deprecated environment variable issue(s)!`,
|
|
);
|
|
console.error('═'.repeat(70));
|
|
|
|
for (const issue of foundIssues) {
|
|
printErrorBlock(issue.name, issue.foundVars, issue.message, issue.docUrl, issue.formatVar);
|
|
}
|
|
|
|
console.error('\n' + '═'.repeat(70));
|
|
console.error(`Please update your environment variables and ${action}.`);
|
|
console.error('═'.repeat(70) + '\n');
|
|
process.exit(1);
|
|
}
|
|
}
|
|
|
|
module.exports = { checkDeprecatedAuth };
|