register-form.js 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  1. import Ember from 'ember';
  2. export default Ember.Component.extend({
  3. tagName: 'form',
  4. classNames: 'form-horizontal',
  5. zxcvbn: Ember.inject.service('zxcvbn'),
  6. isReady: false,
  7. isErrored: false,
  8. isLoading: false,
  9. username: '',
  10. email: '',
  11. password: '',
  12. validation: Ember.Object.create({}),
  13. passwordScore: function() {
  14. return this.get('zxcvbn').scorePassword(this.get('password'), [
  15. this.get('username'), this.get('email')
  16. ]);
  17. }.property('password', 'username', 'email'),
  18. passwordHelpText: function() {
  19. if (Ember.$.trim(this.get('password')).length === 0) {
  20. return null;
  21. }
  22. return [
  23. gettext('Password is very weak.'),
  24. gettext('Password is weak.'),
  25. gettext('Password is average.'),
  26. gettext('Password is strong.'),
  27. gettext('Password is very strong.')
  28. ][this.get('passwordScore')];
  29. }.property('password', 'username', 'email', 'passwordScore'),
  30. passwordBarWidth: function() {
  31. this.$('.progress-bar').css('width', ((this.get('passwordScore') + 1) * 20) + '%');
  32. }.observes('password', 'username', 'email', 'passwordScore'),
  33. passwordBarClass: function() {
  34. return 'progress-bar-' + [
  35. 'danger',
  36. 'warning',
  37. 'warning',
  38. 'primary',
  39. 'success'
  40. ][this.get('passwordScore')];
  41. }.property('password', 'username', 'email', 'passwordScore'),
  42. loadServices: function() {
  43. var self = this;
  44. var promises = [
  45. this.get('zxcvbn').load(),
  46. this.get('captcha').load()
  47. ];
  48. Ember.RSVP.allSettled(promises).then(function(array) {
  49. if (self.isDestroyed) { return; }
  50. if (array[0].state === 'rejected') {
  51. self.set('isErrored', true);
  52. console.log('zxcvbn service failed to load.');
  53. }
  54. if (array[1].state === 'rejected') {
  55. self.set('isErrored', true);
  56. console.log('captcha service failed to load.');
  57. }
  58. self.set('isReady', !self.get('isErrored'));
  59. self.get('captcha').reset();
  60. });
  61. }.on('didInsertElement'),
  62. usernameValidation: function() {
  63. var state = true;
  64. var value = Ember.$.trim(this.get('username'));
  65. var valueLength = value.length;
  66. var limit = 0;
  67. var message = null;
  68. if (valueLength < this.get('settings.username_length_min')) {
  69. limit = this.get('settings.username_length_min');
  70. message = ngettext('Username must be at least one character long.',
  71. 'Username must be at least %(limit)s characters long.',
  72. limit);
  73. state = [interpolate(message, {limit: limit}, true)];
  74. } else if (valueLength > this.get('settings.username_length_max')) {
  75. limit = this.get('settings.username_length_max');
  76. message = ngettext('Username cannot be longer than one characters.',
  77. 'Username cannot be longer than %(limit)s characters.',
  78. limit);
  79. state = [interpolate(message, {limit: limit}, true)];
  80. } else if (!new RegExp('^[0-9a-z]+$', 'i').test(value)) {
  81. state = [gettext('Username can only contain latin alphabet letters and digits.')];
  82. }
  83. if (state === true) {
  84. this.set('validation.username', 'ok');
  85. } else {
  86. this.set('validation.username', state);
  87. }
  88. }.observes('username'),
  89. emailValidation: function() {
  90. var state = true;
  91. var value = Ember.$.trim(this.get('email'));
  92. var valueLength = value.length;
  93. var re = /^([\w-]+(?:\.[\w-]+)*)@((?:[\w-]+\.)*\w[\w-]{0,66})\.([a-z]{2,6}(?:\.[a-z]{2})?)$/i;
  94. if (valueLength < 4) {
  95. state = [gettext('Enter valid e-mail address')];
  96. } else if (!re.test(value)) {
  97. state = [gettext('Invalid e-mail address.')];
  98. }
  99. if (state === true) {
  100. this.set('validation.email', 'ok');
  101. } else {
  102. this.set('validation.email', state);
  103. }
  104. }.observes('email'),
  105. passwordValidation: function() {
  106. var state = true;
  107. var valueLength = Ember.$.trim(this.get('password')).length;
  108. var limit = this.get('settings.password_length_min');
  109. if (valueLength < limit) {
  110. var message = ngettext('Valid password must be at least one character long.',
  111. 'Valid password must be at least %(limit)s characters long.',
  112. limit);
  113. state = [interpolate(message, {limit: limit}, true)];
  114. }
  115. if (state === true) {
  116. this.set('validation.password', 'ok');
  117. } else {
  118. this.set('validation.password', state);
  119. }
  120. }.observes('password'),
  121. captchaValidation: function() {
  122. this.set('validation.captcha', undefined);
  123. }.observes('captcha.value'),
  124. submit: function() {
  125. if (this.get('isLoading')) {
  126. return false;
  127. }
  128. var data = {
  129. username: Ember.$.trim(this.get('username')),
  130. email: Ember.$.trim(this.get('email')),
  131. password: Ember.$.trim(this.get('password')),
  132. captcha: Ember.$.trim(this.get('captcha.value'))
  133. };
  134. var lengths = [data.username.length, data.email.length, data.password.length];
  135. if (lengths.indexOf(0) !== -1) {
  136. this.toast.error(gettext("Fill out all fields."));
  137. return false;
  138. }
  139. if (this.$('.has-error').length) {
  140. this.toast.error(gettext("Form contains errors."));
  141. return false;
  142. }
  143. this.set('isLoading', true);
  144. var self = this;
  145. this.rpc.ajax('users', data
  146. ).then(function(response) {
  147. if (self.isDestroyed) { return; }
  148. self.success(response);
  149. }, function(jqXHR) {
  150. if (self.isDestroyed) { return; }
  151. self.error(jqXHR);
  152. }).finally(function() {
  153. if (self.isDestroyed) { return; }
  154. self.set('isLoading', false);
  155. });
  156. return false;
  157. },
  158. success: function(response) {
  159. console.log(response);
  160. this.get('captcha').reset();
  161. },
  162. error: function(jqXHR) {
  163. if (jqXHR.status === 400) {
  164. this.toast.error(gettext("Form contains errors."));
  165. this.get('validation').setProperties(jqXHR.responseJSON);
  166. if (!this.get('validation.captcha')) {
  167. this.get('captcha').pass();
  168. } else {
  169. this.get('captcha').refresh();
  170. }
  171. }
  172. },
  173. showTermsFootnote: function() {
  174. return this.get('settings.terms_of_service') || this.get('settings.terms_of_service_link');
  175. }.property('settings')
  176. });