mirror of
https://github.com/rgrgogu/new_starr.git
synced 2026-09-27 00:12:54 +08:00
ready to test
Testing Signed-off-by: Kenneth Obsequio <k80308392@gmail.com>
This commit is contained in:
@@ -7,7 +7,9 @@
|
||||
* Syncs Sequelize models to the database on startup.
|
||||
*
|
||||
* Author: rgrgogu
|
||||
* Modified by: Kenneth Obsequio (@lash0000)
|
||||
* Date Created: Oct. 6, 2025
|
||||
* Date Modified: Jun. 17, 2026
|
||||
***********************************************************************************************************************************************************************
|
||||
* HOW TO RUN:
|
||||
* 1. cp .env.example .env (fill in your values)
|
||||
@@ -21,23 +23,31 @@ const express = require('express');
|
||||
const cors = require('cors');
|
||||
const cookieParser = require('cookie-parser');
|
||||
const session = require('express-session');
|
||||
const passport = require('./config/passport.config');
|
||||
const sequelize = require('./config/db.config');
|
||||
|
||||
// ── Middleware ──────────────────────────────────────────────────────────────────
|
||||
const { globalLimiter } = require('./middleware/rateLimiter.middleware');
|
||||
const { csrfErrorHandler } = require('./middleware/csrf.middleware');
|
||||
const originGuard = require('./middleware/originGuard.middleware');
|
||||
|
||||
// ── Routes ─────────────────────────────────────────────────────────────────────
|
||||
const authRoutes = require('./routes/auth.routes');
|
||||
const clientRoutes = require('./routes/client/client.routes');
|
||||
const staffRoutes = require('./routes/staff/staff.routes');
|
||||
const adminRoutes = require('./routes/admin/admin.routes');
|
||||
const healthRoutes = require('./routes/health.routes');
|
||||
const authRoutes = require('./routes/auth.routes');
|
||||
const publicRoutes = require('./routes/public/public.routes');
|
||||
const clientRoutes = require('./routes/client/client.routes');
|
||||
const staffRoutes = require('./routes/staff/staff.routes');
|
||||
const adminRoutes = require('./routes/admin/admin.routes');
|
||||
|
||||
// ── Models (ensure associations are loaded) ────────────────────────────────────
|
||||
require('./models/users/users.mdl');
|
||||
require('./models/users/user_sessions.mdl');
|
||||
require('./models/users/user_groups.mdl');
|
||||
require('./models/notifications/admin_notification.mdl');
|
||||
require('./models/notifications/user_notification.mdl');
|
||||
|
||||
// ── Cron jobs ──────────────────────────────────────────────────────────────────
|
||||
const { startAdminCronJobs } = require('./cron/admin.cron');
|
||||
const { startClientCronJobs } = require('./cron/client.cron');
|
||||
|
||||
const app = express();
|
||||
const PORT = process.env.PORT || 3000;
|
||||
@@ -51,8 +61,8 @@ const allowedOrigins = (process.env.ALLOWED_ORIGINS || process.env.APP_URL || '*
|
||||
|
||||
app.use(cors({
|
||||
origin: (origin, callback) => {
|
||||
if (!origin || allowedOrigins.includes(origin)) return callback(null, true);
|
||||
callback(new Error(`CORS: origin ${origin} not allowed`));
|
||||
if (origin && allowedOrigins.includes(origin)) return callback(null, true);
|
||||
callback(null, false);
|
||||
},
|
||||
credentials: true,
|
||||
preflightContinue: false, // cors() handles OPTIONS and stops — don't pass to next()
|
||||
@@ -68,39 +78,49 @@ app.use(cors({
|
||||
'CSRF-Token',
|
||||
'X-CSRF-Token',
|
||||
],
|
||||
exposedHeaders: ['Content-Disposition'],
|
||||
optionsSuccessStatus: 204,
|
||||
maxAge: 86400,
|
||||
}));
|
||||
|
||||
app.use(express.json());
|
||||
app.use(express.urlencoded({ extended: true }));
|
||||
app.use(cookieParser());
|
||||
// Secret enables req.signedCookies, used by the OIDC state cookie (_oauth).
|
||||
app.use(cookieParser(process.env.SESSION_SECRET));
|
||||
|
||||
// Session — used only by csurf; JWT handles auth state.
|
||||
// CACHE_DRIVER=redis → persist sessions in PostgreSQL (survives restarts).
|
||||
// CACHE_DRIVER=memory → in-process MemoryStore (fine for local dev).
|
||||
const sessionStore = process.env.CACHE_DRIVER !== 'memory'
|
||||
? new (require('connect-pg-simple')(session))({
|
||||
conString: `postgresql://${process.env.DB_USER}:${process.env.DB_PASSWORD}@${process.env.DB_HOST}:${process.env.DB_PORT}/${process.env.DB_NAME}?sslmode=${process.env.DB_SSL === 'false' ? 'disable' : 'require'}`,
|
||||
tableName: 'express_sessions',
|
||||
createTableIfMissing: true,
|
||||
})
|
||||
: undefined; // undefined → express-session uses MemoryStore
|
||||
|
||||
// Session — used only by csurf; JWT handles auth state
|
||||
app.use(session({
|
||||
...(sessionStore && { store: sessionStore }),
|
||||
secret: process.env.SESSION_SECRET || 'change-me',
|
||||
resave: false,
|
||||
saveUninitialized: false,
|
||||
cookie: { secure: process.env.NODE_ENV === 'production', httpOnly: true, sameSite: 'strict' },
|
||||
}));
|
||||
|
||||
app.use(passport.initialize());
|
||||
|
||||
// Global rate limiter (1000 req / 15 min)
|
||||
app.use(globalLimiter);
|
||||
|
||||
// ──────────────────────────────────────────────────────────────────────────────
|
||||
// Routes
|
||||
// ──────────────────────────────────────────────────────────────────────────────
|
||||
app.use('/api/auth', authRoutes);
|
||||
app.use('/api/client', clientRoutes);
|
||||
app.use('/api/staff', staffRoutes);
|
||||
app.use('/api/admin', adminRoutes);
|
||||
// Health — no originGuard: monitoring tools (Uptime Robot, Pingdom, k8s probes) have no Origin
|
||||
app.use('/api/health', healthRoutes);
|
||||
|
||||
// Health check
|
||||
app.get('/api/health', (req, res) => {
|
||||
res.json({ status: 'ok', timestamp: new Date().toISOString(), env: process.env.NODE_ENV });
|
||||
});
|
||||
app.use('/api/auth', originGuard, authRoutes);
|
||||
app.use('/api/public', originGuard, publicRoutes);
|
||||
app.use('/api/client', originGuard, clientRoutes);
|
||||
app.use('/api/staff', originGuard, staffRoutes);
|
||||
app.use('/api/admin', originGuard, adminRoutes);
|
||||
|
||||
// 404 handler
|
||||
app.use((req, res) => {
|
||||
@@ -119,14 +139,51 @@ app.use((err, req, res, next) => {
|
||||
// ──────────────────────────────────────────────────────────────────────────────
|
||||
// Database Sync + Listen
|
||||
// ──────────────────────────────────────────────────────────────────────────────
|
||||
function printCronTable(jobs) {
|
||||
if (!jobs.length) {
|
||||
console.log('\n[ CRON ] No jobs scheduled.\n');
|
||||
return;
|
||||
}
|
||||
|
||||
const H = { name: 'Name', scope: 'Scope', schedule: 'Schedule' };
|
||||
const w = {
|
||||
name: Math.max(H.name.length, ...jobs.map(j => j.name.length)),
|
||||
scope: Math.max(H.scope.length, ...jobs.map(j => j.scope.length)),
|
||||
schedule: Math.max(H.schedule.length, ...jobs.map(j => j.schedule.length)),
|
||||
};
|
||||
|
||||
const cell = (v, width) => ` ${v.padEnd(width)} `;
|
||||
const row = (n, s, c) => `│${cell(n, w.name)}│${cell(s, w.scope)}│${cell(c, w.schedule)}│`;
|
||||
const line = (l, m, r) => l + '─'.repeat(w.name + 2) + m + '─'.repeat(w.scope + 2) + m + '─'.repeat(w.schedule + 2) + r;
|
||||
|
||||
console.log(line('┌', '┬', '┐'));
|
||||
console.log(row(H.name, H.scope, H.schedule));
|
||||
console.log(line('├', '┼', '┤'));
|
||||
jobs.forEach(j => console.log(row(j.name, j.scope, j.schedule)));
|
||||
console.log(line('└', '┴', '┘'));
|
||||
}
|
||||
|
||||
(async () => {
|
||||
try {
|
||||
await sequelize.authenticate();
|
||||
console.log('✅ Database connected.');
|
||||
|
||||
const cronJobs = [
|
||||
...startAdminCronJobs(),
|
||||
...startClientCronJobs(),
|
||||
];
|
||||
|
||||
app.listen(PORT, () => {
|
||||
console.log(`🚀 STARR Server running on http://localhost:${PORT}`);
|
||||
console.log(` Environment : ${process.env.NODE_ENV}`);
|
||||
console.log(`⚙️ Environment : ${process.env.NODE_ENV}`);
|
||||
console.log('ℹ️ For help, for more information:');
|
||||
console.log(' Please see this .MD files');
|
||||
console.log(' 📄 README.md — project setup and overview');
|
||||
console.log(' 📄 ROUTES.md — all available API routes');
|
||||
console.log(' 📊 For actual table documentation please see /admin/documentation directory.');
|
||||
console.log(' 🩺 For actual server situation please go to /api/health and /api/health/ready.');
|
||||
console.log('');
|
||||
printCronTable(cronJobs);
|
||||
});
|
||||
} catch (err) {
|
||||
console.error('❌ Failed to start server:', err);
|
||||
|
||||
Reference in New Issue
Block a user