diff options
author | Eugen Rochko <eugen@zeonfederated.com> | 2017-11-18 00:16:48 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-11-18 00:16:48 +0100 |
commit | 24cafd73a2b644025e9aeaadf4fed46dd3ecea4d (patch) | |
tree | e0a0ad775612644d29193e81a9326f0e4c21d6af /streaming | |
parent | 4a2fc2d444a80050ad9ba5e83aa5e69d3148ab95 (diff) |
Lists (#5703)
* Add structure for lists * Add list timeline streaming API * Add list APIs, bind list-account relation to follow relation * Add API for adding/removing accounts from lists * Add pagination to lists API * Add pagination to list accounts API * Adjust scopes for new APIs - Creating and modifying lists merely requires "write" scope - Fetching information about lists merely requires "read" scope * Add test for wrong user context on list timeline * Clean up tests
Diffstat (limited to 'streaming')
-rw-r--r-- | streaming/index.js | 50 |
1 files changed, 49 insertions, 1 deletions
diff --git a/streaming/index.js b/streaming/index.js index 83903b89b..f0b8ce007 100644 --- a/streaming/index.js +++ b/streaming/index.js @@ -254,6 +254,26 @@ const startWorker = (workerId) => { const placeholders = (arr, shift = 0) => arr.map((_, i) => `$${i + 1 + shift}`).join(', '); + const authorizeListAccess = (id, req, next) => { + pgPool.connect((err, client, done) => { + if (err) { + next(false); + return; + } + + client.query('SELECT id, account_id FROM lists WHERE id = $1 LIMIT 1', [id], (err, result) => { + done(); + + if (err || result.rows.length === 0 || result.rows[0].account_id !== req.accountId) { + next(false); + return; + } + + next(true); + }); + }); + }; + const streamFrom = (id, req, output, attachCloseHandler, needsFiltering = false, notificationOnly = false) => { const streamType = notificationOnly ? ' (notification)' : ''; log.verbose(req.requestId, `Starting stream from ${id} for ${req.accountId}${streamType}`); @@ -410,7 +430,22 @@ const startWorker = (workerId) => { streamFrom(`timeline:hashtag:${req.query.tag.toLowerCase()}:local`, req, streamToHttp(req, res), streamHttpEnd(req), true); }); - const wss = new WebSocket.Server({ server, verifyClient: wsVerifyClient }); + app.get('/api/v1/streaming/list', (req, res) => { + const listId = req.query.list; + + authorizeListAccess(listId, req, authorized => { + if (!authorized) { + res.writeHead(404, { 'Content-Type': 'application/json' }); + res.end(JSON.stringify({ error: 'Not found' })); + return; + } + + const channel = `timeline:list:${listId}`; + streamFrom(channel, req, streamToHttp(req, res), streamHttpEnd(req, subscriptionHeartbeat(channel))); + }); + }); + + const wss = new WebSocket.Server({ server, verifyClient: wsVerifyClient }); wss.on('connection', ws => { const req = ws.upgradeReq; @@ -443,6 +478,19 @@ const startWorker = (workerId) => { case 'hashtag:local': streamFrom(`timeline:hashtag:${location.query.tag.toLowerCase()}:local`, req, streamToWs(req, ws), streamWsEnd(req, ws), true); break; + case 'list': + const listId = location.query.list; + + authorizeListAccess(listId, req, authorized => { + if (!authorized) { + ws.close(); + return; + } + + const channel = `timeline:list:${listId}`; + streamFrom(channel, req, streamToWs(req, ws), streamWsEnd(req, ws, subscriptionHeartbeat(channel))); + }); + break; default: ws.close(); } |