captcha.js 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. /* global grecaptcha */
  2. import React from 'react'; // jshint ignore:line
  3. import FormGroup from 'misago/components/form-group'; // jshint ignore:line
  4. export class BaseCaptcha {
  5. init(context, ajax, include, snackbar) {
  6. this._context = context;
  7. this._ajax = ajax;
  8. this._include = include;
  9. this._snackbar = snackbar;
  10. }
  11. }
  12. export class NoCaptcha extends BaseCaptcha {
  13. load() {
  14. return new Promise(function(resolve) {
  15. // immediately resolve as we don't have anything to validate
  16. resolve();
  17. });
  18. }
  19. validator() {
  20. return null;
  21. }
  22. component() {
  23. return null;
  24. }
  25. }
  26. export class QACaptcha extends BaseCaptcha {
  27. load() {
  28. var self = this;
  29. return new Promise((resolve, reject) => {
  30. self._ajax.get(self._context.get('CAPTCHA_API')).then(
  31. function(data) {
  32. self.question = data.question;
  33. self.helpText = data.help_text;
  34. resolve();
  35. }, function() {
  36. self._snackbar.error(gettext("Failed to load CAPTCHA."));
  37. reject();
  38. });
  39. });
  40. }
  41. validator() {
  42. return [];
  43. }
  44. /* jshint ignore:start */
  45. component(kwargs) {
  46. return (
  47. <FormGroup
  48. label={this.question}
  49. for="id_captcha"
  50. labelClass={kwargs.labelClass || ""}
  51. controlClass={kwargs.controlClass || ""}
  52. validation={kwargs.form.state.errors.captcha}
  53. helpText={this.helpText || null}
  54. >
  55. <input
  56. aria-describedby="id_captcha_status"
  57. className="form-control"
  58. disabled={kwargs.form.state.isLoading}
  59. id="id_captcha"
  60. onChange={kwargs.form.bindInput('captcha')}
  61. type="text"
  62. value={kwargs.form.state.captcha}
  63. />
  64. </FormGroup>
  65. );
  66. }
  67. /* jshint ignore:end */
  68. }
  69. export class ReCaptchaComponent extends React.Component {
  70. componentDidMount() {
  71. grecaptcha.render('recaptcha', {
  72. 'sitekey': this.props.siteKey,
  73. 'callback': (response) => {
  74. // fire fakey event to binding
  75. this.props.binding({
  76. target: {
  77. value: response
  78. }
  79. });
  80. }
  81. });
  82. }
  83. render() {
  84. /* jshint ignore:start */
  85. return <div id="recaptcha" />;
  86. /* jshint ignore:end */
  87. }
  88. }
  89. export class ReCaptcha extends BaseCaptcha {
  90. load() {
  91. this._include.include('https://www.google.com/recaptcha/api.js', true);
  92. return new Promise(function(resolve) {
  93. var wait = function() {
  94. if (typeof grecaptcha === "undefined") {
  95. window.setTimeout(function() {
  96. wait();
  97. }, 200);
  98. } else {
  99. resolve();
  100. }
  101. };
  102. wait();
  103. });
  104. }
  105. validator() {
  106. return [];
  107. }
  108. /* jshint ignore:start */
  109. component(kwargs) {
  110. return (
  111. <FormGroup
  112. label={gettext("Please solve the quick test")}
  113. for="id_captcha"
  114. labelClass={kwargs.labelClass || ""}
  115. controlClass={kwargs.controlClass || ""}
  116. validation={kwargs.form.state.errors.captcha}
  117. helpText={gettext("This test helps us prevent automated spam registrations on our site.")}
  118. >
  119. <ReCaptchaComponent
  120. binding={kwargs.form.bindInput('captcha')}
  121. siteKey={this._context.get('SETTINGS').recaptcha_site_key}
  122. />
  123. </FormGroup>
  124. );
  125. }
  126. /* jshint ignore:end */
  127. }
  128. export class Captcha {
  129. init(context, ajax, include, snackbar) {
  130. switch(context.get('SETTINGS').captcha_type) {
  131. case 'no':
  132. this._captcha = new NoCaptcha();
  133. break;
  134. case 'qa':
  135. this._captcha = new QACaptcha();
  136. break;
  137. case 're':
  138. this._captcha = new ReCaptcha();
  139. break;
  140. }
  141. this._captcha.init(context, ajax, include, snackbar);
  142. }
  143. // accessors for underlying strategy
  144. load() {
  145. return this._captcha.load();
  146. }
  147. validator() {
  148. return this._captcha.validator();
  149. }
  150. component(kwargs) {
  151. return this._captcha.component(kwargs);
  152. }
  153. }
  154. export default new Captcha();