nodebb-plugin-sso-facebook 4.1.3 → 4.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/eslint.config.mjs +10 -0
- package/library.js +278 -279
- package/package.json +9 -2
- package/plugin.json +5 -1
- package/static/lib/admin.js +7 -9
package/library.js
CHANGED
|
@@ -1,318 +1,317 @@
|
|
|
1
|
-
(function (module) {
|
|
2
|
-
'use strict';
|
|
3
|
-
/* globals module, require */
|
|
4
|
-
|
|
5
|
-
var user = require.main.require('./src/user'),
|
|
6
|
-
meta = require.main.require('./src/meta'),
|
|
7
|
-
db = require.main.require('./src/database'),
|
|
8
|
-
passport = require.main.require('passport'),
|
|
9
|
-
passportFacebook = require('passport-facebook').Strategy,
|
|
10
|
-
nconf = require.main.require('nconf'),
|
|
11
|
-
async = require.main.require('async'),
|
|
12
|
-
winston = require.main.require('winston');
|
|
13
|
-
|
|
14
|
-
var authenticationController = require.main.require('./src/controllers/authentication');
|
|
15
|
-
|
|
16
|
-
var constants = Object.freeze({
|
|
17
|
-
'name': 'Facebook',
|
|
18
|
-
'admin': {
|
|
19
|
-
'route': '/plugins/sso-facebook',
|
|
20
|
-
'icon': 'fa-facebook-square'
|
|
21
|
-
}
|
|
22
|
-
});
|
|
23
1
|
|
|
24
|
-
|
|
25
|
-
settings: undefined
|
|
26
|
-
};
|
|
2
|
+
'use strict';
|
|
27
3
|
|
|
28
|
-
|
|
29
|
-
|
|
4
|
+
const passport = require.main.require('passport');
|
|
5
|
+
const passportFacebook = require('passport-facebook').Strategy;
|
|
6
|
+
const nconf = require.main.require('nconf');
|
|
7
|
+
const winston = require.main.require('winston');
|
|
30
8
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
baseUrl: nconf.get('url'),
|
|
35
|
-
});
|
|
36
|
-
});
|
|
9
|
+
const user = require.main.require('./src/user');
|
|
10
|
+
const meta = require.main.require('./src/meta');
|
|
11
|
+
const db = require.main.require('./src/database');
|
|
37
12
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
uid: req.user.uid,
|
|
46
|
-
});
|
|
47
|
-
res.redirect(nconf.get('relative_path') + '/me/edit');
|
|
48
|
-
}));
|
|
13
|
+
const constants = Object.freeze({
|
|
14
|
+
'name': 'Facebook',
|
|
15
|
+
'admin': {
|
|
16
|
+
'route': '/plugins/sso-facebook',
|
|
17
|
+
'icon': 'fa-facebook-square',
|
|
18
|
+
},
|
|
19
|
+
});
|
|
49
20
|
|
|
50
|
-
|
|
51
|
-
|
|
21
|
+
const Facebook = {
|
|
22
|
+
settings: undefined,
|
|
23
|
+
};
|
|
52
24
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
return callback();
|
|
56
|
-
}
|
|
25
|
+
Facebook.init = async function (params) {
|
|
26
|
+
const hostHelpers = require.main.require('./src/routes/helpers');
|
|
57
27
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
28
|
+
hostHelpers.setupAdminPageRoute(params.router, '/admin/plugins/sso-facebook', function (req, res) {
|
|
29
|
+
res.render('admin/plugins/sso-facebook', {
|
|
30
|
+
title: constants.name,
|
|
31
|
+
baseUrl: nconf.get('url'),
|
|
61
32
|
});
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
hostHelpers.setupPageRoute(params.router, '/deauth/facebook', [params.middleware.requireUser], function (req, res) {
|
|
36
|
+
res.render('plugins/sso-facebook/deauth', {
|
|
37
|
+
service: constants.name,
|
|
38
|
+
});
|
|
39
|
+
});
|
|
40
|
+
params.router.post('/deauth/facebook', [params.middleware.requireUser, params.middleware.applyCSRF], hostHelpers.tryRoute(async function (req, res) {
|
|
41
|
+
await Facebook.deleteUserData({
|
|
42
|
+
uid: req.user.uid,
|
|
43
|
+
});
|
|
44
|
+
res.redirect(nconf.get('relative_path') + '/me/edit');
|
|
45
|
+
}));
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
Facebook.getSettings = async function () {
|
|
49
|
+
if (Facebook.settings) {
|
|
50
|
+
return;
|
|
62
51
|
}
|
|
63
52
|
|
|
64
|
-
Facebook.
|
|
65
|
-
|
|
66
|
-
return Facebook.getSettings(function () {
|
|
67
|
-
Facebook.getStrategy(strategies, callback);
|
|
68
|
-
});
|
|
69
|
-
}
|
|
53
|
+
Facebook.settings = await meta.settings.get('sso-facebook');
|
|
54
|
+
};
|
|
70
55
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
56
|
+
Facebook.getStrategy = async function (strategies) {
|
|
57
|
+
if (!Facebook.settings) {
|
|
58
|
+
await Facebook.getSettings();
|
|
59
|
+
return await Facebook.getStrategy(strategies);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
if (
|
|
63
|
+
Facebook.settings !== undefined &&
|
|
64
|
+
Facebook.settings.hasOwnProperty('app_id') && Facebook.settings.app_id &&
|
|
65
|
+
Facebook.settings.hasOwnProperty('secret') && Facebook.settings.secret
|
|
66
|
+
) {
|
|
67
|
+
passport.use(new passportFacebook({
|
|
68
|
+
clientID: Facebook.settings.app_id,
|
|
69
|
+
clientSecret: Facebook.settings.secret,
|
|
70
|
+
callbackURL: nconf.get('url') + '/auth/facebook/callback',
|
|
71
|
+
passReqToCallback: true,
|
|
72
|
+
profileFields: ['id', 'emails', 'name', 'displayName'],
|
|
73
|
+
enableProof: true,
|
|
74
|
+
}, async function (req, accessToken, refreshToken, profile, done) {
|
|
75
|
+
try {
|
|
84
76
|
if (req.hasOwnProperty('user') && req.user.hasOwnProperty('uid') && req.user.uid > 0) {
|
|
85
77
|
// User is already logged-in, associate fb account with uid if account does not have an existing association
|
|
86
|
-
user.getUserField(req.user.uid, 'fbid'
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
done(null, req.user);
|
|
95
|
-
} else {
|
|
96
|
-
done(new Error('[[error:sso-multiple-association]]'));
|
|
97
|
-
}
|
|
98
|
-
});
|
|
78
|
+
const fbid = await user.getUserField(req.user.uid, 'fbid');
|
|
79
|
+
if (!fbid || profile.id === fbid) {
|
|
80
|
+
await user.setUserField(req.user.uid, 'fbid', profile.id);
|
|
81
|
+
await db.setObjectField('fbid:uid', profile.id, req.user.uid);
|
|
82
|
+
done(null, req.user);
|
|
83
|
+
} else {
|
|
84
|
+
done(new Error('[[error:sso-multiple-association]]'));
|
|
85
|
+
}
|
|
99
86
|
} else {
|
|
100
|
-
|
|
87
|
+
let email;
|
|
101
88
|
if (profile._json.hasOwnProperty('email')) {
|
|
102
89
|
email = profile._json.email;
|
|
103
90
|
} else {
|
|
104
91
|
email = (profile.username ? profile.username : profile.id) + '@facebook.com';
|
|
105
92
|
}
|
|
106
93
|
|
|
107
|
-
Facebook.login(profile.id, profile.displayName, email, 'https://graph.facebook.com/' + profile.id + '/picture?type=large', accessToken, refreshToken
|
|
108
|
-
if (err) {
|
|
109
|
-
return done(err);
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
// Require collection of email
|
|
113
|
-
if (email.endsWith('@facebook.com')) {
|
|
114
|
-
req.session.registration = req.session.registration || {};
|
|
115
|
-
req.session.registration.uid = user.uid;
|
|
116
|
-
req.session.registration.fbid = profile.id;
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
authenticationController.onSuccessfulLogin(req, user.uid, function (err) {
|
|
120
|
-
done(err, !err ? user : null);
|
|
121
|
-
});
|
|
122
|
-
});
|
|
123
|
-
}
|
|
124
|
-
}));
|
|
125
|
-
|
|
126
|
-
strategies.push({
|
|
127
|
-
name: 'facebook',
|
|
128
|
-
url: '/auth/facebook',
|
|
129
|
-
callbackURL: '/auth/facebook/callback',
|
|
130
|
-
icon: constants.admin.icon,
|
|
131
|
-
icons: {
|
|
132
|
-
normal: 'fa-brands fa-facebook',
|
|
133
|
-
square: 'fa-brands fa-facebook-square',
|
|
134
|
-
},
|
|
135
|
-
labels: {
|
|
136
|
-
login: '[[social:log-in-with-facebook]]',
|
|
137
|
-
register: '[[social:continue-with-facebook]]',
|
|
138
|
-
},
|
|
139
|
-
color: '#5165b2',
|
|
140
|
-
scope: 'public_profile, email'
|
|
141
|
-
});
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
callback(null, strategies);
|
|
145
|
-
};
|
|
94
|
+
const { queued, uid, message } = await Facebook.login(req, profile.id, profile.displayName, email, 'https://graph.facebook.com/' + profile.id + '/picture?type=large', accessToken, refreshToken);
|
|
146
95
|
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
};
|
|
151
|
-
|
|
152
|
-
Facebook.getAssociation = function (data, callback) {
|
|
153
|
-
user.getUserField(data.uid, 'fbid', function (err, fbId) {
|
|
154
|
-
if (err) {
|
|
155
|
-
return callback(err, data);
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
if (fbId) {
|
|
159
|
-
data.associations.push({
|
|
160
|
-
associated: true,
|
|
161
|
-
url: 'https://facebook.com/' + fbId,
|
|
162
|
-
deauthUrl: nconf.get('url') + '/deauth/facebook',
|
|
163
|
-
name: constants.name,
|
|
164
|
-
icon: constants.admin.icon
|
|
165
|
-
});
|
|
166
|
-
} else {
|
|
167
|
-
data.associations.push({
|
|
168
|
-
associated: false,
|
|
169
|
-
url: nconf.get('url') + '/auth/facebook',
|
|
170
|
-
name: constants.name,
|
|
171
|
-
icon: constants.admin.icon
|
|
172
|
-
});
|
|
173
|
-
}
|
|
96
|
+
if (queued) {
|
|
97
|
+
return done(null, false, { message });
|
|
98
|
+
}
|
|
174
99
|
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
100
|
+
// Require collection of email
|
|
101
|
+
if (email.endsWith('@facebook.com')) {
|
|
102
|
+
req.session.registration = req.session.registration || {};
|
|
103
|
+
req.session.registration.uid = user.uid;
|
|
104
|
+
req.session.registration.fbid = profile.id;
|
|
105
|
+
}
|
|
178
106
|
|
|
179
|
-
|
|
180
|
-
// Only execute if:
|
|
181
|
-
// - uid and fbid are set in session
|
|
182
|
-
// - email ends with "@facebook.com"
|
|
183
|
-
if (data.userData.hasOwnProperty('uid') && data.userData.hasOwnProperty('fbid')) {
|
|
184
|
-
user.getUserField(data.userData.uid, 'email', function (err, email) {
|
|
185
|
-
if (email && email.endsWith('@facebook.com')) {
|
|
186
|
-
data.interstitials.push({
|
|
187
|
-
template: 'partials/sso-facebook/email.tpl',
|
|
188
|
-
data: {},
|
|
189
|
-
callback: Facebook.storeAdditionalData
|
|
190
|
-
});
|
|
107
|
+
done(null, { uid });
|
|
191
108
|
}
|
|
109
|
+
} catch (err) {
|
|
110
|
+
done(err);
|
|
111
|
+
}
|
|
112
|
+
}));
|
|
192
113
|
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
callback
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
async.waterfall([
|
|
202
|
-
// Reset email confirm throttle
|
|
203
|
-
async.apply(db.delete, 'uid:' + userData.uid + ':confirm:email:sent'),
|
|
204
|
-
function (next) {
|
|
205
|
-
user.getUserField(userData.uid, 'email', next);
|
|
114
|
+
strategies.push({
|
|
115
|
+
name: 'facebook',
|
|
116
|
+
url: '/auth/facebook',
|
|
117
|
+
callbackURL: '/auth/facebook/callback',
|
|
118
|
+
icon: constants.admin.icon,
|
|
119
|
+
icons: {
|
|
120
|
+
normal: 'fa-brands fa-facebook',
|
|
121
|
+
square: 'fa-brands fa-facebook-square',
|
|
206
122
|
},
|
|
207
|
-
|
|
208
|
-
|
|
123
|
+
labels: {
|
|
124
|
+
login: '[[social:log-in-with-facebook]]',
|
|
125
|
+
register: '[[social:continue-with-facebook]]',
|
|
209
126
|
},
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
127
|
+
color: '#5165b2',
|
|
128
|
+
scope: 'public_profile, email',
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
return strategies;
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
Facebook.appendUserHashWhitelist = function (data) {
|
|
135
|
+
data.whitelist.push('fbid');
|
|
136
|
+
return data;
|
|
137
|
+
};
|
|
138
|
+
|
|
139
|
+
Facebook.getAssociation = async function (data) {
|
|
140
|
+
const fbId = await user.getUserField(data.uid, 'fbid');
|
|
141
|
+
if (fbId) {
|
|
142
|
+
data.associations.push({
|
|
143
|
+
associated: true,
|
|
144
|
+
url: 'https://facebook.com/' + fbId,
|
|
145
|
+
deauthUrl: nconf.get('url') + '/deauth/facebook',
|
|
146
|
+
name: constants.name,
|
|
147
|
+
icon: constants.admin.icon,
|
|
148
|
+
});
|
|
149
|
+
} else {
|
|
150
|
+
data.associations.push({
|
|
151
|
+
associated: false,
|
|
152
|
+
url: nconf.get('url') + '/auth/facebook',
|
|
153
|
+
name: constants.name,
|
|
154
|
+
icon: constants.admin.icon,
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
return data;
|
|
158
|
+
};
|
|
159
|
+
|
|
160
|
+
Facebook.prepareInterstitial = async function (data) {
|
|
161
|
+
// Only execute if:
|
|
162
|
+
// - uid and fbid are set in session
|
|
163
|
+
// - email ends with "@facebook.com"
|
|
164
|
+
if (data.userData.hasOwnProperty('uid') && data.userData.hasOwnProperty('fbid')) {
|
|
165
|
+
const email = await user.getUserField(data.userData.uid, 'email');
|
|
166
|
+
if (email && email.endsWith('@facebook.com')) {
|
|
167
|
+
data.interstitials.push({
|
|
168
|
+
template: 'partials/sso-facebook/email.tpl',
|
|
169
|
+
data: {},
|
|
170
|
+
callback: Facebook.storeAdditionalData,
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
return data;
|
|
175
|
+
};
|
|
176
|
+
|
|
177
|
+
Facebook.storeAdditionalData = async function (userData, data) {
|
|
178
|
+
await db.delete(`uid:${userData.uid}:confirm:email:sent`);
|
|
179
|
+
const email = await user.getUserField(userData.uid, 'email');
|
|
180
|
+
await db.sortedSetRemove('email:uid', email);
|
|
181
|
+
await user.setUserField(userData.uid, 'email', data.email);
|
|
182
|
+
await user.email.sendValidationEmail(userData.uid, data.email);
|
|
183
|
+
};
|
|
184
|
+
|
|
185
|
+
Facebook.storeTokens = async function (uid, accessToken, refreshToken) {
|
|
186
|
+
//JG: Actually save the useful stuff
|
|
187
|
+
winston.verbose(`Storing received fb access information for uid(${uid}) accessToken(${accessToken}) refreshToken(${refreshToken})`);
|
|
188
|
+
await user.setUserFields(uid, {
|
|
189
|
+
fbaccesstoken: accessToken,
|
|
190
|
+
fbrefreshtoken: refreshToken,
|
|
191
|
+
});
|
|
192
|
+
};
|
|
257
193
|
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
};
|
|
194
|
+
Facebook.login = async function (req, fbid, name, email, picture, accessToken, refreshToken) {
|
|
195
|
+
winston.verbose(`Facebook.login fbid, name, email, picture: ${fbid}, ${name}, ${email}, ${picture}`);
|
|
196
|
+
const autoConfirm = Facebook.settings && Facebook.settings.autoconfirm === 'on' ? 1 : 0;
|
|
262
197
|
|
|
263
|
-
|
|
264
|
-
if (err) {
|
|
265
|
-
return callback(err);
|
|
266
|
-
}
|
|
198
|
+
let uid = await Facebook.getUidByFbid(fbid);
|
|
267
199
|
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
200
|
+
if (uid) {
|
|
201
|
+
// Existing User
|
|
202
|
+
await Facebook.storeTokens(uid, accessToken, refreshToken);
|
|
203
|
+
return { uid: uid };
|
|
204
|
+
}
|
|
273
205
|
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
206
|
+
const success = async (uid) => {
|
|
207
|
+
// Save facebook-specific information to the user
|
|
208
|
+
await Promise.all([
|
|
209
|
+
user.setUserField(uid, 'fbid', fbid),
|
|
210
|
+
db.setObjectField('fbid:uid', fbid, uid),
|
|
211
|
+
]);
|
|
212
|
+
|
|
213
|
+
// Save their photo, if present
|
|
214
|
+
if (picture) {
|
|
215
|
+
await user.setUserFields(uid, {
|
|
216
|
+
uploadedpicture: picture,
|
|
217
|
+
picture: picture,
|
|
218
|
+
});
|
|
219
|
+
}
|
|
278
220
|
|
|
279
|
-
|
|
280
|
-
});
|
|
281
|
-
} else {
|
|
282
|
-
success(uid); // Existing account -- merge
|
|
283
|
-
}
|
|
284
|
-
});
|
|
285
|
-
}
|
|
286
|
-
});
|
|
221
|
+
await Facebook.storeTokens(uid, accessToken, refreshToken);
|
|
287
222
|
};
|
|
288
223
|
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
callback(null, uid);
|
|
295
|
-
});
|
|
296
|
-
};
|
|
224
|
+
uid = await user.getUidByEmail(email);
|
|
225
|
+
if (uid) {
|
|
226
|
+
await success(uid);
|
|
227
|
+
return { uid };
|
|
228
|
+
}
|
|
297
229
|
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
'name': constants.name
|
|
303
|
-
});
|
|
230
|
+
// Abort user creation if registration via SSO is restricted
|
|
231
|
+
if (Facebook.settings.disableRegistration === 'on') {
|
|
232
|
+
throw new Error('[[error:sso-registration-disabled, Facebook]]');
|
|
233
|
+
}
|
|
304
234
|
|
|
305
|
-
|
|
306
|
-
|
|
235
|
+
return await user.createOrQueue(req, {
|
|
236
|
+
fbid,
|
|
237
|
+
picture,
|
|
238
|
+
username: name,
|
|
239
|
+
email,
|
|
240
|
+
}, {
|
|
241
|
+
emailVerification: autoConfirm ? 'verify' : 'send',
|
|
242
|
+
});
|
|
243
|
+
};
|
|
244
|
+
|
|
245
|
+
Facebook.addToApprovalQueue = async (hookData) => {
|
|
246
|
+
await saveFacebookSpecificData(hookData.data, hookData.userData);
|
|
247
|
+
return hookData;
|
|
248
|
+
};
|
|
249
|
+
|
|
250
|
+
Facebook.filterUserCreate = async (hookData) => {
|
|
251
|
+
await saveFacebookSpecificData(hookData.user, hookData.data);
|
|
252
|
+
return hookData;
|
|
253
|
+
};
|
|
254
|
+
|
|
255
|
+
async function saveFacebookSpecificData(targetObj, sourceObj) {
|
|
256
|
+
const { fbid, picture } = sourceObj;
|
|
257
|
+
if (fbid) {
|
|
258
|
+
const uid = await Facebook.getUidByFbid(fbid);
|
|
259
|
+
if (uid) {
|
|
260
|
+
throw new Error('[[error:sso-account-exists, Facebook]]');
|
|
261
|
+
}
|
|
262
|
+
targetObj.fbid = fbid;
|
|
263
|
+
if (picture) {
|
|
264
|
+
targetObj.picture = picture;
|
|
265
|
+
targetObj.uploadedpicture = picture;
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
}
|
|
307
269
|
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
270
|
+
Facebook.actionUserCreate = async (hookData) => {
|
|
271
|
+
const { uid } = hookData.user;
|
|
272
|
+
const fbid = await user.getUserField(uid, 'fbid');
|
|
273
|
+
if (fbid) {
|
|
274
|
+
await db.setObjectField('fbid:uid', fbid, uid);
|
|
275
|
+
}
|
|
276
|
+
};
|
|
277
|
+
|
|
278
|
+
Facebook.filterUserGetRegistrationQueue = async (hookData) => {
|
|
279
|
+
const { users } = hookData;
|
|
280
|
+
users.forEach((user) => {
|
|
281
|
+
if (user?.fbid) {
|
|
282
|
+
user.sso = {
|
|
283
|
+
icon: 'fa-brands fa-facebook',
|
|
284
|
+
name: constants.name,
|
|
285
|
+
};
|
|
314
286
|
}
|
|
315
|
-
};
|
|
287
|
+
});
|
|
288
|
+
return hookData;
|
|
289
|
+
};
|
|
290
|
+
|
|
291
|
+
Facebook.getUidByFbid = async function (fbid) {
|
|
292
|
+
const uid = await db.getObjectField('fbid:uid', fbid);
|
|
293
|
+
return uid;
|
|
294
|
+
};
|
|
295
|
+
|
|
296
|
+
Facebook.addMenuItem = function (custom_header) {
|
|
297
|
+
custom_header.authentication.push({
|
|
298
|
+
'route': constants.admin.route,
|
|
299
|
+
'icon': constants.admin.icon,
|
|
300
|
+
'name': constants.name,
|
|
301
|
+
});
|
|
302
|
+
return custom_header;
|
|
303
|
+
};
|
|
304
|
+
|
|
305
|
+
Facebook.deleteUserData = async function (data) {
|
|
306
|
+
const { uid } = data;
|
|
307
|
+
const fbid = await user.getUserField(uid, 'fbid');
|
|
308
|
+
if (fbid) {
|
|
309
|
+
await Promise.all([
|
|
310
|
+
db.deleteObjectField('fbid:uid', fbid),
|
|
311
|
+
db.deleteObjectField(`user:${uid}`, 'fbid'),
|
|
312
|
+
]);
|
|
313
|
+
}
|
|
314
|
+
};
|
|
315
|
+
|
|
316
|
+
module.exports = Facebook;
|
|
316
317
|
|
|
317
|
-
module.exports = Facebook;
|
|
318
|
-
}(module));
|
package/package.json
CHANGED
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nodebb-plugin-sso-facebook",
|
|
3
|
-
"version": "4.1
|
|
3
|
+
"version": "4.2.1",
|
|
4
4
|
"description": "NodeBB Facebook SSO",
|
|
5
5
|
"main": "library.js",
|
|
6
6
|
"repository": {
|
|
7
7
|
"type": "git",
|
|
8
8
|
"url": "https://github.com/julianlam/nodebb-plugin-sso-facebook"
|
|
9
9
|
},
|
|
10
|
+
"scripts": {
|
|
11
|
+
"lint": "eslint ."
|
|
12
|
+
},
|
|
10
13
|
"keywords": [
|
|
11
14
|
"nodebb",
|
|
12
15
|
"plugin",
|
|
@@ -28,7 +31,11 @@
|
|
|
28
31
|
"dependencies": {
|
|
29
32
|
"passport-facebook": "~1.0.2"
|
|
30
33
|
},
|
|
34
|
+
"devDependencies": {
|
|
35
|
+
"eslint": "10.0.2",
|
|
36
|
+
"eslint-config-nodebb": "^2.0.0"
|
|
37
|
+
},
|
|
31
38
|
"nbbpm": {
|
|
32
|
-
"compatibility": "^4.
|
|
39
|
+
"compatibility": "^4.9.0"
|
|
33
40
|
}
|
|
34
41
|
}
|
package/plugin.json
CHANGED
|
@@ -12,7 +12,11 @@
|
|
|
12
12
|
{ "hook": "filter:admin.header.build", "method": "addMenuItem" },
|
|
13
13
|
{ "hook": "static:user.delete", "method": "deleteUserData" },
|
|
14
14
|
{ "hook": "filter:register.interstitial", "method": "prepareInterstitial" },
|
|
15
|
-
{ "hook": "filter:user.whitelistFields", "method": "appendUserHashWhitelist" }
|
|
15
|
+
{ "hook": "filter:user.whitelistFields", "method": "appendUserHashWhitelist" },
|
|
16
|
+
{ "hook": "filter:user.addToApprovalQueue", "method": "addToApprovalQueue" },
|
|
17
|
+
{ "hook": "filter:user.create", "method": "filterUserCreate" },
|
|
18
|
+
{ "hook": "action:user.create", "method": "actionUserCreate" },
|
|
19
|
+
{ "hook": "filter:user.getRegistrationQueue", "method": "filterUserGetRegistrationQueue" }
|
|
16
20
|
],
|
|
17
21
|
"modules": {
|
|
18
22
|
"../admin/plugins/sso-facebook.js": "static/lib/admin.js"
|
package/static/lib/admin.js
CHANGED
|
@@ -1,22 +1,20 @@
|
|
|
1
|
-
define('admin/plugins/sso-facebook', ['settings', 'alerts'], function(Settings, alerts) {
|
|
1
|
+
define('admin/plugins/sso-facebook', ['settings', 'alerts'], function (Settings, alerts) {
|
|
2
2
|
'use strict';
|
|
3
|
-
|
|
3
|
+
const ACP = {};
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
ACP.init = function() {
|
|
5
|
+
ACP.init = function () {
|
|
8
6
|
Settings.load('sso-facebook', $('.sso-facebook-settings'));
|
|
9
7
|
|
|
10
|
-
$('#save').on('click', function() {
|
|
11
|
-
Settings.save('sso-facebook', $('.sso-facebook-settings'), function() {
|
|
8
|
+
$('#save').on('click', function () {
|
|
9
|
+
Settings.save('sso-facebook', $('.sso-facebook-settings'), function () {
|
|
12
10
|
alerts.alert({
|
|
13
11
|
type: 'success',
|
|
14
12
|
alert_id: 'sso-facebook-saved',
|
|
15
13
|
title: 'Settings Saved',
|
|
16
14
|
message: 'Please reload your NodeBB to apply these settings',
|
|
17
|
-
clickfn: function() {
|
|
15
|
+
clickfn: function () {
|
|
18
16
|
socket.emit('admin.reload');
|
|
19
|
-
}
|
|
17
|
+
},
|
|
20
18
|
});
|
|
21
19
|
});
|
|
22
20
|
});
|