diff --git a/src/function/authentication/index.ts b/src/function/authentication/index.ts index 7af460e..2f15763 100644 --- a/src/function/authentication/index.ts +++ b/src/function/authentication/index.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 @@ -31,7 +31,11 @@ export const createAuthTokenByMailAddress = async ({ mail, database, transaction return token } -export const getMailByAuthToken = async ({ mailAuthToken, database, transaction }: { mailAuthToken: string, database: Database, transaction: Transaction }) => { +export const getMailByAuthToken = async ({ + mailAuthToken, database, transaction, invalidate +}: { + mailAuthToken: string, database: Database, transaction: Transaction, invalidate: boolean +}) => { const entry = await database.authtoken.findOne({ where: { token: mailAuthToken @@ -40,14 +44,31 @@ export const getMailByAuthToken = async ({ mailAuthToken, database, transaction }) if (entry) { + if (invalidate) { + const rowCounter = await database.authtoken.destroy({ + where: { + token: mailAuthToken + }, + transaction + }) + + if (rowCounter !== 1) { + return null + } + } + return entry.mail } else { return null } } -export const requireMailByAuthToken = async ({ mailAuthToken, database, transaction }: { mailAuthToken: string, database: Database, transaction: Transaction }) => { - const mail = await getMailByAuthToken({ mailAuthToken, database, transaction }) +export const requireMailByAuthToken = async ({ + mailAuthToken, database, transaction, invalidate +}: { + mailAuthToken: string, database: Database, transaction: Transaction, invalidate: boolean +}) => { + const mail = await getMailByAuthToken({ mailAuthToken, database, transaction, invalidate }) if (!mail) { throw new Unauthorized() diff --git a/src/function/parent/create-family.ts b/src/function/parent/create-family.ts index 360fe35..8d9452f 100644 --- a/src/function/parent/create-family.ts +++ b/src/function/parent/create-family.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 @@ -37,7 +37,7 @@ export const createFamily = async ({ database, mailAuthToken, firstParentDevice, }) => { return database.transaction(async (transaction) => { const now = Date.now().toString(10) - const mail = await requireMailByAuthToken({ database, mailAuthToken, transaction }) + const mail = await requireMailByAuthToken({ database, mailAuthToken, transaction, invalidate: true }) // ensure that no family was created for this mail yet const exisitngUserEntry = await database.user.findOne({ diff --git a/src/function/parent/get-status-by-mail-address.ts b/src/function/parent/get-status-by-mail-address.ts index 80efb86..f98e57c 100644 --- a/src/function/parent/get-status-by-mail-address.ts +++ b/src/function/parent/get-status-by-mail-address.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 @@ -43,7 +43,7 @@ const getStatusByMailAddress = async ({ export const getStatusByMailToken = async ({ mailAuthToken, database, transaction }: { mailAuthToken: string, database: Database, transaction: Transaction }) => { - const mail = await requireMailByAuthToken({ mailAuthToken, database, transaction }) + const mail = await requireMailByAuthToken({ mailAuthToken, database, transaction, invalidate: false }) const status = await getStatusByMailAddress({ mail, database, transaction }) return { mail, status } diff --git a/src/function/parent/link-mail-address.ts b/src/function/parent/link-mail-address.ts index 39682b9..4fcd1db 100644 --- a/src/function/parent/link-mail-address.ts +++ b/src/function/parent/link-mail-address.ts @@ -45,7 +45,7 @@ export const linkMailAddress = async ({ mailAuthToken, deviceAuthToken, parentUs const familyId = deviceEntry.familyId - const mailAddress = await requireMailByAuthToken({ mailAuthToken, database, transaction }) + const mailAddress = await requireMailByAuthToken({ mailAuthToken, database, transaction, invalidate: true }) const exisitingUser = await database.user.findOne({ where: { diff --git a/src/function/parent/recover-parent-password.ts b/src/function/parent/recover-parent-password.ts index 3040a99..ad57de2 100644 --- a/src/function/parent/recover-parent-password.ts +++ b/src/function/parent/recover-parent-password.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 @@ -31,7 +31,7 @@ export const recoverParentPassword = async ({ database, websocket, password, mai // no transaction here because this is directly called from an API endpoint }) => { await database.transaction(async (transaction) => { - const mail = await requireMailByAuthToken({ mailAuthToken, database, transaction }) + const mail = await requireMailByAuthToken({ mailAuthToken, database, transaction, invalidate: true }) // update the user entry const userEntry = await database.user.findOne({ diff --git a/src/function/parent/sign-in-into-family.ts b/src/function/parent/sign-in-into-family.ts index 81e69b0..c774773 100644 --- a/src/function/parent/sign-in-into-family.ts +++ b/src/function/parent/sign-in-into-family.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 @@ -33,7 +33,7 @@ export const signInIntoFamily = async ({ database, mailAuthToken, newDeviceInfo, // no transaction here because this is directly called from an API endpoint }): Promise<{ deviceId: string; deviceAuthToken: string }> => { return database.transaction(async (transaction) => { - const mail = await requireMailByAuthToken({ database, mailAuthToken, transaction }) + const mail = await requireMailByAuthToken({ database, mailAuthToken, transaction, invalidate: true }) const userEntryUnsafe = await database.user.findOne({ where: {