[stable-25.0.x] validate password - #6663
Merged
Merged
Conversation
Signed-off-by: sowjanyakch <sowjanya.kch@gmail.com> add password logic Signed-off-by: sowjanyakch <sowjanya.kch@gmail.com> handle states of password states Signed-off-by: sowjanyakch <sowjanya.kch@gmail.com> copy password Signed-off-by: sowjanyakch <sowjanya.kch@gmail.com> remove unused function and add copyright info Signed-off-by: sowjanyakch <sowjanya.kch@gmail.com> modify layout and import changes with the package name change Signed-off-by: sowjanyakch <sowjanya.kch@gmail.com> split GuestAccessPasswordDialog into two functions Signed-off-by: sowjanyakch <sowjanya.kch@gmail.com> fix detekt Signed-off-by: sowjanyakch <sowjanya.kch@gmail.com>
…o master The PR was rebased onto a master that had since migrated ConversationInfo to Jetpack Compose, which broke the build: the merge resurrected pre-migration files (GuestAccessHelper.kt, its DialogPasswordBinding/ActivityConversationInfoBinding dialog code) and dropped an unrelated master fix (@serializable on ProvisioningCapability). - Delete GuestAccessHelper.kt (obsolete View/XML-binding helper no longer referenced since the Compose migration) and port its password-validation dialog into ConversationInfoActivity's Compose screen, replacing the stale XML showPasswordDialog(). - Remove dead, unrelated state left over in ConversationInfoViewModel from the old base branch (GetCapabilitiesStartState, CreateRoomUIState) and a duplicate ConversationCreationRepository import. - Restore @serializable on ProvisioningCapability, lost in the merge. - Fix ConversationCreationActivity's password-set dialog not dismissing after a successful save, and drop an unused ktlint-failing import and a misapplied @Suppress in ConversationCreationViewModel. Assisted-by: Claude Code:claude-sonnet-5 Signed-off-by: rapterjet2004 <juliuslinus1@gmail.com>
…e rebase An earlier rebase of this branch reintroduced view-model state that master had deleted during the ConversationInfo Compose migration: eight sealed view-state classes and the LiveData exposing them, plus the profile view state. Nothing in the app reads or writes any of it. Keep only SecurePasswordViewState, which the password-policy validation this branch adds actually uses. Assisted-by: Claude Code:claude-opus-5 Signed-off-by: Andy Scherzinger <info@andy-scherzinger.de>
…read PasswordCapability, PasswordPolicies and PasswordAccount were referenced nowhere, and of PasswordPolicy only api.validate is ever read - the minLength and enforce* mirrors of the server capability, the nested policies object and api.generate were all dead. Drop the three unused classes and the unread fields, and rename Capabilities.passwordCapability to passwordPolicy so the property matches both its type and the password_policy key it maps. Also correct a typo in the SPDX contributor address on the two files that carried it. Assisted-by: Claude Code:claude-opus-5 Signed-off-by: Andy Scherzinger <info@andy-scherzinger.de>
Three leftovers from the earlier rebase that have nothing to do with this feature: a whitespace-only edit to ProvisioningCapability, a TooGenericExceptionCaught suppression on updateConversationPreset (which catches nothing), and a stray blank line in the change-password dialog. Also drop the LongMethod suppression from validatePassword; the function is thirteen lines and only the catch needs suppressing. Assisted-by: Claude Code:claude-opus-5 Signed-off-by: Andy Scherzinger <info@andy-scherzinger.de>
ConversationInfoViewModel injected ConversationCreationRepository purely to reach validatePassword, coupling the conversation-info feature to conversation creation's data layer for an endpoint that belongs to neither. Password-policy validation is an account-level concern, so give it a PasswordPolicyRepository of its own and let both view models depend on that instead. Assisted-by: Claude Code:claude-opus-5 Signed-off-by: Andy Scherzinger <info@andy-scherzinger.de>
…e view model The composables dug the validation endpoint out of currentUser.capabilities and handed it, and in the conversation-info case the credentials too, back to a view model that already holds the user. Give CapabilitiesUtil a getPasswordValidationUrl accessor next to the other capability lookups and let each view model resolve both itself, so validatePassword and securePassword now take only the password. Assisted-by: Claude Code:claude-opus-5 Signed-off-by: Andy Scherzinger <info@andy-scherzinger.de>
…both screens Conversation creation and conversation info each carried their own copy of the feature: two UI state types (ValidPasswordUiState and SecurePasswordViewState) with the same three cases, two view-model methods with the same body, two reset methods, and two composables rendering the same message with different colour rules - one of which decided validity by string-comparing the rendered message against the localized "password is secure" label. Replace all of it with a PasswordValidationState both view models expose, a PasswordPolicyValidator that owns the request and the state, and a PasswordPolicyField that renders the input together with the server's verdict. Validity now reads result.passed through isPasswordAccepted. Assisted-by: Claude Code:claude-opus-5 Signed-off-by: Andy Scherzinger <info@andy-scherzinger.de>
…licy Save was gated on a successful validation round-trip, so on a server that does not advertise the password_policy capability no request was ever made, the state stayed None and the button never enabled - the guest password could not be set at all. Conversation info made it worse by passing an empty string as the endpoint, firing a doomed request at the base URL and settling on Error. Report the missing capability as its own NoPolicy state, which counts as accepted: without a policy to check against there is nothing to fail. Assisted-by: Claude Code:claude-opus-5 Signed-off-by: Andy Scherzinger <info@andy-scherzinger.de>
Every keystroke fired its own request, so typing a ten-character password sent ten of them - each a prefix of the password - and whichever response happened to land last decided whether Save was enabled, regardless of what the field then held. Debounce by half a second and cancel the request in flight, so only the last password typed is sent and only its verdict can be written. Clear the verdict as soon as the password changes, so the previous password's result cannot stand in for one that has not been checked yet. Assisted-by: Claude Code:claude-opus-5 Signed-off-by: Andy Scherzinger <info@andy-scherzinger.de>
The result was unwrapped with ocs?.data!!, so a well-formed response that carried no result threw a NullPointerException into the surrounding catch and surfaced as an error whose message was whatever the NPE said. Unwrap it in the repository, which is the layer that knows the wire format, and fail with a described IllegalStateException. Log what went wrong on the way past, since the dialog only tells the user that something did. Assisted-by: Claude Code:claude-opus-5 Signed-off-by: Andy Scherzinger <info@andy-scherzinger.de>
The XML dialog the Compose one replaced set inputType="textPassword". Its replacement set nothing, so the guest password was drawn in clear text and went through the keyboard's suggestion and learning path. The two dialogs on the conversation creation screen never masked it either. Mask it in the shared field, and hold it in remember rather than rememberSaveable so the plain text is not written into the saved instance state bundle. Assisted-by: Claude Code:claude-opus-5 Signed-off-by: Andy Scherzinger <info@andy-scherzinger.de>
CreatedConversation already flagged the clipboard entry with EXTRA_IS_SENSITIVE and confirmed the copy with a toast, but the two copy actions this branch adds did neither, so on Android 13 and later the password appeared in the clipboard preview and nothing told the user it had been copied. Lift that private helper into ClipboardUtils and use it at all three sites. Assisted-by: Claude Code:claude-opus-5 Signed-off-by: Andy Scherzinger <info@andy-scherzinger.de>
…composition Dialog visibility and the validation state were activity fields written from an observer, while the rest of the screen already collects its state inside setContent. Hold both in the composition, collecting the validator with collectAsStateWithLifecycle like uiState next to it, so the dialog stops outliving the composition that shows it. Assisted-by: Claude Code:claude-opus-5 Signed-off-by: Andy Scherzinger <info@andy-scherzinger.de>
AndyScherzinger
approved these changes
Sep 9, 2026
Contributor
|
APK file: https://github.com/nextcloud/talk-android/actions/runs/34332886381/artifacts/10097454139 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Backport of PR #5955