Expose AdminJS on nudentic.ir: nginx only proxied /api, so /admin never reached Nest.
This commit is contained in:
@@ -29,6 +29,10 @@ FRONTEND_URL=http://localhost:3001
|
||||
# Set true when the app is served over HTTPS (required for Secure auth cookies)
|
||||
COOKIE_SECURE=false
|
||||
|
||||
# AdminJS panel at http://localhost:3000/admin (not under /api)
|
||||
# ADMINJS_EMAIL=admin@dyolink.com
|
||||
# ADMINJS_PASSWORD=admin123
|
||||
|
||||
# OAuth (optional — uncomment when configured)
|
||||
# GOOGLE_CLIENT_ID=your-google-client-id
|
||||
# GOOGLE_CLIENT_SECRET=your-google-client-secret
|
||||
|
||||
@@ -17,7 +17,10 @@ export class AdminModule {
|
||||
const { AdminModule: AdminJSModule } = await import('@adminjs/nestjs');
|
||||
|
||||
const authenticate = async (email: string, password: string) => {
|
||||
if (email === 'admin@dyolink.com' && password === 'admin123') {
|
||||
const adminEmail =
|
||||
process.env.ADMINJS_EMAIL?.trim() || 'admin@dyolink.com';
|
||||
const adminPassword = process.env.ADMINJS_PASSWORD || 'admin123';
|
||||
if (email === adminEmail && password === adminPassword) {
|
||||
return { email, role: 'admin' };
|
||||
}
|
||||
return null;
|
||||
@@ -30,6 +33,19 @@ export class AdminModule {
|
||||
imports: [ConfigModule],
|
||||
inject: [PrismaService, ConfigService],
|
||||
useFactory: (prisma: PrismaService, config: ConfigService) => {
|
||||
const cookieSecure = config.get<boolean>('cookie.secure') === true;
|
||||
const sessionSecret =
|
||||
config.get<string>('jwt.secret') ||
|
||||
config.get('JWT_SECRET') ||
|
||||
'secret-key-change-this';
|
||||
if (
|
||||
process.env.NODE_ENV === 'production' &&
|
||||
!process.env.ADMINJS_PASSWORD
|
||||
) {
|
||||
console.warn(
|
||||
'⚠️ ADMINJS_PASSWORD is unset; AdminJS is using the local default. Set it in backend.env.',
|
||||
);
|
||||
}
|
||||
return {
|
||||
adminJsOptions: {
|
||||
rootPath: '/admin',
|
||||
@@ -93,12 +109,17 @@ export class AdminModule {
|
||||
auth: {
|
||||
authenticate,
|
||||
cookieName: 'dyolink-admin',
|
||||
cookiePassword: config.get('JWT_SECRET') || 'secret-key-change-this',
|
||||
cookiePassword: sessionSecret,
|
||||
},
|
||||
sessionOptions: {
|
||||
resave: false,
|
||||
saveUninitialized: false,
|
||||
secret: config.get('JWT_SECRET') || 'secret-key-change-this',
|
||||
secret: sessionSecret,
|
||||
cookie: {
|
||||
httpOnly: true,
|
||||
sameSite: 'lax' as const,
|
||||
secure: cookieSecure,
|
||||
},
|
||||
},
|
||||
};
|
||||
},
|
||||
|
||||
@@ -30,6 +30,9 @@ async function bootstrap() {
|
||||
// Nest's built-in one would otherwise reject a voice recording at 100 kb.
|
||||
const app = await NestFactory.create(AppModule, { bodyParser: false });
|
||||
|
||||
// Nginx terminates TLS; AdminJS sessions and Secure cookies need the real proto/host.
|
||||
app.getHttpAdapter().getInstance().set('trust proxy', 1);
|
||||
|
||||
// Voice needs a larger JSON limit than everything else; see body-parsers.ts.
|
||||
app.use(createJsonBodyParser());
|
||||
app.use(urlencoded({ extended: true }));
|
||||
|
||||
Reference in New Issue
Block a user