Skip to content
This repository was archived by the owner on Dec 12, 2023. It is now read-only.

fix: allow unstorage drivers other than 'memory' #7

Merged
merged 18 commits into from
Nov 13, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 26 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,10 @@ Here's what the full _default_ module configuration looks like:
// The session cookie same site policy is `lax`
cookieSameSite: 'lax',
// In-memory storage is used (these are `unjs/unstorage` options)
storageOptions: {},
storageOptions: {
driver: 'memory',
options: {}
},
// The request-domain is strictly used for the cookie, no sub-domains allowed
domain: null,
// Sessions aren't pinned to the user's IP address
Expand All @@ -235,6 +238,28 @@ Here's what the full _default_ module configuration looks like:
}
```

```
#### Using a different storage driver

You can use any stroage driver supported by unstorage. For example, this will use the redis driver instead of the default memory driver.
```ts
//nuxt.config.ts
{
...,
session: {
session:{
storageOptions:{
driver: 'redis',
options: {
url: 'redis://localhost:6379'
}
}
}
}
}

```

### Security

This section mostly contains a list of possible security problems and how to mitigate (some) of them. Note that the below flaws exist with many libraries and frameworks we use in our day-to-day when building and working with APIs. E.g., your vanilla-nuxt-app is not safe of some of them like the client sending malicious data. Missing in the below list are estimates of how likely it is that one of the list-items may occur and what impact it will have on your app. This is because that heavily depends on:
Expand Down
3 changes: 2 additions & 1 deletion playground/nuxt.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,6 @@ import { defineNuxtConfig } from 'nuxt/config'
import NuxtSession from '../src/module'

export default defineNuxtConfig({
modules: [NuxtSession]
modules: [NuxtSession],
session: {}
})
14 changes: 12 additions & 2 deletions src/module.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { addImportsDir, addServerHandler, createResolver, defineNuxtModule, useLogger } from '@nuxt/kit'
import { CreateStorageOptions } from 'unstorage'
import { defu } from 'defu'
import { builtinDrivers } from 'unstorage'
import type {
FilledModuleOptions,
ModuleOptions,
Expand All @@ -18,7 +18,10 @@ const defaults: FilledModuleOptions = {
idLength: 64,
storePrefix: 'sessions',
cookieSameSite: 'lax',
storageOptions: {} as CreateStorageOptions,
storageOptions: {
driver: 'memory',
options: {}
},
domain: null,
ipPinning: false as boolean|SessionIpPinningOptions
},
Expand Down Expand Up @@ -59,6 +62,13 @@ export default defineNuxtModule<ModuleOptions>({
const publicConfig: ModulePublicRuntimeConfig = { session: { api: options.api } }
nuxt.options.runtimeConfig.public = defu(nuxt.options.runtimeConfig.public, publicConfig)

// setup unstorage
nuxt.options.nitro.virtual = defu(nuxt.options.nitro.virtual, {
'#session-driver': `export { default } from '${
builtinDrivers[options.session.storageOptions.driver]
}'`
})

// 3. Locate runtime directory and transpile module
const { resolve } = createResolver(import.meta.url)

Expand Down
8 changes: 8 additions & 0 deletions src/runtime/server/middleware/session/sessionStorage.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { createStorage, prefixStorage } from 'unstorage'
import { useRuntimeConfig } from '#imports'
// @ts-ignore
import sessionDriver from '#session-driver'
const sessionConfig = useRuntimeConfig().session.session
const driver = sessionDriver(sessionConfig.storageOptions.options)
const storage = createStorage({ driver }).mount(sessionConfig.storePrefix, driver)
export const sessionStorage = prefixStorage(storage, sessionConfig.storePrefix)
13 changes: 5 additions & 8 deletions src/runtime/server/middleware/session/storage.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
import { createStorage, prefixStorage, StorageValue } from 'unstorage'
import { useRuntimeConfig } from '#imports'

const storage = prefixStorage(createStorage(useRuntimeConfig().session.session.storageOptions), useRuntimeConfig().session.session.storePrefix)

export const getStorageSession = (sessionId: string) => storage.getItem(sessionId)
export const setStorageSession = (sessionId: string, session: StorageValue) => storage.setItem(sessionId, session)
export const dropStorageSession = (sessionId: string) => storage.removeItem(sessionId)
import type { StorageValue } from 'unstorage'
import { sessionStorage } from './sessionStorage'
export const getStorageSession = (sessionId: string) => sessionStorage.getItem(sessionId)
export const setStorageSession = (sessionId: string, session: StorageValue) => sessionStorage.setItem(sessionId, session)
export const dropStorageSession = (sessionId: string) => sessionStorage.removeItem(sessionId)
23 changes: 18 additions & 5 deletions src/types.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,22 @@
import type { CreateStorageOptions } from 'unstorage'
import type { BuiltinDriverName, CreateStorageOptions } from 'unstorage'
import type { FSStorageOptions } from 'unstorage/dist/drivers/fs'
import type { KVOptions } from 'unstorage/dist/drivers/cloudflare-kv-binding'
import type { KVHTTPOptions } from 'unstorage/dist/drivers/cloudflare-kv-http'
import type { GithubOptions } from 'unstorage/dist/drivers/github'
import type { HTTPOptions } from 'unstorage/dist/drivers/http'
import type { OverlayStorageOptions } from 'unstorage/dist/drivers/overlay'
import type { LocalStorageOptions } from 'unstorage/dist/drivers/localstorage'
import type { RedisOptions } from 'unstorage/dist/drivers/redis'

export type SameSiteOptions = 'lax' | 'strict' | 'none'
export type SupportedSessionApiMethods = 'patch' | 'delete' | 'get' | 'post'

export type UnstorageDriverOption = FSStorageOptions | KVOptions | KVHTTPOptions | GithubOptions | HTTPOptions | OverlayStorageOptions | LocalStorageOptions | RedisOptions

export interface StorageOptions {
driver: BuiltinDriverName,
options?: UnstorageDriverOption
}
export interface SessionIpPinningOptions {
/**
* The name of the HTTP header used to retrieve the forwarded (real) IP address of the user
Expand Down Expand Up @@ -45,12 +59,11 @@ export interface SessionOptions {
cookieSameSite: SameSiteOptions
/**
* Driver configuration for session-storage. Per default in-memory storage is used
* @default {}
* @example { driver: redisDriver({ base: 'storage:' }) }
* @type CreateStorageOptions
* @default { driver: 'memory', options: {} }
* @example { driver: 'redis', options: {url: 'redis://localhost:6739' } }
* @docs https://github.com/unjs/unstorage
*/
storageOptions: CreateStorageOptions,
storageOptions: StorageOptions,
/**
* Set the domain the session cookie will be receivable by. Setting `domain: null` results in setting the domain the cookie is initially set on. Specifying a domain will allow the domain and all its sub-domains.
* @default null
Expand Down