mirror of
https://codeberg.org/timelimit/timelimit-server.git
synced 2026-08-31 19:03:45 +02:00
Send mail notifications for new devices and password resets
This commit is contained in:
@@ -22,7 +22,7 @@ import { maxMailNotificationFlags } from '../../database/user'
|
||||
import {
|
||||
generateAuthToken, generateFamilyId, generateIdWithinFamily, generateVersionId
|
||||
} from '../../util/token'
|
||||
import { requireMailByAuthToken } from '../authentication'
|
||||
import { requireMailAndLocaleByAuthToken } from '../authentication'
|
||||
import { prepareDeviceEntry } from '../device/prepare-device-entry'
|
||||
|
||||
export const createFamily = async ({ database, mailAuthToken, firstParentDevice, password, timeZone, parentName, deviceName }: {
|
||||
@@ -37,12 +37,12 @@ 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, invalidate: true })
|
||||
const mailInfo = await requireMailAndLocaleByAuthToken({ database, mailAuthToken, transaction, invalidate: true })
|
||||
|
||||
// ensure that no family was created for this mail yet
|
||||
const exisitngUserEntry = await database.user.findOne({
|
||||
where: {
|
||||
mail
|
||||
mail: mailInfo.mail
|
||||
},
|
||||
transaction
|
||||
})
|
||||
@@ -77,7 +77,7 @@ export const createFamily = async ({ database, mailAuthToken, firstParentDevice,
|
||||
secondPasswordHash: password.secondHash,
|
||||
secondPasswordSalt: password.secondSalt,
|
||||
type: 'parent',
|
||||
mail,
|
||||
mail: mailInfo.mail,
|
||||
timeZone,
|
||||
disableTimelimitsUntil: '0',
|
||||
currentDevice: '',
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
|
||||
import { Database, Transaction } from '../../database'
|
||||
import { StaticMessageException } from '../../exception'
|
||||
import { requireMailByAuthToken } from '../authentication'
|
||||
import { requireMailAndLocaleByAuthToken } from '../authentication'
|
||||
|
||||
const getStatusByMailAddress = async ({
|
||||
mail, database, transaction
|
||||
@@ -43,7 +43,9 @@ const getStatusByMailAddress = async ({
|
||||
export const getStatusByMailToken = async ({
|
||||
mailAuthToken, database, transaction
|
||||
}: { mailAuthToken: string, database: Database, transaction: Transaction }) => {
|
||||
const mail = await requireMailByAuthToken({ mailAuthToken, database, transaction, invalidate: false })
|
||||
const mailInfo = await requireMailAndLocaleByAuthToken({ mailAuthToken, database, transaction, invalidate: false })
|
||||
const mail = mailInfo.mail
|
||||
|
||||
const status = await getStatusByMailAddress({ mail, database, transaction })
|
||||
|
||||
return { mail, status }
|
||||
|
||||
@@ -19,7 +19,7 @@ import { Conflict, Unauthorized } from 'http-errors'
|
||||
import { Database } from '../../database'
|
||||
import { generateVersionId } from '../../util/token'
|
||||
import { WebsocketApi } from '../../websocket'
|
||||
import { requireMailByAuthToken } from '../authentication'
|
||||
import { requireMailAndLocaleByAuthToken } from '../authentication'
|
||||
import { notifyClientsAboutChangesDelayed } from '../websocket'
|
||||
|
||||
export const linkMailAddress = async ({ mailAuthToken, deviceAuthToken, parentUserId, parentPasswordSecondHash, database, websocket }: {
|
||||
@@ -45,11 +45,11 @@ export const linkMailAddress = async ({ mailAuthToken, deviceAuthToken, parentUs
|
||||
|
||||
const familyId = deviceEntry.familyId
|
||||
|
||||
const mailAddress = await requireMailByAuthToken({ mailAuthToken, database, transaction, invalidate: true })
|
||||
const mailInfo = await requireMailAndLocaleByAuthToken({ mailAuthToken, database, transaction, invalidate: true })
|
||||
|
||||
const exisitingUser = await database.user.findOne({
|
||||
where: {
|
||||
mail: mailAddress
|
||||
mail: mailInfo.mail
|
||||
},
|
||||
transaction
|
||||
})
|
||||
@@ -83,7 +83,7 @@ export const linkMailAddress = async ({ mailAuthToken, deviceAuthToken, parentUs
|
||||
throw new Conflict()
|
||||
}
|
||||
|
||||
parentEntry.mail = mailAddress
|
||||
parentEntry.mail = mailInfo.mail
|
||||
|
||||
await parentEntry.save({ transaction })
|
||||
|
||||
|
||||
@@ -18,9 +18,10 @@
|
||||
import { Conflict } from 'http-errors'
|
||||
import { ParentPassword } from '../../api/schema'
|
||||
import { Database } from '../../database'
|
||||
import { sendPasswordRecoveryUsedMail } from '../../util/mail'
|
||||
import { generateVersionId } from '../../util/token'
|
||||
import { WebsocketApi } from '../../websocket'
|
||||
import { requireMailByAuthToken } from '../authentication'
|
||||
import { requireMailAndLocaleByAuthToken } from '../authentication'
|
||||
import { notifyClientsAboutChangesDelayed } from '../websocket'
|
||||
|
||||
export const recoverParentPassword = async ({ database, websocket, password, mailAuthToken }: {
|
||||
@@ -31,12 +32,12 @@ 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, invalidate: true })
|
||||
const mailInfo = await requireMailAndLocaleByAuthToken({ mailAuthToken, database, transaction, invalidate: true })
|
||||
|
||||
// update the user entry
|
||||
const userEntry = await database.user.findOne({
|
||||
where: {
|
||||
mail
|
||||
mail: mailInfo.mail
|
||||
},
|
||||
transaction
|
||||
})
|
||||
@@ -69,5 +70,12 @@ export const recoverParentPassword = async ({ database, websocket, password, mai
|
||||
sourceDeviceId: null,
|
||||
transaction
|
||||
})
|
||||
|
||||
transaction.afterCommit(async () => {
|
||||
await sendPasswordRecoveryUsedMail({
|
||||
receiver: mailInfo.mail,
|
||||
locale: mailInfo.locale
|
||||
})
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
@@ -18,9 +18,10 @@
|
||||
import { Conflict } from 'http-errors'
|
||||
import { NewDeviceInfo } from '../../api/schema'
|
||||
import { Database } from '../../database'
|
||||
import { sendDeviceLinkedMail } from '../../util/mail'
|
||||
import { generateAuthToken, generateIdWithinFamily, generateVersionId } from '../../util/token'
|
||||
import { WebsocketApi } from '../../websocket'
|
||||
import { requireMailByAuthToken } from '../authentication'
|
||||
import { requireMailAndLocaleByAuthToken } from '../authentication'
|
||||
import { prepareDeviceEntry } from '../device/prepare-device-entry'
|
||||
import { notifyClientsAboutChangesDelayed } from '../websocket'
|
||||
|
||||
@@ -33,11 +34,11 @@ 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, invalidate: true })
|
||||
const mailInfo = await requireMailAndLocaleByAuthToken({ database, mailAuthToken, transaction, invalidate: true })
|
||||
|
||||
const userEntryUnsafe = await database.user.findOne({
|
||||
where: {
|
||||
mail
|
||||
mail: mailInfo.mail
|
||||
},
|
||||
attributes: ['familyId', 'userId'],
|
||||
transaction
|
||||
@@ -84,6 +85,14 @@ export const signInIntoFamily = async ({ database, mailAuthToken, newDeviceInfo,
|
||||
transaction
|
||||
})
|
||||
|
||||
transaction.afterCommit(async () => {
|
||||
await sendDeviceLinkedMail({
|
||||
receiver: mailInfo.mail,
|
||||
locale: mailInfo.locale,
|
||||
deviceName
|
||||
})
|
||||
})
|
||||
|
||||
return {
|
||||
deviceId,
|
||||
deviceAuthToken
|
||||
|
||||
Reference in New Issue
Block a user