added hmac auth to report route
This commit is contained in:
parent
2f6119e2f1
commit
d9cbe058ab
19
app/api.js
19
app/api.js
|
@ -61,7 +61,10 @@ async function fetchWithAuth(url, params, keychain) {
|
||||||
const result = {};
|
const result = {};
|
||||||
params = params || {};
|
params = params || {};
|
||||||
const h = await keychain.authHeader();
|
const h = await keychain.authHeader();
|
||||||
params.headers = new Headers({ Authorization: h });
|
params.headers = new Headers({
|
||||||
|
Authorization: h,
|
||||||
|
'Content-Type': 'application/json'
|
||||||
|
});
|
||||||
const response = await fetch(url, params);
|
const response = await fetch(url, params);
|
||||||
result.response = response;
|
result.response = response;
|
||||||
result.ok = response.ok;
|
result.ok = response.ok;
|
||||||
|
@ -439,15 +442,19 @@ export async function getConstants() {
|
||||||
throw new Error(response.status);
|
throw new Error(response.status);
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function reportLink(id, key, reason) {
|
export async function reportLink(id, keychain, reason) {
|
||||||
const response = await fetch(
|
const result = await fetchWithAuthAndRetry(
|
||||||
getApiUrl(`/api/report/${id}`),
|
getApiUrl(`/api/report/${id}`),
|
||||||
post({ key, reason })
|
{
|
||||||
|
method: 'POST',
|
||||||
|
body: JSON.stringify({ reason })
|
||||||
|
},
|
||||||
|
keychain
|
||||||
);
|
);
|
||||||
|
|
||||||
if (response.ok) {
|
if (result.ok) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new Error(response.status);
|
throw new Error(result.response.status);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
import FileSender from './fileSender';
|
import FileSender from './fileSender';
|
||||||
import FileReceiver from './fileReceiver';
|
import FileReceiver from './fileReceiver';
|
||||||
import { reportLink } from './api';
|
|
||||||
import { copyToClipboard, delay, openLinksInNewTab, percent } from './utils';
|
import { copyToClipboard, delay, openLinksInNewTab, percent } from './utils';
|
||||||
import * as metrics from './metrics';
|
import * as metrics from './metrics';
|
||||||
import { bytes, locale } from './utils';
|
import { bytes, locale } from './utils';
|
||||||
|
@ -315,13 +314,7 @@ export default function(state, emitter) {
|
||||||
|
|
||||||
emitter.on('report', async ({ reason }) => {
|
emitter.on('report', async ({ reason }) => {
|
||||||
try {
|
try {
|
||||||
const file = state.fileInfo;
|
await state.transfer.reportLink(reason);
|
||||||
if (!file) {
|
|
||||||
// TODO
|
|
||||||
emitter.emit('pushState', '/error');
|
|
||||||
return render();
|
|
||||||
}
|
|
||||||
await reportLink(file.id, file.secretKey, reason);
|
|
||||||
render();
|
render();
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error(err);
|
console.error(err);
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import Nanobus from 'nanobus';
|
import Nanobus from 'nanobus';
|
||||||
import Keychain from './keychain';
|
import Keychain from './keychain';
|
||||||
import { delay, bytes, streamToArrayBuffer } from './utils';
|
import { delay, bytes, streamToArrayBuffer } from './utils';
|
||||||
import { downloadFile, metadata, getApiUrl } from './api';
|
import { downloadFile, metadata, getApiUrl, reportLink } from './api';
|
||||||
import { blobStream } from './streams';
|
import { blobStream } from './streams';
|
||||||
import Zip from './zip';
|
import Zip from './zip';
|
||||||
|
|
||||||
|
@ -53,6 +53,10 @@ export default class FileReceiver extends Nanobus {
|
||||||
this.state = 'ready';
|
this.state = 'ready';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async reportLink(reason) {
|
||||||
|
await reportLink(this.fileInfo.id, this.keychain, reason);
|
||||||
|
}
|
||||||
|
|
||||||
sendMessageToSw(msg) {
|
sendMessageToSw(msg) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
const channel = new MessageChannel();
|
const channel = new MessageChannel();
|
||||||
|
|
|
@ -9,7 +9,7 @@ import contentDisposition from 'content-disposition';
|
||||||
let noSave = false;
|
let noSave = false;
|
||||||
const map = new Map();
|
const map = new Map();
|
||||||
const IMAGES = /.*\.(png|svg|jpg)$/;
|
const IMAGES = /.*\.(png|svg|jpg)$/;
|
||||||
const VERSIONED_ASSET = /\.[A-Fa-f0-9]{8}\.(js|css|png|svg|jpg)$/;
|
const VERSIONED_ASSET = /\.[A-Fa-f0-9]{8}\.(js|css|png|svg|jpg)(#\w+)?$/;
|
||||||
const DOWNLOAD_URL = /\/api\/download\/([A-Fa-f0-9]{4,})/;
|
const DOWNLOAD_URL = /\/api\/download\/([A-Fa-f0-9]{4,})/;
|
||||||
const FONT = /\.woff2?$/;
|
const FONT = /\.woff2?$/;
|
||||||
|
|
||||||
|
|
|
@ -127,7 +127,7 @@ module.exports = function(app) {
|
||||||
require('./params')
|
require('./params')
|
||||||
);
|
);
|
||||||
app.post(`/api/info/:id${ID_REGEX}`, auth.owner, require('./info'));
|
app.post(`/api/info/:id${ID_REGEX}`, auth.owner, require('./info'));
|
||||||
app.post(`/api/report/:id${ID_REGEX}`, require('./report'));
|
app.post(`/api/report/:id${ID_REGEX}`, auth.hmac, require('./report'));
|
||||||
app.post('/api/metrics', require('./metrics'));
|
app.post('/api/metrics', require('./metrics'));
|
||||||
app.get('/__version__', function(req, res) {
|
app.get('/__version__', function(req, res) {
|
||||||
// eslint-disable-next-line node/no-missing-require
|
// eslint-disable-next-line node/no-missing-require
|
||||||
|
|
|
@ -1,38 +1,21 @@
|
||||||
const storage = require('../storage');
|
const storage = require('../storage');
|
||||||
const Keychain = require('../keychain');
|
|
||||||
const { statReportEvent } = require('../amplitude');
|
const { statReportEvent } = require('../amplitude');
|
||||||
|
|
||||||
module.exports = async function(req, res) {
|
module.exports = async function(req, res) {
|
||||||
try {
|
try {
|
||||||
const id = req.params.id;
|
const id = req.params.id;
|
||||||
const meta = await storage.metadata(id);
|
const meta = await storage.metadata(id);
|
||||||
if (meta.flagged) {
|
storage.flag(id);
|
||||||
return res.sendStatus(200);
|
statReportEvent({
|
||||||
}
|
id,
|
||||||
try {
|
ip: req.ip,
|
||||||
const key = req.body.key;
|
owner: meta.owner,
|
||||||
const keychain = new Keychain(key);
|
reason: req.body.reason,
|
||||||
const metadata = await keychain.decryptMetadata(
|
download_limit: meta.dlimit,
|
||||||
Buffer.from(meta.metadata, 'base64')
|
download_count: meta.dl,
|
||||||
);
|
agent: req.ua.browser.name || req.ua.ua.substring(0, 6)
|
||||||
if (metadata.manifest) {
|
});
|
||||||
storage.flag(id, key);
|
res.sendStatus(200);
|
||||||
statReportEvent({
|
|
||||||
id,
|
|
||||||
ip: req.ip,
|
|
||||||
owner: meta.owner,
|
|
||||||
reason: req.body.reason,
|
|
||||||
download_limit: meta.dlimit,
|
|
||||||
download_count: meta.dl,
|
|
||||||
agent: req.ua.browser.name || req.ua.ua.substring(0, 6)
|
|
||||||
});
|
|
||||||
return res.sendStatus(200);
|
|
||||||
}
|
|
||||||
res.sendStatus(400);
|
|
||||||
} catch (e) {
|
|
||||||
console.error(e);
|
|
||||||
res.sendStatus(400);
|
|
||||||
}
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
res.sendStatus(404);
|
res.sendStatus(404);
|
||||||
}
|
}
|
||||||
|
|
|
@ -80,14 +80,16 @@ class DB {
|
||||||
}
|
}
|
||||||
|
|
||||||
async kill(id) {
|
async kill(id) {
|
||||||
const { filePath } = await this.getPrefixedInfo(id);
|
const { filePath, dead } = await this.getPrefixedInfo(id);
|
||||||
this.storage.del(filePath);
|
if (!dead) {
|
||||||
this.redis.hset(id, 'dead', 1);
|
this.storage.del(filePath);
|
||||||
|
this.redis.hset(id, 'dead', 1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async flag(id, key) {
|
async flag(id) {
|
||||||
await this.kill(id);
|
await this.kill(id);
|
||||||
this.redis.hmset(id, { flagged: 1, key });
|
this.redis.hset(id, 'flagged', 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
async del(id) {
|
async del(id) {
|
||||||
|
|
Loading…
Reference in New Issue