Gitter migration: Setup redirects (rollout pt. 3)
[gitter.git] / server / services / restful.js
blob719c39f3164225ef1cdc989373721cf24dd070d9
1 'use strict';
3 var env = require('gitter-web-env');
4 var logger = env.logger;
6 var Promise = require('bluebird');
7 var StatusError = require('statuserror');
8 var gitHubProfileService = require('gitter-web-github-backend/lib/github-profile-service');
9 var groupService = require('gitter-web-groups/lib/group-service');
10 var groupMembershipService = require('gitter-web-groups/lib/group-membership-service');
11 var restSerializer = require('../serializers/rest-serializer');
12 var unreadItemService = require('gitter-web-unread-items');
13 var chatService = require('gitter-web-chats');
14 var userService = require('gitter-web-users');
15 var userTypeahead = require('./typeaheads/user-typeahead');
16 var eventService = require('gitter-web-events');
17 var roomService = require('gitter-web-rooms');
18 var roomMembershipService = require('gitter-web-rooms/lib/room-membership-service');
19 var orgService = require('./org-service');
20 var repoService = require('./repo-service');
21 var userScopes = require('gitter-web-identity/lib/user-scopes');
23 var survivalMode = !!process.env.SURVIVAL_MODE || false;
25 if (survivalMode) {
26   logger.error('WARNING: Running in survival mode');
29 var DEFAULT_CHAT_COUNT_LIMIT = 30;
30 var DEFAULT_USERS_LIMIT = 30;
31 var MAX_USERS_LIMIT = 100;
33 function serializeTroupesForUser(userId, callback) {
34   if (!userId) return Promise.resolve([]);
36   return roomService
37     .findAllRoomsIdsForUserIncludingMentions(userId)
38     .spread(function(allTroupeIds, nonMemberTroupeIds) {
39       var strategy = new restSerializer.TroupeIdStrategy({
40         currentUserId: userId,
41         includePermissions: true,
42         // This will save the troupeId strategy
43         // from having to do a second query
44         nonMemberTroupeIds: nonMemberTroupeIds,
45         includeTags: true
46       });
48       return restSerializer.serialize(allTroupeIds, strategy);
49     })
50     .nodeify(callback);
53 async function serializeChatsForTroupe(
54   troupeId,
55   userId,
56   { limit = DEFAULT_CHAT_COUNT_LIMIT, lean, aroundId, lookups, beforeInclId, includeThreads }
57 ) {
58   const chatMessages = await chatService.findChatMessagesForTroupe(troupeId, {
59     limit,
60     aroundId,
61     beforeInclId,
62     includeThreads
63   });
64   const strategy = new restSerializer.ChatStrategy({
65     notLoggedIn: !userId,
66     initialId: aroundId,
67     currentUserId: userId,
68     troupeId,
69     lean,
70     lookups
71   });
72   return restSerializer.serialize(chatMessages, strategy);
75 function serializeUsersMatchingSearchTerm(roomId, searchTerm) {
76   if (survivalMode || searchTerm.length < 1) {
77     return Promise.resolve([]);
78   }
80   return userTypeahead.query(searchTerm, { roomId }).then(function(users) {
81     const strategy = new restSerializer.UserStrategy();
82     return restSerializer.serialize(users, strategy);
83   });
86 /**
87  *
88  * @param {*} options Options can be:
89  *      - `limit` - maximum amount of records retrieved
90  *      - `lean` - if true, the result is not full mongoose model, just plain object
91  *      - `skip` - how many first records should be omitted (used for pagination)
92  */
93 function serializeUsersForTroupe(troupeId, userId, { limit, lean, skip }) {
94   limit = isNaN(limit) ? DEFAULT_USERS_LIMIT : limit;
95   skip = isNaN(skip) ? 0 : skip;
96   if (limit > MAX_USERS_LIMIT) {
97     limit = MAX_USERS_LIMIT;
98   }
99   return roomMembershipService
100     .findMembersForRoom(troupeId, { limit, skip })
101     .then(function(userIds) {
102       var strategy = new restSerializer.UserIdStrategy({
103         showPresenceForTroupeId: troupeId,
104         includeRolesForTroupeId: troupeId,
105         currentUserId: userId,
106         lean: !!lean
107       });
109       return restSerializer.serialize(userIds, strategy);
110     });
113 function serializeUnreadItemsForTroupe(troupeId, userId, callback) {
114   return Promise.all([
115     roomMembershipService.getMemberLurkStatus(troupeId, userId),
116     unreadItemService.getUnreadItemsForUser(userId, troupeId)
117   ])
118     .spread(function(isLurking, items) {
119       if (isLurking) {
120         items._meta = { lurk: true };
121       }
122       return items;
123     })
124     .nodeify(callback);
127 function serializeReadBysForChat(troupeId, chatId, callback) {
128   // TODO: assert that troupeId=chat.troupeId....
129   return chatService
130     .findById(chatId)
131     .then(function(chatMessage) {
132       var strategy = new restSerializer.UserIdStrategy({});
134       return restSerializer.serialize(chatMessage.readBy, strategy);
135     })
136     .nodeify(callback);
139 function serializeEventsForTroupe(troupeId, userId, callback) {
140   return eventService
141     .findEventsForTroupe(troupeId, {})
142     .then(function(events) {
143       var strategy = new restSerializer.EventStrategy({
144         currentUserId: userId,
145         troupeId: troupeId
146       });
147       return restSerializer.serialize(events, strategy);
148     })
149     .nodeify(callback);
152 async function serializeOrgsForUser(user) {
153   const orgs = await orgService.getOrgsForUser(user);
155   const strategyMap = {
156     gitlab: new restSerializer.GitlabGroupStrategy(),
157     github: new restSerializer.GithubOrgStrategy({
158       currentUserId: user && user._id
159     })
160   };
162   const serializeOrgPromises = orgs.map(org => {
163     const strategy = strategyMap[org.backend];
165     return restSerializer.serializeObject(org, strategy);
166   });
168   const serializedOrgs = await Promise.all(serializeOrgPromises);
169   return serializedOrgs;
172 function serializeOrgsForUserId(userId, options) {
173   return userService.findById(userId).then(function(user) {
174     if (!user) return [];
176     return serializeOrgsForUser(user, options);
177   });
180 async function _serializeReposForUser(user, repos) {
181   const strategyMap = {
182     gitlab: new restSerializer.GitlabProjectStrategy(),
183     github: new restSerializer.GithubRepoStrategy({
184       currentUserId: user && user._id
185     })
186   };
188   const serializeRepoPromises = repos.map(repo => {
189     const strategy = strategyMap[repo.backend];
191     return restSerializer.serializeObject(repo, strategy);
192   });
194   const serializedRepos = await Promise.all(serializeRepoPromises);
195   return serializedRepos;
198 async function serializeReposForUser(user) {
199   const repos = await repoService.getReposForUser(user);
200   return _serializeReposForUser(user, repos);
203 async function serializeAdminReposForUser(user) {
204   const repos = await repoService.getAdminReposForUser(user);
205   return _serializeReposForUser(user, repos);
208 function serializeProfileForUsername(username) {
209   return userService.findByUsername(username).then(function(user) {
210     if (user) {
211       var strategy = new restSerializer.UserProfileStrategy();
212       return restSerializer.serializeObject(user, strategy);
213     } else {
214       var gitHubUser = { username: username };
216       if (!userScopes.isGitHubUser(gitHubUser)) {
217         throw new StatusError(404);
218       }
220       return gitHubProfileService(gitHubUser, { includeCore: true });
221     }
222   });
225 function serializeGroupsForUserId(userId, options) {
226   if (!userId) return [];
228   return groupMembershipService.findGroupsForUser(userId).then(function(groups) {
229     if (!groups || !groups.length) return [];
231     var strategy = new restSerializer.GroupStrategy({
232       currentUserId: userId,
233       lean: options && options.lean
234     });
236     return restSerializer.serialize(groups, strategy);
237   });
240 function serializeAdminGroupsForUser(user, options) {
241   if (!user) return [];
243   return groupMembershipService.findAdminGroupsForUser(user).then(function(groups) {
244     if (!groups || !groups.length) return [];
246     var strategy = new restSerializer.GroupStrategy({
247       currentUserId: user._id,
248       currentUser: user,
249       lean: options && options.lean
250     });
252     return restSerializer.serialize(groups, strategy);
253   });
256 function serializeRoomsForGroupId(groupId, userId) {
257   return groupService.findRoomsIdForGroup(groupId, userId).then(function(allTroupeIds) {
258     var strategy = new restSerializer.TroupeIdStrategy({
259       currentUserId: userId
260     });
262     return restSerializer.serialize(allTroupeIds, strategy);
263   });
266 module.exports = {
267   serializeTroupesForUser: serializeTroupesForUser,
268   serializeChatsForTroupe: serializeChatsForTroupe,
269   serializeUsersForTroupe: serializeUsersForTroupe,
270   serializeUsersMatchingSearchTerm: serializeUsersMatchingSearchTerm,
271   serializeUnreadItemsForTroupe: serializeUnreadItemsForTroupe,
272   serializeReadBysForChat: serializeReadBysForChat,
273   serializeEventsForTroupe: serializeEventsForTroupe,
274   serializeOrgsForUser: serializeOrgsForUser,
275   serializeOrgsForUserId: serializeOrgsForUserId,
276   serializeReposForUser: serializeReposForUser,
277   serializeAdminReposForUser: serializeAdminReposForUser,
278   serializeProfileForUsername: serializeProfileForUsername,
279   serializeGroupsForUserId: Promise.method(serializeGroupsForUserId),
280   serializeAdminGroupsForUser: Promise.method(serializeAdminGroupsForUser),
281   serializeRoomsForGroupId: serializeRoomsForGroupId