forked from Meteor-Community-Packages/meteor-link-accounts
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathlink_accounts_server.js
100 lines (87 loc) · 3.37 KB
/
link_accounts_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
Accounts.registerLoginHandler(function (options) {
if (!options.link)
return undefined;
check(options.link, {
credentialToken: String,
// When an error occurs while retrieving the access token, we store
// the error in the pending credentials table, with a secret of
// null. The client can call the login method with a secret of null
// to retrieve the error.
credentialSecret: Match.OneOf(null, String)
});
var result = OAuth.retrieveCredential(options.link.credentialToken,
options.link.credentialSecret);
if (!result) {
return { type: "link",
error: new Meteor.Error(
Accounts.LoginCancelledError.numericError,
"No matching link attempt found") };
}
if (result instanceof Error)
throw result;
else
return Accounts.LinkUserFromExternalService(
result.serviceName, result.serviceData, result.options);
});
Accounts.LinkUserFromExternalService = function (serviceName, serviceData, options) {
options = _.clone(options || {});
//We probably throw an error instead of call update or create here.
if (!Meteor.userId())
return new Meteor.Error("You must be logged in to use LinkUserFromExternalService");
if (serviceName === "password" || serviceName === "resume")
throw new Meteor.Error(
"Can't use LinkUserFromExternalService with internal service: "
+ serviceName);
if (!_.has(serviceData, 'id'))
throw new Meteor.Error(
"'id' missing from service data for: " + serviceName);
var user = Meteor.user();
if (!user) {
return new Meteor.Error('User not found for LinkUserFromExternalService');
}
var checkExistingSelector = {};
checkExistingSelector['services.' + serviceName + '.id'] = serviceData.id;
var existingUsers = Meteor.users.find(checkExistingSelector).fetch();
if (existingUsers.length) {
existingUsers.forEach(function(existingUser) {
if (existingUser._id !== Meteor.userId())
throw new Meteor.Error('This social account is already in use by other user');
});
}
//we do not allow link another account from existing service.
//XXX maybe we can override this?
if (user.services && user.services[serviceName] &&
user.services[serviceName].id !== serviceData.id) {
return new Meteor.Error('User can link only one account to service: ' + serviceName);
} else {
var setAttrs = {};
_.each(serviceData, function(value, key) {
setAttrs["services." + serviceName + "." + key] = value;
});
Meteor.users.update(user._id, {$set: setAttrs});
return {
type: serviceName,
userId: user._id
};
}
};
Accounts.unlinkService = function (userId, serviceName, cb) {
check(userId, Match.OneOf(String, Mongo.ObjectID));
if (typeof serviceName !== 'string') {
throw new Meteor.Error('Service name must be string');
}
var user = Meteor.users.findOne({_id: userId});
if (serviceName === 'resume' || serviceName === 'password') {
throw new Meteor.Error('Interal services cannot be unlinked: ' + serviceName);
}
if (user.services[serviceName]) {
var newServices = _.omit(user.services, serviceName);
Meteor.users.update({_id: user._id}, {$set: {services: newServices}}, function (result) {
if (cb && typeof cb === 'function') {
cb(result);
}
});
} else {
throw new Meteor.Error(500, 'no service');
}
};