diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index f78d12dbf4ba744e3885a6dcfe3599063ed05c15..a828efd2ab4c93590767fdfb65db980b7dc1c1f1 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -99,6 +99,11 @@ android:exported="false" android:label="@string/label_topic" android:windowSoftInputMode="adjustResize" /> + <activity + android:name=".ui.chat.passwordchange.PasswordChangeActivity" + android:exported="false" + android:label="@string/label_password_change" + android:windowSoftInputMode="adjustResize" /> <!-- Core Settings --> <activity diff --git a/app/src/main/java/de/kuschku/quasseldroid/dagger/ActivityModule.kt b/app/src/main/java/de/kuschku/quasseldroid/dagger/ActivityModule.kt index 0d955e3b22988bf883b2f02d0bb8435f45f97194..1f03c03c03a0c6aa91daad9dda9bbcd6da8b3ad3 100644 --- a/app/src/main/java/de/kuschku/quasseldroid/dagger/ActivityModule.kt +++ b/app/src/main/java/de/kuschku/quasseldroid/dagger/ActivityModule.kt @@ -32,6 +32,8 @@ import de.kuschku.quasseldroid.ui.chat.info.core.CoreInfoActivity import de.kuschku.quasseldroid.ui.chat.info.core.CoreInfoFragmentProvider import de.kuschku.quasseldroid.ui.chat.info.user.UserInfoActivity import de.kuschku.quasseldroid.ui.chat.info.user.UserInfoFragmentProvider +import de.kuschku.quasseldroid.ui.chat.passwordchange.PasswordChangeActivity +import de.kuschku.quasseldroid.ui.chat.passwordchange.PasswordChangeFragmentProvider import de.kuschku.quasseldroid.ui.chat.topic.TopicActivity import de.kuschku.quasseldroid.ui.chat.topic.TopicFragmentProvider import de.kuschku.quasseldroid.ui.clientsettings.about.AboutActivity @@ -109,6 +111,10 @@ abstract class ActivityModule { @ContributesAndroidInjector(modules = [TopicFragmentProvider::class, SettingsModule::class, DatabaseModule::class, ActivityBaseModule::class]) abstract fun bindTopicActivity(): TopicActivity + @ActivityScope + @ContributesAndroidInjector(modules = [PasswordChangeFragmentProvider::class, SettingsModule::class, DatabaseModule::class, ActivityBaseModule::class]) + abstract fun bindPasswordChangeActivity(): PasswordChangeActivity + @ActivityScope @ContributesAndroidInjector(modules = [ClientSettingsFragmentProvider::class, SettingsModule::class, DatabaseModule::class, ActivityBaseModule::class]) abstract fun bindClientSettingsActivity(): ClientSettingsActivity diff --git a/app/src/main/java/de/kuschku/quasseldroid/ui/chat/ChatActivity.kt b/app/src/main/java/de/kuschku/quasseldroid/ui/chat/ChatActivity.kt index dbde648ea40f9ef7f94d014466480df812df7cf7..23cdf3f20aef44722f40fedb1b660f98f4f51862 100644 --- a/app/src/main/java/de/kuschku/quasseldroid/ui/chat/ChatActivity.kt +++ b/app/src/main/java/de/kuschku/quasseldroid/ui/chat/ChatActivity.kt @@ -319,7 +319,6 @@ class ChatActivity : ServiceBoundActivity(), SharedPreferences.OnSharedPreferenc } } } - // If we connect to a new network without statusbuffer, the bufferid may be -networkId. // In that case, once we’re connected (and a status buffer exists), we want to switch to it. combineLatest(viewModel.allBuffers, viewModel.buffer).map { (buffers, current) -> diff --git a/app/src/main/java/de/kuschku/quasseldroid/ui/chat/passwordchange/PasswordChangeActivity.kt b/app/src/main/java/de/kuschku/quasseldroid/ui/chat/passwordchange/PasswordChangeActivity.kt new file mode 100644 index 0000000000000000000000000000000000000000..67d137603ce8682cba970a243e0afedd802664be --- /dev/null +++ b/app/src/main/java/de/kuschku/quasseldroid/ui/chat/passwordchange/PasswordChangeActivity.kt @@ -0,0 +1,32 @@ +/* + * Quasseldroid - Quassel client for Android + * + * Copyright (c) 2019 Janne Koschinski + * Copyright (c) 2019 The Quassel Project + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 3 as published + * by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +package de.kuschku.quasseldroid.ui.chat.passwordchange + +import android.content.Context +import android.content.Intent +import de.kuschku.quasseldroid.util.ui.settings.ServiceBoundSettingsActivity + +class PasswordChangeActivity : ServiceBoundSettingsActivity(PasswordChangeFragment()) { + companion object { + fun launch(context: Context) = context.startActivity(intent(context)) + + fun intent(context: Context) = Intent(context, PasswordChangeActivity::class.java) + } +} diff --git a/app/src/main/java/de/kuschku/quasseldroid/ui/chat/passwordchange/PasswordChangeFragment.kt b/app/src/main/java/de/kuschku/quasseldroid/ui/chat/passwordchange/PasswordChangeFragment.kt new file mode 100644 index 0000000000000000000000000000000000000000..2a7cac192349f1f50239b2ec438034caa190aee2 --- /dev/null +++ b/app/src/main/java/de/kuschku/quasseldroid/ui/chat/passwordchange/PasswordChangeFragment.kt @@ -0,0 +1,150 @@ +/* + * Quasseldroid - Quassel client for Android + * + * Copyright (c) 2019 Janne Koschinski + * Copyright (c) 2019 The Quassel Project + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 3 as published + * by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +package de.kuschku.quasseldroid.ui.chat.passwordchange + +import android.os.Bundle +import android.text.Editable +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.Button +import android.widget.EditText +import android.widget.TextView +import androidx.lifecycle.Observer +import butterknife.BindView +import butterknife.ButterKnife +import com.google.android.material.textfield.TextInputLayout +import de.kuschku.libquassel.quassel.syncables.RpcHandler +import de.kuschku.libquassel.session.ISession +import de.kuschku.libquassel.util.Optional +import de.kuschku.libquassel.util.helpers.mapMapNullable +import de.kuschku.libquassel.util.helpers.mapSwitchMap +import de.kuschku.libquassel.util.helpers.value +import de.kuschku.quasseldroid.R +import de.kuschku.quasseldroid.persistence.AccountDatabase +import de.kuschku.quasseldroid.util.TextValidator +import de.kuschku.quasseldroid.util.helper.toLiveData +import de.kuschku.quasseldroid.util.service.ServiceBoundFragment +import me.zhanghai.android.materialprogressbar.MaterialProgressBar +import javax.inject.Inject + +class PasswordChangeFragment : ServiceBoundFragment() { + @BindView(R.id.user) + lateinit var user: EditText + + @BindView(R.id.password_old_wrapper) + lateinit var oldPasswordWrapper: TextInputLayout + + @BindView(R.id.password_old) + lateinit var oldPassword: EditText + + @BindView(R.id.password_new) + lateinit var newPassword: EditText + + @BindView(R.id.password_repeat_wrapper) + lateinit var repeatPasswordWrapper: TextInputLayout + + @BindView(R.id.password_repeat) + lateinit var repeatPassword: EditText + + @BindView(R.id.error) + lateinit var error: TextView + + @BindView(R.id.save) + lateinit var save: Button + + @BindView(R.id.progress) + lateinit var progress: MaterialProgressBar + + @Inject + lateinit var accountDatabase: AccountDatabase + + private var waiting: AccountDatabase.Account? = null + + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, + savedInstanceState: Bundle?): View? { + val view = inflater.inflate(R.layout.fragment_passwordchange, container, false) + ButterKnife.bind(this, view) + + val account = accountDatabase.accounts().findById(accountId) + + user.setText(account?.user) + + viewModel.session + .mapMapNullable(ISession::rpcHandler) + .mapSwitchMap(RpcHandler::passwordChanged) + .filter(Optional<Boolean>::isPresent) + .map(Optional<Boolean>::get) + .toLiveData().observe(this, Observer { + val waiting = this.waiting + if (waiting != null) { + if (it) { + save.setText(R.string.label_save) + save.isEnabled = true + save.isClickable = true + progress.visibility = View.GONE + error.visibility = View.GONE + runInBackground { + accountDatabase.accounts().save(waiting) + } + this.waiting = null + activity?.finish() + } else { + error.visibility = View.VISIBLE + } + } + }) + + oldPassword.addTextChangedListener(object : TextValidator( + activity, + oldPasswordWrapper::setError, + getString(R.string.label_password_error_wrong) + ) { + override fun validate(text: Editable) = text.toString() == account?.pass + }) + + repeatPassword.addTextChangedListener(object : TextValidator( + activity, + repeatPasswordWrapper::setError, + getString(R.string.label_password_error_nomatch) + ) { + override fun validate(text: Editable) = text.toString() == newPassword.text.toString() + }) + + save.setOnClickListener { + save.setText(R.string.label_saving) + save.isEnabled = false + save.isClickable = false + progress.visibility = View.VISIBLE + error.visibility = View.GONE + + val pass = newPassword.text.toString() + + waiting = account?.copy(pass = pass) + + viewModel.session.value?.orNull()?.rpcHandler?.changePassword(0L, + user.text.toString(), + oldPassword.text.toString(), + pass) + } + + return view + } +} diff --git a/app/src/main/java/de/kuschku/quasseldroid/ui/chat/passwordchange/PasswordChangeFragmentProvider.kt b/app/src/main/java/de/kuschku/quasseldroid/ui/chat/passwordchange/PasswordChangeFragmentProvider.kt new file mode 100644 index 0000000000000000000000000000000000000000..ca55637560d64fe584eb259482770b8e9d6c85c7 --- /dev/null +++ b/app/src/main/java/de/kuschku/quasseldroid/ui/chat/passwordchange/PasswordChangeFragmentProvider.kt @@ -0,0 +1,34 @@ +/* + * Quasseldroid - Quassel client for Android + * + * Copyright (c) 2019 Janne Koschinski + * Copyright (c) 2019 The Quassel Project + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 3 as published + * by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +package de.kuschku.quasseldroid.ui.chat.passwordchange + +import androidx.fragment.app.FragmentActivity +import dagger.Binds +import dagger.Module +import dagger.android.ContributesAndroidInjector + +@Module +abstract class PasswordChangeFragmentProvider { + @Binds + abstract fun bindFragmentActivity(activity: PasswordChangeActivity): FragmentActivity + + @ContributesAndroidInjector + abstract fun bindPasswordChangeFragment(): PasswordChangeFragment +} diff --git a/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/CoreSettingsFragment.kt b/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/CoreSettingsFragment.kt index 20b56ec87e37501650b78542bfd0e69c5e974399..e23d02b93a5ca43d36d6b53320136feda893f49a 100644 --- a/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/CoreSettingsFragment.kt +++ b/app/src/main/java/de/kuschku/quasseldroid/ui/coresettings/CoreSettingsFragment.kt @@ -36,6 +36,7 @@ import de.kuschku.libquassel.quassel.syncables.Identity import de.kuschku.libquassel.quassel.syncables.Network import de.kuschku.quasseldroid.R import de.kuschku.quasseldroid.ui.chat.info.core.CoreInfoActivity +import de.kuschku.quasseldroid.ui.chat.passwordchange.PasswordChangeActivity import de.kuschku.quasseldroid.ui.coresettings.aliaslist.AliasListActivity import de.kuschku.quasseldroid.ui.coresettings.chatlist.ChatlistCreateActivity import de.kuschku.quasseldroid.ui.coresettings.chatlist.ChatlistEditActivity @@ -63,6 +64,9 @@ class CoreSettingsFragment : ServiceBoundFragment() { @BindView(R.id.coreinfo) lateinit var coreinfo: View + @BindView(R.id.passwordchange) + lateinit var passwordchange: View + @BindView(R.id.networks) lateinit var networks: RecyclerView @@ -116,6 +120,10 @@ class CoreSettingsFragment : ServiceBoundFragment() { CoreInfoActivity.launch(requireContext()) } + passwordchange.setOnClickListener { + PasswordChangeActivity.launch(requireContext()) + } + networks.adapter = networkAdapter networks.layoutManager = LinearLayoutManager(context) networks.addItemDecoration(itemDecoration) diff --git a/app/src/main/java/de/kuschku/quasseldroid/ui/setup/core/CoreSetupActivity.kt b/app/src/main/java/de/kuschku/quasseldroid/ui/setup/core/CoreSetupActivity.kt index d19699b254f7936a74a34573c3b7aaa47bf450a9..571d6278b2ee92462cfebca90545906bcde87c61 100644 --- a/app/src/main/java/de/kuschku/quasseldroid/ui/setup/core/CoreSetupActivity.kt +++ b/app/src/main/java/de/kuschku/quasseldroid/ui/setup/core/CoreSetupActivity.kt @@ -51,17 +51,14 @@ class CoreSetupActivity : ServiceBoundSetupActivity() { val authenticatorBackend = data.getSerializable("authenticator") as? CoreSetupBackend val authenticatorBackendSetup = data.getSerializable("authenticatorSetup") as? HashMap<String, QVariant_> - val setupData = HandshakeMessage.CoreSetupData( + viewModel.sessionManager.value?.orNull()?.setupCore(HandshakeMessage.CoreSetupData( adminUser = user, adminPassword = pass, backend = storageBackend?.backendId, setupData = storageBackendSetup.orEmpty(), authenticator = authenticatorBackend?.backendId, authSetupData = authenticatorBackendSetup.orEmpty() - ) - - viewModel.sessionManager.value?.orNull()?.setupCore(setupData) - println(setupData) + )) setResult(Activity.RESULT_OK) finish() diff --git a/app/src/main/java/de/kuschku/quasseldroid/util/TextValidator.kt b/app/src/main/java/de/kuschku/quasseldroid/util/TextValidator.kt index bd08087f776cb36990ece2dd1d68a7f252a48fe9..d83faef97516e7636b66d53e445170a955cb06f3 100644 --- a/app/src/main/java/de/kuschku/quasseldroid/util/TextValidator.kt +++ b/app/src/main/java/de/kuschku/quasseldroid/util/TextValidator.kt @@ -23,12 +23,12 @@ import android.app.Activity import android.text.Editable import android.text.TextWatcher -abstract class TextValidator(private val activity: Activity, +abstract class TextValidator(private val activity: Activity?, private val errorListener: (String?) -> Unit, private val error: String) : TextWatcher { override fun afterTextChanged(p0: Editable) { isValid = validate(p0) - activity.runOnUiThread { + activity?.runOnUiThread { errorListener(if (isValid) null else error) } onChanged() diff --git a/app/src/main/res/layout/fragment_passwordchange.xml b/app/src/main/res/layout/fragment_passwordchange.xml new file mode 100644 index 0000000000000000000000000000000000000000..caac858f4589bb0d96df44c80d41b612618a8cac --- /dev/null +++ b/app/src/main/res/layout/fragment_passwordchange.xml @@ -0,0 +1,142 @@ +<!-- + Quasseldroid - Quassel client for Android + + Copyright (c) 2019 Janne Koschinski + Copyright (c) 2019 The Quassel Project + + This program is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License version 3 as published + by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program. If not, see <http://www.gnu.org/licenses/>. + --> + +<androidx.core.widget.NestedScrollView xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:app="http://schemas.android.com/apk/res-auto" + xmlns:tools="http://schemas.android.com/tools" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:orientation="vertical"> + + <LinearLayout + android:layout_width="match_parent" + android:layout_height="match_parent" + android:orientation="vertical" + android:padding="32dp"> + + <com.google.android.material.textfield.TextInputLayout + android:id="@+id/userWrapper" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_marginBottom="16dp" + android:hint="@string/label_account_user" + tools:ignore="LabelFor"> + + <EditText + android:id="@+id/user" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:enabled="false" + android:inputType="textVisiblePassword|textNoSuggestions" + app:errorEnabled="true" + tools:text="kuschku" /> + </com.google.android.material.textfield.TextInputLayout> + + <com.google.android.material.textfield.TextInputLayout + android:id="@+id/password_old_wrapper" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_marginBottom="16dp" + android:hint="@string/label_password_old" + app:passwordToggleEnabled="true" + tools:ignore="LabelFor"> + + <EditText + android:id="@+id/password_old" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:inputType="textPassword" + app:errorEnabled="true" /> + </com.google.android.material.textfield.TextInputLayout> + + <com.google.android.material.textfield.TextInputLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:hint="@string/label_password_new" + app:passwordToggleEnabled="true" + tools:ignore="LabelFor"> + + <EditText + android:id="@+id/password_new" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:inputType="textPassword" + app:errorEnabled="true" /> + </com.google.android.material.textfield.TextInputLayout> + + <com.google.android.material.textfield.TextInputLayout + android:id="@+id/password_repeat_wrapper" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_marginBottom="16dp" + android:hint="@string/label_password_repeat" + app:passwordToggleEnabled="true" + tools:ignore="LabelFor"> + + <EditText + android:id="@+id/password_repeat" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:inputType="textPassword" + app:errorEnabled="true" /> + </com.google.android.material.textfield.TextInputLayout> + + + <TextView + android:id="@+id/error" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_marginLeft="4dp" + android:layout_marginRight="4dp" + android:layout_marginBottom="16dp" + android:textColor="?colorForegroundError" + android:visibility="gone" + tools:text="Error occured: Passwords do not match" + tools:visibility="visible" /> + + <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="horizontal"> + + <Button + android:id="@+id/save" + style="@style/Widget.Button.Colored" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="@string/label_save" /> + + <Space + android:layout_width="0dip" + android:layout_height="match_parent" + android:layout_weight="1" /> + + <me.zhanghai.android.materialprogressbar.MaterialProgressBar + android:id="@+id/progress" + android:layout_width="32dp" + android:layout_height="32dp" + android:layout_gravity="center_vertical" + android:visibility="gone" + tools:visibility="visible" /> + + </LinearLayout> + + </LinearLayout> + +</androidx.core.widget.NestedScrollView> diff --git a/app/src/main/res/layout/settings_list.xml b/app/src/main/res/layout/settings_list.xml index c8735d43fec353ddb4530f2499b29a9ccae2f0fe..ed9e18d6eceb5f328c444df14e77c24cfe70c7b8 100644 --- a/app/src/main/res/layout/settings_list.xml +++ b/app/src/main/res/layout/settings_list.xml @@ -211,5 +211,19 @@ style="@style/Widget.CoreSettings.PrimaryItemSwitch" android:text="@string/label_info_core" /> </LinearLayout> + + <LinearLayout + android:id="@+id/passwordchange" + style="@style/Widget.CoreSettings.PrimaryItemGroupHeader" + android:focusable="true"> + + <androidx.appcompat.widget.AppCompatImageView + style="@style/Widget.CoreSettings.PrimaryItemIcon" + app:srcCompat="@drawable/ic_key_variant" /> + + <TextView + style="@style/Widget.CoreSettings.PrimaryItemSwitch" + android:text="@string/label_password_change" /> + </LinearLayout> </LinearLayout> </androidx.core.widget.NestedScrollView> diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 084d80cc0b6626609cdec32fc48b309c728c3eef..80c47c71229030e59b781d22677ce6b192905e8b 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -88,6 +88,12 @@ <string name="label_open">Open</string> <string name="label_part">Leave</string> <string name="label_part_long">Leave Channel</string> + <string name="label_password_change">Change Password</string> + <string name="label_password_error_wrong">Wrong Password</string> + <string name="label_password_error_nomatch">Passwords do not match</string> + <string name="label_password_new">New Password</string> + <string name="label_password_old">Old Password</string> + <string name="label_password_repeat">Repeat Password</string> <string name="label_placeholder_message">Write a message…</string> <string name="label_placeholder_topic">Describe the channel topic…</string> <string name="label_privacy_policy">Privacy Policy</string> @@ -95,6 +101,7 @@ <string name="label_query_long">Open private chat with user</string> <string name="label_rename">Rename</string> <string name="label_save">Save</string> + <string name="label_saving">Saving…</string> <string name="label_search_buffer">Search…</string> <string name="label_select">Select</string> <string name="label_send">Send</string> diff --git a/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/RpcHandler.kt b/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/RpcHandler.kt index 8fb675f6c76e3caeab66def415cf8abf466d9e21..45c49f882f8aa4fc15ce928aa536e2bc71feed2e 100644 --- a/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/RpcHandler.kt +++ b/lib/src/main/java/de/kuschku/libquassel/quassel/syncables/RpcHandler.kt @@ -28,6 +28,7 @@ import de.kuschku.libquassel.session.BacklogStorage import de.kuschku.libquassel.session.NotificationManager import de.kuschku.libquassel.session.Session import de.kuschku.libquassel.util.helpers.deserializeString +import de.kuschku.libquassel.util.rxjava.ReusableUnicastSubject import java.nio.ByteBuffer class RpcHandler( @@ -48,7 +49,11 @@ class RpcHandler( override fun networkCreated(networkId: NetworkId) = session.addNetwork(networkId) override fun networkRemoved(networkId: NetworkId) = session.removeNetwork(networkId) + private val passwordChangedSubject = ReusableUnicastSubject.create<Boolean>() + val passwordChanged = passwordChangedSubject.publish().refCount() + override fun passwordChanged(ignored: Long, success: Boolean) { + passwordChangedSubject.onNext(success) } override fun disconnectFromCore() {