Skip to content
This repository was archived by the owner on Sep 11, 2024. It is now read-only.

Commit 5c1b62c

Browse files
author
Kerry
authored
Disable 3pid fields in settings when m.3pid_changes capability is disabled (#11430)
* check m.3pid_changes capability in user settings * comments * assume 3pid_changes is true for older evrsions
1 parent dfded8d commit 5c1b62c

File tree

7 files changed

+440
-18
lines changed

7 files changed

+440
-18
lines changed

src/components/views/settings/account/EmailAddresses.tsx

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,10 @@ that is available.
4444
interface IExistingEmailAddressProps {
4545
email: ThirdPartyIdentifier;
4646
onRemoved: (emails: ThirdPartyIdentifier) => void;
47+
/**
48+
* Disallow removal of this email address when truthy
49+
*/
50+
disabled?: boolean;
4751
}
4852

4953
interface IExistingEmailAddressState {
@@ -121,7 +125,7 @@ export class ExistingEmailAddress extends React.Component<IExistingEmailAddressP
121125
<span className="mx_GeneralUserSettingsTab_section--discovery_existing_address">
122126
{this.props.email.address}
123127
</span>
124-
<AccessibleButton onClick={this.onRemove} kind="danger_sm">
128+
<AccessibleButton onClick={this.onRemove} kind="danger_sm" disabled={this.props.disabled}>
125129
{_t("Remove")}
126130
</AccessibleButton>
127131
</div>
@@ -132,6 +136,10 @@ export class ExistingEmailAddress extends React.Component<IExistingEmailAddressP
132136
interface IProps {
133137
emails: ThirdPartyIdentifier[];
134138
onEmailsChange: (emails: ThirdPartyIdentifier[]) => void;
139+
/**
140+
* Adding or removing emails is disabled when truthy
141+
*/
142+
disabled?: boolean;
135143
}
136144

137145
interface IState {
@@ -248,11 +256,18 @@ export default class EmailAddresses extends React.Component<IProps, IState> {
248256

249257
public render(): React.ReactNode {
250258
const existingEmailElements = this.props.emails.map((e) => {
251-
return <ExistingEmailAddress email={e} onRemoved={this.onRemoved} key={e.address} />;
259+
return (
260+
<ExistingEmailAddress
261+
email={e}
262+
onRemoved={this.onRemoved}
263+
key={e.address}
264+
disabled={this.props.disabled}
265+
/>
266+
);
252267
});
253268

254269
let addButton = (
255-
<AccessibleButton onClick={this.onAddClick} kind="primary">
270+
<AccessibleButton onClick={this.onAddClick} kind="primary" disabled={this.props.disabled}>
256271
{_t("Add")}
257272
</AccessibleButton>
258273
);
@@ -283,7 +298,7 @@ export default class EmailAddresses extends React.Component<IProps, IState> {
283298
type="text"
284299
label={_t("Email Address")}
285300
autoComplete="email"
286-
disabled={this.state.verifying}
301+
disabled={this.props.disabled || this.state.verifying}
287302
value={this.state.newEmailAddress}
288303
onChange={this.onChangeNewEmailAddress}
289304
/>

src/components/views/settings/account/PhoneNumbers.tsx

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,10 @@ This is a copy/paste of EmailAddresses, mostly.
3939
interface IExistingPhoneNumberProps {
4040
msisdn: ThirdPartyIdentifier;
4141
onRemoved: (phoneNumber: ThirdPartyIdentifier) => void;
42+
/**
43+
* Disable removing phone number
44+
*/
45+
disabled?: boolean;
4246
}
4347

4448
interface IExistingPhoneNumberState {
@@ -116,7 +120,7 @@ export class ExistingPhoneNumber extends React.Component<IExistingPhoneNumberPro
116120
<span className="mx_GeneralUserSettingsTab_section--discovery_existing_address">
117121
+{this.props.msisdn.address}
118122
</span>
119-
<AccessibleButton onClick={this.onRemove} kind="danger_sm">
123+
<AccessibleButton onClick={this.onRemove} kind="danger_sm" disabled={this.props.disabled}>
120124
{_t("Remove")}
121125
</AccessibleButton>
122126
</div>
@@ -127,6 +131,10 @@ export class ExistingPhoneNumber extends React.Component<IExistingPhoneNumberPro
127131
interface IProps {
128132
msisdns: ThirdPartyIdentifier[];
129133
onMsisdnsChange: (phoneNumbers: ThirdPartyIdentifier[]) => void;
134+
/**
135+
* Adding or removing phone numbers is disabled when truthy
136+
*/
137+
disabled?: boolean;
130138
}
131139

132140
interface IState {
@@ -251,11 +259,18 @@ export default class PhoneNumbers extends React.Component<IProps, IState> {
251259

252260
public render(): React.ReactNode {
253261
const existingPhoneElements = this.props.msisdns.map((p) => {
254-
return <ExistingPhoneNumber msisdn={p} onRemoved={this.onRemoved} key={p.address} />;
262+
return (
263+
<ExistingPhoneNumber
264+
msisdn={p}
265+
onRemoved={this.onRemoved}
266+
key={p.address}
267+
disabled={this.props.disabled}
268+
/>
269+
);
255270
});
256271

257272
let addVerifySection = (
258-
<AccessibleButton onClick={this.onAddClick} kind="primary">
273+
<AccessibleButton onClick={this.onAddClick} kind="primary" disabled={this.props.disabled}>
259274
{_t("Add")}
260275
</AccessibleButton>
261276
);
@@ -277,14 +292,18 @@ export default class PhoneNumbers extends React.Component<IProps, IState> {
277292
type="text"
278293
label={_t("Verification code")}
279294
autoComplete="off"
280-
disabled={this.state.continueDisabled}
295+
disabled={this.props.disabled || this.state.continueDisabled}
281296
value={this.state.newPhoneNumberCode}
282297
onChange={this.onChangeNewPhoneNumberCode}
283298
/>
284299
<AccessibleButton
285300
onClick={this.onContinueClick}
286301
kind="primary"
287-
disabled={this.state.continueDisabled || this.state.newPhoneNumberCode.length === 0}
302+
disabled={
303+
this.props.disabled ||
304+
this.state.continueDisabled ||
305+
this.state.newPhoneNumberCode.length === 0
306+
}
288307
>
289308
{_t("Continue")}
290309
</AccessibleButton>
@@ -313,7 +332,7 @@ export default class PhoneNumbers extends React.Component<IProps, IState> {
313332
type="text"
314333
label={_t("Phone Number")}
315334
autoComplete="tel-national"
316-
disabled={this.state.verifying}
335+
disabled={this.props.disabled || this.state.verifying}
317336
prefixComponent={phoneCountry}
318337
value={this.state.newPhoneNumber}
319338
onChange={this.onChangeNewPhoneNumber}

src/components/views/settings/discovery/EmailAddresses.tsx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ TODO: Reduce all the copying between account vs. discovery components.
4646

4747
interface IEmailAddressProps {
4848
email: ThirdPartyIdentifier;
49+
disabled?: boolean;
4950
}
5051

5152
interface IEmailAddressState {
@@ -194,6 +195,7 @@ export class EmailAddress extends React.Component<IEmailAddressProps, IEmailAddr
194195
className="mx_GeneralUserSettingsTab_section--discovery_existing_button"
195196
kind="danger_sm"
196197
onClick={this.onRevokeClick}
198+
disabled={this.props.disabled}
197199
>
198200
{_t("Revoke")}
199201
</AccessibleButton>
@@ -204,6 +206,7 @@ export class EmailAddress extends React.Component<IEmailAddressProps, IEmailAddr
204206
className="mx_GeneralUserSettingsTab_section--discovery_existing_button"
205207
kind="primary_sm"
206208
onClick={this.onShareClick}
209+
disabled={this.props.disabled}
207210
>
208211
{_t("Share")}
209212
</AccessibleButton>
@@ -221,6 +224,7 @@ export class EmailAddress extends React.Component<IEmailAddressProps, IEmailAddr
221224
interface IProps {
222225
emails: ThirdPartyIdentifier[];
223226
isLoading?: boolean;
227+
disabled?: boolean;
224228
}
225229

226230
export default class EmailAddresses extends React.Component<IProps> {
@@ -230,7 +234,7 @@ export default class EmailAddresses extends React.Component<IProps> {
230234
content = <InlineSpinner />;
231235
} else if (this.props.emails.length > 0) {
232236
content = this.props.emails.map((e) => {
233-
return <EmailAddress email={e} key={e.address} />;
237+
return <EmailAddress email={e} key={e.address} disabled={this.props.disabled} />;
234238
});
235239
}
236240

src/components/views/settings/discovery/PhoneNumbers.tsx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ This is a copy/paste of EmailAddresses, mostly.
3838

3939
interface IPhoneNumberProps {
4040
msisdn: ThirdPartyIdentifier;
41+
disabled?: boolean;
4142
}
4243

4344
interface IPhoneNumberState {
@@ -202,6 +203,7 @@ export class PhoneNumber extends React.Component<IPhoneNumberProps, IPhoneNumber
202203
className="mx_GeneralUserSettingsTab_section--discovery_existing_button"
203204
kind="danger_sm"
204205
onClick={this.onRevokeClick}
206+
disabled={this.props.disabled}
205207
>
206208
{_t("Revoke")}
207209
</AccessibleButton>
@@ -212,6 +214,7 @@ export class PhoneNumber extends React.Component<IPhoneNumberProps, IPhoneNumber
212214
className="mx_GeneralUserSettingsTab_section--discovery_existing_button"
213215
kind="primary_sm"
214216
onClick={this.onShareClick}
217+
disabled={this.props.disabled}
215218
>
216219
{_t("Share")}
217220
</AccessibleButton>
@@ -230,6 +233,7 @@ export class PhoneNumber extends React.Component<IPhoneNumberProps, IPhoneNumber
230233
interface IProps {
231234
msisdns: ThirdPartyIdentifier[];
232235
isLoading?: boolean;
236+
disabled?: boolean;
233237
}
234238

235239
export default class PhoneNumbers extends React.Component<IProps> {
@@ -239,7 +243,7 @@ export default class PhoneNumbers extends React.Component<IProps> {
239243
content = <InlineSpinner />;
240244
} else if (this.props.msisdns.length > 0) {
241245
content = this.props.msisdns.map((e) => {
242-
return <PhoneNumber msisdn={e} key={e.address} />;
246+
return <PhoneNumber msisdn={e} key={e.address} disabled={this.props.disabled} />;
243247
});
244248
}
245249

src/components/views/settings/tabs/user/GeneralUserSettingsTab.tsx

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ interface IState {
9191
canChangePassword: boolean;
9292
idServerName?: string;
9393
externalAccountManagementUrl?: string;
94+
canMake3pidChanges: boolean;
9495
}
9596

9697
export default class GeneralUserSettingsTab extends React.Component<IProps, IState> {
@@ -120,6 +121,7 @@ export default class GeneralUserSettingsTab extends React.Component<IProps, ISta
120121
msisdns: [],
121122
loading3pids: true, // whether or not the emails and msisdns have been loaded
122123
canChangePassword: false,
124+
canMake3pidChanges: false,
123125
};
124126

125127
this.dispatcherRef = dis.register(this.onAction);
@@ -174,8 +176,12 @@ export default class GeneralUserSettingsTab extends React.Component<IProps, ISta
174176
const canChangePassword = !changePasswordCap || changePasswordCap["enabled"] !== false;
175177

176178
const externalAccountManagementUrl = getDelegatedAuthAccountUrl(cli.getClientWellKnown());
179+
// https://spec.matrix.org/v1.7/client-server-api/#m3pid_changes-capability
180+
// We support as far back as v1.1 which doesn't have m.3pid_changes
181+
// so the behaviour for when it is missing has to be assume true
182+
const canMake3pidChanges = !capabilities["m.3pid_changes"] || capabilities["m.3pid_changes"].enabled === true;
177183

178-
this.setState({ canChangePassword, externalAccountManagementUrl });
184+
this.setState({ canChangePassword, externalAccountManagementUrl, canMake3pidChanges });
179185
}
180186

181187
private async getThreepidState(): Promise<void> {
@@ -323,12 +329,20 @@ export default class GeneralUserSettingsTab extends React.Component<IProps, ISta
323329
const emails = this.state.loading3pids ? (
324330
<InlineSpinner />
325331
) : (
326-
<AccountEmailAddresses emails={this.state.emails} onEmailsChange={this.onEmailsChange} />
332+
<AccountEmailAddresses
333+
emails={this.state.emails}
334+
onEmailsChange={this.onEmailsChange}
335+
disabled={!this.state.canMake3pidChanges}
336+
/>
327337
);
328338
const msisdns = this.state.loading3pids ? (
329339
<InlineSpinner />
330340
) : (
331-
<AccountPhoneNumbers msisdns={this.state.msisdns} onMsisdnsChange={this.onMsisdnsChange} />
341+
<AccountPhoneNumbers
342+
msisdns={this.state.msisdns}
343+
onMsisdnsChange={this.onMsisdnsChange}
344+
disabled={!this.state.canMake3pidChanges}
345+
/>
332346
);
333347
threepidSection = (
334348
<>
@@ -463,8 +477,16 @@ export default class GeneralUserSettingsTab extends React.Component<IProps, ISta
463477

464478
const threepidSection = this.state.haveIdServer ? (
465479
<>
466-
<DiscoveryEmailAddresses emails={this.state.emails} isLoading={this.state.loading3pids} />
467-
<DiscoveryPhoneNumbers msisdns={this.state.msisdns} isLoading={this.state.loading3pids} />
480+
<DiscoveryEmailAddresses
481+
emails={this.state.emails}
482+
isLoading={this.state.loading3pids}
483+
disabled={!this.state.canMake3pidChanges}
484+
/>
485+
<DiscoveryPhoneNumbers
486+
msisdns={this.state.msisdns}
487+
isLoading={this.state.loading3pids}
488+
disabled={!this.state.canMake3pidChanges}
489+
/>
468490
</>
469491
) : null;
470492

0 commit comments

Comments
 (0)