diff --git a/routes/api/magiclink/index.ts b/routes/api/magiclink/index.ts index 8f588f7..5ec930e 100644 --- a/routes/api/magiclink/index.ts +++ b/routes/api/magiclink/index.ts @@ -1,178 +1,178 @@ import 'npm:iterator-polyfill' import { define } from '../../../utils.ts' // Polyfill AsyncIterator -import { db } from ':src/db/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' -import { User } from '@cohabit/resources-manager/models' -import { sleep } from '@jotsr/delayed' +// import { db } from ':src/db/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' +// import { User } from '@cohabit/resources-manager/models' +// import { sleep } from '@jotsr/delayed' -type MagicLinkInfos = { - remoteId: string - email: string - timestamp: number -} +// type MagicLinkInfos = { +// remoteId: string +// email: string +// timestamp: number +// } -export async function getUserByMail(email: string): Promise { - const [user] = await db.resource.user - .list((user) => user.mail === email) - .take(1) - .toArray() +// export async function getUserByMail(email: string): Promise { +// const [user] = await db.resource.user +// .list((user) => user.mail === email) +// .take(1) +// .toArray() - return user -} -// 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 } +// return user +// } +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 } - // check email before continue - if (!/\S+@\S+\.\S+/.test(email)) { - return respondApi('error', new SyntaxError('empty or invalid email'), 400) - } +// // check email before continue +// if (!/\S+@\S+\.\S+/.test(email)) { +// return respondApi('error', new SyntaxError('empty or invalid email'), 400) +// } - const user = await getUserByMail(email) +// const user = await getUserByMail(email) - // generate magic link - const token = crypto.randomUUID() +// // generate magic link +// const token = crypto.randomUUID() - if (ctx.state.session === undefined) { - return respondApi( - 'error', - new Error('missing server session for current user'), - 500, - ) - } +// 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 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` +// 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, { remoteAddr }), - timestamp: Date.now(), - }) +// // save token to session +// ctx.state.session.flash(`MAGIC_LINK__${token}`, { +// email, +// remoteId: remoteId(request, { remoteAddr }), +// timestamp: Date.now(), +// }) - // send mail to user - try { - if (user) { - // Get user ip through proxy else from tcp connection - const ip = request.headers.get('X-FORWARDED-FOR') ?? remoteAddr.hostname - const device = request.headers.get('Sec-Ch-Ua-Platform') ?? undefined +// // send mail to user +// try { +// if (user) { +// // Get user ip through proxy else from tcp connection +// 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 }) - } else { - //! perform wait to prevent time attacks - await sleep(Math.random() * 5_000 + 2_000) //between 2s and 7s - } - return respondApi('success') - } catch (error) { - console.error('MAGIC_LINK_SENDING', error) - return respondApi( - 'error', - new Error(`unable to send mail to ${email}`), - 500, - ) - } - }, - async GET(ctx) { - const request = ctx.req +// await sendMagicLink(user, { device, ip, endpoint }) +// } else { +// //! perform wait to prevent time attacks +// await sleep(Math.random() * 5_000 + 2_000) //between 2s and 7s +// } +// return respondApi('success') +// } catch (error) { +// console.error('MAGIC_LINK_SENDING', error) +// return respondApi( +// 'error', +// new Error(`unable to send mail to ${email}`), +// 500, +// ) +// } +// }, +// 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') +// const token = ctx.url.searchParams.get('token') +// const redirect = ctx.url.searchParams.get('redirect') +// const sessionId = ctx.url.searchParams.get('session') - // no token or sessionId - if (token === null || sessionId === null) { - return respondApi('error', 'no token or session provided', 400) - } +// // no token or sessionId +// if (token === null || sessionId === null) { +// return respondApi('error', 'no token or session provided', 400) +// } - // set session if 3rd party cookies was blocked - ctx.state.session = ctx.state.session ?? SessionStore.getSession(sessionId) +// // set session if 3rd party cookies was blocked +// ctx.state.session = ctx.state.session ?? SessionStore.getSession(sessionId) - // no session available - if (ctx.state.session === null || ctx.state.session === undefined) { - return respondApi('error', 'no session datas', 401) - } +// // no session available +// if (ctx.state.session === null || ctx.state.session === undefined) { +// return respondApi('error', 'no session datas', 401) +// } - // wrong or timeout token - const entry = ctx.state.session.get(`MAGIC_LINK__${token}`) +// // wrong or timeout token +// const entry = ctx.state.session.get(`MAGIC_LINK__${token}`) - const lifespan = Date.now() - 10 * 60 * 1_000 // ten minutes +// const lifespan = Date.now() - 10 * 60 * 1_000 // ten minutes - if (entry === undefined || entry.timestamp < lifespan) { - return respondApi('error', 'wrong token or timeout exceeded', 401) - } +// if (entry === undefined || entry.timestamp < lifespan) { +// 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) - } +// 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, { remoteAddr })) { - const user = await getUserByMail(entry.email) - ctx.state.session.set('user', user) +// // check remote id (same user/machine that has query the token) +// if (entry.remoteId === remoteId(request, { remoteAddr })) { +// const user = await getUserByMail(entry.email) +// ctx.state.session.set('user', user) - if (redirect) { - return Response.redirect(new URL(redirect, ctx.url.origin)) - } +// if (redirect) { +// return Response.redirect(new URL(redirect, ctx.url.origin)) +// } - return respondApi('success', user) - } +// return respondApi('success', user) +// } - return respondApi( - 'error', - new Error( - 'invalid id, use the same device/ip to query token and verify token', - ), - 401, - ) - }, -}) +// return respondApi( +// 'error', +// new Error( +// 'invalid id, use the same device/ip to query token and verify token', +// ), +// 401, +// ) +// }, +// }) -function remoteId( - { headers }: { headers: Headers }, - { remoteAddr }: { remoteAddr: Deno.NetAddr }, -): string { - const forwardedAddress = headers.get('X-FORWARDED-FOR') - const forwardedProto = headers.get('X-FORWARDED-PROTO') +// function remoteId( +// { headers }: { headers: Headers }, +// { remoteAddr }: { remoteAddr: Deno.NetAddr }, +// ): string { +// const forwardedAddress = headers.get('X-FORWARDED-FOR') +// const forwardedProto = headers.get('X-FORWARDED-PROTO') - if (forwardedAddress && forwardedProto) { - return `${forwardedProto}://${forwardedAddress}` - } +// if (forwardedAddress && forwardedProto) { +// return `${forwardedProto}://${forwardedAddress}` +// } - return `(${remoteAddr.transport}):${remoteAddr.hostname}:${remoteAddr.port}` -} +// return `(${remoteAddr.transport}):${remoteAddr.hostname}:${remoteAddr.port}` +// } -async function sendMagicLink( - { firstname, lastname, mail }: User, - { device, ip, endpoint }: { device?: string; ip?: string; endpoint: string }, -): Promise { - const message: Mail = { - from: Contact.expand('contact'), - to: [Contact.fromString(`${firstname} ${lastname} <${mail}>`)], - subject: 'Lien de connection pour FabLab Coh@bit', - body: magicLinkTemplate.builder({ - device, - ip, - endpoint, - })!, - options: { - cc: [], - cci: [], - attachments: [], - }, - } +// async function sendMagicLink( +// { firstname, lastname, mail }: User, +// { device, ip, endpoint }: { device?: string; ip?: string; endpoint: string }, +// ): Promise { +// const message: Mail = { +// from: Contact.expand('contact'), +// to: [Contact.fromString(`${firstname} ${lastname} <${mail}>`)], +// subject: 'Lien de connection pour FabLab Coh@bit', +// body: magicLinkTemplate.builder({ +// device, +// ip, +// endpoint, +// })!, +// options: { +// cc: [], +// cci: [], +// attachments: [], +// }, +// } - await send(message) -} +// await send(message) +// }