Skip to content

Commit

Permalink
Fix plugin imports...
Browse files Browse the repository at this point in the history
  • Loading branch information
irees committed Mar 21, 2024
1 parent f6c03be commit 64f7ec3
Show file tree
Hide file tree
Showing 4 changed files with 157 additions and 121 deletions.
21 changes: 16 additions & 5 deletions src/module.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
import { defineNuxtModule, addPlugin, addImportsDir, createResolver } from '@nuxt/kit'

export { proxyHandler } from './proxy'
import { defineNuxtModule, addPlugin, addImportsDir, createResolver, addServerHandler } from '@nuxt/kit'

// Config handler
export interface ModuleOptions{
bulma: string,
useProxy: boolean,
}

export default defineNuxtModule<ModuleOptions>({
meta: {
name: 'tlv2-ui',
configKey: 'tlv2-ui',
configKey: 'tlv2',
compatibility: {
nuxt: '^3.4.0'
}
Expand All @@ -19,18 +19,29 @@ export default defineNuxtModule<ModuleOptions>({
const { resolve } = createResolver(import.meta.url)
const resolveRuntimeModule = (path: string) => resolve('./runtime', path)

// Setup CSS
if (options.bulma) {
nuxt.options.css.push(options.bulma)
} else {
nuxt.options.css.push(resolveRuntimeModule('assets/bulma.scss'))
}
nuxt.options.css.push(resolveRuntimeModule('assets/main.css'))

// Setup plugins
addPlugin(resolveRuntimeModule('plugins/auth'))
addPlugin(resolveRuntimeModule('plugins/apollo'))
addPlugin(resolveRuntimeModule('plugins/oruga'))
addPlugin(resolveRuntimeModule('plugins/filters'))
nuxt.options.css.push(resolveRuntimeModule('assets/main.css'))
addImportsDir(resolveRuntimeModule('composables'))

// Proxy
if (options.useProxy) {
addServerHandler({
route: '/api/v2/**',
handler: resolveRuntimeModule('plugins/proxy')
})
}

// Add assets
nuxt.hook('nitro:config', (nitroConfig) => {
nitroConfig.publicAssets ||= []
Expand Down
18 changes: 14 additions & 4 deletions src/runtime/plugins/apollo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,23 @@ import { ApolloClients, provideApolloClients } from '@vue/apollo-composable'
import { createApolloProvider } from '@vue/apollo-option'
import { ApolloClient, ApolloLink, concat, HttpLink, InMemoryCache } from '@apollo/client/core/index.js'
import { useJwt } from './auth'
import { defineNuxtPlugin, useRuntimeConfig } from '#imports'
import { defineNuxtPlugin } from '#imports'

export function getApolloClient() {
const config = useRuntimeConfig()
return initApolloClient(
String(config.public.apiBase || ''),
String(config.allowedReferer || '')
)
}

export function initApolloClient(
apiBase: string,
allowedReferer: string
) {
console.log('initApolloClient apiBase:', apiBase, 'allowedReferer:', allowedReferer)
const httpLink = new HttpLink({
uri: config.public.apiBase + '/query'
uri: apiBase + '/query'
})
const authMiddleware = new ApolloLink(async(operation, forward) => {
// add the authorization to the headers
Expand All @@ -18,7 +29,7 @@ export function getApolloClient() {
// Set Authoriation header
authorization: token ? `Bearer ${token}` : '',
// Needed for SSR
referer: config.allowedReferer
referer: allowedReferer
}
})
return forward(operation)
Expand All @@ -33,7 +44,6 @@ export function getApolloClient() {

export default defineNuxtPlugin((nuxtApp) => {
const apolloClient = getApolloClient()

// options api
const apolloProvider = createApolloProvider({
defaultClient: apolloClient,
Expand Down
229 changes: 117 additions & 112 deletions src/runtime/plugins/auth.ts
Original file line number Diff line number Diff line change
@@ -1,37 +1,72 @@
import { useLocalStorage } from '@vueuse/core'
import { Auth0Client } from '@auth0/auth0-spa-js'
import { useLocalStorage } from '@vueuse/core'
import { gql } from 'graphql-tag'
import { getApolloClient } from './apollo'
import { defineNuxtPlugin, addRouteMiddleware, useRuntimeConfig, navigateTo } from '#imports'
import { defineNuxtPlugin, addRouteMiddleware, navigateTo } from '#imports'

const RECHECK_INTERVAL = 600_000

class User {
loggedIn = false
id = ''
name = ''
email = ''
roles = []
externalData = {}
checked = 0
constructor(v: any) {
Object.assign(this, v)
// Auth0 client init
let authInit = false
let authClient: Auth0Client

export function getAuth0Client() {
if (authInit) {
return authClient
}
if (process.server) {
return
}
const config = useRuntimeConfig()
return initAuth0Client(
config.public.auth0ClientId,
config.public.auth0Domain,
config.public.auth0RedirectUri,
config.public.auth0Audience,
config.public.auth0Scope
)
}

hasRole(v: string): boolean {
for (const s of this.roles) {
if (s === v) {
return true
}
export function initAuth0Client(
auth0ClientId: string,
auth0Domain: string,
auth0RedirectUri: string,
auth0Audience: string,
auth0Scope: string
) {
authInit = true
authClient = new Auth0Client({
domain: auth0Domain,
clientId: auth0ClientId,
cacheLocation: 'localstorage',
authorizationParams: {
redirect_uri: auth0RedirectUri,
audience: auth0Audience,
scope: auth0Scope
}
return false
}
})
return authClient
}

function defaultUser() {
return new User({})
// JWT
export const useJwt = async() => {
let token = ''

// Client side only
const authClient = getAuth0Client()
if (authClient && await authClient.isAuthenticated()) {
try {
token = await authClient.getTokenSilently()
} catch (error) {
console.log('useJwt: error in getTokenSilently; log in again')
login()
}
}
// console.log('useJwt: return', token)
return token
}

// Login, logout
export async function login() {
console.log('auth: login')
const authClient = getAuth0Client()
Expand All @@ -50,26 +85,71 @@ export async function logout() {
}
}

// User
export class User {
loggedIn = false
id = ''
name = ''
email = ''
roles = []
externalData = {}
checked = 0
constructor(v: any) {
Object.assign(this, v)
}

hasRole(v: string): boolean {
for (const s of this.roles) {
if (s === v) {
return true
}
}
return false
}
}

function defaultUser() {
return new User({})
}

export const useUser = () => {
const user = useLocalStorage('user', defaultUser())
return new User(user?.value || {})
}

export const useJwt = async() => {
let token = ''
async function setUser (data: User) {
const checkUser = useLocalStorage('user', defaultUser())
console.log('buildUser: set user state')
const auth0user = await authClient.getUser()
checkUser.value = new User({
loggedIn: true,
id: data?.id,
name: auth0user?.name || '',
email: auth0user?.email || '',
externalData: data?.externalData || {},
roles: data?.roles || [],
checked: Date.now()
})
}

// Client side only
const authClient = getAuth0Client()
if (authClient && await authClient.isAuthenticated()) {
try {
token = await authClient.getTokenSilently()
} catch (error) {
console.log('useJwt: error in getTokenSilently; log in again')
login()
}
}
// console.log('useJwt: return', token)
return token
export async function buildUser() {
// Build user object
// Get additional user metadata from GraphQL
console.log('buildUser: await me response')
const apolloClient = getApolloClient()
const meData = await apolloClient.query({
query: gql`query{me{id name email external_data roles}}`
}).then((data) => {
console.log('buildUser: me graphql response:', data.data.me)
return data.data.me
})

// // Save checkUser
await setUser(new User({
id: meData?.id || '',
externalData: meData?.external_data || {},
roles: meData?.roles || []
}))
}

export default defineNuxtPlugin(() => {
Expand All @@ -80,7 +160,7 @@ export default defineNuxtPlugin(() => {
if (authClient) {
console.log('auth mw: handle login')
await authClient.handleRedirectCallback()
await buildUser(authClient)
await buildUser()
return navigateTo({
name: 'index',
query: {}
Expand All @@ -93,82 +173,7 @@ export default defineNuxtPlugin(() => {
const lastChecked = Date.now() - (user?.checked || 0)
if (authClient && user?.loggedIn && lastChecked > RECHECK_INTERVAL) {
console.log('auth mw: recheck user')
buildUser(authClient) // don't await
buildUser() // don't await
}
}, { global: true })
})

async function buildUser(authClient: Auth0Client) {
// Build user object
// Get additional user metadata from GraphQL
console.log('buildUser: await me response')
const apolloClient = getApolloClient()
const meData = await apolloClient.query({
query: gql`query{me{id name email external_data roles}}`
}).then((data) => {
console.log('buildUser: me graphql response:', data.data.me)
return data.data.me
})

// Save checkUser
const checkUser = useLocalStorage('user', defaultUser())
console.log('buildUser: set user state')
const auth0user = await authClient.getUser()
checkUser.value = new User({
loggedIn: true,
id: meData?.id || '',
name: auth0user?.name || '',
email: auth0user?.email || '',
externalData: meData?.external_data || {},
roles: meData?.roles || [],
checked: Date.now()
})
}

let init = false
let auth: Auth0Client

function getAuth0Client() {
if (init) {
return auth
}
if (process.server) {
return
}
const config = useRuntimeConfig()
if (!config.public.auth0ClientId) {
console.log('no auth config')
return
}
return initAuth0Client(
String(config.public.auth0ClientId),
String(config.public.auth0Domain),
String(config.public.auth0RedirectUri),
String(config.public.auth0Audience),
String(config.public.auth0Scope)
)
}

function initAuth0Client(
auth0ClientId: string,
auth0Domain: string,
auth0RedirectUri: string,
auth0Audience: string,
auth0Scope: string
) {
if (init) {
return auth
}
init = true
auth = new Auth0Client({
domain: auth0Domain,
clientId: auth0ClientId,
cacheLocation: 'localstorage',
authorizationParams: {
redirect_uri: auth0RedirectUri,
audience: auth0Audience,
scope: auth0Scope
}
})
return auth
}
10 changes: 10 additions & 0 deletions src/proxy.ts → src/runtime/plugins/proxy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,3 +54,13 @@ export function proxyHandler(
// )
return proxyRequest(event, target.toString(), { headers })
}

export default defineEventHandler((event) => {
const config = useRuntimeConfig()
return proxyHandler(
event,
config.proxyBase,
config.allowedReferer,
config.graphqlApikey
)
})

0 comments on commit 64f7ec3

Please sign in to comment.