Merge branch 'develop' into swn
This commit is contained in:
commit
e0dc391cf6
4
.gitignore
vendored
4
.gitignore
vendored
|
@ -9,6 +9,10 @@
|
||||||
/node_modules
|
/node_modules
|
||||||
report.*.json
|
report.*.json
|
||||||
|
|
||||||
|
# Cypress
|
||||||
|
cypress/screenshots
|
||||||
|
cypress/videos
|
||||||
|
|
||||||
# config
|
# config
|
||||||
/.config/*
|
/.config/*
|
||||||
!/.config/example.yml
|
!/.config/example.yml
|
||||||
|
|
|
@ -14,6 +14,8 @@
|
||||||
### Improvements
|
### Improvements
|
||||||
- ActivityPub: リモートユーザーのDeleteアクティビティに対応
|
- ActivityPub: リモートユーザーのDeleteアクティビティに対応
|
||||||
- ActivityPub: add resolver check for blocked instance
|
- ActivityPub: add resolver check for blocked instance
|
||||||
|
- アカウントが凍結された場合に、凍結された旨を表示してからログアウトするように
|
||||||
|
- 凍結されたアカウントにログインしようとしたときに、凍結されている旨を表示するように
|
||||||
- UIの改善
|
- UIの改善
|
||||||
|
|
||||||
### Bugfixes
|
### Bugfixes
|
||||||
|
|
|
@ -1,10 +1,14 @@
|
||||||
describe('Basic', () => {
|
describe('Before setup instance', () => {
|
||||||
before(() => {
|
beforeEach(() => {
|
||||||
cy.request('POST', '/api/reset-db');
|
cy.request('POST', '/api/reset-db').as('reset');
|
||||||
|
cy.get('@reset').its('status').should('equal', 204);
|
||||||
|
cy.reload(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
beforeEach(() => {
|
afterEach(() => {
|
||||||
cy.reload(true);
|
// テスト終了直前にページ遷移するようなテストケース(例えばアカウント作成)だと、たぶんCypressのバグでブラウザの内容が次のテストケースに引き継がれてしまう(例えばアカウントが作成し終わった段階からテストが始まる)。
|
||||||
|
// waitを入れることでそれを防止できる
|
||||||
|
cy.wait(1000);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('successfully loads', () => {
|
it('successfully loads', () => {
|
||||||
|
@ -14,56 +18,172 @@ describe('Basic', () => {
|
||||||
it('setup instance', () => {
|
it('setup instance', () => {
|
||||||
cy.visit('/');
|
cy.visit('/');
|
||||||
|
|
||||||
|
cy.intercept('POST', '/api/admin/accounts/create').as('signup');
|
||||||
|
|
||||||
cy.get('[data-cy-admin-username] input').type('admin');
|
cy.get('[data-cy-admin-username] input').type('admin');
|
||||||
|
|
||||||
cy.get('[data-cy-admin-password] input').type('admin1234');
|
cy.get('[data-cy-admin-password] input').type('admin1234');
|
||||||
|
|
||||||
cy.get('[data-cy-admin-ok]').click();
|
cy.get('[data-cy-admin-ok]').click();
|
||||||
|
|
||||||
|
// なぜか動かない
|
||||||
|
//cy.wait('@signup').should('have.property', 'response.statusCode');
|
||||||
|
cy.wait('@signup');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('After setup instance', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
cy.request('POST', '/api/reset-db').as('reset');
|
||||||
|
cy.get('@reset').its('status').should('equal', 204);
|
||||||
|
cy.reload(true);
|
||||||
|
|
||||||
|
// インスタンス初期セットアップ
|
||||||
|
cy.request('POST', '/api/admin/accounts/create', {
|
||||||
|
username: 'admin',
|
||||||
|
password: 'pass',
|
||||||
|
}).its('body').as('admin');
|
||||||
|
|
||||||
|
cy.get('@admin');
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
// テスト終了直前にページ遷移するようなテストケース(例えばアカウント作成)だと、たぶんCypressのバグでブラウザの内容が次のテストケースに引き継がれてしまう(例えばアカウントが作成し終わった段階からテストが始まる)。
|
||||||
|
// waitを入れることでそれを防止できる
|
||||||
|
cy.wait(1000);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('successfully loads', () => {
|
||||||
|
cy.visit('/');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('signup', () => {
|
it('signup', () => {
|
||||||
cy.visit('/');
|
cy.visit('/');
|
||||||
|
|
||||||
|
cy.intercept('POST', '/api/signup').as('signup');
|
||||||
|
|
||||||
cy.get('[data-cy-signup]').click();
|
cy.get('[data-cy-signup]').click();
|
||||||
|
|
||||||
cy.get('[data-cy-signup-username] input').type('alice');
|
cy.get('[data-cy-signup-username] input').type('alice');
|
||||||
|
|
||||||
cy.get('[data-cy-signup-password] input').type('alice1234');
|
cy.get('[data-cy-signup-password] input').type('alice1234');
|
||||||
|
|
||||||
cy.get('[data-cy-signup-password-retype] input').type('alice1234');
|
cy.get('[data-cy-signup-password-retype] input').type('alice1234');
|
||||||
|
|
||||||
cy.get('[data-cy-signup-submit]').click();
|
cy.get('[data-cy-signup-submit]').click();
|
||||||
|
|
||||||
|
cy.wait('@signup');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('After user signup', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
cy.request('POST', '/api/reset-db').as('reset');
|
||||||
|
cy.get('@reset').its('status').should('equal', 204);
|
||||||
|
cy.reload(true);
|
||||||
|
|
||||||
|
// インスタンス初期セットアップ
|
||||||
|
cy.request('POST', '/api/admin/accounts/create', {
|
||||||
|
username: 'admin',
|
||||||
|
password: 'pass',
|
||||||
|
}).its('body').as('admin');
|
||||||
|
|
||||||
|
cy.get('@admin').then(() => {
|
||||||
|
// ユーザー作成
|
||||||
|
cy.request('POST', '/api/signup', {
|
||||||
|
username: 'alice',
|
||||||
|
password: 'alice1234',
|
||||||
|
}).its('body').as('alice');
|
||||||
|
});
|
||||||
|
|
||||||
|
cy.get('@alice');
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
// テスト終了直前にページ遷移するようなテストケース(例えばアカウント作成)だと、たぶんCypressのバグでブラウザの内容が次のテストケースに引き継がれてしまう(例えばアカウントが作成し終わった段階からテストが始まる)。
|
||||||
|
// waitを入れることでそれを防止できる
|
||||||
|
cy.wait(1000);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('successfully loads', () => {
|
||||||
|
cy.visit('/');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('signin', () => {
|
it('signin', () => {
|
||||||
cy.visit('/');
|
cy.visit('/');
|
||||||
|
|
||||||
|
cy.intercept('POST', '/api/signin').as('signin');
|
||||||
|
|
||||||
cy.get('[data-cy-signin]').click();
|
cy.get('[data-cy-signin]').click();
|
||||||
|
|
||||||
cy.get('[data-cy-signin-username] input').type('alice');
|
cy.get('[data-cy-signin-username] input').type('alice');
|
||||||
|
|
||||||
// Enterキーでサインインできるかの確認も兼ねる
|
// Enterキーでサインインできるかの確認も兼ねる
|
||||||
cy.get('[data-cy-signin-password] input').type('alice1234{enter}');
|
cy.get('[data-cy-signin-password] input').type('alice1234{enter}');
|
||||||
|
|
||||||
|
cy.wait('@signin');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('suspend', function() {
|
||||||
|
cy.request('POST', '/api/admin/suspend-user', {
|
||||||
|
i: this.admin.token,
|
||||||
|
userId: this.alice.id,
|
||||||
|
});
|
||||||
|
|
||||||
|
cy.visit('/');
|
||||||
|
|
||||||
|
cy.get('[data-cy-signin]').click();
|
||||||
|
cy.get('[data-cy-signin-username] input').type('alice');
|
||||||
|
cy.get('[data-cy-signin-password] input').type('alice1234{enter}');
|
||||||
|
|
||||||
|
cy.contains('アカウントが凍結されています');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('After user singed in', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
cy.request('POST', '/api/reset-db').as('reset');
|
||||||
|
cy.get('@reset').its('status').should('equal', 204);
|
||||||
|
cy.reload(true);
|
||||||
|
|
||||||
|
// インスタンス初期セットアップ
|
||||||
|
cy.request('POST', '/api/admin/accounts/create', {
|
||||||
|
username: 'admin',
|
||||||
|
password: 'pass',
|
||||||
|
}).its('body').as('admin');
|
||||||
|
|
||||||
|
cy.get('@admin').then(() => {
|
||||||
|
// ユーザー作成
|
||||||
|
cy.request('POST', '/api/signup', {
|
||||||
|
username: 'alice',
|
||||||
|
password: 'alice1234',
|
||||||
|
}).its('body').as('alice');
|
||||||
|
});
|
||||||
|
|
||||||
|
cy.get('@alice').then(() => {
|
||||||
|
cy.visit('/');
|
||||||
|
|
||||||
|
cy.intercept('POST', '/api/signin').as('signin');
|
||||||
|
|
||||||
|
cy.get('[data-cy-signin]').click();
|
||||||
|
cy.get('[data-cy-signin-username] input').type('alice');
|
||||||
|
cy.get('[data-cy-signin-password] input').type('alice1234{enter}');
|
||||||
|
|
||||||
|
cy.wait('@signin').as('signedIn');
|
||||||
|
});
|
||||||
|
|
||||||
|
cy.get('@signedIn');
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
// テスト終了直前にページ遷移するようなテストケース(例えばアカウント作成)だと、たぶんCypressのバグでブラウザの内容が次のテストケースに引き継がれてしまう(例えばアカウントが作成し終わった段階からテストが始まる)。
|
||||||
|
// waitを入れることでそれを防止できる
|
||||||
|
cy.wait(1000);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('successfully loads', () => {
|
||||||
|
cy.visit('/');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('note', () => {
|
it('note', () => {
|
||||||
cy.visit('/');
|
cy.visit('/');
|
||||||
|
|
||||||
//#region TODO: この辺はUI操作ではなくAPI操作でログインする
|
|
||||||
cy.get('[data-cy-signin]').click();
|
|
||||||
|
|
||||||
cy.get('[data-cy-signin-username] input').type('alice');
|
|
||||||
|
|
||||||
// Enterキーでサインインできるかの確認も兼ねる
|
|
||||||
cy.get('[data-cy-signin-password] input').type('alice1234{enter}');
|
|
||||||
//#endregion
|
|
||||||
|
|
||||||
cy.get('[data-cy-open-post-form]').click();
|
cy.get('[data-cy-open-post-form]').click();
|
||||||
|
|
||||||
cy.get('[data-cy-post-form-text]').type('Hello, Misskey!');
|
cy.get('[data-cy-post-form-text]').type('Hello, Misskey!');
|
||||||
|
|
||||||
cy.get('[data-cy-open-post-form-submit]').click();
|
cy.get('[data-cy-open-post-form-submit]').click();
|
||||||
|
|
||||||
// TODO: 投稿した文字列が画面内にあるか(=タイムラインに流れてきたか)のテスト
|
cy.contains('Hello, Misskey!');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -529,6 +529,8 @@ removeAllFollowing: "フォローを全解除"
|
||||||
removeAllFollowingDescription: "{host}からのフォローをすべて解除します。そのインスタンスがもう存在しなくなった場合などに実行してください。"
|
removeAllFollowingDescription: "{host}からのフォローをすべて解除します。そのインスタンスがもう存在しなくなった場合などに実行してください。"
|
||||||
userSuspended: "このユーザーは凍結されています。"
|
userSuspended: "このユーザーは凍結されています。"
|
||||||
userSilenced: "このユーザーはサイレンスされています。"
|
userSilenced: "このユーザーはサイレンスされています。"
|
||||||
|
yourAccountSuspendedTitle: "アカウントが凍結されています"
|
||||||
|
yourAccountSuspendedDescription: "このアカウントは、サーバーの利用規約に違反したなどの理由により、凍結されています。詳細については管理者までお問い合わせください。新しいアカウントを作らないでください。"
|
||||||
menu: "メニュー"
|
menu: "メニュー"
|
||||||
divider: "分割線"
|
divider: "分割線"
|
||||||
addItem: "項目を追加"
|
addItem: "項目を追加"
|
||||||
|
|
|
@ -3,6 +3,7 @@ import { reactive } from 'vue';
|
||||||
import { apiUrl } from '@client/config';
|
import { apiUrl } from '@client/config';
|
||||||
import { waiting } from '@client/os';
|
import { waiting } from '@client/os';
|
||||||
import { unisonReload, reloadChannel } from '@client/scripts/unison-reload';
|
import { unisonReload, reloadChannel } from '@client/scripts/unison-reload';
|
||||||
|
import { showSuspendedDialog } from './scripts/show-suspended-dialog';
|
||||||
|
|
||||||
// TODO: 他のタブと永続化されたstateを同期
|
// TODO: 他のタブと永続化されたstateを同期
|
||||||
|
|
||||||
|
@ -82,17 +83,20 @@ function fetchAccount(token): Promise<Account> {
|
||||||
i: token
|
i: token
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
.then(res => res.json())
|
||||||
.then(res => {
|
.then(res => {
|
||||||
// When failed to authenticate user
|
if (res.error) {
|
||||||
if (res.status !== 200 && res.status < 500) {
|
if (res.error.id === 'a8c724b3-6e9c-4b46-b1a8-bc3ed6258370') {
|
||||||
return signout();
|
showSuspendedDialog().then(() => {
|
||||||
}
|
signout();
|
||||||
|
|
||||||
// Parse response
|
|
||||||
res.json().then(i => {
|
|
||||||
i.token = token;
|
|
||||||
done(i);
|
|
||||||
});
|
});
|
||||||
|
} else {
|
||||||
|
signout();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
res.token = token;
|
||||||
|
done(res);
|
||||||
|
}
|
||||||
})
|
})
|
||||||
.catch(fail);
|
.catch(fail);
|
||||||
});
|
});
|
||||||
|
|
|
@ -54,6 +54,7 @@ import { apiUrl, host } from '@client/config';
|
||||||
import { byteify, hexify } from '@client/scripts/2fa';
|
import { byteify, hexify } from '@client/scripts/2fa';
|
||||||
import * as os from '@client/os';
|
import * as os from '@client/os';
|
||||||
import { login } from '@client/account';
|
import { login } from '@client/account';
|
||||||
|
import { showSuspendedDialog } from '../scripts/show-suspended-dialog';
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
components: {
|
components: {
|
||||||
|
@ -169,15 +170,7 @@ export default defineComponent({
|
||||||
this.signing = false;
|
this.signing = false;
|
||||||
this.challengeData = res;
|
this.challengeData = res;
|
||||||
return this.queryKey();
|
return this.queryKey();
|
||||||
}).catch(() => {
|
}).catch(this.loginFailed);
|
||||||
os.dialog({
|
|
||||||
type: 'error',
|
|
||||||
text: this.$ts.signinFailed
|
|
||||||
});
|
|
||||||
this.challengeData = null;
|
|
||||||
this.totpLogin = false;
|
|
||||||
this.signing = false;
|
|
||||||
});
|
|
||||||
} else {
|
} else {
|
||||||
this.totpLogin = true;
|
this.totpLogin = true;
|
||||||
this.signing = false;
|
this.signing = false;
|
||||||
|
@ -190,14 +183,36 @@ export default defineComponent({
|
||||||
}).then(res => {
|
}).then(res => {
|
||||||
this.$emit('login', res);
|
this.$emit('login', res);
|
||||||
this.onLogin(res);
|
this.onLogin(res);
|
||||||
}).catch(() => {
|
}).catch(this.loginFailed);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
loginFailed(err) {
|
||||||
|
switch (err.id) {
|
||||||
|
case '6cc579cc-885d-43d8-95c2-b8c7fc963280': {
|
||||||
os.dialog({
|
os.dialog({
|
||||||
type: 'error',
|
type: 'error',
|
||||||
text: this.$ts.loginFailed
|
title: this.$ts.loginFailed,
|
||||||
|
text: this.$ts.noSuchUser
|
||||||
});
|
});
|
||||||
this.signing = false;
|
break;
|
||||||
|
}
|
||||||
|
case 'e03a5f46-d309-4865-9b69-56282d94e1eb': {
|
||||||
|
showSuspendedDialog();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
os.dialog({
|
||||||
|
type: 'error',
|
||||||
|
title: this.$ts.loginFailed,
|
||||||
|
text: JSON.stringify(err)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.challengeData = null;
|
||||||
|
this.totpLogin = false;
|
||||||
|
this.signing = false;
|
||||||
},
|
},
|
||||||
|
|
||||||
resetPassword() {
|
resetPassword() {
|
||||||
|
|
10
src/client/scripts/show-suspended-dialog.ts
Normal file
10
src/client/scripts/show-suspended-dialog.ts
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
import * as os from '@client/os';
|
||||||
|
import { i18n } from '@client/i18n';
|
||||||
|
|
||||||
|
export function showSuspendedDialog() {
|
||||||
|
return os.dialog({
|
||||||
|
type: 'error',
|
||||||
|
title: i18n.locale.yourAccountSuspendedTitle,
|
||||||
|
text: i18n.locale.yourAccountSuspendedDescription
|
||||||
|
});
|
||||||
|
}
|
|
@ -18,4 +18,6 @@ export default define(meta, async (ps, user) => {
|
||||||
if (process.env.NODE_ENV !== 'test') throw 'NODE_ENV is not a test';
|
if (process.env.NODE_ENV !== 'test') throw 'NODE_ENV is not a test';
|
||||||
|
|
||||||
await resetDb();
|
await resetDb();
|
||||||
|
|
||||||
|
await new Promise(resolve => setTimeout(resolve, 1000));
|
||||||
});
|
});
|
||||||
|
|
|
@ -18,6 +18,11 @@ export default async (ctx: Koa.Context) => {
|
||||||
const password = body['password'];
|
const password = body['password'];
|
||||||
const token = body['token'];
|
const token = body['token'];
|
||||||
|
|
||||||
|
function error(status: number, error: { id: string }) {
|
||||||
|
ctx.status = status;
|
||||||
|
ctx.body = { error };
|
||||||
|
}
|
||||||
|
|
||||||
if (typeof username != 'string') {
|
if (typeof username != 'string') {
|
||||||
ctx.status = 400;
|
ctx.status = 400;
|
||||||
return;
|
return;
|
||||||
|
@ -40,15 +45,15 @@ export default async (ctx: Koa.Context) => {
|
||||||
}) as ILocalUser;
|
}) as ILocalUser;
|
||||||
|
|
||||||
if (user == null) {
|
if (user == null) {
|
||||||
ctx.throw(404, {
|
error(404, {
|
||||||
error: 'user not found'
|
id: '6cc579cc-885d-43d8-95c2-b8c7fc963280',
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (user.isSuspended) {
|
if (user.isSuspended) {
|
||||||
ctx.throw(403, {
|
error(403, {
|
||||||
error: 'user is suspended'
|
id: 'e03a5f46-d309-4865-9b69-56282d94e1eb',
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -58,7 +63,7 @@ export default async (ctx: Koa.Context) => {
|
||||||
// Compare password
|
// Compare password
|
||||||
const same = await bcrypt.compare(password, profile.password!);
|
const same = await bcrypt.compare(password, profile.password!);
|
||||||
|
|
||||||
async function fail(status?: number, failure?: { error: string }) {
|
async function fail(status?: number, failure?: { id: string }) {
|
||||||
// Append signin history
|
// Append signin history
|
||||||
await Signins.insert({
|
await Signins.insert({
|
||||||
id: genId(),
|
id: genId(),
|
||||||
|
@ -69,7 +74,7 @@ export default async (ctx: Koa.Context) => {
|
||||||
success: false
|
success: false
|
||||||
});
|
});
|
||||||
|
|
||||||
ctx.throw(status || 500, failure || { error: 'someting happened' });
|
error(status || 500, failure || { id: '4e30e80c-e338-45a0-8c8f-44455efa3b76' });
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!profile.twoFactorEnabled) {
|
if (!profile.twoFactorEnabled) {
|
||||||
|
@ -78,7 +83,7 @@ export default async (ctx: Koa.Context) => {
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
await fail(403, {
|
await fail(403, {
|
||||||
error: 'incorrect password'
|
id: '932c904e-9460-45b7-9ce6-7ed33be7eb2c'
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -87,7 +92,7 @@ export default async (ctx: Koa.Context) => {
|
||||||
if (token) {
|
if (token) {
|
||||||
if (!same) {
|
if (!same) {
|
||||||
await fail(403, {
|
await fail(403, {
|
||||||
error: 'incorrect password'
|
id: '932c904e-9460-45b7-9ce6-7ed33be7eb2c'
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -104,14 +109,14 @@ export default async (ctx: Koa.Context) => {
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
await fail(403, {
|
await fail(403, {
|
||||||
error: 'invalid token'
|
id: 'cdf1235b-ac71-46d4-a3a6-84ccce48df6f'
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} else if (body.credentialId) {
|
} else if (body.credentialId) {
|
||||||
if (!same && !profile.usePasswordLessLogin) {
|
if (!same && !profile.usePasswordLessLogin) {
|
||||||
await fail(403, {
|
await fail(403, {
|
||||||
error: 'incorrect password'
|
id: '932c904e-9460-45b7-9ce6-7ed33be7eb2c'
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -127,7 +132,7 @@ export default async (ctx: Koa.Context) => {
|
||||||
|
|
||||||
if (!challenge) {
|
if (!challenge) {
|
||||||
await fail(403, {
|
await fail(403, {
|
||||||
error: 'non-existent challenge'
|
id: '2715a88a-2125-4013-932f-aa6fe72792da'
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -139,7 +144,7 @@ export default async (ctx: Koa.Context) => {
|
||||||
|
|
||||||
if (new Date().getTime() - challenge.createdAt.getTime() >= 5 * 60 * 1000) {
|
if (new Date().getTime() - challenge.createdAt.getTime() >= 5 * 60 * 1000) {
|
||||||
await fail(403, {
|
await fail(403, {
|
||||||
error: 'non-existent challenge'
|
id: '2715a88a-2125-4013-932f-aa6fe72792da'
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -155,7 +160,7 @@ export default async (ctx: Koa.Context) => {
|
||||||
|
|
||||||
if (!securityKey) {
|
if (!securityKey) {
|
||||||
await fail(403, {
|
await fail(403, {
|
||||||
error: 'invalid credentialId'
|
id: '66269679-aeaf-4474-862b-eb761197e046'
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -174,14 +179,14 @@ export default async (ctx: Koa.Context) => {
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
await fail(403, {
|
await fail(403, {
|
||||||
error: 'invalid challenge data'
|
id: '93b86c4b-72f9-40eb-9815-798928603d1e'
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (!same && !profile.usePasswordLessLogin) {
|
if (!same && !profile.usePasswordLessLogin) {
|
||||||
await fail(403, {
|
await fail(403, {
|
||||||
error: 'incorrect password'
|
id: '932c904e-9460-45b7-9ce6-7ed33be7eb2c'
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -192,7 +197,7 @@ export default async (ctx: Koa.Context) => {
|
||||||
|
|
||||||
if (keys.length === 0) {
|
if (keys.length === 0) {
|
||||||
await fail(403, {
|
await fail(403, {
|
||||||
error: 'no keys found'
|
id: 'f27fd449-9af4-4841-9249-1f989b9fa4a4'
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue