diff --git a/routes/api/magiclink/index.ts b/routes/api/magiclink/index.ts index 9f332e3..8f588f7 100644 --- a/routes/api/magiclink/index.ts +++ b/routes/api/magiclink/index.ts @@ -1,10 +1,8 @@ import 'npm:iterator-polyfill' import { define } from '../../../utils.ts' // Polyfill AsyncIterator - -import { FreshContext } from 'fresh' import { db } from ':src/db/mod.ts' -import { SessionHandlers, SessionStore } from ':src/session/mod.ts' +import { SessionStore } from ':src/session/mod.ts' import { respondApi } from ':src/utils.ts' import { Contact, type Mail, send } from '@cohabit/mailer' import { magicLinkTemplate } from '@cohabit/mailer/templates' @@ -25,9 +23,8 @@ export async function getUserByMail(email: string): Promise { return user } -*/ -export const handler = define.handlers({}) -/* +// export const handler = define.handlers({}) +export const handler = define.handlers({ async POST(ctx) { const request = ctx.req const { email } = await request.json() as { email: string } @@ -41,13 +38,27 @@ export const handler = define.handlers({}) // generate magic link const token = crypto.randomUUID() + + if (ctx.state.session === undefined) { + return respondApi( + 'error', + new Error('missing server session for current user'), + 500, + ) + } + + const remoteAddr = ctx.info.remoteAddr + if (!('hostname' in remoteAddr)) { + return respondApi('error', new Error('connection is not using http'), 500) + } + const endpoint = `${ctx.url.origin}/api/magiclink?token=${token}&session=${ctx.state.session.uuid}&redirect=/profil` // save token to session ctx.state.session.flash(`MAGIC_LINK__${token}`, { email, - remoteId: remoteId(request, ctx), + remoteId: remoteId(request, { remoteAddr }), timestamp: Date.now(), }) @@ -55,8 +66,7 @@ export const handler = define.handlers({}) try { if (user) { // Get user ip through proxy else from tcp connection - const ip = request.headers.get('X-FORWARDED-FOR') ?? - ctx.remoteAddr.hostname + const ip = request.headers.get('X-FORWARDED-FOR') ?? remoteAddr.hostname const device = request.headers.get('Sec-Ch-Ua-Platform') ?? undefined await sendMagicLink(user, { device, ip, endpoint }) @@ -74,7 +84,9 @@ export const handler = define.handlers({}) ) } }, - async GET(request, ctx) { + async GET(ctx) { + const request = ctx.req + const token = ctx.url.searchParams.get('token') const redirect = ctx.url.searchParams.get('redirect') const sessionId = ctx.url.searchParams.get('session') @@ -88,7 +100,7 @@ export const handler = define.handlers({}) ctx.state.session = ctx.state.session ?? SessionStore.getSession(sessionId) // no session available - if (ctx.state.session === null) { + if (ctx.state.session === null || ctx.state.session === undefined) { return respondApi('error', 'no session datas', 401) } @@ -101,8 +113,13 @@ export const handler = define.handlers({}) return respondApi('error', 'wrong token or timeout exceeded', 401) } + const remoteAddr = ctx.info.remoteAddr + if (!('hostname' in remoteAddr)) { + return respondApi('error', new Error('connection is not using http'), 500) + } + // check remote id (same user/machine that has query the token) - if (entry.remoteId === remoteId(request, ctx)) { + if (entry.remoteId === remoteId(request, { remoteAddr })) { const user = await getUserByMail(entry.email) ctx.state.session.set('user', user) @@ -122,10 +139,10 @@ export const handler = define.handlers({}) ) }, }) -/* + function remoteId( { headers }: { headers: Headers }, - { remoteAddr }: { remoteAddr: FreshContext['remoteAddr'] }, + { remoteAddr }: { remoteAddr: Deno.NetAddr }, ): string { const forwardedAddress = headers.get('X-FORWARDED-FOR') const forwardedProto = headers.get('X-FORWARDED-PROTO')