From 510fb1ba2f26e9e4d354a37dfeea82ad737eac32 Mon Sep 17 00:00:00 2001 From: David Baker Date: Tue, 2 Jul 2024 11:04:07 +0100 Subject: [PATCH] Disable profile controls if the HS doesn't allow them to be set (#12652) * Disable profile controls if the HS doesn't allow them to be set Also updates to the js-sdk interface changes in https://github.com/matrix-org/matrix-js-sdk/pull/4246 * Remove unnecessary await * Pass disabled prop to accessiblebutton in avatarsetting * Use getCapabilities in case there are no cached capabilities * Fix test * Go back to just using getCapabilities Rather than change the other places --- .../views/settings/AvatarSetting.tsx | 2 ++ .../views/settings/UserProfileSettings.tsx | 19 +++++++++++++-- .../tabs/user/GeneralUserSettingsTab.tsx | 23 ++++++++++++++++--- src/i18n/strings/en_EN.json | 1 + .../settings/UserProfileSettings-test.tsx | 2 +- test/test-utils/client.ts | 2 +- 6 files changed, 42 insertions(+), 7 deletions(-) diff --git a/src/components/views/settings/AvatarSetting.tsx b/src/components/views/settings/AvatarSetting.tsx index 81f1cd5201..0e95deed38 100644 --- a/src/components/views/settings/AvatarSetting.tsx +++ b/src/components/views/settings/AvatarSetting.tsx @@ -170,6 +170,7 @@ const AvatarSetting: React.FC = ({ aria-labelledby={disabled ? undefined : a11yId} // Inhibit tab stop as we have explicit upload/remove buttons tabIndex={-1} + disabled={disabled} > @@ -184,6 +185,7 @@ const AvatarSetting: React.FC = ({ onClick={uploadAvatar} // Inhibit tab stop as we have explicit upload/remove buttons tabIndex={-1} + disabled={disabled} /> ); } diff --git a/src/components/views/settings/UserProfileSettings.tsx b/src/components/views/settings/UserProfileSettings.tsx index bd61f762ff..6d1bccb30e 100644 --- a/src/components/views/settings/UserProfileSettings.tsx +++ b/src/components/views/settings/UserProfileSettings.tsx @@ -55,10 +55,17 @@ const UsernameBox: React.FC = ({ username }) => { ); }; +interface UserProfileSettingsProps { + // Whether the homeserver allows the user to set their display name. + canSetDisplayName: boolean; + // Whether the homeserver allows the user to set their avatar. + canSetAvatar: boolean; +} + /** * A group of settings views to allow the user to set their profile information. */ -const UserProfileSettings: React.FC = () => { +const UserProfileSettings: React.FC = ({ canSetDisplayName, canSetAvatar }) => { const [avatarURL, setAvatarURL] = useState(OwnProfileStore.instance.avatarMxc); const [displayName, setDisplayName] = useState(OwnProfileStore.instance.displayName ?? ""); const [initialDisplayName, setInitialDisplayName] = useState(OwnProfileStore.instance.displayName ?? ""); @@ -143,10 +150,16 @@ const UserProfileSettings: React.FC = () => { [client], ); + const someFieldsDisabled = !canSetDisplayName || !canSetAvatar; + return (

{_t("common|profile")}

-
{_t("settings|general|profile_subtitle")}
+
+ {someFieldsDisabled + ? _t("settings|general|profile_subtitle_oidc") + : _t("settings|general|profile_subtitle")} +
{ removeAvatar={avatarURL ? onAvatarRemove : undefined} placeholderName={displayName} placeholderId={client.getUserId() ?? ""} + disabled={!canSetAvatar} /> { onCancel={onDisplayNameCancel} onSave={onDisplayNameSave} error={displayNameError ? _t("settings|general|display_name_error") : undefined} + disabled={!canSetDisplayName} />
{avatarError && ( diff --git a/src/components/views/settings/tabs/user/GeneralUserSettingsTab.tsx b/src/components/views/settings/tabs/user/GeneralUserSettingsTab.tsx index 3b53e5f2f1..ef90077f2d 100644 --- a/src/components/views/settings/tabs/user/GeneralUserSettingsTab.tsx +++ b/src/components/views/settings/tabs/user/GeneralUserSettingsTab.tsx @@ -56,6 +56,8 @@ interface IState { idServerName?: string; externalAccountManagementUrl?: string; canMake3pidChanges: boolean; + canSetDisplayName: boolean; + canSetAvatar: boolean; } export default class GeneralUserSettingsTab extends React.Component { @@ -72,6 +74,8 @@ export default class GeneralUserSettingsTab extends React.Component { const cli = this.context.client!; - const capabilities = await cli.getCapabilities(); // this is cached + const capabilities = (await cli.getCapabilities()) ?? {}; const changePasswordCap = capabilities["m.change_password"]; // You can change your password so long as the capability isn't explicitly disabled. The implicit @@ -110,7 +114,17 @@ export default class GeneralUserSettingsTab extends React.Component { @@ -309,7 +323,10 @@ export default class GeneralUserSettingsTab extends React.Component - + {this.renderAccountSection()} {this.renderLanguageSection()} diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index de8e33927f..6667df5788 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -2527,6 +2527,7 @@ "password_change_success": "Your password was successfully changed.", "personal_info": "Personal info", "profile_subtitle": "This is how you appear to others on the app.", + "profile_subtitle_oidc": "Your account is managed separately by an identity provider and so some of your personal information can’t be changed here.", "remove_email_prompt": "Remove %(email)s?", "remove_msisdn_prompt": "Remove %(phone)s?", "spell_check_locale_placeholder": "Choose a locale", diff --git a/test/components/views/settings/UserProfileSettings-test.tsx b/test/components/views/settings/UserProfileSettings-test.tsx index fd72772977..6b7f278e5a 100644 --- a/test/components/views/settings/UserProfileSettings-test.tsx +++ b/test/components/views/settings/UserProfileSettings-test.tsx @@ -67,7 +67,7 @@ const renderProfileSettings = (toastRack: Partial, client: MatrixClie return render( - + , ); diff --git a/test/test-utils/client.ts b/test/test-utils/client.ts index 00f5aa3f7b..43d8392a15 100644 --- a/test/test-utils/client.ts +++ b/test/test-utils/client.ts @@ -129,7 +129,7 @@ export const mockClientMethodsEvents = () => ({ export const mockClientMethodsServer = (): Partial, unknown>> => ({ getIdentityServerUrl: jest.fn(), getHomeserverUrl: jest.fn(), - getCapabilities: jest.fn().mockReturnValue({}), + getCapabilities: jest.fn().mockResolvedValue({}), getClientWellKnown: jest.fn().mockReturnValue({}), waitForClientWellKnown: jest.fn().mockResolvedValue({}), doesServerSupportUnstableFeature: jest.fn().mockResolvedValue(false),