captcha.js 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  1. /* global grecaptcha */
  2. import React from "react"
  3. import FormGroup from "misago/components/form-group"
  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. },
  36. function() {
  37. self._snackbar.error(gettext("Failed to load CAPTCHA."))
  38. reject()
  39. }
  40. )
  41. })
  42. }
  43. validator() {
  44. return []
  45. }
  46. component(kwargs) {
  47. return (
  48. <FormGroup
  49. label={this.question}
  50. for="id_captcha"
  51. labelClass={kwargs.labelClass || ""}
  52. controlClass={kwargs.controlClass || ""}
  53. validation={kwargs.form.state.errors.captcha}
  54. helpText={this.helpText || null}
  55. >
  56. <input
  57. aria-describedby="id_captcha_status"
  58. className="form-control"
  59. disabled={kwargs.form.state.isLoading}
  60. id="id_captcha"
  61. onChange={kwargs.form.bindInput("captcha")}
  62. type="text"
  63. value={kwargs.form.state.captcha}
  64. />
  65. </FormGroup>
  66. )
  67. }
  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. return <div id="recaptcha" />
  85. }
  86. }
  87. export class ReCaptcha extends BaseCaptcha {
  88. load() {
  89. this._include.include("https://www.google.com/recaptcha/api.js", true)
  90. return new Promise(function(resolve) {
  91. var wait = function() {
  92. if (typeof grecaptcha === "undefined") {
  93. window.setTimeout(function() {
  94. wait()
  95. }, 200)
  96. } else {
  97. resolve()
  98. }
  99. }
  100. wait()
  101. })
  102. }
  103. validator() {
  104. return []
  105. }
  106. component(kwargs) {
  107. return (
  108. <FormGroup
  109. label={gettext("Please solve the quick test")}
  110. for="id_captcha"
  111. labelClass={kwargs.labelClass || ""}
  112. controlClass={kwargs.controlClass || ""}
  113. validation={kwargs.form.state.errors.captcha}
  114. helpText={gettext(
  115. "This test helps us prevent automated spam registrations on our site."
  116. )}
  117. >
  118. <ReCaptchaComponent
  119. binding={kwargs.form.bindInput("captcha")}
  120. siteKey={this._context.get("SETTINGS").recaptcha_site_key}
  121. />
  122. </FormGroup>
  123. )
  124. }
  125. }
  126. export class Captcha {
  127. init(context, ajax, include, snackbar) {
  128. switch (context.get("SETTINGS").captcha_type) {
  129. case "no":
  130. this._captcha = new NoCaptcha()
  131. break
  132. case "qa":
  133. this._captcha = new QACaptcha()
  134. break
  135. case "re":
  136. this._captcha = new ReCaptcha()
  137. break
  138. }
  139. this._captcha.init(context, ajax, include, snackbar)
  140. }
  141. // accessors for underlying strategy
  142. load() {
  143. return this._captcha.load()
  144. }
  145. validator() {
  146. return this._captcha.validator()
  147. }
  148. component(kwargs) {
  149. return this._captcha.component(kwargs)
  150. }
  151. }
  152. export default new Captcha()