1
0
Fork 0
mirror of synced 2024-09-21 11:53:49 +12:00
budibase/packages/backend-core/src/security/sessions.ts

124 lines
3.7 KiB
TypeScript
Raw Normal View History

import * as redis from "../redis/init"
import { v4 as uuidv4 } from "uuid"
import { logWarn } from "../logging"
import env from "../environment"
import { Duration } from "../utils"
2022-09-06 23:25:57 +12:00
import {
Session,
ScannedSession,
SessionKey,
CreateSession,
} from "@budibase/types"
// a week expiry is the default
const EXPIRY_SECONDS = env.SESSION_EXPIRY_SECONDS
? parseInt(env.SESSION_EXPIRY_SECONDS)
: Duration.fromDays(7).toSeconds()
2021-07-07 05:10:04 +12:00
function makeSessionID(userId: string, sessionId: string) {
return `${userId}/${sessionId}`
2021-07-07 05:10:04 +12:00
}
export async function getSessionsForUser(userId: string): Promise<Session[]> {
2022-08-08 20:34:45 +12:00
if (!userId) {
console.trace("Cannot get sessions for undefined userId")
return []
}
const client = await redis.getSessionClient()
const sessions: ScannedSession[] = await client.scan(userId)
return sessions.map(session => session.value)
2021-07-07 05:10:04 +12:00
}
export async function invalidateSessions(
userId: string,
opts: { sessionIds?: string[]; reason?: string } = {}
) {
2022-05-25 09:57:32 +12:00
try {
const reason = opts?.reason || "unknown"
let sessionIds: string[] = opts.sessionIds || []
let sessionKeys: SessionKey[]
2022-05-25 09:57:32 +12:00
// If no sessionIds, get all the sessions for the user
if (sessionIds.length === 0) {
const sessions = await getSessionsForUser(userId)
sessionKeys = sessions.map(session => ({
key: makeSessionID(session.userId, session.sessionId),
}))
2022-05-25 09:57:32 +12:00
} else {
// use the passed array of sessionIds
sessionIds = Array.isArray(sessionIds) ? sessionIds : [sessionIds]
sessionKeys = sessionIds.map(sessionId => ({
2022-05-25 09:57:32 +12:00
key: makeSessionID(userId, sessionId),
}))
}
if (sessionKeys && sessionKeys.length > 0) {
const client = await redis.getSessionClient()
const promises = []
for (let sessionKey of sessionKeys) {
promises.push(client.delete(sessionKey.key))
}
if (!env.isTest()) {
logWarn(
`Invalidating sessions for ${userId} (reason: ${reason}) - ${sessionKeys
.map(sessionKey => sessionKey.key)
.join(", ")}`
)
}
await Promise.all(promises)
2022-05-25 09:57:32 +12:00
}
} catch (err) {
console.error(`Error invalidating sessions: ${err}`)
2021-07-07 05:10:04 +12:00
}
}
export async function createASession(
userId: string,
createSession: CreateSession
) {
// invalidate all other sessions
await invalidateSessions(userId, { reason: "creation" })
const client = await redis.getSessionClient()
const sessionId = createSession.sessionId
const csrfToken = createSession.csrfToken ? createSession.csrfToken : uuidv4()
const key = makeSessionID(userId, sessionId)
const session: Session = {
...createSession,
csrfToken,
createdAt: new Date().toISOString(),
lastAccessedAt: new Date().toISOString(),
userId,
}
await client.store(key, session, EXPIRY_SECONDS)
2022-11-23 11:24:45 +13:00
return session
}
export async function updateSessionTTL(session: Session) {
2021-07-07 05:10:04 +12:00
const client = await redis.getSessionClient()
2021-07-08 10:29:19 +12:00
const key = makeSessionID(session.userId, session.sessionId)
2021-07-08 10:30:14 +12:00
session.lastAccessedAt = new Date().toISOString()
2021-07-08 10:29:19 +12:00
await client.store(key, session, EXPIRY_SECONDS)
2021-07-07 05:10:04 +12:00
}
export async function endSession(userId: string, sessionId: string) {
2021-07-07 05:10:04 +12:00
const client = await redis.getSessionClient()
await client.delete(makeSessionID(userId, sessionId))
}
export async function getSession(
userId: string,
sessionId: string
): Promise<Session> {
if (!userId || !sessionId) {
throw new Error(`Invalid session details - ${userId} - ${sessionId}`)
2021-07-07 05:10:04 +12:00
}
const client = await redis.getSessionClient()
const session = await client.get(makeSessionID(userId, sessionId))
if (!session) {
throw new Error(`Session not found - ${userId} - ${sessionId}`)
}
return session
2021-07-07 05:10:04 +12:00
}