forked from Sewdn/meteor-fb-connect
-
Notifications
You must be signed in to change notification settings - Fork 0
/
server.js
178 lines (142 loc) · 6.19 KB
/
server.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
// OVERRIDE CORE METHOD for custom naver user selection on email
// this can be removed when the pull-request is merged
// https://github.com/meteor/meteor/pull/2318
///
/// OAuth Encryption Support
///
var OAuthEncryption = Package["oauth-encryption"] && Package["oauth-encryption"].OAuthEncryption;
var usingOAuthEncryption = function () {
return OAuthEncryption && OAuthEncryption.keyIsLoaded();
};
// OAuth service data is temporarily stored in the pending credentials
// collection during the oauth authentication process. Sensitive data
// such as access tokens are encrypted without the user id because
// we don't know the user id yet. We re-encrypt these fields with the
// user id included when storing the service data permanently in
// the users collection.
//
var pinEncryptedFieldsToUser = function (serviceData, userId) {
_.each(_.keys(serviceData), function (key) {
var value = serviceData[key];
if (OAuthEncryption && OAuthEncryption.isSealed(value))
value = OAuthEncryption.seal(OAuthEncryption.open(value), userId);
serviceData[key] = value;
});
};
///
/// MANAGING USER OBJECTS
///
// Updates or creates a user after we authenticate with a 3rd party.
//
// @param serviceName {String} Service name (eg, twitter).
// @param serviceData {Object} Data to store in the user's record
// under services[serviceName]. Must include an "id" field
// which is a unique identifier for the user in the service.
// @param options {Object, optional} Other options to pass to insertUserDoc
// (eg, profile)
// @returns {Object} Object with token and id keys, like the result
// of the "login" method.
//
Accounts.updateOrCreateUserFromExternalService = function (serviceName, serviceData, options) {
// 실명, 생일 삭제
delete options.profile.name;
delete options.profile.birthday;
// naver는 options에 유저 정보가 있어서 serviceData로 데이터 이동
serviceData = _.extend(serviceData, options.profile);
options = _.clone(options || {});
if (serviceName === "password" || serviceName === "resume")
throw new Error(
"Can't use updateOrCreateUserFromExternalService with internal service "
+ serviceName);
if (!_.has(serviceData, 'id'))
throw new Error(
"Service data for service " + serviceName + " must include id");
var selector = Accounts.externalServiceSelector(serviceName, serviceData, options);
if (!selector)
return false;
var user = Meteor.users.findOne(selector);
if (user) {
pinEncryptedFieldsToUser(serviceData, user._id);
// We *don't* process options (eg, profile) for update, but we do replace
// the serviceData (eg, so that we keep an unexpired access token and
// don't cache old email addresses in serviceData.email).
// XXX provide an onUpdateUser hook which would let apps update
// the profile too
var setAttrs = {};
_.each(serviceData, function (value, key) {
setAttrs["services." + serviceName + "." + key] = value;
if ( serviceData.email ) setAttrs['emails.0.verified'] = true;
});
// XXX Maybe we should re-use the selector above and notice if the update
// touches nothing?
Meteor.users.update(user._id, {$set: setAttrs});
return {
type: serviceName,
userId: user._id
};
} else {
// Create a new user with the service data. Pass other options through to
// insertUserDoc.
user = {services: {}};
user.services[serviceName] = serviceData;
return {
type: serviceName,
userId: Accounts.insertUserDoc(options, user)
};
}
};
Accounts.externalServiceSelector = function (serviceName, serviceData, options) {
var selector = false;
//check if specific selector is available for service
var selectorMethod = "externalServiceSelector";
selectorMethod += serviceName.charAt(0).toUpperCase() + serviceName.slice(1);
if (Accounts[selectorMethod]) {
selector = Accounts[selectorMethod](serviceName, serviceData, options);
}
// Look for a user with the appropriate service user id.
if (!selector && !!serviceData.id) {
var serviceIdKey = "services." + serviceName + ".id";
selector[serviceIdKey] = serviceData.id;
}
return selector;
};
/// this must remain in this package after pull request merge
//our custom naver selector to also select users on naver-email
Accounts.externalServiceSelectorNaver = function (serviceName, serviceData, options) {
console.log('Accounts.externalServiceSelectorNaver', serviceName, serviceData, options);
var serviceIdKey = "services." + serviceName + ".id";
var selector = {};
selector["$or"] = [{}, {}];
selector["$or"][0][serviceIdKey] = serviceData.id;
//also check on email
selector["$or"][1]["emails.address"] = serviceData.email;
if (!serviceData.email) selector["$or"][1]["emails.address"] = null;
//selector = false;
return selector;
};
Meteor.methods({
connectUserWithNaver: function (token, secret) {
//errors
if (!this.userId)
throw new Meteor.Error(403, "user must be loggedin");
var user = Meteor.user();
if (user.services && user.services.naver)
throw new Meteor.Error(403, "user can not have a naver connected account");
if (Meteor.isServer) {
var naverData = Naver.retrieveCredential(token, secret);
if (!naverData)
throw new Meteor.Error(403, "not able to retreive naver data");
//check if no accounts exists for this naver user
var existing = Meteor.users.find({'services.naver.id': naverData.serviceData.id}).count();
if (existing)
throw new Meteor.Error(403, "user can not have a naver connected account");
// 페이스북 인증시 이메일 인증 true으로 변경
Meteor.users.update(this.userId, {
$set: {
'services.naver': naverData.serviceData,
'emails.0.verified': true
}
});
}
}
});