-
-
Notifications
You must be signed in to change notification settings - Fork 6
/
Copy pathserver.js
158 lines (135 loc) · 4.2 KB
/
server.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
require('dotenv').config();
const express = require('express');
const cookieParser = require('cookie-parser');
const session = require('express-session');
const crypto = require('crypto');
const https = require('https');
// Hide debug messages in production
if (process.env.NODE_ENV === 'production') console.debug = () => {};
// Import routes
const AdminRoutes = require('./routes/adminRoutes');
const AuthRoutes = require('./routes/authRoutes');
const apiAdminRoutes = require('./routes/apiAdminRoutes');
const apiVoucherRoutes = require('./routes/apiVoucherRoutes');
const apiWLANRoutes = require('./routes/apiWLANRoutes');
const guestRoutes = require('./routes/guestRoutes');
// Import controllers
const Backgrounds = require('./controllers/background');
const Redis = require('./controllers/redis');
const UniFi = require('./controllers/unifi');
// Initialize app and set port
const app = express();
const port = process.env.PORT || 3000;
// Set EJS as the view engine
app.set('views', __dirname + '/views');
app.set('view engine', 'ejs');
// Middleware setup
app.use(express.json());
app.use(cookieParser(crypto.randomUUID()));
// Allow for reverse proxy
app.set('trust proxy', 1);
app.use(session({
secret: crypto.randomUUID(),
resave: false,
saveUninitialized: false,
cookie: {
sameSite: true,
secure: process.env.ORIGIN.toString().startsWith('https'),
},
}));
// Initialize background images
const backgrounds = new Backgrounds(
process.env.IMG_PATH, process.env.HEMISPHERE,
);
const bg = backgrounds.listImages();
app.use((req, res, next) => {
req.bg = bg;
next();
});
// Initialize Redis client
const redis = new Redis();
app.use((req, res, next) => {
req.redis = redis;
next();
});
// Initialize UniFi controller
const unifi = new UniFi(
process.env.UNIFI_HOST,
process.env.UNIFI_PORT || 443,
process.env.UNIFI_TLS === 'true',
process.env.UNIFI_SITE || 'default',
);
unifi.login(process.env.UNIFI_USERNAME, process.env.UNIFI_PASSWORD).
then(() => {
const uri = `http${process.env.UNIFI_TLS ? 's':''
}://${process.env.UNIFI_HOST}:${process.env.UNIFI_PORT}`;
console.log(`UniFi controller: ${uri}`);
console.log(`Accepting requests for SSID "${process.env.UNIFI_SSID}"`);
console.log(`Using UniFi site "${process.env.UNIFI_SITE}"`);
}).
catch(() => {
throw new Error('Unable to login to UniFi controller');
});
// Attach UniFi controller to specific routes
app.post('/api/:type(voucher|wlan)/*', (req, res, next) => {
req.unifi = unifi;
next();
});
app.get('/admin', (req, res, next) => {
req.unifi = unifi;
next();
});
// Register routes
app.use(AdminRoutes);
app.use(AuthRoutes);
app.use(apiAdminRoutes);
app.use(apiVoucherRoutes);
app.use(apiWLANRoutes);
app.use(guestRoutes);
// Root route redirect
app.get('/', (req, res) => res.redirect(`guest/s/${process.env.UNIFI_SITE}`));
// Serve Bing image of the day if no local backgrounds are found
app.get('/img/bg.jpg', async (req, res) => {
const bg = new Backgrounds();
const imageUrl = await bg.getBingImage();
https.get(imageUrl, (response) => {
res.setHeader('Content-Type', 'image/jpeg');
response.pipe(res);
});
});
app.get('/healthcheck', (req,res)=> {
res.sendStatus(204)
})
// Serve static files
app.use(express.static('./node_modules/bootstrap-icons/font/'));
app.use(express.static('./node_modules/@fontsource/'));
app.use(express.static('public'));
// Start the server
app.listen(port, () => {
console.log(`Express server listening on *:${port}`);
console.log(`Admin panel accessible on ${process.env.ORIGIN}/admin`);
});
// Handle uncaught exceptions
process.on('uncaughtException', async (err) => {
process.env.NODE_ENV === 'production' ?
console.error('Error:', err.message):
console.error(err.stack);
await cleanup();
process.exit(1); // Exit the process to avoid an unstable state
});
// Handle termination signals
process.on('SIGINT', cleanup);
process.on('SIGTERM', cleanup);
// Cleanup function to close connections
async function cleanup() {
try {
await redis.close();
console.debug('Redis connection closed');
await unifi.logout();
console.debug('UniFi connection closed');
process.exit(0);
} catch (e) {
console.error(e);
process.exit(1);
}
}