Skip to content

Commit 5a6ed96

Browse files
authored
feat(core): delete passkey (#7416)
1 parent ff8d204 commit 5a6ed96

File tree

22 files changed

+100
-35
lines changed

22 files changed

+100
-35
lines changed

packages/core/src/routes/account/email-and-phone.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ export default function emailAndPhoneRoutes<T extends UserRouter>(...args: Route
4242
const { fields } = ctx.accountCenter;
4343
assertThat(
4444
fields.email === AccountCenterControlValue.Edit,
45-
'account_center.filed_not_editable'
45+
'account_center.field_not_editable'
4646
);
4747

4848
assertThat(scopes.has(UserScope.Email), 'auth.unauthorized');
@@ -87,7 +87,7 @@ export default function emailAndPhoneRoutes<T extends UserRouter>(...args: Route
8787
const { fields } = ctx.accountCenter;
8888
assertThat(
8989
fields.email === AccountCenterControlValue.Edit,
90-
'account_center.filed_not_editable'
90+
'account_center.field_not_editable'
9191
);
9292

9393
assertThat(scopes.has(UserScope.Email), 'auth.unauthorized');
@@ -131,7 +131,7 @@ export default function emailAndPhoneRoutes<T extends UserRouter>(...args: Route
131131
const { fields } = ctx.accountCenter;
132132
assertThat(
133133
fields.phone === AccountCenterControlValue.Edit,
134-
'account_center.filed_not_editable'
134+
'account_center.field_not_editable'
135135
);
136136

137137
assertThat(scopes.has(UserScope.Phone), 'auth.unauthorized');
@@ -172,7 +172,7 @@ export default function emailAndPhoneRoutes<T extends UserRouter>(...args: Route
172172
const { fields } = ctx.accountCenter;
173173
assertThat(
174174
fields.phone === AccountCenterControlValue.Edit,
175-
'account_center.filed_not_editable'
175+
'account_center.field_not_editable'
176176
);
177177

178178
assertThat(scopes.has(UserScope.Phone), 'auth.unauthorized');

packages/core/src/routes/account/identities.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ export default function identitiesRoutes<T extends UserRouter>(
4040
const { fields } = ctx.accountCenter;
4141
assertThat(
4242
fields.social === AccountCenterControlValue.Edit,
43-
'account_center.filed_not_editable'
43+
'account_center.field_not_editable'
4444
);
4545

4646
assertThat(scopes.has(UserScope.Identities), 'auth.unauthorized');
@@ -98,7 +98,7 @@ export default function identitiesRoutes<T extends UserRouter>(
9898
const { fields } = ctx.accountCenter;
9999
assertThat(
100100
fields.social === AccountCenterControlValue.Edit,
101-
'account_center.filed_not_editable'
101+
'account_center.field_not_editable'
102102
);
103103

104104
assertThat(scopes.has(UserScope.Identities), 'auth.unauthorized');

packages/core/src/routes/account/index.openapi.json

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -322,6 +322,30 @@
322322
}
323323
}
324324
}
325+
},
326+
"/api/my-account/mfa-verifications/{verificationId}": {
327+
"delete": {
328+
"tags": ["Dev feature"],
329+
"parameters": [
330+
{
331+
"name": "verificationId",
332+
"in": "path",
333+
"required": true,
334+
"schema": {
335+
"type": "string"
336+
},
337+
"description": "The ID of the MFA verification to delete."
338+
}
339+
],
340+
"operationId": "DeleteMfaVerification",
341+
"summary": "Delete an MFA verification",
342+
"description": "Delete an MFA verification, a logto-verification-id in header is required for checking sensitive permissions.",
343+
"responses": {
344+
"204": {
345+
"description": "The MFA verification was deleted successfully."
346+
}
347+
}
348+
}
325349
}
326350
}
327351
}

packages/core/src/routes/account/index.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -69,15 +69,15 @@ export default function accountRoutes<T extends UserRouter>(...args: RouterInitA
6969

7070
assertThat(
7171
name === undefined || fields.name === AccountCenterControlValue.Edit,
72-
'account_center.filed_not_editable'
72+
'account_center.field_not_editable'
7373
);
7474
assertThat(
7575
avatar === undefined || fields.avatar === AccountCenterControlValue.Edit,
76-
'account_center.filed_not_editable'
76+
'account_center.field_not_editable'
7777
);
7878
assertThat(
7979
username === undefined || fields.username === AccountCenterControlValue.Edit,
80-
'account_center.filed_not_editable'
80+
'account_center.field_not_editable'
8181
);
8282
assertThat(scopes.has(UserScope.Profile), 'auth.unauthorized');
8383

@@ -122,7 +122,7 @@ export default function accountRoutes<T extends UserRouter>(...args: RouterInitA
122122

123123
assertThat(
124124
fields.profile === AccountCenterControlValue.Edit,
125-
'account_center.filed_not_editable'
125+
'account_center.field_not_editable'
126126
);
127127
assertThat(scopes.has(UserScope.Profile), 'auth.unauthorized');
128128

@@ -159,7 +159,7 @@ export default function accountRoutes<T extends UserRouter>(...args: RouterInitA
159159
const { fields } = ctx.accountCenter;
160160
assertThat(
161161
fields.password === AccountCenterControlValue.Edit,
162-
'account_center.filed_not_editable'
162+
'account_center.field_not_editable'
163163
);
164164

165165
const user = await findUserById(userId);

packages/core/src/routes/account/mfa-verifications.ts

Lines changed: 43 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ export default function mfaVerificationsRoutes<T extends UserRouter>(
4040
const { fields } = ctx.accountCenter;
4141
assertThat(
4242
fields.mfa === AccountCenterControlValue.Edit,
43-
'account_center.filed_not_editable'
43+
'account_center.field_not_editable'
4444
);
4545

4646
assertThat(scopes.has(UserScope.Identities), 'auth.unauthorized');
@@ -107,7 +107,7 @@ export default function mfaVerificationsRoutes<T extends UserRouter>(
107107
const { fields } = ctx.accountCenter;
108108
assertThat(
109109
fields.mfa === AccountCenterControlValue.Edit,
110-
'account_center.filed_not_editable'
110+
'account_center.field_not_editable'
111111
);
112112

113113
assertThat(scopes.has(UserScope.Identities), 'auth.unauthorized');
@@ -135,4 +135,45 @@ export default function mfaVerificationsRoutes<T extends UserRouter>(
135135
return next();
136136
}
137137
);
138+
139+
router.delete(
140+
`${accountApiPrefix}/mfa-verifications/:verificationId`,
141+
koaGuard({
142+
params: z.object({
143+
verificationId: z.string(),
144+
}),
145+
status: [204, 400, 401],
146+
}),
147+
async (ctx, next) => {
148+
const { id: userId, scopes, identityVerified } = ctx.auth;
149+
assertThat(
150+
identityVerified,
151+
new RequestError({ code: 'verification_record.permission_denied', status: 401 })
152+
);
153+
const { fields } = ctx.accountCenter;
154+
assertThat(
155+
fields.mfa === AccountCenterControlValue.Edit,
156+
'account_center.field_not_editable'
157+
);
158+
assertThat(scopes.has(UserScope.Identities), 'auth.unauthorized');
159+
160+
const user = await findUserById(userId);
161+
const mfaVerification = user.mfaVerifications.find(
162+
(mfaVerification) => mfaVerification.id === ctx.guard.params.verificationId
163+
);
164+
assertThat(mfaVerification, 'verification_record.not_found');
165+
166+
const updatedUser = await updateUserById(userId, {
167+
mfaVerifications: user.mfaVerifications.filter(
168+
(mfaVerification) => mfaVerification.id !== ctx.guard.params.verificationId
169+
),
170+
});
171+
172+
ctx.appendDataHookContext('User.Data.Updated', { user: updatedUser });
173+
174+
ctx.status = 204;
175+
176+
return next();
177+
}
178+
);
138179
}

packages/integration-tests/src/tests/api/account/account-center-reject.test.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ import { enableAllPasswordSignInMethods } from '#src/helpers/sign-in-experience.
2424
import { generateEmail, generatePhone } from '#src/utils.js';
2525

2626
const expectedError = {
27-
code: 'account_center.filed_not_editable',
27+
code: 'account_center.field_not_editable',
2828
status: 400,
2929
};
3030

@@ -63,26 +63,26 @@ describe('account center fields disabled', () => {
6363
const api = await signInAndGetUserApi(username, password);
6464

6565
await expectRejects(updateUser(api, { name: 'name' }), {
66-
code: 'account_center.filed_not_editable',
66+
code: 'account_center.field_not_editable',
6767
status: 400,
6868
});
6969
await expectRejects(updateUser(api, { avatar: 'https://example.com/avatar.png' }), {
70-
code: 'account_center.filed_not_editable',
70+
code: 'account_center.field_not_editable',
7171
status: 400,
7272
});
7373
await expectRejects(updateUser(api, { username: 'username' }), {
74-
code: 'account_center.filed_not_editable',
74+
code: 'account_center.field_not_editable',
7575
status: 400,
7676
});
7777

7878
await expectRejects(updateOtherProfile(api, { profile: 'profile' }), {
79-
code: 'account_center.filed_not_editable',
79+
code: 'account_center.field_not_editable',
8080
status: 400,
8181
});
8282

8383
const verificationRecordId = await createVerificationRecordByPassword(api, password);
8484
await expectRejects(updatePassword(api, verificationRecordId, 'new-password'), {
85-
code: 'account_center.filed_not_editable',
85+
code: 'account_center.field_not_editable',
8686
status: 400,
8787
});
8888

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
const account_center = {
22
not_enabled: 'مركز الحسابات غير ممكّن.',
3-
filed_not_editable: 'الحقل غير قابل للتعديل.',
3+
field_not_editable: 'الحقل غير قابل للتعديل.',
44
};
55

66
export default Object.freeze(account_center);
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
const account_center = {
22
not_enabled: 'Account Center ist nicht aktiviert.',
3-
filed_not_editable: 'Feld ist nicht bearbeitbar.',
3+
field_not_editable: 'Feld ist nicht bearbeitbar.',
44
};
55

66
export default Object.freeze(account_center);
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
const account_center = {
22
not_enabled: 'Account center is not enabled.',
3-
filed_not_editable: 'Field is not editable.',
3+
field_not_editable: 'Field is not editable.',
44
};
55

66
export default Object.freeze(account_center);
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
const account_center = {
22
not_enabled: 'El centro de cuentas no está habilitado.',
3-
filed_not_editable: 'El campo no es editable.',
3+
field_not_editable: 'El campo no es editable.',
44
};
55

66
export default Object.freeze(account_center);
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
const account_center = {
22
not_enabled: "Le centre de compte n'est pas activé.",
3-
filed_not_editable: "Le champ n'est pas modifiable.",
3+
field_not_editable: "Le champ n'est pas modifiable.",
44
};
55

66
export default Object.freeze(account_center);
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
const account_center = {
22
not_enabled: 'Centro account non è abilitato.',
3-
filed_not_editable: 'Il campo non è modificabile.',
3+
field_not_editable: 'Il campo non è modificabile.',
44
};
55

66
export default Object.freeze(account_center);
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
const account_center = {
22
not_enabled: 'アカウントセンターが有効になっていません。',
3-
filed_not_editable: 'フィールドは編集できません。',
3+
field_not_editable: 'フィールドは編集できません。',
44
};
55

66
export default Object.freeze(account_center);
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
const account_center = {
22
not_enabled: '계정 센터가 활성화되어 있지 않습니다.',
3-
filed_not_editable: '필드를 편집할 수 없습니다.',
3+
field_not_editable: '필드를 편집할 수 없습니다.',
44
};
55

66
export default Object.freeze(account_center);
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
const account_center = {
22
not_enabled: 'Centrum konta nie jest aktywowane.',
3-
filed_not_editable: 'Pole nie jest edytowalne.',
3+
field_not_editable: 'Pole nie jest edytowalne.',
44
};
55

66
export default Object.freeze(account_center);
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
const account_center = {
22
not_enabled: 'O centro de contas não está ativado.',
3-
filed_not_editable: 'O campo não é editável.',
3+
field_not_editable: 'O campo não é editável.',
44
};
55

66
export default Object.freeze(account_center);
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
const account_center = {
22
not_enabled: 'O centro de contas não está ativado.',
3-
filed_not_editable: 'O campo não é editável.',
3+
field_not_editable: 'O campo não é editável.',
44
};
55

66
export default Object.freeze(account_center);
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
const account_center = {
22
not_enabled: 'Центр аккаунта не включен.',
3-
filed_not_editable: 'Поле не редактируется.',
3+
field_not_editable: 'Поле не редактируется.',
44
};
55

66
export default Object.freeze(account_center);
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
const account_center = {
22
not_enabled: 'Hesap merkezi etkin değil.',
3-
filed_not_editable: 'Alan düzenlenemez.',
3+
field_not_editable: 'Alan düzenlenemez.',
44
};
55

66
export default Object.freeze(account_center);
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
const account_center = {
22
not_enabled: '账户中心未启用。',
3-
filed_not_editable: '字段不可编辑。',
3+
field_not_editable: '字段不可编辑。',
44
};
55

66
export default Object.freeze(account_center);
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
const account_center = {
22
not_enabled: '帳戶中心未啟用。',
3-
filed_not_editable: '此欄位不可編輯。',
3+
field_not_editable: '此欄位不可編輯。',
44
};
55

66
export default Object.freeze(account_center);
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
const account_center = {
22
not_enabled: '帳戶中心尚未啟用。',
3-
filed_not_editable: '欄位不可編輯。',
3+
field_not_editable: '欄位不可編輯。',
44
};
55

66
export default Object.freeze(account_center);

0 commit comments

Comments
 (0)