server.js 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. /* global
  2. AT: false,
  3. AccountsTemplates: false
  4. */
  5. "use strict";
  6. // Initialization
  7. AT.prototype.init = function() {
  8. console.warn("[AccountsTemplates] There is no more need to call AccountsTemplates.init()! Simply remove the call ;-)");
  9. };
  10. AT.prototype._init = function() {
  11. if (this._initialized) {
  12. return;
  13. }
  14. // Checks there is at least one account service installed
  15. if (!Package["accounts-password"] && (!Accounts.oauth || Accounts.oauth.serviceNames().length === 0)) {
  16. throw Error("AccountsTemplates: You must add at least one account service!");
  17. }
  18. // A password field is strictly required
  19. var password = this.getField("password");
  20. if (!password) {
  21. throw Error("A password field is strictly required!");
  22. }
  23. if (password.type !== "password") {
  24. throw Error("The type of password field should be password!");
  25. }
  26. // Then we can have "username" or "email" or even both of them
  27. // but at least one of the two is strictly required
  28. var username = this.getField("username");
  29. var email = this.getField("email");
  30. if (!username && !email) {
  31. throw Error("At least one field out of username and email is strictly required!");
  32. }
  33. if (username && !username.required) {
  34. throw Error("The username field should be required!");
  35. }
  36. if (email) {
  37. if (email.type !== "email") {
  38. throw Error("The type of email field should be email!");
  39. }
  40. if (username) {
  41. // username and email
  42. if (username.type !== "text") {
  43. throw Error("The type of username field should be text when email field is present!");
  44. }
  45. } else {
  46. // email only
  47. if (!email.required) {
  48. throw Error("The email field should be required when username is not present!");
  49. }
  50. }
  51. } else {
  52. // username only
  53. if (username.type !== "text" && username.type !== "tel") {
  54. throw Error("The type of username field should be text or tel!");
  55. }
  56. }
  57. // Possibly publish more user data in order to be able to show add/remove
  58. // buttons for 3rd-party services
  59. if (this.options.showAddRemoveServices) {
  60. // Publish additional current user info to get the list of registered services
  61. // XXX TODO: use
  62. // Accounts.addAutopublishFields({
  63. // forLoggedInUser: ['services.facebook'],
  64. // forOtherUsers: [],
  65. // })
  66. // ...adds only user.services.*.id
  67. Meteor.publish("userRegisteredServices", function() {
  68. var userId = this.userId;
  69. return Meteor.users.find(userId, {fields: {services: 1}});
  70. /*
  71. if (userId) {
  72. var user = Meteor.users.findOne(userId);
  73. var services_id = _.chain(user.services)
  74. .keys()
  75. .reject(function(service) {return service === "resume";})
  76. .map(function(service) {return "services." + service + ".id";})
  77. .value();
  78. var projection = {};
  79. _.each(services_id, function(key) {projection[key] = 1;});
  80. return Meteor.users.find(userId, {fields: projection});
  81. }
  82. */
  83. });
  84. }
  85. // Security stuff
  86. if (this.options.overrideLoginErrors) {
  87. Accounts.validateLoginAttempt(function(attempt) {
  88. if (attempt.error) {
  89. var reason = attempt.error.reason;
  90. if (reason === "User not found" || reason === "Incorrect password") {
  91. throw new Meteor.Error(403, AccountsTemplates.texts.errors.loginForbidden);
  92. }
  93. }
  94. return attempt.allowed;
  95. });
  96. }
  97. if (this.options.sendVerificationEmail && this.options.enforceEmailVerification) {
  98. Accounts.validateLoginAttempt(function(attempt) {
  99. if (!attempt.allowed) {
  100. return false;
  101. }
  102. if (attempt.type !== "password" || attempt.methodName !== "login") {
  103. return attempt.allowed;
  104. }
  105. var user = attempt.user;
  106. if (!user) {
  107. return attempt.allowed;
  108. }
  109. var ok = true;
  110. var loginEmail = attempt.methodArguments[0].user.email.toLowerCase();
  111. if (loginEmail) {
  112. var email = _.filter(user.emails, function(obj) {
  113. return obj.address.toLowerCase() === loginEmail;
  114. });
  115. if (!email.length || !email[0].verified) {
  116. ok = false;
  117. }
  118. } else {
  119. // we got the username, lets check there's at lease one verified email
  120. var emailVerified = _.chain(user.emails)
  121. .pluck('verified')
  122. .any()
  123. .value();
  124. if (!emailVerified) {
  125. ok = false;
  126. }
  127. }
  128. if (!ok) {
  129. throw new Meteor.Error(401, AccountsTemplates.texts.errors.verifyEmailFirst);
  130. }
  131. return attempt.allowed;
  132. });
  133. }
  134. //Check that reCaptcha secret keys are available
  135. if (this.options.showReCaptcha) {
  136. var atSecretKey = AccountsTemplates.options.reCaptcha && AccountsTemplates.options.reCaptcha.secretKey;
  137. var settingsSecretKey = Meteor.settings.reCaptcha && Meteor.settings.reCaptcha.secretKey;
  138. if (!atSecretKey && !settingsSecretKey) {
  139. throw new Meteor.Error(401, "User Accounts: reCaptcha secret key not found! Please provide it or set showReCaptcha to false." );
  140. }
  141. }
  142. // Marks AccountsTemplates as initialized
  143. this._initialized = true;
  144. };
  145. AccountsTemplates = new AT();
  146. // Client side account creation is disabled by default:
  147. // the methos ATCreateUserServer is used instead!
  148. // to actually disable client side account creation use:
  149. //
  150. // AccountsTemplates.config({
  151. // forbidClientAccountCreation: true
  152. // });
  153. Accounts.config({
  154. forbidClientAccountCreation: true
  155. });
  156. // Initialization
  157. Meteor.startup(function() {
  158. AccountsTemplates._init();
  159. });