Skip to content

Commit

Permalink
feat: add sessionHooks to extend user sessions
Browse files Browse the repository at this point in the history
  • Loading branch information
atinux committed Dec 13, 2023
1 parent c60fde7 commit c470319
Show file tree
Hide file tree
Showing 8 changed files with 62 additions and 2 deletions.
19 changes: 19 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,25 @@ export default oauth.githubEventHandler({

Make sure to set the callback URL in your OAuth app settings as `<your-domain>/auth/github`.

### Extend Session

We leverage hooks to let you extend the session data with your own data or to log when the user clear its session.

```ts
// server/plugins/session.ts
export default defineNitroPlugin(() => {
sessionHooks.hook('verify', async (session, event) => {
// extend User Session by calling your database
// or
// throw createError({ ... }) if session is invalid for example
})

sessionHooks.hook('clear', async (session, event) => {
// Log that user logged out
})
})
```

## Development

```bash
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
"dependencies": {
"@nuxt/kit": "^3.8.2",
"defu": "^6.1.3",
"hookable": "^5.5.3",
"ofetch": "^1.3.3",
"ohash": "^1.1.3"
},
Expand Down
1 change: 1 addition & 0 deletions playground/auth.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ declare module '#auth-utils' {
battledotnet?: any
linkedin?: any
}
extended?: any
loggedInAt: number
}
}
Expand Down
14 changes: 14 additions & 0 deletions playground/server/plugins/session.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
export default defineNitroPlugin(() => {
sessionHooks.hook('verify', async (session) => {
// Extend User Session
// Or throw createError({ ... }) if session is invalid
session.extended = {
fromHooks: true
}
})

sessionHooks.hook('clear', async () => {
// Log that user logged out
})
})

3 changes: 3 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions src/module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ export default defineNuxtModule<ModuleOptions>({
{
from: resolver.resolve('./runtime/server/utils/session'),
imports: [
'sessionHooks',
'getUserSession',
'setUserSession',
'clearUserSession',
Expand Down
8 changes: 6 additions & 2 deletions src/runtime/server/api/session.get.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
import { eventHandler } from 'h3'
import { requireUserSession } from '../utils/session'
import { requireUserSession, sessionHooks } from '../utils/session'

export default eventHandler(async (event) => {
return await requireUserSession(event)
const session = await requireUserSession(event)

await sessionHooks.callHookParallel('verify', event, session)

Check failure on line 7 in src/runtime/server/api/session.get.ts

View workflow job for this annotation

GitHub Actions / test

Type 'H3Event<EventHandlerRequest>' has no properties in common with type 'UserSession'.

return session
})
17 changes: 17 additions & 0 deletions src/runtime/server/utils/session.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,25 @@
import type { H3Event, SessionConfig } from 'h3'
import { useSession, createError } from 'h3'
import { defu } from 'defu'
import { createHooks } from 'hookable'
import { useRuntimeConfig } from '#imports'
import type { UserSession } from '#auth-utils'

export interface SessionHooks {
/**
* Called when fetching the session from the API
* - Add extra properties to the session
* - Throw an error if the session could not be verified (with a database for example)
*/
'verify': (session: UserSession, event: H3Event) => void | Promise<void>
/**
* Called before clearing the session
*/
'clear': (session: UserSession, event: H3Event) => void | Promise<void>
}

export const sessionHooks = createHooks<SessionHooks>()

export async function getUserSession (event: H3Event) {
return (await _useSession(event)).data
}
Expand All @@ -23,6 +39,7 @@ export async function setUserSession (event: H3Event, data: UserSession) {
export async function clearUserSession (event: H3Event) {
const session = await _useSession(event)

await sessionHooks.callHookParallel('clear', event, session)

Check failure on line 42 in src/runtime/server/utils/session.ts

View workflow job for this annotation

GitHub Actions / test

Type 'H3Event<EventHandlerRequest>' has no properties in common with type 'UserSession'.
await session.clear()

return true
Expand Down

0 comments on commit c470319

Please sign in to comment.