feat(profile): sign-in methods matrix — email add/change, provider link/unlink
Profile shows the account's sign-in methods for guests and durable accounts alike: add or change email, link Telegram on the web (login widget), and unlink a linked provider. Email is never unlinked (it is changed); unlink is offered only when another identity remains, and a change to an address owned by another account shows the non-disclosing 'check the address or contact support'. Add-VK-on-web stays deferred (no VK OAuth). Wires linkUnlink / changeEmailRequest / changeEmailConfirm through the client, transport, mock and codec (encodeLinkUnlink + LinkResult 'unlinked'/'changed' statuses); codec wire tests; ru/en i18n.
This commit is contained in:
@@ -656,20 +656,37 @@ export class MockGateway implements GatewayClient {
|
||||
};
|
||||
}
|
||||
this.profile.isGuest = false;
|
||||
this.profile.email = email;
|
||||
return emptyLinked();
|
||||
}
|
||||
async linkEmailMerge(_email: string, _code: string): Promise<LinkResult> {
|
||||
async linkEmailMerge(email: string, _code: string): Promise<LinkResult> {
|
||||
this.profile.isGuest = false;
|
||||
this.profile.email = email;
|
||||
return { ...emptyLinked(), status: 'merged' };
|
||||
}
|
||||
async linkTelegram(_data: string): Promise<LinkResult> {
|
||||
this.profile.isGuest = false;
|
||||
this.profile.telegramLinked = true;
|
||||
return emptyLinked();
|
||||
}
|
||||
async linkTelegramMerge(_data: string): Promise<LinkResult> {
|
||||
this.profile.isGuest = false;
|
||||
this.profile.telegramLinked = true;
|
||||
return { ...emptyLinked(), status: 'merged' };
|
||||
}
|
||||
async linkUnlink(kind: string): Promise<LinkResult> {
|
||||
if (kind === 'telegram') this.profile.telegramLinked = false;
|
||||
if (kind === 'vk') this.profile.vkLinked = false;
|
||||
return { ...emptyLinked(), status: 'unlinked' };
|
||||
}
|
||||
async changeEmailRequest(_email: string): Promise<void> {}
|
||||
async changeEmailConfirm(email: string, _code: string): Promise<LinkResult> {
|
||||
// An address containing "taken" stands in for one confirmed by another account, so the
|
||||
// mock can drive the non-disclosing refusal (never a merge).
|
||||
if (email.includes('taken')) throw new GatewayError('email_taken');
|
||||
this.profile.email = email;
|
||||
return { ...emptyLinked(), status: 'changed' };
|
||||
}
|
||||
async statsGet(): Promise<Stats> {
|
||||
return { ...this.stats };
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user