Remove account deletion on the server
This commit is contained in:
parent
f67ca1d61d
commit
e5659c1da1
@ -283,6 +283,15 @@ public final class LocalDB implements EventListener {
|
|||||||
* @since Envoy Client v0.3-beta
|
* @since Envoy Client v0.3-beta
|
||||||
*/
|
*/
|
||||||
public void delete() {
|
public void delete() {
|
||||||
|
try {
|
||||||
|
|
||||||
|
// Save ID generator - can be used for other users in that db
|
||||||
|
if (hasIDGenerator())
|
||||||
|
SerializationUtils.write(idGeneratorFile, idGenerator);
|
||||||
|
} catch (final IOException e) {
|
||||||
|
EnvoyLog.getLogger(LocalDB.class).log(Level.SEVERE, "Unable to save local database: ",
|
||||||
|
e);
|
||||||
|
}
|
||||||
if (lastLoginFile != null)
|
if (lastLoginFile != null)
|
||||||
lastLoginFile.delete();
|
lastLoginFile.delete();
|
||||||
userFile.delete();
|
userFile.delete();
|
||||||
@ -427,10 +436,7 @@ public final class LocalDB implements EventListener {
|
|||||||
if (user.getID() == deletion.get())
|
if (user.getID() == deletion.get())
|
||||||
logger.log(Level.WARNING,
|
logger.log(Level.WARNING,
|
||||||
"I have been informed by the server that I have been deleted without even knowing it...");
|
"I have been informed by the server that I have been deleted without even knowing it...");
|
||||||
getChat(deletion.get()).ifPresent(chat -> {
|
getChat(deletion.get()).ifPresent(chat -> chat.setDisabled(true));
|
||||||
chat.setDisabled(true);
|
|
||||||
chat.setUnderlyingContactDeleted(true);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
package envoy.event.contact;
|
package envoy.client.event;
|
||||||
|
|
||||||
import envoy.event.Event;
|
import envoy.event.Event;
|
||||||
|
|
@ -18,7 +18,7 @@ import envoy.event.contact.*;
|
|||||||
import envoy.util.Bounds;
|
import envoy.util.Bounds;
|
||||||
|
|
||||||
import envoy.client.data.*;
|
import envoy.client.data.*;
|
||||||
import envoy.client.event.BackEvent;
|
import envoy.client.event.*;
|
||||||
import envoy.client.ui.control.*;
|
import envoy.client.ui.control.*;
|
||||||
import envoy.client.ui.listcell.ListCellFactory;
|
import envoy.client.ui.listcell.ListCellFactory;
|
||||||
|
|
||||||
|
@ -13,6 +13,7 @@ import javafx.scene.image.*;
|
|||||||
import javafx.scene.input.InputEvent;
|
import javafx.scene.input.InputEvent;
|
||||||
import javafx.scene.layout.HBox;
|
import javafx.scene.layout.HBox;
|
||||||
import javafx.stage.FileChooser;
|
import javafx.stage.FileChooser;
|
||||||
|
import javafx.util.Duration;
|
||||||
|
|
||||||
import dev.kske.eventbus.EventBus;
|
import dev.kske.eventbus.EventBus;
|
||||||
|
|
||||||
@ -38,7 +39,7 @@ public final class UserSettingsPane extends OnlineOnlySettingsPane {
|
|||||||
private final PasswordField newPasswordField = new PasswordField();
|
private final PasswordField newPasswordField = new PasswordField();
|
||||||
private final PasswordField repeatNewPasswordField = new PasswordField();
|
private final PasswordField repeatNewPasswordField = new PasswordField();
|
||||||
private final Button saveButton = new Button("Save");
|
private final Button saveButton = new Button("Save");
|
||||||
private final Button deleteAccountButton = new Button("Delete Account");
|
private final Button deleteAccountButton = new Button("Delete Account (Locally)");
|
||||||
|
|
||||||
private static final EventBus eventBus = EventBus.getInstance();
|
private static final EventBus eventBus = EventBus.getInstance();
|
||||||
private static final Logger logger = EnvoyLog.getLogger(UserSettingsPane.class);
|
private static final Logger logger = EnvoyLog.getLogger(UserSettingsPane.class);
|
||||||
@ -148,6 +149,13 @@ public final class UserSettingsPane extends OnlineOnlySettingsPane {
|
|||||||
// Displaying the delete account button
|
// Displaying the delete account button
|
||||||
deleteAccountButton.setAlignment(Pos.BASELINE_CENTER);
|
deleteAccountButton.setAlignment(Pos.BASELINE_CENTER);
|
||||||
deleteAccountButton.setOnAction(e -> UserUtil.deleteAccount());
|
deleteAccountButton.setOnAction(e -> UserUtil.deleteAccount());
|
||||||
|
deleteAccountButton.setText("Delete Account (locally)");
|
||||||
|
deleteAccountButton.setPrefHeight(25);
|
||||||
|
deleteAccountButton.getStyleClass().clear();
|
||||||
|
deleteAccountButton.getStyleClass().add("danger-button");
|
||||||
|
final var tooltip = new Tooltip("Remote deletion is currently unsupported.");
|
||||||
|
tooltip.setShowDelay(Duration.millis(100));
|
||||||
|
deleteAccountButton.setTooltip(tooltip);
|
||||||
getChildren().add(deleteAccountButton);
|
getChildren().add(deleteAccountButton);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10,7 +10,7 @@ import dev.kske.eventbus.EventBus;
|
|||||||
import envoy.data.*;
|
import envoy.data.*;
|
||||||
import envoy.data.User.UserStatus;
|
import envoy.data.User.UserStatus;
|
||||||
import envoy.event.*;
|
import envoy.event.*;
|
||||||
import envoy.event.contact.*;
|
import envoy.event.contact.UserOperation;
|
||||||
import envoy.util.EnvoyLog;
|
import envoy.util.EnvoyLog;
|
||||||
|
|
||||||
import envoy.client.data.Context;
|
import envoy.client.data.Context;
|
||||||
@ -129,32 +129,27 @@ public final class UserUtil {
|
|||||||
* @since Envoy Client v0.3-beta
|
* @since Envoy Client v0.3-beta
|
||||||
*/
|
*/
|
||||||
public static void deleteAccount() {
|
public static void deleteAccount() {
|
||||||
if (!context.getClient().isOnline())
|
|
||||||
return;
|
|
||||||
else {
|
|
||||||
|
|
||||||
// Show the first wall of defense, if not disabled by the user
|
// Show the first wall of defense, if not disabled by the user
|
||||||
final var outerAlert = new Alert(AlertType.CONFIRMATION);
|
final var outerAlert = new Alert(AlertType.CONFIRMATION);
|
||||||
outerAlert.setContentText(
|
outerAlert.setContentText(
|
||||||
"Are you sure you want to delete your account entirely? This action can seriously not be undone.");
|
"Are you sure you want to delete your account entirely? This action can seriously not be undone.");
|
||||||
outerAlert.setTitle("Delete Account?");
|
outerAlert.setTitle("Delete Account?");
|
||||||
AlertHelper.confirmAction(outerAlert, () -> {
|
AlertHelper.confirmAction(outerAlert, () -> {
|
||||||
|
|
||||||
// Show the final wall of defense in every case
|
// Show the final wall of defense in every case
|
||||||
final var lastAlert = new Alert(AlertType.WARNING,
|
final var lastAlert = new Alert(AlertType.WARNING,
|
||||||
"Do you REALLY want to delete your account? Last Warning. Proceed?",
|
"Do you REALLY want to delete your account? Last Warning. Proceed?",
|
||||||
ButtonType.CANCEL, ButtonType.OK);
|
ButtonType.CANCEL, ButtonType.OK);
|
||||||
lastAlert.setTitle("Delete Account?");
|
lastAlert.setTitle("Delete Account?");
|
||||||
lastAlert.showAndWait().filter(ButtonType.OK::equals).ifPresent(b2 -> {
|
lastAlert.showAndWait().filter(ButtonType.OK::equals).ifPresent(b2 -> {
|
||||||
|
|
||||||
// Delete the account
|
// Delete the account
|
||||||
context.getClient()
|
// TODO: Notify server of account deletion
|
||||||
.send(new AccountDeletion(context.getLocalDB().getUser().getID()));
|
context.getLocalDB().delete();
|
||||||
context.getLocalDB().delete();
|
logger.log(Level.INFO, "The user just deleted his account. Goodbye.");
|
||||||
logger.log(Level.INFO, "The user just deleted his account. Goodbye.");
|
ShutdownHelper.exit(true);
|
||||||
ShutdownHelper.exit(true);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
}
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -70,6 +70,17 @@
|
|||||||
-fx-text-fill: gray;
|
-fx-text-fill: gray;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.danger-button {
|
||||||
|
-fx-background-color: red;
|
||||||
|
-fx-text-fill: white;
|
||||||
|
-fx-background-radius: 0.2em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.danger-button:hover {
|
||||||
|
-fx-scale-x: 1.05;
|
||||||
|
-fx-scale-y: 1.05;
|
||||||
|
}
|
||||||
|
|
||||||
.received-message {
|
.received-message {
|
||||||
-fx-alignment: center-left;
|
-fx-alignment: center-left;
|
||||||
-fx-background-radius: 1.3em;
|
-fx-background-radius: 1.3em;
|
||||||
|
@ -30,6 +30,10 @@
|
|||||||
-fx-background-color: black;
|
-fx-background-color: black;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.tooltip {
|
||||||
|
-fx-text-fill: black;
|
||||||
|
}
|
||||||
|
|
||||||
#login-input-field {
|
#login-input-field {
|
||||||
-fx-border-color: black;
|
-fx-border-color: black;
|
||||||
}
|
}
|
||||||
|
@ -59,8 +59,7 @@ public final class Startup {
|
|||||||
new NameChangeProcessor(),
|
new NameChangeProcessor(),
|
||||||
new ProfilePicChangeProcessor(),
|
new ProfilePicChangeProcessor(),
|
||||||
new PasswordChangeRequestProcessor(),
|
new PasswordChangeRequestProcessor(),
|
||||||
new IssueProposalProcessor(),
|
new IssueProposalProcessor())));
|
||||||
new AccountDeletionProcessor())));
|
|
||||||
|
|
||||||
// Initialize the current message ID
|
// Initialize the current message ID
|
||||||
final var persistenceManager = PersistenceManager.getInstance();
|
final var persistenceManager = PersistenceManager.getInstance();
|
||||||
|
@ -27,18 +27,14 @@ import envoy.data.Message.MessageStatus;
|
|||||||
@Entity
|
@Entity
|
||||||
@Table(name = "messages")
|
@Table(name = "messages")
|
||||||
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
|
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
|
||||||
@NamedQueries({
|
@NamedQuery(name = Message.getPending, query = "SELECT m FROM Message m WHERE "
|
||||||
@NamedQuery(name = Message.getPending, query = "SELECT m FROM Message m WHERE "
|
// Send to or by the user before last seen
|
||||||
// Send to or by the user before last seen
|
+ "(m.sender = :user OR m.recipient = :user) AND m.creationDate > :lastSeen "
|
||||||
+ "(m.sender = :user OR m.recipient = :user) AND m.creationDate > :lastSeen "
|
// SENT to the user
|
||||||
// SENT to the user
|
+ "OR m.recipient = :user AND m.status = envoy.data.Message$MessageStatus.SENT "
|
||||||
+ "OR m.recipient = :user AND m.status = envoy.data.Message$MessageStatus.SENT "
|
// Sent by the user and RECEIVED / READ after last seen
|
||||||
// Sent by the user and RECEIVED / READ after last seen
|
+ "OR m.sender = :user AND (m.status = envoy.data.Message$MessageStatus.RECEIVED AND m.receivedDate > :lastSeen "
|
||||||
+ "OR m.sender = :user AND (m.status = envoy.data.Message$MessageStatus.RECEIVED AND m.receivedDate > :lastSeen "
|
+ "OR m.status = envoy.data.Message$MessageStatus.READ AND m.readDate > :lastSeen)")
|
||||||
+ "OR m.status = envoy.data.Message$MessageStatus.READ AND m.readDate > :lastSeen)"),
|
|
||||||
@NamedQuery(name = Message.deleteByRecipient, query = "DELETE FROM Message m WHERE m.recipient = :deleted OR m.sender = :deleted")
|
|
||||||
|
|
||||||
})
|
|
||||||
public class Message {
|
public class Message {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -49,13 +45,6 @@ public class Message {
|
|||||||
*/
|
*/
|
||||||
public static final String getPending = "Message.getPending";
|
public static final String getPending = "Message.getPending";
|
||||||
|
|
||||||
/**
|
|
||||||
* Named query deleting all messages of a user (parameter {@code :deleted}).
|
|
||||||
*
|
|
||||||
* @since Envoy Server v0.3-beta
|
|
||||||
*/
|
|
||||||
public static final String deleteByRecipient = "Message.deleteByRecipient";
|
|
||||||
|
|
||||||
@Id
|
@Id
|
||||||
protected long id;
|
protected long id;
|
||||||
|
|
||||||
|
@ -121,12 +121,9 @@ public final class PersistenceManager {
|
|||||||
transaction(() -> {
|
transaction(() -> {
|
||||||
|
|
||||||
// Remove this contact from the contact list of his contacts
|
// Remove this contact from the contact list of his contacts
|
||||||
for (final var remainingContact : contact.getContacts())
|
for (final var remainingContact : contact.contacts)
|
||||||
remainingContact.getContacts().remove(contact);
|
remainingContact.getContacts().remove(contact);
|
||||||
|
contact.contacts.clear();
|
||||||
entityManager
|
|
||||||
.createNamedQuery(Message.deleteByRecipient).setParameter("deleted", contact)
|
|
||||||
.executeUpdate();
|
|
||||||
});
|
});
|
||||||
remove(contact);
|
remove(contact);
|
||||||
}
|
}
|
||||||
|
@ -1,33 +0,0 @@
|
|||||||
package envoy.server.processors;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.time.Instant;
|
|
||||||
|
|
||||||
import envoy.event.contact.AccountDeletion;
|
|
||||||
|
|
||||||
import envoy.server.data.*;
|
|
||||||
import envoy.server.net.ObjectWriteProxy;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Leon Hofmeister
|
|
||||||
* @since Envoy Server v0.3-beta
|
|
||||||
*/
|
|
||||||
public class AccountDeletionProcessor implements ObjectProcessor<AccountDeletion> {
|
|
||||||
|
|
||||||
private static final PersistenceManager persistenceManager = PersistenceManager.getInstance();
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void process(AccountDeletion input, long socketID, ObjectWriteProxy writeProxy)
|
|
||||||
throws IOException {
|
|
||||||
final var contact = persistenceManager.getContactByID(input.get());
|
|
||||||
|
|
||||||
contact.getContacts().forEach(c -> {
|
|
||||||
persistenceManager.removeContactBidirectional(contact, c);
|
|
||||||
if (c instanceof User)
|
|
||||||
((User) c).setLatestContactDeletion(Instant.now());
|
|
||||||
});
|
|
||||||
|
|
||||||
writeProxy.writeToOnlineContacts(contact.getContacts(), input);
|
|
||||||
persistenceManager.deleteContact(contact);
|
|
||||||
}
|
|
||||||
}
|
|
@ -38,6 +38,8 @@ public final class GroupMessageStatusChangeProcessor
|
|||||||
}
|
}
|
||||||
|
|
||||||
GroupMessage gmsg = (GroupMessage) persistenceManager.getMessageByID(statusChange.getID());
|
GroupMessage gmsg = (GroupMessage) persistenceManager.getMessageByID(statusChange.getID());
|
||||||
|
if (gmsg == null)
|
||||||
|
return;
|
||||||
|
|
||||||
// Any other status than READ is not supposed to be sent to the server
|
// Any other status than READ is not supposed to be sent to the server
|
||||||
if (statusChange.get() != MessageStatus.READ) {
|
if (statusChange.get() != MessageStatus.READ) {
|
||||||
|
@ -4,7 +4,6 @@ import java.time.Instant;
|
|||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
|
|
||||||
import envoy.event.GroupResize;
|
import envoy.event.GroupResize;
|
||||||
import envoy.event.contact.AccountDeletion;
|
|
||||||
import envoy.util.EnvoyLog;
|
import envoy.util.EnvoyLog;
|
||||||
|
|
||||||
import envoy.server.data.*;
|
import envoy.server.data.*;
|
||||||
@ -25,11 +24,9 @@ public final class GroupResizeProcessor implements ObjectProcessor<GroupResize>
|
|||||||
final var group = persistenceManager.getGroupByID(groupResize.getGroupID());
|
final var group = persistenceManager.getGroupByID(groupResize.getGroupID());
|
||||||
final var sender = persistenceManager.getUserByID(groupResize.get().getID());
|
final var sender = persistenceManager.getUserByID(groupResize.get().getID());
|
||||||
|
|
||||||
// Inform the sender that this group has already been deleted
|
// TODO: Inform the sender that this group has already been deleted
|
||||||
if (group == null) {
|
if (group == null)
|
||||||
writeProxy.write(socketID, new AccountDeletion(groupResize.getGroupID()));
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
// Perform the desired operation
|
// Perform the desired operation
|
||||||
switch (groupResize.getOperation()) {
|
switch (groupResize.getOperation()) {
|
||||||
|
@ -32,6 +32,8 @@ public final class MessageStatusChangeProcessor implements ObjectProcessor<Messa
|
|||||||
}
|
}
|
||||||
|
|
||||||
final var msg = persistenceManager.getMessageByID(statusChange.getID());
|
final var msg = persistenceManager.getMessageByID(statusChange.getID());
|
||||||
|
if (msg == null)
|
||||||
|
return;
|
||||||
msg.read();
|
msg.read();
|
||||||
persistenceManager.updateMessage(msg);
|
persistenceManager.updateMessage(msg);
|
||||||
|
|
||||||
|
@ -4,7 +4,7 @@ import java.time.Instant;
|
|||||||
import java.util.logging.*;
|
import java.util.logging.*;
|
||||||
|
|
||||||
import envoy.event.ElementOperation;
|
import envoy.event.ElementOperation;
|
||||||
import envoy.event.contact.*;
|
import envoy.event.contact.UserOperation;
|
||||||
import envoy.util.EnvoyLog;
|
import envoy.util.EnvoyLog;
|
||||||
|
|
||||||
import envoy.server.data.PersistenceManager;
|
import envoy.server.data.PersistenceManager;
|
||||||
@ -27,11 +27,9 @@ public final class UserOperationProcessor implements ObjectProcessor<UserOperati
|
|||||||
final long contactID = evt.get().getID();
|
final long contactID = evt.get().getID();
|
||||||
final var recipient = persistenceManager.getUserByID(contactID);
|
final var recipient = persistenceManager.getUserByID(contactID);
|
||||||
|
|
||||||
// Inform the sender if the requested contact has already been deleted
|
// TODO: Inform the sender if the requested contact has already been deleted
|
||||||
if (recipient == null) {
|
if (recipient == null)
|
||||||
writeProxy.write(socketID, new AccountDeletion(contactID));
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
final var sender = persistenceManager.getUserByID(userID);
|
final var sender = persistenceManager.getUserByID(userID);
|
||||||
switch (evt.getOperationType()) {
|
switch (evt.getOperationType()) {
|
||||||
|
Reference in New Issue
Block a user