Added multiple download option
This commit is contained in:
parent
beb3a6e67b
commit
7b4060f9e1
22 changed files with 1159 additions and 453 deletions
|
@ -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);
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
@ -42,26 +42,32 @@ module.exports = function(app) {
|
|||
force: !IS_DEV
|
||||
})
|
||||
);
|
||||
app.use(
|
||||
helmet.contentSecurityPolicy({
|
||||
directives: {
|
||||
defaultSrc: ["'self'"],
|
||||
connectSrc: [
|
||||
"'self'",
|
||||
'https://sentry.prod.mozaws.net',
|
||||
'https://www.google-analytics.com'
|
||||
],
|
||||
imgSrc: ["'self'", 'https://www.google-analytics.com'],
|
||||
scriptSrc: ["'self'"],
|
||||
styleSrc: ["'self'", "'unsafe-inline'", 'https://code.cdn.mozilla.net'],
|
||||
fontSrc: ["'self'", 'https://code.cdn.mozilla.net'],
|
||||
formAction: ["'none'"],
|
||||
frameAncestors: ["'none'"],
|
||||
objectSrc: ["'none'"],
|
||||
reportUri: '/__cspreport__'
|
||||
}
|
||||
})
|
||||
);
|
||||
if (!IS_DEV) {
|
||||
app.use(
|
||||
helmet.contentSecurityPolicy({
|
||||
directives: {
|
||||
defaultSrc: ["'self'"],
|
||||
connectSrc: [
|
||||
"'self'",
|
||||
'https://sentry.prod.mozaws.net',
|
||||
'https://www.google-analytics.com'
|
||||
],
|
||||
imgSrc: ["'self'", 'https://www.google-analytics.com'],
|
||||
scriptSrc: ["'self'"],
|
||||
styleSrc: [
|
||||
"'self'",
|
||||
"'unsafe-inline'",
|
||||
'https://code.cdn.mozilla.net'
|
||||
],
|
||||
fontSrc: ["'self'", 'https://code.cdn.mozilla.net'],
|
||||
formAction: ["'none'"],
|
||||
frameAncestors: ["'none'"],
|
||||
objectSrc: ["'none'"],
|
||||
reportUri: '/__cspreport__'
|
||||
}
|
||||
})
|
||||
);
|
||||
}
|
||||
app.use(
|
||||
busboy({
|
||||
limits: {
|
||||
|
@ -88,6 +94,7 @@ 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.get('/__version__', function(req, res) {
|
||||
res.sendFile(require.resolve('../../dist/version.json'));
|
||||
|
|
|
@ -17,12 +17,14 @@ 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({
|
||||
|
|
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);
|
||||
}
|
||||
};
|
|
@ -20,12 +20,13 @@ 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);
|
||||
res.set('WWW-Authenticate', `send-v1 ${nonce}`);
|
||||
} catch (e) {
|
||||
res.sendStatus(404);
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -134,7 +134,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 => {
|
||||
|
@ -145,10 +145,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);
|
||||
|
@ -230,10 +230,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