better error with Request Entitlement and sending user_id

This commit is contained in:
simonredfern 2025-12-02 02:08:16 +01:00
parent 4a5239e5aa
commit b97f39b4e1
4 changed files with 170 additions and 19 deletions

2
env_ai
View File

@ -10,7 +10,7 @@ VITE_OPB_SERVER_SESSION_PASSWORD=asidudhiuh33875
VITE_OBP_REDIS_URL=redis://127.0.0.1:6379
### Opey Configuration ###
VITE_CHATBOT_ENABLED=true
VITE_CHATBOT_ENABLED=false
VITE_CHATBOT_URL=http://localhost:5000
### OAuth2/OIDC Configuration ###

View File

@ -30,6 +30,7 @@ import { Request, Response } from 'express'
import OBPClientService from '../services/OBPClientService'
import { Service, Container } from 'typedi'
import { OAuth2Service } from '../services/OAuth2Service'
import { DEFAULT_OBP_API_VERSION } from '../../shared-constants'
@Service()
@Controller('/user')
@ -129,9 +130,25 @@ export class UserController {
}
}
// Get actual user ID from OBP-API
let obpUserId = oauth2User.sub // Default to sub if OBP call fails
try {
const version = process.env.VITE_OBP_API_VERSION ?? DEFAULT_OBP_API_VERSION
const obpUser = await this.obpClientService.get(
`/obp/${version}/users/current`,
session['clientConfig']
)
if (obpUser && obpUser.user_id) {
obpUserId = obpUser.user_id
console.log('UserController: Got OBP user ID:', obpUserId)
}
} catch (error) {
console.warn('UserController: Could not fetch OBP user ID, using token sub:', error)
}
// Return user info in format compatible with frontend
return response.json({
user_id: oauth2User.sub,
user_id: obpUserId,
username: oauth2User.username,
email: oauth2User.email,
email_verified: oauth2User.email_verified,

View File

@ -28,6 +28,16 @@
import { Service } from 'typedi'
import { DEFAULT_OBP_API_VERSION } from '../../shared-constants'
// Custom error class to preserve HTTP status codes
class OBPAPIError extends Error {
status: number
constructor(status: number, message: string) {
super(message)
this.status = status
this.name = 'OBPAPIError'
}
}
// OAuth2 Bearer token configuration
interface OAuth2Config {
accessToken: string
@ -140,7 +150,7 @@ export default class OBPClientService {
if (!response.ok) {
const errorText = await response.text()
console.error('OBPClientService: GET request failed:', response.status, errorText)
throw new Error(`HTTP ${response.status}: ${errorText}`)
throw new OBPAPIError(response.status, errorText)
}
return await response.json()
@ -170,7 +180,7 @@ export default class OBPClientService {
if (!response.ok) {
const errorText = await response.text()
console.error('OBPClientService: POST request failed:', response.status, errorText)
throw new Error(`HTTP ${response.status}: ${errorText}`)
throw new OBPAPIError(response.status, errorText)
}
return await response.json()
@ -200,7 +210,7 @@ export default class OBPClientService {
if (!response.ok) {
const errorText = await response.text()
console.error('OBPClientService: PUT request failed:', response.status, errorText)
throw new Error(`HTTP ${response.status}: ${errorText}`)
throw new OBPAPIError(response.status, errorText)
}
return await response.json()
@ -228,7 +238,7 @@ export default class OBPClientService {
if (!response.ok) {
const errorText = await response.text()
console.error('OBPClientService: DELETE request failed:', response.status, errorText)
throw new Error(`HTTP ${response.status}: ${errorText}`)
throw new OBPAPIError(response.status, errorText)
}
return await response.json()

View File

@ -184,32 +184,156 @@ const highlightCode = (json) => {
}
}
const submitEntitlement = async () => {
requiredRoles.value.forEach(async (formRole, idx) => {
for (const [idx, formRole] of requiredRoles.value.entries()) {
const role = roleForm[`role${formRole.role}${idx}`]
if (formRole.requires_bank_id) {
const role = roleForm[`role${formRole.role}${idx}`]
// Bank-level entitlement
const bankId = roleForm[`bankId${formRole.role}${idx}`]
if (role && bankId && isUserLogon) {
const response = await createEntitlement(bankId, role)
let type = 'success'
if ('code' in response && response['code'] >= 400) {
type = 'error'
}
if (!role || !bankId) {
ElNotification({
duration: elMessageDuration,
message: response.message,
title: 'Missing Information',
message: 'Bank ID is required for this role.',
position: 'bottom-right',
type
type: 'error'
})
} else {
continue
}
if (!isUserLogon) {
ElNotification({
duration: elMessageDuration,
message: 'Bank Id is required.',
title: 'Not Authenticated',
message: 'Please login to request this role.',
position: 'bottom-right',
type: 'error'
})
continue
}
try {
const response = await createEntitlement(bankId, role)
// Check if response is an error object (from superagent)
const isError = response && response.error && response.error.response
const errorBody = isError ? response.error.response.body : null
const statusCode = isError ? response.error.status : null
if (isError && errorBody && errorBody.code >= 400) {
// Parse error message from body
let errorMessage = 'Failed to create entitlement'
if (errorBody.message) {
// Message might be double-encoded JSON string
try {
const parsedMessage = JSON.parse(errorBody.message)
errorMessage = parsedMessage.message || errorBody.message
} catch {
errorMessage = errorBody.message
}
}
ElNotification({
duration: elMessageDuration,
title: `Error (${errorBody.code})`,
message: errorMessage,
position: 'bottom-right',
type: 'error'
})
} else {
// Success
ElNotification({
duration: elMessageDuration,
title: 'Success',
message: `Entitlement "${role}" requested successfully for bank "${bankId}"`,
position: 'bottom-right',
type: 'success'
})
}
} catch (error: any) {
ElNotification({
duration: elMessageDuration,
title: 'Request Failed',
message: error.message || 'An error occurred while requesting the entitlement',
position: 'bottom-right',
type: 'error'
})
}
} else {
// System-wide entitlement (no bank_id required)
if (!role) {
ElNotification({
duration: elMessageDuration,
title: 'Missing Information',
message: 'Role name is required.',
position: 'bottom-right',
type: 'error'
})
continue
}
if (!isUserLogon) {
ElNotification({
duration: elMessageDuration,
title: 'Not Authenticated',
message: 'Please login to request this role.',
position: 'bottom-right',
type: 'error'
})
continue
}
try {
// System-wide entitlement uses empty string for bank_id
const response = await createEntitlement('', role)
// Check if response is an error object (from superagent)
const isError = response && response.error && response.error.response
const errorBody = isError ? response.error.response.body : null
const statusCode = isError ? response.error.status : null
if (isError && errorBody && errorBody.code >= 400) {
// Parse error message from body
let errorMessage = 'Failed to create entitlement'
if (errorBody.message) {
// Message might be double-encoded JSON string
try {
const parsedMessage = JSON.parse(errorBody.message)
errorMessage = parsedMessage.message || errorBody.message
} catch {
errorMessage = errorBody.message
}
}
ElNotification({
duration: elMessageDuration,
title: `Error (${errorBody.code})`,
message: errorMessage,
position: 'bottom-right',
type: 'error'
})
} else {
// Success
ElNotification({
duration: elMessageDuration,
title: 'Success',
message: `System-wide entitlement "${role}" requested successfully`,
position: 'bottom-right',
type: 'success'
})
}
} catch (error: any) {
ElNotification({
duration: elMessageDuration,
title: 'Request Failed',
message: error.message || 'An error occurred while requesting the entitlement',
position: 'bottom-right',
type: 'error'
})
}
}
})
}
}
onBeforeMount(async () => {
const route = useRoute()