feat: store user-agent (extracted OBS version only) for each track when uploading
This commit is contained in:
parent
2da013583b
commit
3b1376b661
|
@ -254,4 +254,31 @@ function* parseObsver2(body) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = { parseTrackPoints, detectFormat, parseObsver1, parseObsver2, replaceDollarNewlinesHack };
|
/**
|
||||||
|
* This function normalizes a User-Agent header for storage in the database. It
|
||||||
|
* make sure that we only store the user-agent if it matches the pattern
|
||||||
|
* `OBS/*`, and extracts that part of the user agent, if it contains more
|
||||||
|
* information. This is the only part we are interested in, the
|
||||||
|
* remainder is too privacy sensitive to keep.
|
||||||
|
*/
|
||||||
|
function normalizeUserAgent(userAgent) {
|
||||||
|
if (!userAgent) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const match = userAgent.match(/\bOBS\/[^\s]+/);
|
||||||
|
if (match) {
|
||||||
|
return match[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
detectFormat,
|
||||||
|
normalizeUserAgent,
|
||||||
|
parseObsver1,
|
||||||
|
parseObsver2,
|
||||||
|
parseTrackPoints,
|
||||||
|
replaceDollarNewlinesHack,
|
||||||
|
};
|
||||||
|
|
|
@ -1,4 +1,11 @@
|
||||||
const { parseTrackPoints, parseObsver1, detectFormat, parseObsver2, replaceDollarNewlinesHack } = require('./tracks');
|
const {
|
||||||
|
detectFormat,
|
||||||
|
normalizeUserAgent,
|
||||||
|
parseObsver1,
|
||||||
|
parseObsver2,
|
||||||
|
parseTrackPoints,
|
||||||
|
replaceDollarNewlinesHack,
|
||||||
|
} = require('./tracks');
|
||||||
|
|
||||||
const { test1, test2, test3 } = require('./_tracks_testdata');
|
const { test1, test2, test3 } = require('./_tracks_testdata');
|
||||||
|
|
||||||
|
@ -92,3 +99,44 @@ describe('detectFormat', () => {
|
||||||
expect(detectFormat('')).toBe('invalid');
|
expect(detectFormat('')).toBe('invalid');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('normalizeUserAgent', () => {
|
||||||
|
it('is a function', () => {
|
||||||
|
expect(typeof normalizeUserAgent).toBe('function');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('ignores falsy values', () => {
|
||||||
|
expect(normalizeUserAgent(null)).toBe(null);
|
||||||
|
expect(normalizeUserAgent('')).toBe(null);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('ignores normal browser agents', () => {
|
||||||
|
const browserAgents = [
|
||||||
|
'Mozilla/5.0 (Linux; Android 6.0.1; Nexus 6P Build/MMB29P) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/47.0.2526.83 Mobile Safari/537.36',
|
||||||
|
'Mozilla/5.0 (Linux; Android 6.0; HTC One M9 Build/MRA58K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.98 Mobile Safari/537.3',
|
||||||
|
'Mozilla/5.0 (Linux; Android 8.0.0; SM-G960F Build/R16NW) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.84 Mobile Safari/537.36',
|
||||||
|
'Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A5370a Safari/604.1',
|
||||||
|
'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:15.0) Gecko/20100101 Firefox/15.0.1',
|
||||||
|
];
|
||||||
|
|
||||||
|
for (const browserAgent of browserAgents) {
|
||||||
|
expect(normalizeUserAgent(browserAgent)).toBe(null);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
it('detects OBS versions', () => {
|
||||||
|
const agents = ['OBS/123', 'OBS/2', 'OBS/1.2.3.4.5-rc123'];
|
||||||
|
|
||||||
|
for (const agent of agents) {
|
||||||
|
expect(normalizeUserAgent(agent)).toBe(agent);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
it('extracts OBS versions from extended formats', () => {
|
||||||
|
const agents = ['foo OBS/123', 'OBS/123 bar', 'foo OBS/123 bar'];
|
||||||
|
|
||||||
|
for (const agent of agents) {
|
||||||
|
expect(normalizeUserAgent(agent)).toBe('OBS/123');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
|
@ -9,6 +9,7 @@ const TrackSchema = new mongoose.Schema(
|
||||||
description: String,
|
description: String,
|
||||||
body: String,
|
body: String,
|
||||||
visible: Boolean,
|
visible: Boolean,
|
||||||
|
uploadedByUserAgent: String,
|
||||||
numEvents: { type: Number, default: 0 },
|
numEvents: { type: Number, default: 0 },
|
||||||
comments: [{ type: mongoose.Schema.Types.ObjectId, ref: 'Comment' }],
|
comments: [{ type: mongoose.Schema.Types.ObjectId, ref: 'Comment' }],
|
||||||
author: { type: mongoose.Schema.Types.ObjectId, ref: 'User' },
|
author: { type: mongoose.Schema.Types.ObjectId, ref: 'User' },
|
||||||
|
|
|
@ -7,7 +7,7 @@ const User = mongoose.model('User');
|
||||||
const busboy = require('connect-busboy');
|
const busboy = require('connect-busboy');
|
||||||
const auth = require('../auth');
|
const auth = require('../auth');
|
||||||
const currentTracks = new Map();
|
const currentTracks = new Map();
|
||||||
const { parseTrackPoints } = require('../../logic/tracks');
|
const { parseTrackPoints, normalizeUserAgent } = require('../../logic/tracks');
|
||||||
const wrapRoute = require('../../_helpers/wrapRoute');
|
const wrapRoute = require('../../_helpers/wrapRoute');
|
||||||
|
|
||||||
// Preload track objects on routes with ':track'
|
// Preload track objects on routes with ':track'
|
||||||
|
@ -216,6 +216,7 @@ router.post(
|
||||||
|
|
||||||
if (track.body) {
|
if (track.body) {
|
||||||
trackData.points = Array.from(parseTrackPoints(track.body));
|
trackData.points = Array.from(parseTrackPoints(track.body));
|
||||||
|
track.uploadedByUserAgent = normalizeUserAgent(req.headers['user-agent']);
|
||||||
}
|
}
|
||||||
|
|
||||||
track.visible = track.author.areTracksVisibleForAll;
|
track.visible = track.author.areTracksVisibleForAll;
|
||||||
|
@ -242,6 +243,7 @@ router.post(
|
||||||
const trackData = new TrackData();
|
const trackData = new TrackData();
|
||||||
track.trackData = trackData._id;
|
track.trackData = trackData._id;
|
||||||
track.author = user;
|
track.author = user;
|
||||||
|
track.uploadedByUserAgent = normalizeUserAgent(req.headers['user-agent']);
|
||||||
|
|
||||||
await track.save();
|
await track.save();
|
||||||
await trackData.save();
|
await trackData.save();
|
||||||
|
@ -372,6 +374,7 @@ router.put(
|
||||||
req.track.trackData = trackData._id;
|
req.track.trackData = trackData._id;
|
||||||
}
|
}
|
||||||
trackData.points = Array.from(parseTrackPoints(req.track.body));
|
trackData.points = Array.from(parseTrackPoints(req.track.body));
|
||||||
|
req.track.uploadedByUserAgent = normalizeUserAgent(req.headers['user-agent']);
|
||||||
await trackData.save();
|
await trackData.save();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,8 @@ const jwt = require('express-jwt');
|
||||||
const secret = require('../config').secret;
|
const secret = require('../config').secret;
|
||||||
|
|
||||||
function getTokenFromHeader(req) {
|
function getTokenFromHeader(req) {
|
||||||
const [tokenType, token] = req.headers.authorization?.split(' ') || [];
|
const authorization = req.headers.authorization;
|
||||||
|
const [tokenType, token] = (authorization && authorization.split(' ')) || [];
|
||||||
|
|
||||||
if (tokenType === 'Token' || tokenType === 'Bearer') {
|
if (tokenType === 'Token' || tokenType === 'Bearer') {
|
||||||
return token;
|
return token;
|
||||||
|
|
Loading…
Reference in a new issue