feat: enhance authentication error handling and schema fetching

Handle authentication errors related to consent and login in the Apollo 
client by redirecting users to the Auth0 login page as necessary. Update
the schema-fetching logic to support dynamic references from the URL, 
removing mock data and improving overall data integrity in the 
application.
Ensure proper loading states during the fetching process.
This commit is contained in:
2025-11-23 14:01:32 +01:00
parent de1f4b6e86
commit 5c17c798c4
3 changed files with 67 additions and 51 deletions
+48 -48
View File
@@ -124,14 +124,60 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { useAuth0 } from '@auth0/auth0-vue'
import { useLatestSchemaQuery } from '~/graphql/generated'
const auth0 = useAuth0()
const route = useRoute() const route = useRoute()
const _config = useRuntimeConfig() const _config = useRuntimeConfig()
const schema = ref<any>(null) // Parse the ID which should contain both ref and service info
const loading = ref(true) // The ID format from backend is typically: orgId_ref_service or similar
const schemaId = route.params.id as string
const snackbar = ref(false) const snackbar = ref(false)
const snackbarText = ref('') const snackbarText = ref('')
// We need to fetch all schemas and find the matching one
// Since we don't have a direct query for a single subgraph by ID,
// we'll need to get it from the URL or store it in a better format
// For now, let's extract ref from the route query or use a default
const schemaRef = computed(() => {
return (route.query.ref as string) || 'production'
})
// Fetch latest schema for the ref
const latestSchemaQuery = useLatestSchemaQuery(() => ({
ref: schemaRef.value,
}), () => ({
skip: !auth0.isAuthenticated.value,
}))
// Find the specific subgraph matching our ID
const schema = computed(() => {
if (!latestSchemaQuery.result.value?.latestSchema?.subGraphs) return null
const subgraph = latestSchemaQuery.result.value.latestSchema.subGraphs.find(
s => s.id === schemaId,
)
if (!subgraph) return null
return {
id: subgraph.id,
service: subgraph.service,
ref: schemaRef.value,
url: subgraph.url || 'N/A',
wsUrl: subgraph.wsUrl,
updatedAt: new Date(subgraph.changedAt).toLocaleString(),
updatedBy: subgraph.changedBy,
sdl: subgraph.sdl,
}
})
const loading = computed(() => latestSchemaQuery.loading.value)
const downloadSchema = () => { const downloadSchema = () => {
if (!schema.value) return if (!schema.value) return
@@ -164,52 +210,6 @@ const viewFederationGraph = () => {
if (!schema.value?.ref) return if (!schema.value?.ref) return
navigateTo(`/graph/${schema.value.ref}`) navigateTo(`/graph/${schema.value.ref}`)
} }
// TODO: Fetch actual data from the GraphQL API
onMounted(() => {
// Mock data for now
setTimeout(() => {
schema.value = {
id: route.params.id,
service: 'users-service',
ref: 'production',
url: 'http://users.example.com/graphql',
wsUrl: 'ws://users.example.com/graphql',
updatedAt: '2024-11-21 19:30:00',
updatedBy: 'john.doe@example.com',
sdl: `type User @key(fields: "id") {
id: ID!
username: String!
email: String!
createdAt: DateTime!
}
type Query {
user(id: ID!): User
users(limit: Int, offset: Int): [User!]!
}
type Mutation {
createUser(input: CreateUserInput!): User!
updateUser(id: ID!, input: UpdateUserInput!): User!
deleteUser(id: ID!): Boolean!
}
input CreateUserInput {
username: String!
email: String!
}
input UpdateUserInput {
username: String
email: String
}
scalar DateTime`,
}
loading.value = false
}, 500)
})
</script> </script>
<style scoped> <style scoped>
+1 -1
View File
@@ -59,7 +59,7 @@
md="6" md="6"
lg="4" lg="4"
> >
<v-card hover @click="navigateTo(`/schemas/${schema.id}`)"> <v-card hover @click="navigateTo(`/schemas/${schema.id}?ref=${schema.ref}`)">
<v-card-title> <v-card-title>
<v-icon icon="mdi-graphql" class="mr-2" /> <v-icon icon="mdi-graphql" class="mr-2" />
{{ schema.service }} {{ schema.service }}
+17 -1
View File
@@ -51,9 +51,25 @@ export default defineNuxtPlugin((nuxtApp) => {
} }
} }
} }
} catch (error) { } catch (error: any) {
// Handle consent required error
if (error?.error === 'consent_required') {
console.warn('[Apollo] Consent required, redirecting to login...')
const auth0Instance = (nuxtApp.vueApp.config.globalProperties as any).$auth0
// Trigger login with consent
await auth0Instance.loginWithRedirect({
authorizationParams: {
prompt: 'consent',
},
})
} else if (error?.error === 'login_required') {
console.warn('[Apollo] Login required, redirecting...')
const auth0Instance = (nuxtApp.vueApp.config.globalProperties as any).$auth0
await auth0Instance.loginWithRedirect()
} else {
console.error('[Apollo] Failed to get Auth0 token:', error) console.error('[Apollo] Failed to get Auth0 token:', error)
} }
}
return { headers } return { headers }
}) })