This commit is contained in:
2025-08-22 20:36:23 -04:00
parent 483ea399dc
commit 303599f618
2 changed files with 243 additions and 100 deletions

View File

@ -61,6 +61,8 @@ const Tokens: React.FC = () => {
const [tokenDetailsVisible, setTokenDetailsVisible] = useState(false); const [tokenDetailsVisible, setTokenDetailsVisible] = useState(false);
const [selectedToken, setSelectedToken] = useState<TokenWithApp | null>(null); const [selectedToken, setSelectedToken] = useState<TokenWithApp | null>(null);
const [newTokenResponse, setNewTokenResponse] = useState<CreateTokenResponse | null>(null); const [newTokenResponse, setNewTokenResponse] = useState<CreateTokenResponse | null>(null);
const [verifyResult, setVerifyResult] = useState<any>(null);
const [verifyLoading, setVerifyLoading] = useState(false);
const [form] = Form.useForm(); const [form] = Form.useForm();
const [verifyForm] = Form.useForm(); const [verifyForm] = Form.useForm();
@ -169,8 +171,17 @@ const Tokens: React.FC = () => {
} }
}; };
const handleOpenVerifyModal = () => {
verifyForm.resetFields();
setVerifyResult(null);
setVerifyLoading(false);
setVerifyModalVisible(true);
};
const handleVerifyToken = async (values: any) => { const handleVerifyToken = async (values: any) => {
try { try {
setVerifyLoading(true);
const verifyRequest: VerifyRequest = { const verifyRequest: VerifyRequest = {
app_id: values.app_id, app_id: values.app_id,
type: 'static', type: 'static',
@ -178,64 +189,40 @@ const Tokens: React.FC = () => {
permissions: values.permissions || [], permissions: values.permissions || [],
}; };
console.log('Verifying token with request:', verifyRequest);
const response = await apiService.verifyToken(verifyRequest); const response = await apiService.verifyToken(verifyRequest);
console.log('Token verification response:', response);
Modal.info({ // Store the result in state to display in the modal
title: 'Token Verification Result', setVerifyResult(response);
width: 600,
content: (
<div>
<Space direction="vertical" size="middle" style={{ width: '100%' }}>
<div>
<Text strong>Status: </Text>
{response.valid ? (
<Tag color="green" icon={<CheckCircleOutlined />}>VALID</Tag>
) : (
<Tag color="red" icon={<ExclamationCircleOutlined />}>INVALID</Tag>
)}
</div>
{response.permissions && response.permissions.length > 0 && ( // Show success message
<div> if (response && response.valid) {
<Text strong>Permissions:</Text> message.success('Token verification completed successfully!', 3);
<div style={{ marginTop: '8px' }}> } else {
{response.permissions.map(permission => ( message.warning('Token verification completed - token is invalid', 3);
<Tag key={permission} color="blue">{permission}</Tag> }
))}
</div>
</div>
)}
{response.permission_results && (
<div>
<Text strong>Permission Check Results:</Text>
<div style={{ marginTop: '8px' }}>
{Object.entries(response.permission_results).map(([permission, granted]) => (
<div key={permission} style={{ marginBottom: '4px' }}>
<Tag color={granted ? 'green' : 'red'}>
{permission}: {granted ? 'GRANTED' : 'DENIED'}
</Tag>
</div>
))}
</div>
</div>
)}
{response.error && (
<Alert
message="Error"
description={response.error}
type="error"
showIcon
/>
)}
</Space>
</div>
),
});
} catch (error) { } catch (error) {
console.error('Failed to verify token:', error); console.error('Failed to verify token:', error);
message.error('Failed to verify token');
// Store error result in state
setVerifyResult({
valid: false,
error: error instanceof Error ? error.message : 'An unexpected error occurred while verifying the token.',
errorDetails: {
networkError: true,
suggestions: [
'Check your network connection',
'Verify the token format is correct',
'Ensure the selected application is correct',
'Confirm the API server is running'
]
}
});
message.error('Failed to verify token. Please check your network connection and try again.');
} finally {
setVerifyLoading(false);
} }
}; };
@ -339,7 +326,7 @@ const Tokens: React.FC = () => {
<Space> <Space>
<Button <Button
icon={<CheckCircleOutlined />} icon={<CheckCircleOutlined />}
onClick={() => setVerifyModalVisible(true)} onClick={handleOpenVerifyModal}
> >
Verify Token Verify Token
</Button> </Button>
@ -514,54 +501,209 @@ const Tokens: React.FC = () => {
open={verifyModalVisible} open={verifyModalVisible}
onCancel={() => setVerifyModalVisible(false)} onCancel={() => setVerifyModalVisible(false)}
onOk={() => verifyForm.submit()} onOk={() => verifyForm.submit()}
width={600} confirmLoading={verifyLoading}
width={800}
> >
<Form <Space direction="vertical" size="large" style={{ width: '100%' }}>
form={verifyForm} <Form
layout="vertical" form={verifyForm}
onFinish={handleVerifyToken} layout="vertical"
> onFinish={handleVerifyToken}
<Form.Item
name="app_id"
label="Application"
rules={[{ required: true, message: 'Please select an application' }]}
> >
<Select placeholder="Select application"> <Form.Item
{applications.map(app => ( name="app_id"
<Option key={app.app_id} value={app.app_id}> label="Application"
{app.app_id} rules={[{ required: true, message: 'Please select an application' }]}
</Option> >
))} <Select placeholder="Select application">
</Select> {applications.map(app => (
</Form.Item> <Option key={app.app_id} value={app.app_id}>
{app.app_id}
<Form.Item </Option>
name="token"
label="Token"
rules={[{ required: true, message: 'Please enter the token to verify' }]}
>
<TextArea
placeholder="Enter the token to verify"
rows={3}
style={{ fontFamily: 'monospace' }}
/>
</Form.Item>
<Form.Item
name="permissions"
label="Permissions to Check (Optional)"
>
<Checkbox.Group>
<Row>
{availablePermissions.map(permission => (
<Col span={8} key={permission} style={{ marginBottom: '8px' }}>
<Checkbox value={permission}>{permission}</Checkbox>
</Col>
))} ))}
</Row> </Select>
</Checkbox.Group> </Form.Item>
</Form.Item>
</Form> <Form.Item
name="token"
label="Token"
rules={[{ required: true, message: 'Please enter the token to verify' }]}
>
<TextArea
placeholder="Enter the token to verify"
rows={3}
style={{ fontFamily: 'monospace' }}
/>
</Form.Item>
<Form.Item
name="permissions"
label="Permissions to Check (Optional)"
>
<Checkbox.Group>
<Row>
{availablePermissions.map(permission => (
<Col span={8} key={permission} style={{ marginBottom: '8px' }}>
<Checkbox value={permission}>{permission}</Checkbox>
</Col>
))}
</Row>
</Checkbox.Group>
</Form.Item>
</Form>
{/* Verification Results */}
{verifyResult && (
<div>
<Title level={4} style={{ marginBottom: '16px' }}>
<div style={{ display: 'flex', alignItems: 'center', gap: '8px' }}>
{verifyResult.valid ? (
<CheckCircleOutlined style={{ color: '#52c41a' }} />
) : (
<ExclamationCircleOutlined style={{ color: '#ff4d4f' }} />
)}
Verification Results
</div>
</Title>
<Space direction="vertical" size="large" style={{ width: '100%' }}>
{/* Overall Status */}
<Card size="small" style={{ backgroundColor: verifyResult.valid ? '#f6ffed' : '#fff2f0' }}>
<Space direction="vertical" size="small" style={{ width: '100%' }}>
<div>
<Text strong>Token Status: </Text>
{verifyResult.valid ? (
<Tag color="green" icon={<CheckCircleOutlined />} style={{ fontSize: '14px' }}>
VALID
</Tag>
) : (
<Tag color="red" icon={<ExclamationCircleOutlined />} style={{ fontSize: '14px' }}>
INVALID
</Tag>
)}
</div>
{verifyResult.permitted !== undefined && (
<div>
<Text strong>Permission Status: </Text>
{verifyResult.permitted ? (
<Tag color="green" icon={<CheckCircleOutlined />} style={{ fontSize: '14px' }}>
ALL PERMISSIONS GRANTED
</Tag>
) : (
<Tag color="orange" icon={<ExclamationCircleOutlined />} style={{ fontSize: '14px' }}>
SOME PERMISSIONS DENIED
</Tag>
)}
</div>
)}
{verifyResult.token_type && (
<div>
<Text strong>Token Type: </Text>
<Tag color="blue" style={{ fontSize: '14px' }}>
{verifyResult.token_type.toUpperCase()}
</Tag>
</div>
)}
</Space>
</Card>
{/* Token Permissions */}
{verifyResult.permissions && verifyResult.permissions.length > 0 && (
<div>
<Text strong style={{ fontSize: '16px' }}>Available Token Permissions:</Text>
<div style={{ marginTop: '12px', padding: '12px', backgroundColor: '#fafafa', borderRadius: '6px' }}>
<Space wrap>
{verifyResult.permissions.map((permission: string) => (
<Tag key={permission} color="blue" style={{ margin: '2px' }}>
{permission}
</Tag>
))}
</Space>
</div>
</div>
)}
{/* Requested Permission Results */}
{verifyResult.permission_results && Object.keys(verifyResult.permission_results).length > 0 && (
<div>
<Text strong style={{ fontSize: '16px' }}>Requested Permission Results:</Text>
<div style={{ marginTop: '12px' }}>
{Object.entries(verifyResult.permission_results).map(([permission, granted]) => (
<div key={permission} style={{
marginBottom: '8px',
padding: '8px 12px',
backgroundColor: granted ? '#f6ffed' : '#fff2f0',
borderRadius: '4px',
border: `1px solid ${granted ? '#b7eb8f' : '#ffccc7'}`
}}>
<Space>
{granted ? (
<CheckCircleOutlined style={{ color: '#52c41a' }} />
) : (
<ExclamationCircleOutlined style={{ color: '#ff4d4f' }} />
)}
<Text strong>{permission}</Text>
<Tag color={granted ? 'green' : 'red'} style={{ marginLeft: 'auto' }}>
{granted ? 'GRANTED' : 'DENIED'}
</Tag>
</Space>
</div>
))}
</div>
</div>
)}
{/* Error Information */}
{verifyResult.error && (
<Alert
message="Verification Error"
description={verifyResult.error}
type="error"
showIcon
style={{ marginTop: '16px' }}
/>
)}
{/* Error Details with Suggestions */}
{verifyResult.errorDetails && verifyResult.errorDetails.networkError && (
<div>
<Text type="secondary">
Please check:
</Text>
<ul style={{ marginTop: '8px', paddingLeft: '20px' }}>
{verifyResult.errorDetails.suggestions.map((suggestion: string, index: number) => (
<li key={index}>{suggestion}</li>
))}
</ul>
</div>
)}
{/* Additional Information */}
{(verifyResult.expires_at || verifyResult.max_valid_at) && (
<div>
<Text strong style={{ fontSize: '16px' }}>Token Timing Information:</Text>
<div style={{ marginTop: '12px', padding: '12px', backgroundColor: '#fafafa', borderRadius: '6px' }}>
{verifyResult.expires_at && (
<div style={{ marginBottom: '8px' }}>
<Text strong>Expires At: </Text>
<Text code>{new Date(verifyResult.expires_at).toLocaleString()}</Text>
</div>
)}
{verifyResult.max_valid_at && (
<div>
<Text strong>Max Valid Until: </Text>
<Text code>{new Date(verifyResult.max_valid_at).toLocaleString()}</Text>
</div>
)}
</div>
</div>
)}
</Space>
</div>
)}
</Space>
</Modal> </Modal>
{/* Token Details Modal */} {/* Token Details Modal */}

View File

@ -78,6 +78,7 @@ export interface VerifyRequest {
export interface VerifyResponse { export interface VerifyResponse {
valid: boolean; valid: boolean;
permitted: boolean;
user_id?: string; user_id?: string;
permissions: string[]; permissions: string[];
permission_results?: Record<string, boolean>; permission_results?: Record<string, boolean>;