i0110 commited on
Commit
198475b
·
verified ·
1 Parent(s): ab5afa3

Update server.js

Browse files
Files changed (1) hide show
  1. server.js +83 -4
server.js CHANGED
@@ -1,9 +1,14 @@
1
  const express = require('express');
2
  const path = require('path');
3
  const axios = require('axios');
 
4
  const app = express();
5
  const port = process.env.PORT || 8080;
6
 
 
 
 
 
7
  // 从环境变量获取 HuggingFace 用户名和对应的 API Token 映射
8
  const userTokenMapping = {};
9
  const usernames = [];
@@ -26,6 +31,10 @@ if (hfUserConfig) {
26
  const ADMIN_USERNAME = process.env.USER_NAME || 'admin';
27
  const ADMIN_PASSWORD = process.env.USER_PASSWORD || 'password';
28
 
 
 
 
 
29
  // 缓存管理
30
  class SpaceCache {
31
  constructor() {
@@ -58,6 +67,65 @@ app.get('/api/config', (req, res) => {
58
  res.json({ usernames: usernames.join(',') });
59
  });
60
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
61
  // 获取所有 spaces 列表(包括私有)
62
  app.get('/api/proxy/spaces', async (req, res) => {
63
  try {
@@ -121,8 +189,8 @@ app.get('/api/proxy/spaces', async (req, res) => {
121
  }
122
  });
123
 
124
- // 代理重启 Space
125
- app.post('/api/proxy/restart/:repoId(*)', async (req, res) => {
126
  try {
127
  const { repoId } = req.params;
128
  console.log(`尝试重启 Space: ${repoId}`);
@@ -148,8 +216,8 @@ app.post('/api/proxy/restart/:repoId(*)', async (req, res) => {
148
  }
149
  });
150
 
151
- // 代理重建 Space
152
- app.post('/api/proxy/rebuild/:repoId(*)', async (req, res) => {
153
  try {
154
  const { repoId } = req.params;
155
  console.log(`尝试重建 Space: ${repoId}`);
@@ -336,6 +404,17 @@ app.get('*', (req, res) => {
336
  res.sendFile(path.join(__dirname, 'public', 'index.html'));
337
  });
338
 
 
 
 
 
 
 
 
 
 
 
 
339
  app.listen(port, () => {
340
  console.log(`Server running on port ${port}`);
341
  console.log(`User configurations:`, usernames.map(user => `${user}: ${userTokenMapping[user] ? 'Token Configured' : 'No Token'}`).join(', ') || 'None');
 
1
  const express = require('express');
2
  const path = require('path');
3
  const axios = require('axios');
4
+ const crypto = require('crypto');
5
  const app = express();
6
  const port = process.env.PORT || 8080;
7
 
8
+ // 启用 JSON 和 URL-encoded 请求解析
9
+ app.use(express.json());
10
+ app.use(express.urlencoded({ extended: true }));
11
+
12
  // 从环境变量获取 HuggingFace 用户名和对应的 API Token 映射
13
  const userTokenMapping = {};
14
  const usernames = [];
 
31
  const ADMIN_USERNAME = process.env.USER_NAME || 'admin';
32
  const ADMIN_PASSWORD = process.env.USER_PASSWORD || 'password';
33
 
34
+ // 存储会话 token 的简单内存数据库(生产环境中应使用数据库或 Redis)
35
+ const sessions = new Map();
36
+ const SESSION_TIMEOUT = 24 * 60 * 60 * 1000; // 24小时超时
37
+
38
  // 缓存管理
39
  class SpaceCache {
40
  constructor() {
 
67
  res.json({ usernames: usernames.join(',') });
68
  });
69
 
70
+ // 登录 API 接口
71
+ app.post('/api/login', (req, res) => {
72
+ const { username, password } = req.body;
73
+ if (username === ADMIN_USERNAME && password === ADMIN_PASSWORD) {
74
+ // 生成一个随机 token 作为会话标识
75
+ const token = crypto.randomBytes(16).toString('hex');
76
+ const expiresAt = Date.now() + SESSION_TIMEOUT;
77
+ sessions.set(token, { username, expiresAt });
78
+ console.log(`用户 ${username} 登录成功,生成 token: ${token.slice(0, 8)}...`);
79
+ res.json({ success: true, token });
80
+ } else {
81
+ console.log(`用户 ${username} 登录失败,凭据无效`);
82
+ res.status(401).json({ success: false, message: '用户名或密码错误' });
83
+ }
84
+ });
85
+
86
+ // 验证登录状态 API 接口
87
+ app.post('/api/verify-token', (req, res) => {
88
+ const { token } = req.body;
89
+ const session = sessions.get(token);
90
+ if (session && session.expiresAt > Date.now()) {
91
+ res.json({ success: true, message: 'Token 有效' });
92
+ } else {
93
+ if (session) {
94
+ sessions.delete(token); // 删除过期的 token
95
+ console.log(`Token ${token.slice(0, 8)}... 已过期,已删除`);
96
+ }
97
+ res.status(401).json({ success: false, message: 'Token 无效或已过期' });
98
+ }
99
+ });
100
+
101
+ // 登出 API 接口
102
+ app.post('/api/logout', (req, res) => {
103
+ const { token } = req.body;
104
+ sessions.delete(token);
105
+ console.log(`Token ${token.slice(0, 8)}... 已手动登出`);
106
+ res.json({ success: true, message: '登出成功' });
107
+ });
108
+
109
+ // 中间件:验证请求中的 token
110
+ const authenticateToken = (req, res, next) => {
111
+ const authHeader = req.headers['authorization'];
112
+ if (!authHeader || !authHeader.startsWith('Bearer ')) {
113
+ return res.status(401).json({ error: '未提供有效的认证令牌' });
114
+ }
115
+ const token = authHeader.split(' ')[1];
116
+ const session = sessions.get(token);
117
+ if (session && session.expiresAt > Date.now()) {
118
+ req.session = session;
119
+ next();
120
+ } else {
121
+ if (session) {
122
+ sessions.delete(token); // 删除过期的 token
123
+ console.log(`Token ${token.slice(0, 8)}... 已过期,拒绝访问`);
124
+ }
125
+ return res.status(401).json({ error: '认证令牌无效或已过期' });
126
+ }
127
+ };
128
+
129
  // 获取所有 spaces 列表(包括私有)
130
  app.get('/api/proxy/spaces', async (req, res) => {
131
  try {
 
189
  }
190
  });
191
 
192
+ // 代理重启 Space(需要认证)
193
+ app.post('/api/proxy/restart/:repoId(*)', authenticateToken, async (req, res) => {
194
  try {
195
  const { repoId } = req.params;
196
  console.log(`尝试重启 Space: ${repoId}`);
 
216
  }
217
  });
218
 
219
+ // 代理重建 Space(需要认证)
220
+ app.post('/api/proxy/rebuild/:repoId(*)', authenticateToken, async (req, res) => {
221
  try {
222
  const { repoId } = req.params;
223
  console.log(`尝试重建 Space: ${repoId}`);
 
404
  res.sendFile(path.join(__dirname, 'public', 'index.html'));
405
  });
406
 
407
+ // 定期清理过期的会话
408
+ setInterval(() => {
409
+ const now = Date.now();
410
+ for (const [token, session] of sessions.entries()) {
411
+ if (session.expiresAt < now) {
412
+ sessions.delete(token);
413
+ console.log(`Token ${token.slice(0, 8)}... 已过期,自动清理`);
414
+ }
415
+ }
416
+ }, 60 * 60 * 1000); // 每小时清理一次
417
+
418
  app.listen(port, () => {
419
  console.log(`Server running on port ${port}`);
420
  console.log(`User configurations:`, usernames.map(user => `${user}: ${userTokenMapping[user] ? 'Token Configured' : 'No Token'}`).join(', ') || 'None');