Adding sessions API.
This commit is contained in:
parent
278d984006
commit
cc67e2caa6
|
@ -68,7 +68,7 @@ module.exports = (noAuthPatterns = [], opts) => {
|
|||
clearCookie(ctx, Cookies.Auth)
|
||||
} else {
|
||||
// make sure we denote that the session is still in use
|
||||
await updateSessionTTL(userId, sessionId)
|
||||
await updateSessionTTL(session)
|
||||
}
|
||||
}
|
||||
const apiKey = ctx.request.headers["x-budibase-api-key"]
|
||||
|
|
|
@ -62,14 +62,12 @@ async function authenticate(token, tokenSecret, profile, done) {
|
|||
|
||||
// authenticate
|
||||
const sessionId = newid()
|
||||
const payload = {
|
||||
await createASession(dbUser._id, sessionId)
|
||||
|
||||
dbUser.token = jwt.sign({
|
||||
userId: dbUser._id,
|
||||
sessionId,
|
||||
}
|
||||
await createASession(dbUser._id, sessionId, payload)
|
||||
dbUser.sessionId = sessionId
|
||||
|
||||
dbUser.token = jwt.sign(payload, env.JWT_SECRET)
|
||||
}, env.JWT_SECRET)
|
||||
|
||||
return done(null, dbUser)
|
||||
}
|
||||
|
|
|
@ -34,14 +34,12 @@ exports.authenticate = async function (email, password, done) {
|
|||
// authenticate
|
||||
if (await compare(password, dbUser.password)) {
|
||||
const sessionId = newid()
|
||||
const payload = {
|
||||
await createASession(dbUser._id, sessionId)
|
||||
|
||||
dbUser.token = jwt.sign({
|
||||
userId: dbUser._id,
|
||||
sessionId,
|
||||
}
|
||||
await createASession(dbUser._id, sessionId, payload)
|
||||
dbUser.sessionId = sessionId
|
||||
|
||||
dbUser.token = jwt.sign(payload, env.JWT_SECRET)
|
||||
}, env.JWT_SECRET)
|
||||
// Remove users password in payload
|
||||
delete dbUser.password
|
||||
|
||||
|
|
|
@ -4,16 +4,23 @@ const EXPIRY_SECONDS = 86400
|
|||
|
||||
async function getSessionsForUser(userId) {
|
||||
const client = await redis.getSessionClient()
|
||||
return client.scan(userId)
|
||||
const sessions = await client.scan(userId)
|
||||
return sessions.map(session => session.value)
|
||||
}
|
||||
|
||||
function makeSessionID(userId, sessionId) {
|
||||
return `${userId}/${sessionId}`
|
||||
}
|
||||
|
||||
exports.createASession = async (userId, sessionId, token) => {
|
||||
exports.createASession = async (userId, sessionId) => {
|
||||
const client = await redis.getSessionClient()
|
||||
await client.store(makeSessionID(userId, sessionId), token, EXPIRY_SECONDS)
|
||||
const session = {
|
||||
createdAt: (new Date()).toISOString(),
|
||||
lastAccessedAt: (new Date()).toISOString(),
|
||||
sessionId,
|
||||
userId,
|
||||
}
|
||||
await client.store(makeSessionID(userId, sessionId), session, EXPIRY_SECONDS)
|
||||
}
|
||||
|
||||
exports.invalidateSessions = async (userId, sessionId = null) => {
|
||||
|
@ -31,9 +38,11 @@ exports.invalidateSessions = async (userId, sessionId = null) => {
|
|||
await Promise.all(promises)
|
||||
}
|
||||
|
||||
exports.updateSessionTTL = async (userId, sessionId) => {
|
||||
exports.updateSessionTTL = async session => {
|
||||
const client = await redis.getSessionClient()
|
||||
await client.setExpiry(makeSessionID(userId, sessionId), EXPIRY_SECONDS)
|
||||
const key = makeSessionID(session.userId, session.sessionId)
|
||||
session.lastAccessedAt = (new Date()).toISOString()
|
||||
await client.store(key, session, EXPIRY_SECONDS)
|
||||
}
|
||||
|
||||
exports.endSession = async (userId, sessionId) => {
|
||||
|
@ -41,6 +50,8 @@ exports.endSession = async (userId, sessionId) => {
|
|||
await client.delete(makeSessionID(userId, sessionId))
|
||||
}
|
||||
|
||||
exports.getUserSessions = getSessionsForUser
|
||||
|
||||
exports.getSession = async (userId, sessionId) => {
|
||||
try {
|
||||
const client = await redis.getSessionClient()
|
||||
|
@ -53,5 +64,6 @@ exports.getSession = async (userId, sessionId) => {
|
|||
|
||||
exports.getAllSessions = async () => {
|
||||
const client = await redis.getSessionClient()
|
||||
return client.scan()
|
||||
const sessions = await client.scan()
|
||||
return sessions.map(session => session.value)
|
||||
}
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
const { getAllSessions, getUserSessions, invalidateSessions } = require("@budibase/auth/sessions")
|
||||
|
||||
exports.fetch = async ctx => {
|
||||
ctx.body = await getAllSessions()
|
||||
}
|
||||
|
||||
exports.find = async ctx => {
|
||||
const { userId } = ctx.params
|
||||
const sessions = await getUserSessions(userId)
|
||||
ctx.body = sessions.map(session => session.value)
|
||||
}
|
||||
|
||||
exports.invalidateUser = async ctx => {
|
||||
const { userId } = ctx.params
|
||||
await invalidateSessions(userId)
|
||||
ctx.body = {
|
||||
message: "User sessions invalidated"
|
||||
}
|
||||
}
|
||||
|
||||
exports.selfSessions = async ctx => {
|
||||
const userId = ctx.user._id
|
||||
ctx.body = await getUserSessions(userId)
|
||||
}
|
||||
|
||||
exports.invalidateSession = async ctx => {
|
||||
const userId = ctx.user._id
|
||||
const { sessionId } = ctx.params
|
||||
await invalidateSessions(userId, sessionId)
|
||||
ctx.body = {
|
||||
message: "Session invalidated successfully."
|
||||
}
|
||||
}
|
|
@ -122,13 +122,16 @@ exports.removeAppRole = async ctx => {
|
|||
const db = new CouchDB(GLOBAL_DB)
|
||||
const users = await allUsers()
|
||||
const bulk = []
|
||||
const cacheInvalidations = []
|
||||
for (let user of users) {
|
||||
if (user.roles[appId]) {
|
||||
cacheInvalidations.push(userCache.invalidateUser(user._id))
|
||||
delete user.roles[appId]
|
||||
bulk.push(user)
|
||||
}
|
||||
}
|
||||
await db.bulkDocs(bulk)
|
||||
await Promise.all(cacheInvalidations)
|
||||
ctx.body = {
|
||||
message: "App role removed from all users",
|
||||
}
|
||||
|
@ -158,6 +161,7 @@ exports.updateSelf = async ctx => {
|
|||
...user,
|
||||
...ctx.request.body,
|
||||
})
|
||||
await userCache.invalidateUser(user._id)
|
||||
ctx.body = {
|
||||
_id: response.id,
|
||||
_rev: response.rev,
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
const Router = require("@koa/router")
|
||||
const controller = require("../../controllers/admin/sessions")
|
||||
const adminOnly = require("../../../middleware/adminOnly")
|
||||
|
||||
const router = Router()
|
||||
|
||||
router
|
||||
.get("/api/admin/sessions", adminOnly, controller.fetch)
|
||||
.get("/api/admin/sessions/self", controller.selfSessions)
|
||||
.get("/api/admin/sessions/:userId", adminOnly, controller.find)
|
||||
.delete("/api/admin/sessions/:userId", adminOnly, controller.invalidateUser)
|
||||
.delete("/api/admin/sessions/self/:sessionId", controller.invalidateSession)
|
||||
|
||||
module.exports = router
|
|
@ -5,6 +5,7 @@ const templateRoutes = require("./admin/templates")
|
|||
const emailRoutes = require("./admin/email")
|
||||
const authRoutes = require("./admin/auth")
|
||||
const roleRoutes = require("./admin/roles")
|
||||
const sessionRoutes = require("./admin/sessions")
|
||||
const appRoutes = require("./app")
|
||||
|
||||
exports.routes = [
|
||||
|
@ -15,5 +16,6 @@ exports.routes = [
|
|||
appRoutes,
|
||||
templateRoutes,
|
||||
emailRoutes,
|
||||
sessionRoutes,
|
||||
roleRoutes,
|
||||
]
|
||||
|
|
Loading…
Reference in New Issue