feat(api/magiclink): reactivate magic link API
This commit is contained in:
parent
e0869c5e24
commit
385143c859
|
|
@ -1,10 +1,8 @@
|
||||||
import 'npm:iterator-polyfill'
|
import 'npm:iterator-polyfill'
|
||||||
import { define } from '../../../utils.ts'
|
import { define } from '../../../utils.ts'
|
||||||
// Polyfill AsyncIterator
|
// Polyfill AsyncIterator
|
||||||
|
|
||||||
import { FreshContext } from 'fresh'
|
|
||||||
import { db } from ':src/db/mod.ts'
|
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 { respondApi } from ':src/utils.ts'
|
||||||
import { Contact, type Mail, send } from '@cohabit/mailer'
|
import { Contact, type Mail, send } from '@cohabit/mailer'
|
||||||
import { magicLinkTemplate } from '@cohabit/mailer/templates'
|
import { magicLinkTemplate } from '@cohabit/mailer/templates'
|
||||||
|
|
@ -25,9 +23,8 @@ export async function getUserByMail(email: string): Promise<User | undefined> {
|
||||||
|
|
||||||
return user
|
return user
|
||||||
}
|
}
|
||||||
*/
|
// export const handler = define.handlers({})
|
||||||
export const handler = define.handlers({})
|
export const handler = define.handlers({
|
||||||
/*
|
|
||||||
async POST(ctx) {
|
async POST(ctx) {
|
||||||
const request = ctx.req
|
const request = ctx.req
|
||||||
const { email } = await request.json() as { email: string }
|
const { email } = await request.json() as { email: string }
|
||||||
|
|
@ -41,13 +38,27 @@ export const handler = define.handlers({})
|
||||||
|
|
||||||
// generate magic link
|
// generate magic link
|
||||||
const token = crypto.randomUUID()
|
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 =
|
const endpoint =
|
||||||
`${ctx.url.origin}/api/magiclink?token=${token}&session=${ctx.state.session.uuid}&redirect=/profil`
|
`${ctx.url.origin}/api/magiclink?token=${token}&session=${ctx.state.session.uuid}&redirect=/profil`
|
||||||
|
|
||||||
// save token to session
|
// save token to session
|
||||||
ctx.state.session.flash<MagicLinkInfos>(`MAGIC_LINK__${token}`, {
|
ctx.state.session.flash<MagicLinkInfos>(`MAGIC_LINK__${token}`, {
|
||||||
email,
|
email,
|
||||||
remoteId: remoteId(request, ctx),
|
remoteId: remoteId(request, { remoteAddr }),
|
||||||
timestamp: Date.now(),
|
timestamp: Date.now(),
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
@ -55,8 +66,7 @@ export const handler = define.handlers({})
|
||||||
try {
|
try {
|
||||||
if (user) {
|
if (user) {
|
||||||
// Get user ip through proxy else from tcp connection
|
// Get user ip through proxy else from tcp connection
|
||||||
const ip = request.headers.get('X-FORWARDED-FOR') ??
|
const ip = request.headers.get('X-FORWARDED-FOR') ?? remoteAddr.hostname
|
||||||
ctx.remoteAddr.hostname
|
|
||||||
const device = request.headers.get('Sec-Ch-Ua-Platform') ?? undefined
|
const device = request.headers.get('Sec-Ch-Ua-Platform') ?? undefined
|
||||||
|
|
||||||
await sendMagicLink(user, { device, ip, endpoint })
|
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 token = ctx.url.searchParams.get('token')
|
||||||
const redirect = ctx.url.searchParams.get('redirect')
|
const redirect = ctx.url.searchParams.get('redirect')
|
||||||
const sessionId = ctx.url.searchParams.get('session')
|
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)
|
ctx.state.session = ctx.state.session ?? SessionStore.getSession(sessionId)
|
||||||
|
|
||||||
// no session available
|
// no session available
|
||||||
if (ctx.state.session === null) {
|
if (ctx.state.session === null || ctx.state.session === undefined) {
|
||||||
return respondApi('error', 'no session datas', 401)
|
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)
|
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)
|
// 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)
|
const user = await getUserByMail(entry.email)
|
||||||
ctx.state.session.set('user', user)
|
ctx.state.session.set('user', user)
|
||||||
|
|
||||||
|
|
@ -122,10 +139,10 @@ export const handler = define.handlers({})
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
/*
|
|
||||||
function remoteId(
|
function remoteId(
|
||||||
{ headers }: { headers: Headers },
|
{ headers }: { headers: Headers },
|
||||||
{ remoteAddr }: { remoteAddr: FreshContext['remoteAddr'] },
|
{ remoteAddr }: { remoteAddr: Deno.NetAddr },
|
||||||
): string {
|
): string {
|
||||||
const forwardedAddress = headers.get('X-FORWARDED-FOR')
|
const forwardedAddress = headers.get('X-FORWARDED-FOR')
|
||||||
const forwardedProto = headers.get('X-FORWARDED-PROTO')
|
const forwardedProto = headers.get('X-FORWARDED-PROTO')
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue