diff --git a/package-lock.json b/package-lock.json index eddbeed..26fe22a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -550,6 +550,15 @@ "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" }, + "cors": { + "version": "2.8.5", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", + "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", + "requires": { + "object-assign": "^4", + "vary": "^1" + } + }, "cross-spawn": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", diff --git a/package.json b/package.json index 0b433f0..234faa3 100644 --- a/package.json +++ b/package.json @@ -12,6 +12,7 @@ "license": "ISC", "dependencies": { "bcrypt": "^5.0.0", + "cors": "^2.8.5", "express": "^4.17.1", "express-basic-auth": "^1.2.0", "mysql": "^2.18.1" diff --git a/server/event.js b/server/event.js index ea6e544..170717e 100644 --- a/server/event.js +++ b/server/event.js @@ -6,13 +6,14 @@ const pool = require('./db.js'); const express = require('express'); const basicAuth = require('express-basic-auth'); const basicAuthConfig = require('./config.js') +const cors = require('cors'); class Event { static types = [ - 'view', - 'click', - 'error', - 'crash', + 'VIEW', + 'CLICK', + 'ERROR', + 'CRASH', ]; id = randomId(32); @@ -167,16 +168,18 @@ router.get('/', basicAuth(basicAuthConfig), (req, res) => { // events will be coming from all over the place, I don't think it makes // sense to try to put auth in front of this. Even some kind of client // "secret" would be trivial to deduce by examining the requests. -router.post('/', (req, res) => { +router.post('/', cors({origin: true, methods: ['POST']}), (req, res) => { + console.log(req.body); if (typeof req.body.appId === "undefined") { res.status(400).json({ message: 'Invalid appId' }); return; } - if (typeof req.body.sessionId === "undefined") { - res.status(400).json({ message: 'Invalid sessionId' }); - return; - } + // Without Cookies, websites can't consistently send the same sessionId + // if (typeof req.body.sessionId === "undefined") { + // res.status(400).json({ message: 'Invalid sessionId' }); + // return; + // } if (Event.types.indexOf(req.body.type) === -1) { res.status(400).json({ message: 'Invalid event type' }); @@ -192,7 +195,7 @@ router.post('/', (req, res) => { EventRepository.createEvent(new Event( req.body.appId, new Date(req.body.date), - req.body.userAgent, + req.headers['User-Agent'], req.body.platform, req.body.manufacturer, req.body.model, diff --git a/server/index.js b/server/index.js index fedd8e2..ed177a8 100644 --- a/server/index.js +++ b/server/index.js @@ -1,23 +1,21 @@ const express = require('express'); const eventRouter = require('./event.js').router; const port = require('./config.js').port; -const randomId = require('./util.js').randomId; const appRouter = require('./app.js').router; +const cors = require('cors'); const app = express(); app.use(express.json()); +app.use(cors()); // TODO: Enable this for event creation only -app.get('/', (req, res) => { - res.send('Hello, world!'); -}); +// app.get('/id', (req, res) => { +// const length = Number.parseInt(req.query['length']) || 32; +// res.send(require('./util.js').randomId(length)); +// }); -app.get('/id', (req, res) => { - const length = Number.parseInt(req.query['length']) || 32; - res.send(randomId(length)); -}); - -app.use('/api/apps', appRouter) -app.use('/api/events', eventRouter) +app.use(express.static('server/static')); +app.use('/api/apps', appRouter); +app.use('/api/events', eventRouter); app.listen(port, () => { console.log(`Started Flayre server on port ${port}`); diff --git a/server/static/flayre.js b/server/static/flayre.js new file mode 100644 index 0000000..bb49594 --- /dev/null +++ b/server/static/flayre.js @@ -0,0 +1,23 @@ +(function () { + if (window.navigator.doNotTrack === '1') { + console.log('Flayre respects DNT'); + return; + } + const flayreDomain = document.currentScript.src.split('/').slice(0, 3).join('/'); + const app = document.currentScript.dataset.app; + + fetch(`${flayreDomain}/api/events`, { + method: 'POST', + headers: { + 'Content-type': 'application/json', + }, + body: JSON.stringify({ + appId: app, + date: new Date().toISOString(), + platform: window.navigator.platform, + locale: window.navigator.language, + data: window.location.pathname, + type: 'VIEW' + }) + }); +})(); \ No newline at end of file