UNPKG

3.87 kBJavaScriptView Raw
1// Copyright Michael Rhodes. 2017,2018. All Rights Reserved.
2// This file is licensed under the MIT License.
3// License text available at https://opensource.org/licenses/MIT
4
5var fixIfBehindProxy = require('../lib/utilities').fixIfBehindProxy;
6var debug = require('debug')('antisocial-friends');
7var VError = require('verror').VError;
8var WError = require('verror').WError;
9var async = require('async');
10var request = require('request');
11var _ = require('lodash');
12
13module.exports = function mountFriendRequestAccept(antisocialApp) {
14
15 var router = antisocialApp.router;
16 var config = antisocialApp.config;
17 var db = antisocialApp.db;
18 var authUserMiddleware = antisocialApp.authUserMiddleware;
19
20 var acceptRegex = /^\/([a-zA-Z0-9\-.]+)\/friend-request-accept$/;
21
22 debug('mounting GET /username/friend-request-accept', acceptRegex);
23
24 router.post(acceptRegex, authUserMiddleware, function handleFriendRequestAccept(req, res) {
25 var matches = req.path.match(acceptRegex);
26 var username = matches[1];
27
28 var endpoint = req.body.endpoint;
29
30 if (!endpoint) {
31 debug('endpoint not supplied');
32 return res.status(400).send('endpoint not supplied');
33 }
34
35 if (!endpoint.match(/(^|\s)((https?:\/\/)?[\w-]+(\.[\w-]+)+\.?(:\d+)?(\/\S*)?)/gi)) {
36 debug('endpoint not a valid url');
37 return res.status(400).send('endpoint not a valid url');
38 }
39
40 // must be a logged in user
41 var currentUser = req.antisocialUser;
42 if (!currentUser) {
43 debug('not logged in');
44 return res.sendStatus(401);
45 }
46
47 // by convention expects user to match username
48 if (currentUser.username !== username) {
49 debug('username mismatch');
50 return res.status(400).send('username mismatch');
51 }
52
53 async.waterfall([
54 function findFriend(cb) {
55 debug('/friend-request-accept findFriend');
56 db.getInstances('friends', [{
57 'property': 'userId',
58 'value': currentUser.id
59 }, {
60 'property': 'remoteEndPoint',
61 'value': req.body.endpoint
62 }, {
63 'property': 'status',
64 'value': 'pending'
65 }], function (err, friendInstances) {
66 if (err) {
67 return cb(new VError(err, 'error reading friends'));
68 }
69
70 if (friendInstances.length !== 1) {
71 return cb(new VError(err, 'friend request not found'));
72 }
73
74 cb(null, friendInstances[0]);
75 });
76 },
77 function callWebHook(friend, cb) {
78 debug('/friend-request-accept callWebhook');
79
80 var payload = {
81 'accessToken': friend.remoteAccessToken,
82 'action': 'friend-request-accepted'
83 };
84
85 var options = {
86 'url': fixIfBehindProxy(friend.remoteEndPoint + '/friend-webhook'),
87 'form': payload,
88 'json': true
89 };
90
91 request.post(options, function (err, response, body) {
92 if (err) {
93 return cb(new VError(err, '/friend-request-accept callWebhook failed'));
94 }
95 if (response.statusCode !== 200) {
96 return cb(new VError('/friend-request-accept callWebhook http error ' + response.statusCode));
97 }
98 if (_.get(body, 'status') !== 'ok') {
99 return cb(new VError('/friend-request-accept callWebhook unexpected result %j' + body));
100 }
101
102 cb(null, friend);
103 });
104 },
105 function updateFriend(friend, cb) {
106 friend.audiences.push('friends');
107 var update = {
108 'status': 'accepted',
109 'audiences': friend.audiences
110 };
111
112 db.updateInstance('friends', friend.id, update, function (err, friend) {
113 if (err) {
114 var e = new VError(err, '/friend-request-accept updateFriend error');
115 return cb(e, friend);
116 }
117
118 cb(null, friend);
119 });
120 }
121 ], function (err, friend) {
122 if (err) {
123 var e = new WError(err, '/friend-request-accept failed');
124 return res.send({
125 'status': 'error',
126 'reason': e.message,
127 'details': e.cause().message
128 });
129 }
130
131 antisocialApp.emit('new-friend', currentUser, friend);
132
133 res.send({
134 'status': 'ok'
135 });
136 });
137 });
138};