UNPKG

7.2 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 express = require('express');
6var cookieParser = require('cookie-parser');
7var uuid = require('uuid');
8
9var app = express();
10
11app.use(express.json());
12app.use(express.urlencoded({
13 extended: false
14}));
15app.use(cookieParser());
16
17
18// mount the friend API under /antisocial
19var antisocial = require('./index');
20
21
22// Example database adaptor for persistant storage of users and friends
23// adapt these abstract methods to your application data storage scheme
24
25function dbHandler() {
26 var self = this;
27
28 self.collections = {
29 'users': {},
30 'friends': {},
31 'invitations': {},
32 'blocks': {}
33 };
34
35 // store an item after assigning an unique id
36 this.newInstance = function (collectionName, data, cb) {
37 data.id = uuid();
38 self.collections[collectionName][data.id] = data;
39 if (cb) {
40 cb(null, data);
41 }
42 else {
43 return data;
44 }
45 };
46
47 // get an item by matching some property
48 this.getInstances = function (collectionName, pairs, cb) {
49 var found = [];
50 for (var item in self.collections[collectionName]) {
51 if (self.collections[collectionName].hasOwnProperty(item)) {
52 var instance = self.collections[collectionName][item];
53
54 var match = 0;
55 for (var i = 0; i < pairs.length; i++) {
56 var prop = pairs[i].property;
57 var value = pairs[i].value;
58 if (instance[prop] === value) {
59 ++match;
60 }
61 }
62
63 if (match == pairs.length) {
64 found.push(instance);
65 }
66 }
67 }
68 if (cb) {
69 cb(null, found);
70 }
71 else {
72 return found;
73 }
74 };
75
76 // update item properties by id
77 this.updateInstance = function (collectionName, id, patch, cb) {
78 var item = self.collections[collectionName][id];
79 if (!item) {
80 if (cb) {
81 return cb('not found', null);
82 }
83 console.log('attempt to update a non existant instance %s.%s', collectionName, id);
84 return;
85 }
86 for (var prop in patch) {
87 if (patch.hasOwnProperty(prop)) {
88 item[prop] = patch[prop];
89 }
90 }
91 if (cb) {
92 cb(null, item);
93 }
94 else {
95 return item;
96 }
97 };
98
99 this.deleteInstance = function (collectionName, id, cb) {
100 var item = self.collections[collectionName][id];
101 if (!item) {
102 cb('not found', null);
103 }
104 delete self.collections[collectionName][id];
105 if (cb) {
106 cb(null);
107 }
108 };
109}
110
111var db = new dbHandler();
112
113
114/*
115 Example middleware adaptor to get the logged in user.
116 exposes the current user on req.antisocialUser
117 normally this would use a cookie via some sort of token
118 to find the user in this case we use the 'token' property
119 in the users collection
120*/
121
122function getAuthenticatedUser(req, res, next) {
123 var token;
124
125 if (req.cookies && req.cookies.access_token) {
126 token = req.cookies.access_token;
127 }
128
129 if (req.body && req.body.access_token) {
130 token = req.body.access_token;
131 }
132
133 if (!token) {
134 return next();
135 }
136
137 db.getInstances('users', [{
138 'property': 'token',
139 'value': token
140 }], function (err, userInstances) {
141 req.antisocialUser = userInstances[0];
142 next();
143 });
144}
145
146app.db = db;
147
148// user register route for tests
149var router = express.Router();
150router.all('/register', function (req, res) {
151 var params = req.method === 'GET' ? req.query : req.body;
152 app.db.newInstance('users', {
153 'name': params.name,
154 'username': params.username,
155 'token': uuid(),
156 'id': uuid(),
157 'community': params.community
158 }, function (err, user) {
159 res.cookie('access_token', user.token).send({
160 'status': 'ok',
161 'result': user
162 });
163 });
164});
165
166app.use(router);
167
168var server = null;
169
170app.start = function (port) {
171 var http = require('http');
172 server = http.createServer(app);
173 var listener = server.listen(port);
174
175
176 var config = {
177 'APIPrefix': '/antisocial',
178 'publicHost': 'http://127.0.0.1:3000',
179 'port': 3000
180 };
181
182 var antisocialApp = antisocial(app, config, db, getAuthenticatedUser);
183
184 app.postIdMap = {};
185 app.highwaterMap = {};
186
187 antisocialApp.on('new-friend-request', function (user, friend) {
188 console.log('antisocial new-friend-request %s %j', user.username, friend.remoteEndPoint);
189 });
190
191 antisocialApp.on('new-friend', function (user, friend) {
192 console.log('antisocial new-friend %s %j', user.username, friend.remoteEndPoint);
193
194 // simulate 10 'post' app items
195
196 if (!app.highwaterMap[friend.id]) {
197 app.highwaterMap[friend.id] = 0;
198 }
199 if (!app.postIdMap[user.id]) {
200 app.postIdMap[user.id] = 10;
201 }
202 });
203
204 antisocialApp.on('friend-updated', function (user, friend) {
205 console.log('antisocial friend-updated %s %s', user.username, friend.remoteEndPoint);
206 });
207
208 antisocialApp.on('friend-deleted', function (user, friend) {
209 console.log('antisocial friend-deleted %s %s', user.username, friend.remoteEndPoint);
210 });
211
212 antisocialApp.on('open-activity-connection', function (user, friend, emitter, info) {
213 console.log('antisocial open-activity-connection %s<-%s', user.username, friend.remoteEndPoint);
214 emitter('post', 'highwater', app.highwaterMap[friend.id] ? app.highwaterMap[friend.id] : 0);
215 });
216
217 antisocialApp.on('close-activity-connection', function (user, friend, reason, info) {
218 console.log('antisocial close-activity-connection %s<-%s %s', user.username, friend.remoteEndpoint, reason);
219 });
220
221 antisocialApp.on('open-notification-connection', function (user, emitter, info) {
222 console.log('antisocial open-notification-connection %s', user.username);
223 });
224
225 antisocialApp.on('close-notification-connection', function (user, reason, info) {
226 console.log('antisocial close-notification-connection %s %s', user.username, reason);
227 });
228
229 antisocialApp.on('activity-data-test', function (user, friend, data) {
230 console.log('antisocial activity-data-test user: %s friend: %s data: %j', user.name, friend.remoteEndPoint, data);
231 if (data.postId > app.highwaterMap[friend.id]) {
232 app.highwaterMap[friend.id] = data.postId;
233 }
234 });
235
236 antisocialApp.on('activity-backfill-test', function (user, friend, highwater, emitter) {
237 console.log('antisocial activity-backfill-test user: %s friend: %s highwater: %s', user.name, friend.remoteEndPoint, highwater);
238
239 // send posts from requested highwater to end of posts
240 for (var i = highwater + 1; i <= app.postIdMap[user.id]; i++) {
241 emitter('test', 'data', {
242 'backfill': true,
243 'postId': i,
244 'source': user.username
245 });
246 }
247 });
248
249 antisocialApp.on('notification-data-test', function (user, data) {
250 console.log('notification-data-test user: %s data: %j', user.name, data);
251 });
252
253 antisocialApp.on('notification-backfill-test', function (user, highwater, emitter) {
254 console.log('notification-backfill-test user: %s backfill: %s', user.username, highwater);
255 });
256
257 antisocialApp.listen(listener);
258};
259
260app.stop = function () {
261 server.close();
262};
263
264if (require.main === module) {
265 app.start(3000);
266}
267
268module.exports = app;