From 68e4b61808ee76730cdc9f4302700a60a2ebb3b5 Mon Sep 17 00:00:00 2001 From: Dessalines Date: Fri, 1 Nov 2019 23:41:57 -0700 Subject: Password reset mostly working. --- ui/src/components/login.tsx | 10 ++- ui/src/components/password_change.tsx | 160 ++++++++++++++++++++++++++++++++++ ui/src/index.tsx | 5 ++ ui/src/services/WebSocketService.ts | 5 ++ ui/src/translations/en.ts | 2 + ui/src/utils.ts | 5 ++ 6 files changed, 183 insertions(+), 4 deletions(-) create mode 100644 ui/src/components/password_change.tsx (limited to 'ui') diff --git a/ui/src/components/login.tsx b/ui/src/components/login.tsx index c2db7ee6..8d0df3e3 100644 --- a/ui/src/components/login.tsx +++ b/ui/src/components/login.tsx @@ -9,7 +9,7 @@ import { PasswordResetForm, } from '../interfaces'; import { WebSocketService, UserService } from '../services'; -import { msgOp } from '../utils'; +import { msgOp, validEmail } from '../utils'; import { i18n } from '../i18next'; import { T } from 'inferno-i18next'; @@ -113,12 +113,13 @@ export class Login extends Component { class="form-control" required /> -
# -
+
@@ -287,6 +288,7 @@ export class Login extends Component { } handlePasswordReset(i: Login) { + event.preventDefault(); let resetForm: PasswordResetForm = { email: i.state.loginForm.username_or_email, }; diff --git a/ui/src/components/password_change.tsx b/ui/src/components/password_change.tsx new file mode 100644 index 00000000..3e542f7b --- /dev/null +++ b/ui/src/components/password_change.tsx @@ -0,0 +1,160 @@ +import { Component, linkEvent } from 'inferno'; +import { Subscription } from 'rxjs'; +import { retryWhen, delay, take } from 'rxjs/operators'; +import { + UserOperation, + LoginResponse, + PasswordChangeForm, +} from '../interfaces'; +import { WebSocketService, UserService } from '../services'; +import { msgOp, capitalizeFirstLetter } from '../utils'; +import { i18n } from '../i18next'; +import { T } from 'inferno-i18next'; + +interface State { + passwordChangeForm: PasswordChangeForm; + loading: boolean; +} + +export class PasswordChange extends Component { + private subscription: Subscription; + + emptyState: State = { + passwordChangeForm: { + token: this.props.match.params.token, + password: undefined, + password_verify: undefined, + }, + loading: false, + }; + + constructor(props: any, context: any) { + super(props, context); + + this.state = this.emptyState; + + this.subscription = WebSocketService.Instance.subject + .pipe( + retryWhen(errors => + errors.pipe( + delay(3000), + take(10) + ) + ) + ) + .subscribe( + msg => this.parseMessage(msg), + err => console.error(err), + () => console.log('complete') + ); + } + + componentWillUnmount() { + this.subscription.unsubscribe(); + } + + componentDidMount() { + document.title = `${i18n.t('password_change')} - ${ + WebSocketService.Instance.site.name + }`; + } + + render() { + return ( +
+
+
+
+ # +
+ {this.passwordChangeForm()} +
+
+
+ ); + } + + passwordChangeForm() { + return ( +
+
+ +
+ +
+
+
+ +
+ +
+
+
+
+ +
+
+
+ ); + } + + handlePasswordChange(i: PasswordChange, event: any) { + i.state.passwordChangeForm.password = event.target.value; + i.setState(i.state); + } + + handleVerifyPasswordChange(i: PasswordChange, event: any) { + i.state.passwordChangeForm.password_verify = event.target.value; + i.setState(i.state); + } + + handlePasswordChangeSubmit(i: PasswordChange, event: any) { + event.preventDefault(); + i.state.loading = true; + i.setState(i.state); + + WebSocketService.Instance.passwordChange(i.state.passwordChangeForm); + } + + parseMessage(msg: any) { + let op: UserOperation = msgOp(msg); + if (msg.error) { + alert(i18n.t(msg.error)); + this.state.loading = false; + this.setState(this.state); + return; + } else { + if (op == UserOperation.PasswordChange) { + this.state = this.emptyState; + this.setState(this.state); + let res: LoginResponse = msg; + UserService.Instance.login(res); + this.props.history.push('/'); + } + } + } +} diff --git a/ui/src/index.tsx b/ui/src/index.tsx index f3c7ff38..2e50db88 100644 --- a/ui/src/index.tsx +++ b/ui/src/index.tsx @@ -7,6 +7,7 @@ import { Footer } from './components/footer'; import { Login } from './components/login'; import { CreatePost } from './components/create-post'; import { CreateCommunity } from './components/create-community'; +import { PasswordChange } from './components/password_change'; import { Post } from './components/post'; import { Community } from './components/community'; import { Communities } from './components/communities'; @@ -74,6 +75,10 @@ class Index extends Component { /> +
diff --git a/ui/src/services/WebSocketService.ts b/ui/src/services/WebSocketService.ts index c77816df..34da5850 100644 --- a/ui/src/services/WebSocketService.ts +++ b/ui/src/services/WebSocketService.ts @@ -31,6 +31,7 @@ import { UserSettingsForm, DeleteAccountForm, PasswordResetForm, + PasswordChangeForm, } from '../interfaces'; import { webSocket } from 'rxjs/webSocket'; import { Subject } from 'rxjs'; @@ -279,6 +280,10 @@ export class WebSocketService { this.subject.next(this.wsSendWrapper(UserOperation.PasswordReset, form)); } + public passwordChange(form: PasswordChangeForm) { + this.subject.next(this.wsSendWrapper(UserOperation.PasswordChange, form)); + } + private wsSendWrapper(op: UserOperation, data: any) { let send = { op: UserOperation[op], data: data }; console.log(send); diff --git a/ui/src/translations/en.ts b/ui/src/translations/en.ts index 4e0d81db..f73e0d09 100644 --- a/ui/src/translations/en.ts +++ b/ui/src/translations/en.ts @@ -118,6 +118,8 @@ export const en = { verify_password: 'Verify Password', forgot_password: 'forgot password', reset_password_mail_sent: 'Sent an Email to reset your password.', + password_change: 'Password Change', + new_password: 'New Password', no_email_setup: "This server hasn't correctly set up email.", email: 'Email', optional: 'Optional', diff --git a/ui/src/utils.ts b/ui/src/utils.ts index b9220a2d..9d2e720e 100644 --- a/ui/src/utils.ts +++ b/ui/src/utils.ts @@ -152,6 +152,11 @@ export function validURL(str: string) { } } +export function validEmail(email: string) { + let re = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/; + return re.test(String(email).toLowerCase()); +} + export function capitalizeFirstLetter(str: string): string { return str.charAt(0).toUpperCase() + str.slice(1); } -- cgit v1.2.3