Adding permanently delete account comments and posts.
- Fixes #285 - Fixes #58
This commit is contained in:
parent
c0821fcaa5
commit
903d73d665
7 changed files with 117 additions and 2 deletions
|
@ -56,6 +56,7 @@ pub enum UserOperation {
|
||||||
SaveUserSettings,
|
SaveUserSettings,
|
||||||
TransferCommunity,
|
TransferCommunity,
|
||||||
TransferSite,
|
TransferSite,
|
||||||
|
DeleteAccount,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Fail, Debug)]
|
#[derive(Fail, Debug)]
|
||||||
|
|
|
@ -103,6 +103,11 @@ pub struct GetReplies {
|
||||||
auth: String,
|
auth: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize)]
|
||||||
|
pub struct DeleteAccount {
|
||||||
|
auth: String,
|
||||||
|
}
|
||||||
|
|
||||||
impl Perform<LoginResponse> for Oper<Login> {
|
impl Perform<LoginResponse> for Oper<Login> {
|
||||||
fn perform(&self) -> Result<LoginResponse, Error> {
|
fn perform(&self) -> Result<LoginResponse, Error> {
|
||||||
let data: &Login = &self.data;
|
let data: &Login = &self.data;
|
||||||
|
@ -583,3 +588,67 @@ impl Perform<GetRepliesResponse> for Oper<MarkAllAsRead> {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Perform<LoginResponse> for Oper<DeleteAccount> {
|
||||||
|
fn perform(&self) -> Result<LoginResponse, Error> {
|
||||||
|
let data: &DeleteAccount = &self.data;
|
||||||
|
let conn = establish_connection();
|
||||||
|
|
||||||
|
let claims = match Claims::decode(&data.auth) {
|
||||||
|
Ok(claims) => claims.claims,
|
||||||
|
Err(_e) => return Err(APIError::err(&self.op, "not_logged_in"))?,
|
||||||
|
};
|
||||||
|
|
||||||
|
let user_id = claims.id;
|
||||||
|
|
||||||
|
// Comments
|
||||||
|
let comments = CommentView::list(&conn, &SortType::New, None, Some(user_id), None, None, false, None, Some(std::i64::MAX))?;
|
||||||
|
|
||||||
|
for comment in &comments {
|
||||||
|
let comment_form = CommentForm {
|
||||||
|
content: "*Permananently Deleted*".to_string(),
|
||||||
|
parent_id: comment.to_owned().parent_id,
|
||||||
|
post_id: comment.to_owned().post_id,
|
||||||
|
creator_id: comment.to_owned().creator_id,
|
||||||
|
removed: None,
|
||||||
|
deleted: Some(true),
|
||||||
|
read: None,
|
||||||
|
updated: Some(naive_now()),
|
||||||
|
};
|
||||||
|
|
||||||
|
let _updated_comment = match Comment::update(&conn, comment.id, &comment_form) {
|
||||||
|
Ok(comment) => comment,
|
||||||
|
Err(_e) => return Err(APIError::err(&self.op, "couldnt_update_comment"))?,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Posts
|
||||||
|
let posts = PostView::list(&conn, PostListingType::All, &SortType::New,None, Some(user_id), None, None, None, true, false, false, None, Some(std::i64::MAX))?;
|
||||||
|
|
||||||
|
for post in &posts {
|
||||||
|
let post_form = PostForm {
|
||||||
|
name: "*Permananently Deleted*".to_string(),
|
||||||
|
url: Some("https://deleted.com".to_string()),
|
||||||
|
body: Some("*Permananently Deleted*".to_string()),
|
||||||
|
creator_id: post.to_owned().creator_id,
|
||||||
|
community_id: post.to_owned().community_id,
|
||||||
|
removed: None,
|
||||||
|
deleted: Some(true),
|
||||||
|
nsfw: post.to_owned().nsfw,
|
||||||
|
locked: None,
|
||||||
|
stickied: None,
|
||||||
|
updated: Some(naive_now()),
|
||||||
|
};
|
||||||
|
|
||||||
|
let _updated_post = match Post::update(&conn, post.id, &post_form) {
|
||||||
|
Ok(post) => post,
|
||||||
|
Err(_e) => return Err(APIError::err(&self.op, "couldnt_update_post"))?,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(LoginResponse {
|
||||||
|
op: self.op.to_string(),
|
||||||
|
jwt: data.auth.to_owned(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -519,5 +519,10 @@ fn parse_json_message(chat: &mut ChatServer, msg: StandardMessage) -> Result<Str
|
||||||
let res = Oper::new(user_operation, transfer_site).perform()?;
|
let res = Oper::new(user_operation, transfer_site).perform()?;
|
||||||
Ok(serde_json::to_string(&res)?)
|
Ok(serde_json::to_string(&res)?)
|
||||||
}
|
}
|
||||||
|
UserOperation::DeleteAccount => {
|
||||||
|
let delete_account: DeleteAccount = serde_json::from_str(data)?;
|
||||||
|
let res = Oper::new(user_operation, delete_account).perform()?;
|
||||||
|
Ok(serde_json::to_string(&res)?)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
34
ui/src/components/user.tsx
vendored
34
ui/src/components/user.tsx
vendored
|
@ -31,6 +31,8 @@ interface UserState {
|
||||||
loading: boolean;
|
loading: boolean;
|
||||||
userSettingsForm: UserSettingsForm;
|
userSettingsForm: UserSettingsForm;
|
||||||
userSettingsLoading: boolean;
|
userSettingsLoading: boolean;
|
||||||
|
deleteAccountLoading: boolean;
|
||||||
|
deleteAccountShowConfirm: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class User extends Component<any, UserState> {
|
export class User extends Component<any, UserState> {
|
||||||
|
@ -65,6 +67,8 @@ export class User extends Component<any, UserState> {
|
||||||
auth: null,
|
auth: null,
|
||||||
},
|
},
|
||||||
userSettingsLoading: null,
|
userSettingsLoading: null,
|
||||||
|
deleteAccountLoading: null,
|
||||||
|
deleteAccountShowConfirm: false,
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(props: any, context: any) {
|
constructor(props: any, context: any) {
|
||||||
|
@ -307,8 +311,17 @@ export class User extends Component<any, UserState> {
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group row mb-0">
|
<div class="form-group row mb-0">
|
||||||
<div class="col-12">
|
<div class="col-12">
|
||||||
<button type="submit" class="btn btn-secondary">{this.state.userSettingsLoading ?
|
<button type="submit" class="btn btn-secondary mr-4">{this.state.userSettingsLoading ?
|
||||||
<svg class="icon icon-spinner spin"><use xlinkHref="#icon-spinner"></use></svg> : capitalizeFirstLetter(i18n.t('save'))}</button>
|
<svg class="icon icon-spinner spin"><use xlinkHref="#icon-spinner"></use></svg> : capitalizeFirstLetter(i18n.t('save'))}</button>
|
||||||
|
<button class="btn btn-danger" onClick={linkEvent(this, this.handleDeleteAccountShowConfirmToggle)}><T i18nKey="delete_account">#</T></button>
|
||||||
|
{this.state.deleteAccountShowConfirm &&
|
||||||
|
<>
|
||||||
|
<div class="mt-2 alert alert-danger" role="alert"><T i18nKey="delete_account_confirm">#</T></div>
|
||||||
|
<button class="btn btn-danger mr-4" onClick={linkEvent(this, this.handleDeleteAccount)}>{this.state.deleteAccountLoading ?
|
||||||
|
<svg class="icon icon-spinner spin"><use xlinkHref="#icon-spinner"></use></svg> : capitalizeFirstLetter(i18n.t('yes'))}</button>
|
||||||
|
<button class="btn btn-secondary" onClick={linkEvent(this, this.handleDeleteAccountShowConfirmToggle)}><T i18nKey="cancel">#</T></button>
|
||||||
|
</>
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
@ -434,6 +447,20 @@ export class User extends Component<any, UserState> {
|
||||||
WebSocketService.Instance.saveUserSettings(i.state.userSettingsForm);
|
WebSocketService.Instance.saveUserSettings(i.state.userSettingsForm);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
handleDeleteAccountShowConfirmToggle(i: User, event: any) {
|
||||||
|
event.preventDefault();
|
||||||
|
i.state.deleteAccountShowConfirm = !i.state.deleteAccountShowConfirm;
|
||||||
|
i.setState(i.state);
|
||||||
|
}
|
||||||
|
|
||||||
|
handleDeleteAccount(i: User, event: any) {
|
||||||
|
event.preventDefault();
|
||||||
|
i.state.deleteAccountLoading = true;
|
||||||
|
i.setState(i.state);
|
||||||
|
|
||||||
|
WebSocketService.Instance.deleteAccount();
|
||||||
|
}
|
||||||
|
|
||||||
parseMessage(msg: any) {
|
parseMessage(msg: any) {
|
||||||
console.log(msg);
|
console.log(msg);
|
||||||
let op: UserOperation = msgOp(msg);
|
let op: UserOperation = msgOp(msg);
|
||||||
|
@ -505,6 +532,11 @@ export class User extends Component<any, UserState> {
|
||||||
this.setState(this.state);
|
this.setState(this.state);
|
||||||
let res: LoginResponse = msg;
|
let res: LoginResponse = msg;
|
||||||
UserService.Instance.login(res);
|
UserService.Instance.login(res);
|
||||||
|
} else if (op == UserOperation.DeleteAccount) {
|
||||||
|
this.state.deleteAccountLoading = false;
|
||||||
|
this.state.deleteAccountShowConfirm = false;
|
||||||
|
this.setState(this.state);
|
||||||
|
this.context.router.history.push('/');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
2
ui/src/interfaces.ts
vendored
2
ui/src/interfaces.ts
vendored
|
@ -1,5 +1,5 @@
|
||||||
export enum UserOperation {
|
export enum UserOperation {
|
||||||
Login, Register, CreateCommunity, CreatePost, ListCommunities, ListCategories, GetPost, GetCommunity, CreateComment, EditComment, SaveComment, CreateCommentLike, GetPosts, CreatePostLike, EditPost, SavePost, EditCommunity, FollowCommunity, GetFollowedCommunities, GetUserDetails, GetReplies, GetModlog, BanFromCommunity, AddModToCommunity, CreateSite, EditSite, GetSite, AddAdmin, BanUser, Search, MarkAllAsRead, SaveUserSettings, TransferCommunity, TransferSite
|
Login, Register, CreateCommunity, CreatePost, ListCommunities, ListCategories, GetPost, GetCommunity, CreateComment, EditComment, SaveComment, CreateCommentLike, GetPosts, CreatePostLike, EditPost, SavePost, EditCommunity, FollowCommunity, GetFollowedCommunities, GetUserDetails, GetReplies, GetModlog, BanFromCommunity, AddModToCommunity, CreateSite, EditSite, GetSite, AddAdmin, BanUser, Search, MarkAllAsRead, SaveUserSettings, TransferCommunity, TransferSite, DeleteAccount
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum CommentSortType {
|
export enum CommentSortType {
|
||||||
|
|
6
ui/src/services/WebSocketService.ts
vendored
6
ui/src/services/WebSocketService.ts
vendored
|
@ -199,6 +199,12 @@ export class WebSocketService {
|
||||||
this.subject.next(this.wsSendWrapper(UserOperation.SaveUserSettings, userSettingsForm));
|
this.subject.next(this.wsSendWrapper(UserOperation.SaveUserSettings, userSettingsForm));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public deleteAccount() {
|
||||||
|
let form = {};
|
||||||
|
this.setAuth(form);
|
||||||
|
this.subject.next(this.wsSendWrapper(UserOperation.DeleteAccount, form));
|
||||||
|
}
|
||||||
|
|
||||||
private wsSendWrapper(op: UserOperation, data: any) {
|
private wsSendWrapper(op: UserOperation, data: any) {
|
||||||
let send = { op: UserOperation[op], data: data };
|
let send = { op: UserOperation[op], data: data };
|
||||||
console.log(send);
|
console.log(send);
|
||||||
|
|
2
ui/src/translations/en.ts
vendored
2
ui/src/translations/en.ts
vendored
|
@ -55,6 +55,8 @@ export const en = {
|
||||||
mark_as_unread: 'mark as unread',
|
mark_as_unread: 'mark as unread',
|
||||||
delete: 'delete',
|
delete: 'delete',
|
||||||
deleted: 'deleted',
|
deleted: 'deleted',
|
||||||
|
delete_account: 'Delete Account',
|
||||||
|
delete_account_confirm: 'Warning: this will permanently delete all your data. Are you sure?',
|
||||||
restore: 'restore',
|
restore: 'restore',
|
||||||
ban: 'ban',
|
ban: 'ban',
|
||||||
ban_from_site: 'ban from site',
|
ban_from_site: 'ban from site',
|
||||||
|
|
Loading…
Reference in a new issue