Merge branch 'master' into on-redis-expire
This commit is contained in:
commit
af3848586c
113 changed files with 4178 additions and 1427 deletions
|
@ -19,6 +19,11 @@ const conf = convict({
|
|||
default: false,
|
||||
env: 'REDIS_EVENT_EXPIRE'
|
||||
},
|
||||
listen_address: {
|
||||
format: 'ipaddress',
|
||||
default: '0.0.0.0',
|
||||
env: 'IP_ADDRESS'
|
||||
},
|
||||
listen_port: {
|
||||
format: 'port',
|
||||
default: 1443,
|
||||
|
|
|
@ -24,4 +24,4 @@ app.use(
|
|||
|
||||
app.use(pages.notfound);
|
||||
|
||||
app.listen(config.listen_port);
|
||||
app.listen(config.listen_port, config.listen_address);
|
||||
|
|
|
@ -12,15 +12,15 @@ module.exports = async function(req, res) {
|
|||
return;
|
||||
}
|
||||
|
||||
const delete_token = req.body.delete_token;
|
||||
const ownerToken = req.body.owner_token || req.body.delete_token;
|
||||
|
||||
if (!delete_token) {
|
||||
if (!ownerToken) {
|
||||
res.sendStatus(404);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const err = await storage.delete(id, delete_token);
|
||||
const err = await storage.delete(id, ownerToken);
|
||||
if (!err) {
|
||||
res.sendStatus(200);
|
||||
}
|
||||
|
|
|
@ -19,12 +19,12 @@ module.exports = async function(req, res) {
|
|||
const hmac = crypto.createHmac('sha256', Buffer.from(meta.auth, 'base64'));
|
||||
hmac.update(Buffer.from(meta.nonce, 'base64'));
|
||||
const verifyHash = hmac.digest();
|
||||
const nonce = crypto.randomBytes(16).toString('base64');
|
||||
storage.setField(id, 'nonce', nonce);
|
||||
if (!verifyHash.equals(Buffer.from(auth, 'base64'))) {
|
||||
res.set('WWW-Authenticate', `send-v1 ${nonce}`);
|
||||
res.set('WWW-Authenticate', `send-v1 ${meta.nonce}`);
|
||||
return res.sendStatus(401);
|
||||
}
|
||||
const nonce = crypto.randomBytes(16).toString('base64');
|
||||
storage.setField(id, 'nonce', nonce);
|
||||
const contentLength = await storage.length(id);
|
||||
res.writeHead(200, {
|
||||
'Content-Disposition': 'attachment',
|
||||
|
@ -36,10 +36,16 @@ module.exports = async function(req, res) {
|
|||
const file_stream = storage.get(id);
|
||||
|
||||
file_stream.on('end', async () => {
|
||||
const dl = (+meta.dl || 0) + 1;
|
||||
const dlimit = +meta.dlimit || 1;
|
||||
try {
|
||||
await storage.forceDelete(id);
|
||||
if (dl >= dlimit) {
|
||||
await storage.forceDelete(id);
|
||||
} else {
|
||||
await storage.setField(id, 'dl', dl);
|
||||
}
|
||||
} catch (e) {
|
||||
log.info('DeleteError:', id);
|
||||
log.info('StorageError:', id);
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
@ -11,8 +11,11 @@ module.exports = async (req, res) => {
|
|||
}
|
||||
|
||||
try {
|
||||
await storage.exists(id);
|
||||
res.sendStatus(200);
|
||||
const meta = await storage.metadata(id);
|
||||
res.set('WWW-Authenticate', `send-v1 ${meta.nonce}`);
|
||||
res.send({
|
||||
password: meta.pwd !== '0'
|
||||
});
|
||||
} catch (e) {
|
||||
res.sendStatus(404);
|
||||
}
|
||||
|
|
|
@ -54,7 +54,11 @@ module.exports = function(app) {
|
|||
],
|
||||
imgSrc: ["'self'", 'https://www.google-analytics.com'],
|
||||
scriptSrc: ["'self'"],
|
||||
styleSrc: ["'self'", 'https://code.cdn.mozilla.net'],
|
||||
styleSrc: [
|
||||
"'self'",
|
||||
"'unsafe-inline'",
|
||||
'https://code.cdn.mozilla.net'
|
||||
],
|
||||
fontSrc: ["'self'", 'https://code.cdn.mozilla.net'],
|
||||
formAction: ["'none'"],
|
||||
frameAncestors: ["'none'"],
|
||||
|
@ -90,6 +94,8 @@ module.exports = function(app) {
|
|||
app.post('/api/upload', require('./upload'));
|
||||
app.post('/api/delete/:id', require('./delete'));
|
||||
app.post('/api/password/:id', require('./password'));
|
||||
app.post('/api/params/:id', require('./params'));
|
||||
app.post('/api/info/:id', require('./info'));
|
||||
|
||||
app.get('/__version__', function(req, res) {
|
||||
res.sendFile(require.resolve('../../dist/version.json'));
|
||||
|
|
31
server/routes/info.js
Normal file
31
server/routes/info.js
Normal file
|
@ -0,0 +1,31 @@
|
|||
const storage = require('../storage');
|
||||
|
||||
function validateID(route_id) {
|
||||
return route_id.match(/^[0-9a-fA-F]{10}$/) !== null;
|
||||
}
|
||||
|
||||
module.exports = async function(req, res) {
|
||||
const id = req.params.id;
|
||||
if (!validateID(id)) {
|
||||
return res.sendStatus(404);
|
||||
}
|
||||
const ownerToken = req.body.owner_token;
|
||||
if (!ownerToken) {
|
||||
return res.sendStatus(400);
|
||||
}
|
||||
|
||||
try {
|
||||
const meta = await storage.metadata(id);
|
||||
if (meta.owner !== ownerToken) {
|
||||
return res.sendStatus(400);
|
||||
}
|
||||
const ttl = await storage.ttl(id);
|
||||
return res.send({
|
||||
dlimit: meta.dlimit,
|
||||
dtotal: meta.dl,
|
||||
ttl
|
||||
});
|
||||
} catch (e) {
|
||||
res.sendStatus(404);
|
||||
}
|
||||
};
|
|
@ -17,16 +17,19 @@ module.exports = async function(req, res) {
|
|||
const hmac = crypto.createHmac('sha256', Buffer.from(meta.auth, 'base64'));
|
||||
hmac.update(Buffer.from(meta.nonce, 'base64'));
|
||||
const verifyHash = hmac.digest();
|
||||
if (!verifyHash.equals(Buffer.from(auth, 'base64'))) {
|
||||
res.set('WWW-Authenticate', `send-v1 ${meta.nonce}`);
|
||||
return res.sendStatus(401);
|
||||
}
|
||||
const nonce = crypto.randomBytes(16).toString('base64');
|
||||
storage.setField(id, 'nonce', nonce);
|
||||
res.set('WWW-Authenticate', `send-v1 ${nonce}`);
|
||||
if (!verifyHash.equals(Buffer.from(auth, 'base64'))) {
|
||||
return res.sendStatus(401);
|
||||
}
|
||||
|
||||
const size = await storage.length(id);
|
||||
const ttl = await storage.ttl(id);
|
||||
res.send({
|
||||
metadata: meta.metadata,
|
||||
finalDownload: +meta.dl + 1 === +meta.dlimit,
|
||||
size,
|
||||
ttl
|
||||
});
|
||||
|
|
|
@ -35,7 +35,7 @@ module.exports = {
|
|||
routes.toString(
|
||||
`/download/${req.params.id}`,
|
||||
Object.assign(state(req), {
|
||||
fileInfo: { nonce, pwd: +pwd }
|
||||
fileInfo: { nonce, requiresPassword: +pwd }
|
||||
})
|
||||
)
|
||||
)
|
||||
|
|
32
server/routes/params.js
Normal file
32
server/routes/params.js
Normal file
|
@ -0,0 +1,32 @@
|
|||
const storage = require('../storage');
|
||||
|
||||
function validateID(route_id) {
|
||||
return route_id.match(/^[0-9a-fA-F]{10}$/) !== null;
|
||||
}
|
||||
|
||||
module.exports = async function(req, res) {
|
||||
const id = req.params.id;
|
||||
if (!validateID(id)) {
|
||||
return res.sendStatus(404);
|
||||
}
|
||||
const ownerToken = req.body.owner_token;
|
||||
if (!ownerToken) {
|
||||
return res.sendStatus(400);
|
||||
}
|
||||
|
||||
const dlimit = req.body.dlimit;
|
||||
if (!dlimit || dlimit > 20) {
|
||||
return res.sendStatus(400);
|
||||
}
|
||||
|
||||
try {
|
||||
const meta = await storage.metadata(id);
|
||||
if (meta.owner !== ownerToken) {
|
||||
return res.sendStatus(400);
|
||||
}
|
||||
storage.setField(id, 'dlimit', dlimit);
|
||||
res.sendStatus(200);
|
||||
} catch (e) {
|
||||
res.sendStatus(404);
|
||||
}
|
||||
};
|
|
@ -1,5 +1,4 @@
|
|||
const storage = require('../storage');
|
||||
const crypto = require('crypto');
|
||||
|
||||
function validateID(route_id) {
|
||||
return route_id.match(/^[0-9a-fA-F]{10}$/) !== null;
|
||||
|
@ -10,26 +9,24 @@ module.exports = async function(req, res) {
|
|||
if (!validateID(id)) {
|
||||
return res.sendStatus(404);
|
||||
}
|
||||
if (!req.body.auth) {
|
||||
const ownerToken = req.body.owner_token;
|
||||
if (!ownerToken) {
|
||||
return res.sendStatus(404);
|
||||
}
|
||||
const auth = req.body.auth;
|
||||
if (!auth) {
|
||||
return res.sendStatus(400);
|
||||
}
|
||||
|
||||
try {
|
||||
const auth = req.header('Authorization').split(' ')[1];
|
||||
const meta = await storage.metadata(id);
|
||||
const hmac = crypto.createHmac('sha256', Buffer.from(meta.auth, 'base64'));
|
||||
hmac.update(Buffer.from(meta.nonce, 'base64'));
|
||||
const verifyHash = hmac.digest();
|
||||
const nonce = crypto.randomBytes(16).toString('base64');
|
||||
storage.setField(id, 'nonce', nonce);
|
||||
if (!verifyHash.equals(Buffer.from(auth, 'base64'))) {
|
||||
res.set('WWW-Authenticate', `send-v1 ${nonce}`);
|
||||
return res.sendStatus(401);
|
||||
if (meta.owner !== ownerToken) {
|
||||
return res.sendStatus(404);
|
||||
}
|
||||
storage.setField(id, 'auth', auth);
|
||||
storage.setField(id, 'pwd', 1);
|
||||
res.sendStatus(200);
|
||||
} catch (e) {
|
||||
res.sendStatus(404);
|
||||
return res.sendStatus(404);
|
||||
}
|
||||
storage.setField(id, 'auth', req.body.auth);
|
||||
storage.setField(id, 'pwd', 1);
|
||||
res.sendStatus(200);
|
||||
};
|
||||
|
|
|
@ -12,9 +12,12 @@ module.exports = function(req, res) {
|
|||
if (!metadata || !auth) {
|
||||
return res.sendStatus(400);
|
||||
}
|
||||
|
||||
const owner = crypto.randomBytes(10).toString('hex');
|
||||
const meta = {
|
||||
delete: crypto.randomBytes(10).toString('hex'),
|
||||
dlimit: 1,
|
||||
dl: 0,
|
||||
owner,
|
||||
delete: owner, // delete is deprecated
|
||||
metadata,
|
||||
pwd: 0,
|
||||
auth: auth.split(' ')[1],
|
||||
|
@ -30,7 +33,7 @@ module.exports = function(req, res) {
|
|||
res.set('WWW-Authenticate', `send-v1 ${meta.nonce}`);
|
||||
res.json({
|
||||
url,
|
||||
delete: meta.delete,
|
||||
owner: meta.owner,
|
||||
id: newId
|
||||
});
|
||||
} catch (e) {
|
||||
|
|
|
@ -148,7 +148,7 @@ function localSet(newId, file, meta) {
|
|||
redis_client.hmset(newId, meta);
|
||||
redis_client.expire(newId, config.expire_seconds);
|
||||
log.info('localSet:', 'Upload Finished of ' + newId);
|
||||
resolve(meta.delete);
|
||||
resolve(meta.owner);
|
||||
});
|
||||
|
||||
fstream.on('error', err => {
|
||||
|
@ -159,10 +159,10 @@ function localSet(newId, file, meta) {
|
|||
});
|
||||
}
|
||||
|
||||
function localDelete(id, delete_token) {
|
||||
function localDelete(id, ownerToken) {
|
||||
return new Promise((resolve, reject) => {
|
||||
redis_client.hget(id, 'delete', (err, reply) => {
|
||||
if (!reply || delete_token !== reply) {
|
||||
if (!reply || ownerToken !== reply) {
|
||||
reject();
|
||||
} else {
|
||||
redis_client.del(id);
|
||||
|
@ -244,10 +244,10 @@ function awsSet(newId, file, meta) {
|
|||
);
|
||||
}
|
||||
|
||||
function awsDelete(id, delete_token) {
|
||||
function awsDelete(id, ownerToken) {
|
||||
return new Promise((resolve, reject) => {
|
||||
redis_client.hget(id, 'delete', (err, reply) => {
|
||||
if (!reply || delete_token !== reply) {
|
||||
if (!reply || ownerToken !== reply) {
|
||||
reject();
|
||||
} else {
|
||||
const params = {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue