UserOperation,
PasswordResetForm,
GetSiteResponse,
+ GetCaptchaResponse,
WebSocketJsonResponse,
Site,
-} from '../interfaces';
+} from 'lemmy-js-client';
import { WebSocketService, UserService } from '../services';
import { wsJsonToRes, validEmail, toast } from '../utils';
import { i18n } from '../i18next';
registerForm: RegisterForm;
loginLoading: boolean;
registerLoading: boolean;
- mathQuestion: {
- a: number;
- b: number;
- answer: number;
- };
+ captcha: GetCaptchaResponse;
+ captchaPlaying: boolean;
site: Site;
}
password_verify: undefined,
admin: false,
show_nsfw: false,
+ captcha_uuid: undefined,
+ captcha_answer: undefined,
},
loginLoading: false,
registerLoading: false,
- mathQuestion: {
- a: Math.floor(Math.random() * 10) + 1,
- b: Math.floor(Math.random() * 10) + 1,
- answer: undefined,
- },
+ captcha: undefined,
+ captchaPlaying: false,
site: {
id: undefined,
name: undefined,
);
WebSocketService.Instance.getSite();
+ WebSocketService.Instance.getCaptcha();
}
componentWillUnmount() {
</div>
);
}
+
registerForm() {
return (
<form onSubmit={linkEvent(this, this.handleRegisterSubmit)}>
/>
</div>
</div>
- <div class="form-group row">
- <label class="col-sm-10 col-form-label" htmlFor="register-math">
- {i18n.t('what_is')}{' '}
- {`${this.state.mathQuestion.a} + ${this.state.mathQuestion.b}?`}
- </label>
- <div class="col-sm-2">
- <input
- type="number"
- id="register-math"
- class="form-control"
- value={this.state.mathQuestion.answer}
- onInput={linkEvent(this, this.handleMathAnswerChange)}
- required
- />
+ {this.state.captcha && (
+ <div class="form-group row">
+ <label class="col-sm-2" htmlFor="register-captcha">
+ <span class="mr-2">{i18n.t('enter_code')}</span>
+ <button
+ type="button"
+ class="btn btn-secondary"
+ onClick={linkEvent(this, this.handleRegenCaptcha)}
+ >
+ <svg class="icon icon-refresh-cw">
+ <use xlinkHref="#icon-refresh-cw"></use>
+ </svg>
+ </button>
+ </label>
+ {this.showCaptcha()}
+ <div class="col-sm-6">
+ <input
+ type="text"
+ class="form-control"
+ id="register-captcha"
+ value={this.state.registerForm.captcha_answer}
+ onInput={linkEvent(
+ this,
+ this.handleRegisterCaptchaAnswerChange
+ )}
+ required
+ />
+ </div>
</div>
- </div>
+ )}
{this.state.site.enable_nsfw && (
<div class="form-group row">
<div class="col-sm-10">
)}
<div class="form-group row">
<div class="col-sm-10">
- <button
- type="submit"
- class="btn btn-secondary"
- disabled={this.mathCheck}
- >
+ <button type="submit" class="btn btn-secondary">
{this.state.registerLoading ? (
<svg class="icon icon-spinner spin">
<use xlinkHref="#icon-spinner"></use>
);
}
+ showCaptcha() {
+ return (
+ <div class="col-sm-4">
+ {this.state.captcha.ok && (
+ <>
+ <img
+ class="rounded-top img-fluid"
+ src={this.captchaPngSrc()}
+ style="border-bottom-right-radius: 0; border-bottom-left-radius: 0;"
+ />
+ {this.state.captcha.ok.wav && (
+ <button
+ class="rounded-bottom btn btn-sm btn-secondary btn-block"
+ style="border-top-right-radius: 0; border-top-left-radius: 0;"
+ title={i18n.t('play_captcha_audio')}
+ onClick={linkEvent(this, this.handleCaptchaPlay)}
+ type="button"
+ disabled={this.state.captchaPlaying}
+ >
+ <svg class="icon icon-play">
+ <use xlinkHref="#icon-play"></use>
+ </svg>
+ </button>
+ )}
+ </>
+ )}
+ </div>
+ );
+ }
+
handleLoginSubmit(i: Login, event: any) {
event.preventDefault();
i.state.loginLoading = true;
event.preventDefault();
i.state.registerLoading = true;
i.setState(i.state);
-
- if (!i.mathCheck) {
- WebSocketService.Instance.register(i.state.registerForm);
- }
+ WebSocketService.Instance.register(i.state.registerForm);
}
handleRegisterUsernameChange(i: Login, event: any) {
i.setState(i.state);
}
- handleMathAnswerChange(i: Login, event: any) {
- i.state.mathQuestion.answer = event.target.value;
+ handleRegisterCaptchaAnswerChange(i: Login, event: any) {
+ i.state.registerForm.captcha_answer = event.target.value;
i.setState(i.state);
}
+ handleRegenCaptcha(_i: Login, _event: any) {
+ event.preventDefault();
+ WebSocketService.Instance.getCaptcha();
+ }
+
handlePasswordReset(i: Login) {
event.preventDefault();
let resetForm: PasswordResetForm = {
WebSocketService.Instance.passwordReset(resetForm);
}
- get mathCheck(): boolean {
- return (
- this.state.mathQuestion.answer !=
- this.state.mathQuestion.a + this.state.mathQuestion.b
- );
+ handleCaptchaPlay(i: Login) {
+ event.preventDefault();
+ let snd = new Audio('data:audio/wav;base64,' + i.state.captcha.ok.wav);
+ snd.play();
+ i.state.captchaPlaying = true;
+ i.setState(i.state);
+ snd.addEventListener('ended', () => {
+ snd.currentTime = 0;
+ i.state.captchaPlaying = false;
+ i.setState(this.state);
+ });
+ }
+
+ captchaPngSrc() {
+ return `data:image/png;base64,${this.state.captcha.ok.png}`;
}
parseMessage(msg: WebSocketJsonResponse) {
if (msg.error) {
toast(i18n.t(msg.error), 'danger');
this.state = this.emptyState;
+ this.state.registerForm.captcha_answer = undefined;
+ // Refetch another captcha
+ WebSocketService.Instance.getCaptcha();
this.setState(this.state);
return;
} else {
UserService.Instance.login(data);
WebSocketService.Instance.userJoin();
this.props.history.push('/communities');
+ } else if (res.op == UserOperation.GetCaptcha) {
+ let data = res.data as GetCaptchaResponse;
+ if (data.ok) {
+ this.state.captcha = data;
+ this.state.registerForm.captcha_uuid = data.ok.uuid;
+ this.setState(this.state);
+ }
} else if (res.op == UserOperation.PasswordReset) {
toast(i18n.t('reset_password_mail_sent'));
} else if (res.op == UserOperation.GetSite) {