From 7331767a855038bb643e8ddcf80db6482ea1eea0 Mon Sep 17 00:00:00 2001 From: Jonas Lochmann Date: Mon, 27 Dec 2021 01:00:00 +0100 Subject: [PATCH] Save the locale during mail login processes --- src/database/authtoken.ts | 25 ++++++++-- src/database/maillogintoken.ts | 25 ++++++++-- .../migrations/20181014-setup-tables.ts | 4 +- .../migrations/20190113-mail-login-tokens.ts | 4 +- ...213027-add-login-process-locale-storage.ts | 47 +++++++++++++++++++ src/function/authentication/index.ts | 9 +++- src/function/authentication/login-by-mail.ts | 10 +++- 7 files changed, 110 insertions(+), 14 deletions(-) create mode 100644 src/database/migration/migrations/20213027-add-login-process-locale-storage.ts diff --git a/src/database/authtoken.ts b/src/database/authtoken.ts index d9d9f5c..7f1e21a 100644 --- a/src/database/authtoken.ts +++ b/src/database/authtoken.ts @@ -1,6 +1,6 @@ /* * server component for the TimeLimit App - * Copyright (C) 2019 Jonas Lochmann + * Copyright (C) 2019 - 2021 Jonas Lochmann * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as @@ -19,18 +19,24 @@ import * as Sequelize from 'sequelize' import { authTokenColumn, timestampColumn } from './columns' import { SequelizeAttributes } from './types' -export interface AuthTokenAttributes { +export interface AuthTokenAttributesVersion1 { token: string mail: string createdAt: string } +export interface AuthTokenAttributesVersion2 { + locale: string +} + +export type AuthTokenAttributes = AuthTokenAttributesVersion1 & AuthTokenAttributesVersion2 + export type AuthTokenModel = Sequelize.Model & AuthTokenAttributes export type AuthTokenModelStatic = typeof Sequelize.Model & { new (values?: object, options?: Sequelize.BuildOptions): AuthTokenModel; } -export const attributes: SequelizeAttributes = { +export const attributesVersion1: SequelizeAttributes = { token: { ...authTokenColumn, primaryKey: true @@ -45,4 +51,17 @@ export const attributes: SequelizeAttributes = { createdAt: { ...timestampColumn } } +export const attributesVersion2: SequelizeAttributes = { + locale: { + type: Sequelize.STRING, + allowNull: false, + defaultValue: 'en' + } +} + +export const attributes: SequelizeAttributes = { + ...attributesVersion1, + ...attributesVersion2 +} + export const createAuthtokenModel = (sequelize: Sequelize.Sequelize): AuthTokenModelStatic => sequelize.define('AuthToken', attributes) as AuthTokenModelStatic diff --git a/src/database/maillogintoken.ts b/src/database/maillogintoken.ts index db3cd7c..ed3b0a7 100644 --- a/src/database/maillogintoken.ts +++ b/src/database/maillogintoken.ts @@ -1,6 +1,6 @@ /* * server component for the TimeLimit App - * Copyright (C) 2019 - 2020 Jonas Lochmann + * Copyright (C) 2019 - 2021 Jonas Lochmann * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as @@ -19,7 +19,7 @@ import * as Sequelize from 'sequelize' import { authTokenColumn, timestampColumn } from './columns' import { SequelizeAttributes } from './types' -export interface MailLoginTokenAttributes { +export interface MailLoginTokenAttributesVersion1 { mailLoginToken: string receivedCode: string mail: string @@ -27,12 +27,18 @@ export interface MailLoginTokenAttributes { remainingAttempts: number } +export interface MailLoginTokenAttributesVersion2 { + locale: string +} + +export type MailLoginTokenAttributes = MailLoginTokenAttributesVersion1 & MailLoginTokenAttributesVersion2 + export type MailLoginTokenModel = Sequelize.Model & MailLoginTokenAttributes export type MailLoginTokenModelStatic = typeof Sequelize.Model & { new (values?: object, options?: Sequelize.BuildOptions): MailLoginTokenModel; } -export const attributes: SequelizeAttributes = { +export const attributesVersion1: SequelizeAttributes = { mailLoginToken: { ...authTokenColumn, primaryKey: true @@ -61,4 +67,17 @@ export const attributes: SequelizeAttributes = { } } +export const attributesVersion2: SequelizeAttributes = { + locale: { + type: Sequelize.STRING, + allowNull: false, + defaultValue: 'en' + } +} + +export const attributes: SequelizeAttributes = { + ...attributesVersion1, + ...attributesVersion2 +} + export const createMailLoginTokenModel = (sequelize: Sequelize.Sequelize): MailLoginTokenModelStatic => sequelize.define('MailLoginToken', attributes) as MailLoginTokenModelStatic diff --git a/src/database/migration/migrations/20181014-setup-tables.ts b/src/database/migration/migrations/20181014-setup-tables.ts index 7804155..7f9f63c 100644 --- a/src/database/migration/migrations/20181014-setup-tables.ts +++ b/src/database/migration/migrations/20181014-setup-tables.ts @@ -1,6 +1,6 @@ /* * server component for the TimeLimit App - * Copyright (C) 2019 - 2020 Jonas Lochmann + * Copyright (C) 2019 - 2021 Jonas Lochmann * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as @@ -18,7 +18,7 @@ import { QueryInterface, Sequelize, Transaction } from 'sequelize' import { attributes as addDeviceTokenAttributes } from '../../adddevicetoken' import { attributes as appAttributes } from '../../app' -import { attributes as authTokenAttributes } from '../../authtoken' +import { attributesVersion1 as authTokenAttributes } from '../../authtoken' import { attributesVersion1 as categoryAttributes } from '../../category' import { attributes as categoryAppAttributes } from '../../categoryapp' import { attributesVersion1 as deviceAttributes } from '../../device' diff --git a/src/database/migration/migrations/20190113-mail-login-tokens.ts b/src/database/migration/migrations/20190113-mail-login-tokens.ts index 0f122ab..0c40ae9 100644 --- a/src/database/migration/migrations/20190113-mail-login-tokens.ts +++ b/src/database/migration/migrations/20190113-mail-login-tokens.ts @@ -1,6 +1,6 @@ /* * server component for the TimeLimit App - * Copyright (C) 2019 Jonas Lochmann + * Copyright (C) 2019 - 2021 Jonas Lochmann * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as @@ -16,7 +16,7 @@ */ import { QueryInterface, Sequelize, Transaction } from 'sequelize' -import { attributes as mailLoginTokenAttributes } from '../../maillogintoken' +import { attributesVersion1 as mailLoginTokenAttributes } from '../../maillogintoken' export async function up (queryInterface: QueryInterface, sequelize: Sequelize) { await sequelize.transaction({ diff --git a/src/database/migration/migrations/20213027-add-login-process-locale-storage.ts b/src/database/migration/migrations/20213027-add-login-process-locale-storage.ts new file mode 100644 index 0000000..35951e7 --- /dev/null +++ b/src/database/migration/migrations/20213027-add-login-process-locale-storage.ts @@ -0,0 +1,47 @@ +/* + * server component for the TimeLimit App + * Copyright (C) 2019 - 2021 Jonas Lochmann + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, version 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +import { QueryInterface, Sequelize, Transaction } from 'sequelize' +import { attributesVersion2 as authTokenAttributes } from '../../authtoken' +import { attributesVersion2 as mailLoginTokenAttributes } from '../../maillogintoken' + +export async function up (queryInterface: QueryInterface, sequelize: Sequelize) { + await sequelize.transaction({ + type: Transaction.TYPES.EXCLUSIVE + }, async (transaction) => { + await queryInterface.addColumn('AuthTokens', 'locale', { + ...authTokenAttributes.locale + }, { + transaction + }) + + await queryInterface.addColumn('MailLoginTokens', 'locale', { + ...mailLoginTokenAttributes.locale + }, { + transaction + }) + }) +} + +export async function down (queryInterface: QueryInterface, sequelize: Sequelize) { + await sequelize.transaction({ + type: Transaction.TYPES.EXCLUSIVE + }, async (transaction) => { + await queryInterface.removeColumn('AuthTokens', 'locale', { transaction }) + await queryInterface.removeColumn('MailLoginTokens', 'locale', { transaction }) + }) +} diff --git a/src/function/authentication/index.ts b/src/function/authentication/index.ts index 2f15763..eed0f9b 100644 --- a/src/function/authentication/index.ts +++ b/src/function/authentication/index.ts @@ -19,13 +19,18 @@ import { Unauthorized } from 'http-errors' import { Database, Transaction } from '../../database' import { generateAuthToken } from '../../util/token' -export const createAuthTokenByMailAddress = async ({ mail, database, transaction }: { mail: string, database: Database, transaction: Transaction }) => { +export const createAuthTokenByMailAddress = async ({ + mail, database, transaction, locale +}: { + mail: string, database: Database, transaction: Transaction, locale: string +}) => { const token = generateAuthToken() await database.authtoken.create({ token, mail, - createdAt: Date.now().toString() + createdAt: Date.now().toString(), + locale }, { transaction }) return token diff --git a/src/function/authentication/login-by-mail.ts b/src/function/authentication/login-by-mail.ts index 6497792..32f6b27 100644 --- a/src/function/authentication/login-by-mail.ts +++ b/src/function/authentication/login-by-mail.ts @@ -91,7 +91,8 @@ export const sendLoginCode = async ({ mail, deviceAuthToken, locale, database }: receivedCode: code, mail, createdAt: Date.now().toString(10), - remainingAttempts: 3 + remainingAttempts: 3, + locale }, { transaction }) }) @@ -143,7 +144,12 @@ export const signInByMailCode = async ({ mailLoginToken, receivedCode, database throw new Gone() } - const mailAuthToken = await createAuthTokenByMailAddress({ mail: entry.mail, database, transaction }) + const mailAuthToken = await createAuthTokenByMailAddress({ + mail: entry.mail, + locale: entry.locale, + database, + transaction + }) return { mailAuthToken } })