Commit 835ab151 authored by Julian Sparber's avatar Julian Sparber

accountsettings: password change and account destruction

* Allow a user to change the accounts password
* Allow users to delete there own account

https://gitlab.gnome.org/World/fractal/issues/21
parent ba74610a
......@@ -179,6 +179,14 @@ impl Backend {
let r = user::delete_three_pid(self, medium, address);
bkerror!(r, tx, BKResponse::DeleteThreePIDError);
}
Ok(BKCommand::ChangePassword(username, old_password, new_password)) => {
let r = user::change_password(self, username, old_password, new_password);
bkerror!(r, tx, BKResponse::ChangePasswordError);
}
Ok(BKCommand::AccountDestruction(username, password, flag)) => {
let r = user::account_destruction(self, username, password, flag);
bkerror!(r, tx, BKResponse::AccountDestructionError);
}
Ok(BKCommand::GetAvatar) => {
let r = user::get_avatar(self);
bkerror!(r, tx, BKResponse::AvatarError);
......
......@@ -32,6 +32,8 @@ pub enum BKCommand {
SubmitPhoneToken(String, String, String, String),
AddThreePID(String, String, String),
DeleteThreePID(String, String),
ChangePassword(String, String, String),
AccountDestruction(String, String, bool),
GetAvatar,
SetUserAvatar(String),
Sync,
......@@ -87,6 +89,8 @@ pub enum BKResponse {
GetTokenPhoneUsed,
GetTokenEmailUsed,
DeleteThreePID,
ChangePassword,
AccountDestruction,
Avatar(String),
SetUserAvatar(String),
Sync(String),
......@@ -129,6 +133,8 @@ pub enum BKResponse {
SubmitPhoneTokenError(Error),
AddThreePIDError(Error),
DeleteThreePIDError(Error),
ChangePasswordError(Error),
AccountDestructionError(Error),
AvatarError(Error),
SetUserAvatarError(Error),
LoginError(Error),
......
......@@ -229,6 +229,58 @@ pub fn delete_three_pid(bk: &Backend, medium: String, address: String) -> Result
Ok(())
}
pub fn change_password(bk: &Backend, username: String, old_password: String, new_password: String) -> Result<(), Error> {
let url = bk.url(&format!("account/password"), vec![])?;
let attrs = json!({
"new_password": new_password,
"auth": {
"type": "m.login.password",
"user": username,
"password": old_password,
}
});
let tx = bk.tx.clone();
post!(&url, &attrs,
|r: JsonValue| {
println!("{}", r);
tx.send(BKResponse::ChangePassword).unwrap();
},
|err| {
tx.send(BKResponse::ChangePasswordError(err)).unwrap();
}
);
Ok(())
}
pub fn account_destruction(bk: &Backend, username: String, password: String, flag: bool) -> Result<(), Error> {
let url = bk.url(&format!("account/deactivate"), vec![])?;
let attrs = json!({
"erase": flag,
"auth": {
"type": "m.login.password",
"user": username,
"password": password,
}
});
let tx = bk.tx.clone();
post!(&url, &attrs,
|r: JsonValue| {
println!("{}", r);
tx.send(BKResponse::AccountDestruction).unwrap();
},
|err| {
tx.send(BKResponse::AccountDestructionError(err)).unwrap();
}
);
Ok(())
}
pub fn get_avatar(bk: &Backend) -> Result<(), Error> {
let baseu = bk.get_base_url()?;
let userid = bk.data.lock().unwrap().user_id.clone();
......
......@@ -195,7 +195,32 @@
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="margin-top">18</property>
<property name="label" translatable="yes">●●●●●</property>
<child>
<object class="GtkStack" id="account_settings_password_stack">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkLabel" id="account_settings_password_button_label">
<property name="can_focus">True</property>
<property name="visible">True</property>
<property name="label" translatable="yes">●●●●●</property>
</object>
<packing>
<property name="name">label</property>
</packing>
</child>
<child>
<object class="GtkSpinner" id="account_settings_password_button_spinner">
<property name="can_focus">True</property>
<property name="visible">True</property>
<property name="active">True</property>
</object>
<packing>
<property name="name">spinner</property>
</packing>
</child>
</object>
</child>
</object>
<packing>
<property name="top-attach">3</property>
......@@ -425,17 +450,26 @@
<property name="wrap">True</property>
<property name="max-width-chars">35</property>
<property name="xalign">0</property>
<property name="label" translatable="yes">To confirm that you really want to deactivate this account type in your email address:</property>
<property name="label" translatable="yes">To confirm that you really want to deactivate this account type in your password:</property>
</object>
</child>
<child>
<object class="GtkEntry">
<object class="GtkEntry" id="account_settings_delete_password_confirm">
<property name="visible">True</property>
<property name="visibility">False</property>
<property name="can_focus">True</property>
</object>
</child>
<child>
<object class="GtkButton" id="account_settings_delete_account_btn">
<object class="GtkCheckButton" id="account_settings_delete_check">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="halign">end</property>
<property name="label" translatable="yes">Also erase all messages</property>
</object>
</child>
<child>
<object class="GtkButton" id="account_settings_delete_btn">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="halign">end</property>
......
......@@ -189,6 +189,11 @@ pub fn backend_loop(rx: Receiver<BKResponse>) {
}
// errors
Ok(BKResponse::ChangePasswordError(err)) => {
let error = gettext("Couldn't change the password");
println!("ERROR: {:?}", err);
APPOP!(show_password_error_dialog, (error));
},
Ok(BKResponse::GetTokenEmailError(err)) => {
let error = gettext("Couldn't add the email address.");
println!("ERROR: {:?}", err);
......
......@@ -49,6 +49,12 @@ impl App {
let verify_password = self.ui.builder
.get_object::<gtk::Entry>("password-dialog-verify-entry")
.expect("Can't find password-dialog-verify-entry in ui file.");
let destruction_entry = self.ui.builder
.get_object::<gtk::Entry>("account_settings_delete_password_confirm")
.expect("Can't find account_settings_delete_password_confirm in ui file.");
let destruction_btn = self.ui.builder
.get_object::<gtk::Button>("account_settings_delete_btn")
.expect("Can't find account_settings_delete_btn in ui file.");
dialog.connect_delete_event(clone!(op => move |_, _| {
op.lock().unwrap().close_account_settings_dialog();
......@@ -152,6 +158,7 @@ impl App {
}));
confirm_password.connect_clicked(clone!(op => move |_| {
op.lock().unwrap().set_new_password();
op.lock().unwrap().close_password_dialog();
}));
......@@ -195,11 +202,19 @@ impl App {
}
glib::signal::Inhibit(false)
}));
/*
invite.set_sensitive(false);
invite.connect_clicked(clone!(op => move |_| {
op.lock().unwrap().start_chat();
}));
*/
destruction_entry.connect_property_text_notify(clone!(destruction_btn => move |w| {
if let Some(text) = w.get_text() {
if text != "" {
destruction_btn.set_sensitive(true);
return;
}
}
destruction_btn.set_sensitive(false);
}));
destruction_btn.connect_clicked(clone!(op => move |_| {
op.lock().unwrap().account_destruction();
}));
}
}
......@@ -28,20 +28,20 @@ impl AppOp {
let _ = self.backend.send(BKCommand::AddThreePID(String::from("vector.im"), String::from("canitworksandia2"), sid.clone()));
}
else {
self.show_three_pid_error_dialog(String::from("The validation code is not correct."));
self.show_error_dialog(String::from("The validation code is not correct."));
self.get_three_pid();
}
}
pub fn show_phone_dialog(&self, sid: String) {
let parent = self.ui.builder
.get_object::<gtk::Dialog>("account_settings_dialog")
.expect("Can't find account_settings_dialog in ui file.");
pub fn show_phone_dialog(&self, sid: String) {
let parent = self.ui.builder
.get_object::<gtk::Dialog>("account_settings_dialog")
.expect("Can't find account_settings_dialog in ui file.");
let entry = gtk::Entry::new();
let msg = String::from("Insert the code recived via SMS");
let flags = gtk::DialogFlags::MODAL | gtk::DialogFlags::DESTROY_WITH_PARENT;
let dialog = gtk::MessageDialog::new(Some(&parent), flags, gtk::MessageType::Error, gtk::ButtonsType::None, &msg);
let msg = String::from("Insert the code recived via SMS");
let flags = gtk::DialogFlags::MODAL | gtk::DialogFlags::DESTROY_WITH_PARENT;
let dialog = gtk::MessageDialog::new(Some(&parent), flags, gtk::MessageType::Error, gtk::ButtonsType::None, &msg);
if let Some(area) = dialog.get_message_area() {
if let Ok(area) = area.downcast::<gtk::Box>() {
area.add(&entry);
......@@ -107,6 +107,10 @@ impl AppOp {
}
pub fn show_three_pid_error_dialog(&self, error: String) {
self.show_error_dialog(error);
}
pub fn show_error_dialog(&self, error: String) {
let parent = self.ui.builder
.get_object::<gtk::Dialog>("account_settings_dialog")
.expect("Can't find account_settings_dialog in ui file.");
......@@ -141,7 +145,6 @@ impl AppOp {
}
}
pub fn show_account_settings_dialog(&self) {
let dialog = self.ui.builder
.get_object::<gtk::Dialog>("account_settings_dialog")
......@@ -167,6 +170,18 @@ impl AppOp {
let stack = self.ui.builder
.get_object::<gtk::Stack>("account_settings_stack")
.expect("Can't find account_settings_delete_box in ui file.");
let destruction_btn = self.ui.builder
.get_object::<gtk::Button>("account_settings_delete_btn")
.expect("Can't find account_settings_delete_btn in ui file.");
let destruction_entry = self.ui.builder
.get_object::<gtk::Entry>("account_settings_delete_password_confirm")
.expect("Can't find account_settings_delete_password_confirm in ui file.");
let password_btn = self.ui.builder
.get_object::<gtk::Button>("account_settings_password")
.expect("Can't find account_settings_password in ui file.");
let password_btn_stack = self.ui.builder
.get_object::<gtk::Stack>("account_settings_password_stack")
.expect("Can't find account_settings_password_stack in ui file.");
stack.set_visible_child_name("loading");
self.get_three_pid();
......@@ -185,6 +200,13 @@ impl AppOp {
avatar.add(&w);
avatar.show();
/* reset the password button */
password_btn_stack.set_visible_child_name("label");
password_btn.set_sensitive(true);
destruction_btn.set_sensitive(false);
destruction_entry.set_text("");
dialog.set_redraw_on_allocate(true);
advanced_box.set_redraw_on_allocate(true);
delete_box.set_redraw_on_allocate(true);
......@@ -204,6 +226,9 @@ impl AppOp {
let stack = self.ui.builder
.get_object::<gtk::Stack>("account_settings_stack")
.expect("Can't find account_settings_delete_box in ui file.");
let password = self.ui.builder
.get_object::<gtk::Button>("account_settings_password")
.expect("Can't find account_settings_password in ui file.");
let mut first_email = true;
let mut first_phone = true;
......@@ -212,7 +237,7 @@ impl AppOp {
let mut child = grid.get_child_at(1, i);
while child.is_some() {
if let Some(child) = child.clone() {
if child != phone && child != email {
if child != phone && child != email && child != password {
grid.remove_row(i);
}
else {
......@@ -300,21 +325,12 @@ impl AppOp {
let command = BKCommand::SetUserAvatar(user.to_string());
self.backend.send(command).unwrap();
}
}
pub fn close_account_settings_dialog(&mut self) {
let dialog = self.ui.builder
.get_object::<gtk::Dialog>("account_settings_dialog")
.expect("Can't find account_settings_dialog in ui file.");
/*
let avatar = self.ui.builder
.get_object::<gtk::Container>("account_settings_avatar")
.expect("Can't find account_settings_avatar in ui file.");
let name = self.ui.builder
.get_object::<gtk::Entry>("account_settings_name")
.expect("Can't find account_settings_name in ui file.");
*/
let advanced = self.ui.builder
.get_object::<gtk::Revealer>("account_settings_advanced")
.expect("Can't find account_settings_advanced in ui file.");
......@@ -338,6 +354,45 @@ impl AppOp {
dialog.resize(700, 200);
}
pub fn set_new_password(&mut self) {
let old_password = self.ui.builder
.get_object::<gtk::Entry>("password-dialog-old-entry")
.expect("Can't find password-dialog-old-entry in ui file.");
let new_password = self.ui.builder
.get_object::<gtk::Entry>("password-dialog-entry")
.expect("Can't find password-dialog-entry in ui file.");
let password_btn = self.ui.builder
.get_object::<gtk::Button>("account_settings_password")
.expect("Can't find account_settings_password in ui file.");
let password_btn_stack = self.ui.builder
.get_object::<gtk::Stack>("account_settings_password_stack")
.expect("Can't find account_settings_password_stack in ui file.");
if let Some(old) = old_password.get_text() {
if let Some(new) = new_password.get_text() {
if let Some(mxid) = self.uid.clone() {
if old != "" && new != "" {
password_btn.set_sensitive(false);
password_btn_stack.set_visible_child_name("spinner");
let _ = self.backend.send(BKCommand::ChangePassword(mxid, old, new));
}
}
}
}
}
pub fn show_password_error_dialog(&self, error: String) {
let password_btn = self.ui.builder
.get_object::<gtk::Button>("account_settings_password")
.expect("Can't find account_settings_password in ui file.");
let password_btn_stack = self.ui.builder
.get_object::<gtk::Stack>("account_settings_password_stack")
.expect("Can't find account_settings_password_stack in ui file.");
self.show_error_dialog(error);
password_btn.set_sensitive(true);
password_btn_stack.set_visible_child_name("label");
}
pub fn close_password_dialog(&mut self) {
let dialog = self.ui.builder
.get_object::<gtk::Dialog>("password_dialog")
......@@ -357,4 +412,19 @@ impl AppOp {
verify_password.set_text("");
dialog.hide();
}
pub fn account_destruction(&self) {
let entry = self.ui.builder
.get_object::<gtk::Entry>("account_settings_delete_password_confirm")
.expect("Can't find account_settings_delete_password_confirm in ui file.");
let mark = self.ui.builder
.get_object::<gtk::CheckButton>("account_settings_delete_check")
.expect("Can't find account_settings_delete_check in ui file.");
let flag = mark.get_active();
if let Some(password) = entry.get_text() {
if let Some(mxid) = self.uid.clone() {
let _ = self.backend.send(BKCommand::AccountDestruction(mxid, password, flag));
}
}
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment