Skip to content

Commit

Permalink
feat: support auth per db preset
Browse files Browse the repository at this point in the history
  • Loading branch information
sandros94 committed May 30, 2024
1 parent 34b33d6 commit c55c1c5
Show file tree
Hide file tree
Showing 8 changed files with 340 additions and 214 deletions.
62 changes: 56 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,18 +16,68 @@ A Nuxt module aimed to simplify the use of [SurrealDB](https://surrealdb.com).
This module is still under development and not suitable for production use, proceed at your own risk. Expect breaking changes!
There are no docs atm, so please refer to the [playground](/playground/app.vue) or the [source code](/src/).

## Roadmap

- [x] custom fetch plugin and composable.
- [ ] ~~on PAR with the official [SurrealDB Rest integration](https://surrealdb.com/docs/surrealdb/integration/http).~~
- [ ] on PAR with the official [SurrealDB RPC integration](https://surrealdb.com/docs/surrealdb/integration/rpc).
- [ ] auth support.
- [ ] custom websocket composable.

## Features

<!-- Highlight some of the features your module provide here -->
- 🚀 &nbsp;Custom built-in `$surrealFetch` and `useSurrealFetch`.
- 📦 &nbsp;Custom Database Presets, each with its `host`, `namespace`, `database`, `auth` (optional)

## Roadmap
### Database Presets

- [x] custom fetch plugin and composable.
- [ ] on PAR with the official [SurrealDB Rest integration](https://surrealdb.com/docs/surrealdb/integration/http).
- [ ] auth support.
- [ ] custom websocket composable.
- [ ] on PAR with the official [SurrealDB RPC integration](https://surrealdb.com/docs/surrealdb/integration/rpc) via Websockets.
It is possible to customize the `default` preset or define your own Database presets either via `nuxt.config.ts` or `.env`.

> [!NOTE]
> When passing variables to a custom preset like `production` below, it is important to initialize it as an empty object inside `nuxt.config.ts`
```dotenv
NUXT_PUBLIC_SURREALDB_DATABASES_PRODUCTION_HOST="https://example.com"
NUXT_PUBLIC_SURREALDB_DATABASES_PRODUCTION_NS="surrealdb"
NUXT_PUBLIC_SURREALDB_DATABASES_PRODUCTION_DB="docs"
# For auth
# user and pass separated by a colon
NUXT_PUBLIC_SURREALDB_DATABASES_PRODUCTION_AUTH="root:root"
# Or as a Bearer
NUXT_PUBLIC_SURREALDB_DATABASES_PRODUCTION_AUTH="Bearer mySuperLongBearerToken"
# Or as an object
NUXT_PUBLIC_SURREALDB_DATABASES_PRODUCTION_AUTH_USER="root"
NUXT_PUBLIC_SURREALDB_DATABASES_PRODUCTION_AUTH_PASS="root"
```

```ts
export default defineNuxtConfig({
modules: ['nuxt-surrealdb'],
surrealdb: {
databases: {
staging: {
host: 'https://staging.example.com',
NS: 'staging',
DB: 'demo',

// Auth examples
auth: 'root:root'
auth: 'Bearer mySuperLongBearerToken'
auth: {
user: 'root',
pass: 'root'
}
},
production: {},
},
},
// ...
})
```

---

## Quick Setup

Expand Down
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,8 @@
"test:types": "vue-tsc --noEmit && cd playground && vue-tsc --noEmit"
},
"dependencies": {
"@nuxt/kit": "^3.11.2"
"@nuxt/kit": "^3.11.2",
"undio": "^0.2.0"
},
"devDependencies": {
"@nuxt/devtools": "^1.2.0",
Expand Down
6 changes: 1 addition & 5 deletions playground/nuxt.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,7 @@ export default defineNuxtConfig({
modules: ['nuxt-surrealdb'],
surrealdb: {
databases: {
staging: {
host: '',
NS: '',
DB: '',
},
staging: {},
},
},
devtools: { enabled: true },
Expand Down
421 changes: 222 additions & 199 deletions pnpm-lock.yaml

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions src/module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ export default defineNuxtModule<ModuleOptions>({
host: '',
NS: '',
DB: '',
auth: undefined,
},
},
tokenCookieName: 'surrealdb_token',
Expand Down
30 changes: 28 additions & 2 deletions src/runtime/composables/surreal-fetch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { useFetch, useNuxtApp, useRuntimeConfig } from 'nuxt/app'
import type { AsyncData, UseFetchOptions } from 'nuxt/app'
import { type MaybeRefOrGetter, ref } from 'vue'
import type { FetchError } from 'ofetch'
import { textToBase64 } from 'undio'

import type {
DatabasePreset,
Expand All @@ -21,17 +22,39 @@ export function useSurrealFetch<T = any>(
token,
...opts
} = options
const _token = ref<string | undefined>(token)

function authToken(db: DatabasePreset): string | undefined {
if (db.auth) {
if (typeof db.auth === 'string') {
if (db.auth.startsWith('Bearer ')) {
return db.auth
}
else {
const [user, pass] = db.auth.split(':')
if (user && pass) {
return `Basic ${textToBase64(`${user}:${pass}`, { dataURL: false })}`
}
}
}
else if (db.auth.user && db.auth.pass) {
return `Basic ${textToBase64(`${db.auth.user}:${db.auth.pass}`, { dataURL: false })}`
}
}
}

const headers: Record<string, string> = {}
if (database !== undefined) {
const db = ref<DatabasePreset>()

if (typeof database !== 'string' && typeof database !== 'number' && typeof database !== 'symbol') {
db.value = database
}
else {
const { databases } = useRuntimeConfig().public.surrealdb
db.value = databases[database]
}

if (db.value.host && !opts.baseURL) {
opts.baseURL = db.value.host
}
Expand All @@ -41,9 +64,12 @@ export function useSurrealFetch<T = any>(
if (db.value.DB) {
headers.DB = db.value.DB
}
if (db.value.auth && !token) {
_token.value = authToken(db.value)
}
}
if (token) {
headers.Authorization = token
if (_token.value) {
headers.Authorization = _token.value
}

return useFetch(endpoint, {
Expand Down
27 changes: 26 additions & 1 deletion src/runtime/plugin.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// The following nitropack import is from https://github.com/nuxt/module-builder/issues/141#issuecomment-2078248248
import type {} from 'nitropack'
import type { FetchOptions, ResponseType } from 'ofetch'
import { textToBase64 } from 'undio'

import type { DatabasePreset, Overrides } from './types'
import { defineNuxtPlugin, useCookie } from '#app'
Expand All @@ -9,6 +10,25 @@ export default defineNuxtPlugin(({ $config }) => {
const { databases, tokenCookieName } = $config.public.surrealdb
const userAuth = useCookie(tokenCookieName)

let authToken: string | undefined = undefined

if (databases.default.auth) {
if (typeof databases.default.auth === 'string') {
if (databases.default.auth.startsWith('Bearer ')) {
authToken = databases.default.auth
}
else {
const [user, pass] = databases.default.auth.split(':')
if (user && pass) {
authToken = `Basic ${textToBase64(`${user}:${pass}`, { dataURL: false })}`
}
}
}
else if (databases.default.auth.user && databases.default.auth.pass) {
authToken = `Basic ${textToBase64(`${databases.default.auth.user}:${databases.default.auth.pass}`, { dataURL: false })}`
}
}

const surrealFetch = $fetch.create({
baseURL: databases.default.host,
onRequest({ options }) {
Expand All @@ -25,7 +45,12 @@ export default defineNuxtPlugin(({ $config }) => {
options.headers.DB = databases.default.DB
}
// @ts-expect-error Authorization header type missing
if (userAuth.value && !options.headers.Authorization) {
if (authToken && !userAuth.value && !options.headers.Authorization) {
// @ts-expect-error Authorization header type missing
options.headers.Authorization = authToken
}
// @ts-expect-error Authorization header type missing
else if (userAuth.value && !options.headers.Authorization) {
// @ts-expect-error Authorization header type missing
options.headers.Authorization = `Bearer ${userAuth.value}`
}
Expand Down
4 changes: 4 additions & 0 deletions src/runtime/types/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ export interface DatabasePreset {
host?: string
NS?: string | null
DB?: string | null
auth?: string | {
user: string
pass: string
}
}

/* Module build utils */
Expand Down

0 comments on commit c55c1c5

Please sign in to comment.