Browse Source

Add option for download testdata though different host

master
Menci 6 years ago
parent
commit
3d18c0c0ba
  1. 3
      config-example.json
  2. 6
      modules/api.js
  3. 28
      modules/api_v2.js
  4. 20
      modules/problem.js
  5. 6
      utility.js

3
config-example.json

@ -125,5 +125,6 @@
}, },
"no_cdn": false, "no_cdn": false,
"submissions_page_fast_pagination": false, "submissions_page_fast_pagination": false,
"username_regex": "^[a-zA-Z0-9\\-\\_]+$" "username_regex": "^[a-zA-Z0-9\\-\\_]+$",
"site_for_download": ""
} }

6
modules/api.js

@ -42,8 +42,7 @@ app.post('/api/forget', async (req, res) => {
expiresIn: '12h' expiresIn: '12h'
}); });
const currentProto = req.get("X-Forwarded-Proto") || req.protocol; const vurl = syzoj.utils.getCurrentLocation(req, true) + syzoj.utils.makeUrl(['api', 'forget_confirm'], { token: token });
const vurl = currentProto + '://' + req.get('host') + syzoj.utils.makeUrl(['api', 'forget_confirm'], { token: token });
try { try {
await Email.send(user.email, await Email.send(user.email,
`${user.username}${syzoj.config.title} 密码重置邮件`, `${user.username}${syzoj.config.title} 密码重置邮件`,
@ -93,8 +92,7 @@ app.post('/api/sign_up', async (req, res) => {
expiresIn: '2d' expiresIn: '2d'
}); });
const currentProto = req.get("X-Forwarded-Proto") || req.protocol; const vurl = syzoj.utils.getCurrentLocation(req, true) + syzoj.utils.makeUrl(['api', 'sign_up_confirm'], { token: token });
const vurl = currentProto + '://' + req.get('host') + syzoj.utils.makeUrl(['api', 'sign_up_confirm'], { token: token });
try { try {
await Email.send(req.body.email, await Email.send(req.body.email,
`${req.body.username}${syzoj.config.title} 注册验证邮件`, `${req.body.username}${syzoj.config.title} 注册验证邮件`,

28
modules/api_v2.js

@ -1,3 +1,5 @@
const jwt = require('jsonwebtoken');
app.get('/api/v2/search/users/:keyword*?', async (req, res) => { app.get('/api/v2/search/users/:keyword*?', async (req, res) => {
try { try {
let User = syzoj.model('user'); let User = syzoj.model('user');
@ -104,3 +106,29 @@ app.apiRouter.post('/api/v2/markdown', async (req, res) => {
res.send(e); res.send(e);
} }
}); });
function verifyJWT(token) {
try {
jwt.verify(token, syzoj.config.session_secret);
return true;
} catch (e) {
return false;
}
}
app.apiRouter.get('/api/v2/download/:token', async (req, res) => {
try {
const token = req.params.token, data = jwt.decode(token);
if (!data) throw new ErrorMessage("无效的令牌。");
if (verifyJWT(token)) {
res.download(data.filename, data.sendName);
} else {
res.redirect(data.originUrl);
}
} catch (e) {
syzoj.log(e);
res.render('error', {
err: e
});
}
})

20
modules/problem.js

@ -7,6 +7,7 @@ let Article = syzoj.model('article');
const randomstring = require('randomstring'); const randomstring = require('randomstring');
const fs = require('fs-extra'); const fs = require('fs-extra');
const jwt = require('jsonwebtoken');
let Judger = syzoj.lib('judger'); let Judger = syzoj.lib('judger');
let CodeFormatter = syzoj.lib('code_formatter'); let CodeFormatter = syzoj.lib('code_formatter');
@ -816,6 +817,20 @@ app.post('/problem/:id/testdata/delete/:filename', async (req, res) => {
} }
}); });
function downloadOrRedirect(req, res, filename, sendName) {
if (syzoj.config.site_for_download) {
res.redirect(syzoj.config.site_for_download + syzoj.utils.makeUrl(['api', 'v2', 'download', jwt.sign({
filename: filename,
sendName: sendName,
originUrl: syzoj.utils.getCurrentLocation(req)
}, syzoj.config.session_secret, {
expiresIn: '2m'
})]));
} else {
res.download(filename, sendName);
}
}
app.get('/problem/:id/testdata/download/:filename?', async (req, res) => { app.get('/problem/:id/testdata/download/:filename?', async (req, res) => {
try { try {
let id = parseInt(req.params.id); let id = parseInt(req.params.id);
@ -833,7 +848,8 @@ app.get('/problem/:id/testdata/download/:filename?', async (req, res) => {
let path = require('path'); let path = require('path');
let filename = req.params.filename ? path.join(problem.getTestdataPath(), req.params.filename) : (problem.getTestdataArchivePath()); let filename = req.params.filename ? path.join(problem.getTestdataPath(), req.params.filename) : (problem.getTestdataArchivePath());
if (!await syzoj.utils.isFile(filename)) throw new ErrorMessage('文件不存在。'); if (!await syzoj.utils.isFile(filename)) throw new ErrorMessage('文件不存在。');
res.download(filename, path.basename(filename));
downloadOrRedirect(req, res, filename, path.basename(filename));
} catch (e) { } catch (e) {
syzoj.log(e); syzoj.log(e);
res.status(404); res.status(404);
@ -866,7 +882,7 @@ app.get('/problem/:id/download/additional_file', async (req, res) => {
if (!problem.additional_file) throw new ErrorMessage('无附加文件。'); if (!problem.additional_file) throw new ErrorMessage('无附加文件。');
res.download(problem.additional_file.getPath(), `additional_file_${id}.zip`); downloadOrRedirect(req, res, problem.additional_file.getPath(), `additional_file_${id}.zip`);
} catch (e) { } catch (e) {
syzoj.log(e); syzoj.log(e);
res.status(404); res.status(404);

6
utility.js

@ -317,5 +317,11 @@ module.exports = {
} }
attempt(); attempt();
}); });
},
getCurrentLocation(req, hostOnly) {
const currentProto = req.get("X-Forwarded-Proto") || req.protocol,
host = currentProto + '://' + req.get('host');
if (hostOnly) return host;
else return host + req.originalUrl;
} }
}; };

Loading…
Cancel
Save