From 69d1301723c991404356679c46b7c206e6aa48d2 Mon Sep 17 00:00:00 2001 From: Dessalines Date: Thu, 17 Oct 2019 21:25:23 -0700 Subject: [PATCH] Make delete account require password. - Fixes #301 --- server/src/api/user.rs | 9 +++++++++ ui/src/components/user.tsx | 22 +++++++++++++++++----- ui/src/interfaces.ts | 4 ++++ ui/src/services/WebSocketService.ts | 5 ++--- ui/src/translations/en.ts | 2 +- 5 files changed, 33 insertions(+), 9 deletions(-) diff --git a/server/src/api/user.rs b/server/src/api/user.rs index b0ed5a4bb..2de809055 100644 --- a/server/src/api/user.rs +++ b/server/src/api/user.rs @@ -105,6 +105,7 @@ pub struct GetReplies { #[derive(Serialize, Deserialize)] pub struct DeleteAccount { + password: String, auth: String, } @@ -601,6 +602,14 @@ impl Perform for Oper { let user_id = claims.id; + let user: User_ = User_::read(&conn, user_id)?; + + // Verify the password + let valid: bool = verify(&data.password, &user.password_encrypted).unwrap_or(false); + if !valid { + return Err(APIError::err(&self.op, "password_incorrect"))?; + } + // Comments let comments = CommentView::list( &conn, diff --git a/ui/src/components/user.tsx b/ui/src/components/user.tsx index c53a672a0..88476bc82 100644 --- a/ui/src/components/user.tsx +++ b/ui/src/components/user.tsx @@ -2,7 +2,7 @@ import { Component, linkEvent } from 'inferno'; import { Link } from 'inferno-router'; import { Subscription } from "rxjs"; import { retryWhen, delay, take } from 'rxjs/operators'; -import { UserOperation, Post, Comment, CommunityUser, GetUserDetailsForm, SortType, UserDetailsResponse, UserView, CommentResponse, UserSettingsForm, LoginResponse, BanUserResponse, AddAdminResponse } from '../interfaces'; +import { UserOperation, Post, Comment, CommunityUser, GetUserDetailsForm, SortType, UserDetailsResponse, UserView, CommentResponse, UserSettingsForm, LoginResponse, BanUserResponse, AddAdminResponse, DeleteAccountForm } from '../interfaces'; import { WebSocketService, UserService } from '../services'; import { msgOp, fetchLimit, routeSortTypeToEnum, capitalizeFirstLetter, themes, setTheme } from '../utils'; import { PostListing } from './post-listing'; @@ -33,6 +33,7 @@ interface UserState { userSettingsLoading: boolean; deleteAccountLoading: boolean; deleteAccountShowConfirm: boolean; + deleteAccountForm: DeleteAccountForm; } export class User extends Component { @@ -69,6 +70,9 @@ export class User extends Component { userSettingsLoading: null, deleteAccountLoading: null, deleteAccountShowConfirm: false, + deleteAccountForm: { + password: null, + } } constructor(props: any, context: any) { @@ -316,9 +320,10 @@ export class User extends Component { {this.state.deleteAccountShowConfirm && <> - - + + + } @@ -453,12 +458,17 @@ export class User extends Component { i.setState(i.state); } + handleDeleteAccountPasswordChange(i: User, event: any) { + i.state.deleteAccountForm.password = event.target.value; + i.setState(i.state); + } + handleDeleteAccount(i: User, event: any) { event.preventDefault(); i.state.deleteAccountLoading = true; i.setState(i.state); - WebSocketService.Instance.deleteAccount(); + WebSocketService.Instance.deleteAccount(i.state.deleteAccountForm); } parseMessage(msg: any) { @@ -466,6 +476,8 @@ export class User extends Component { let op: UserOperation = msgOp(msg); if (msg.error) { alert(i18n.t(msg.error)); + this.state.deleteAccountLoading = false; + this.setState(this.state); return; } else if (op == UserOperation.GetUserDetails) { let res: UserDetailsResponse = msg; diff --git a/ui/src/interfaces.ts b/ui/src/interfaces.ts index 4bd013ce9..e11dee04a 100644 --- a/ui/src/interfaces.ts +++ b/ui/src/interfaces.ts @@ -600,3 +600,7 @@ export interface SearchResponse { communities: Array; users: Array; } + +export interface DeleteAccountForm { + password: string; +} diff --git a/ui/src/services/WebSocketService.ts b/ui/src/services/WebSocketService.ts index f8838d400..987cbfdf1 100644 --- a/ui/src/services/WebSocketService.ts +++ b/ui/src/services/WebSocketService.ts @@ -1,5 +1,5 @@ import { wsUri } from '../env'; -import { LoginForm, RegisterForm, UserOperation, CommunityForm, PostForm, SavePostForm, CommentForm, SaveCommentForm, CommentLikeForm, GetPostsForm, CreatePostLikeForm, FollowCommunityForm, GetUserDetailsForm, ListCommunitiesForm, GetModlogForm, BanFromCommunityForm, AddModToCommunityForm, TransferCommunityForm, AddAdminForm, TransferSiteForm, BanUserForm, SiteForm, Site, UserView, GetRepliesForm, SearchForm, UserSettingsForm } from '../interfaces'; +import { LoginForm, RegisterForm, UserOperation, CommunityForm, PostForm, SavePostForm, CommentForm, SaveCommentForm, CommentLikeForm, GetPostsForm, CreatePostLikeForm, FollowCommunityForm, GetUserDetailsForm, ListCommunitiesForm, GetModlogForm, BanFromCommunityForm, AddModToCommunityForm, TransferCommunityForm, AddAdminForm, TransferSiteForm, BanUserForm, SiteForm, Site, UserView, GetRepliesForm, SearchForm, UserSettingsForm, DeleteAccountForm } from '../interfaces'; import { webSocket } from 'rxjs/webSocket'; import { Subject } from 'rxjs'; import { retryWhen, delay, take } from 'rxjs/operators'; @@ -199,8 +199,7 @@ export class WebSocketService { this.subject.next(this.wsSendWrapper(UserOperation.SaveUserSettings, userSettingsForm)); } - public deleteAccount() { - let form = {}; + public deleteAccount(form: DeleteAccountForm) { this.setAuth(form); this.subject.next(this.wsSendWrapper(UserOperation.DeleteAccount, form)); } diff --git a/ui/src/translations/en.ts b/ui/src/translations/en.ts index 7df3d0236..7a23e2099 100644 --- a/ui/src/translations/en.ts +++ b/ui/src/translations/en.ts @@ -56,7 +56,7 @@ export const en = { delete: 'delete', deleted: 'deleted', delete_account: 'Delete Account', - delete_account_confirm: 'Warning: this will permanently delete all your data. Are you sure?', + delete_account_confirm: 'Warning: this will permanently delete all your data. Enter your password to confirm.', restore: 'restore', ban: 'ban', ban_from_site: 'ban from site',