Merge branch 'hotfix/21.56.9' into master
[gitter.git] / modules / backend-muxer / lib / backend-muxer.js
blobb71f02fd80ed2c111f23c3589447d9766ef4dbd0
1 'use strict';
3 var Promise = require('bluebird');
4 var userScopes = require('gitter-web-identity/lib/user-scopes');
5 var identityService = require('gitter-web-identity');
7 var registeredBackends = {
8   google: require('gitter-web-google-backend'),
9   github: require('gitter-web-github-backend'),
10   gitlab: require('gitter-web-gitlab-backend'),
11   twitter: require('gitter-web-twitter-backend'),
12   linkedin: require('gitter-web-linkedin-backend')
13   // ...
16 function resolveBackendForProvider(provider) {
17   return registeredBackends[provider];
20 function resolveUserBackends(user) {
21   var userBackends = [];
23   return identityService
24     .listForUser(user)
25     .then(function(identities) {
26       return identities.reduce(function(map, identity) {
27         map[identity.provider] = identity;
28         return map;
29       }, {});
30     })
31     .then(function(identityMap) {
32       if (user && userScopes.isGitHubUser(user)) {
33         var Backend = resolveBackendForProvider('github');
34         userBackends.push(new Backend(user, identityMap.github));
35       }
37       if (user && user.identities) {
38         user.identities.forEach(function(identity) {
39           var Backend = resolveBackendForProvider(identity.provider);
40           userBackends.push(new Backend(user, identityMap[identity.provider]));
41         });
42       }
44       return userBackends;
45     });
48 function BackendMuxer(user) {
49   this.user = user;
52 // Use this when each Backend returns an object or value and you just want them
53 // all as one array.
54 BackendMuxer.prototype.findResults = function(method, args) {
55   args = args || [];
57   return resolveUserBackends(this.user).then(function(userBackends) {
58     return Promise.map(userBackends, function(backend) {
59       return backend[method].apply(backend, args);
60     });
61   });
64 // Use this when each backend returns an array and you want to concatenate them
65 // all into one array.
66 BackendMuxer.prototype.findAllResults = function(method, args) {
67   return this.findResults(method, args).then(function(arrays) {
68     return Array.prototype.concat.apply([], arrays);
69   });
72 function getFirstResultForBackends(method, args) {
73   return function(backends) {
74     if (!backends.length) return Promise.resolve();
76     var i = 0;
78     function tryNext() {
79       if (i >= backends.length) return Promise.resolve();
81       var nextBackend = backends[i];
82       return Promise.resolve(nextBackend[method].apply(nextBackend, args)).then(function(result) {
83         if (result) return result;
85         i++;
86         return tryNext();
87       });
88     }
90     return tryNext();
91   };
94 // Try the backends one by one and return the first one that returns a result's
95 // result.
96 BackendMuxer.prototype.getFirstResult = function(method, args) {
97   return resolveUserBackends(this.user).then(getFirstResultForBackends(method, args || []));
100 BackendMuxer.prototype.getEmailAddress = function(preferStoredEmail) {
101   return this.getFirstResult('getEmailAddress', [preferStoredEmail]);
104 BackendMuxer.prototype.findOrgs = function() {
105   return this.findAllResults('findOrgs');
108 BackendMuxer.prototype.findProfiles = function() {
109   return this.findResults('getProfile');
112 BackendMuxer.testOnly = {
113   getFirstResultForBackends: getFirstResultForBackends,
114   resolveUserBackends: resolveUserBackends
117 module.exports = BackendMuxer;