fix(oauth): align custom binding response fields in frontend (#6818)
* fix(oauth): align custom binding response fields in frontend * fix(oauth): restore custom access policy guidance
This commit is contained in:
+40
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
Copyright (C) 2023-2026 QuantumNous
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
For commercial licensing, please contact support@quantumnous.com
|
||||
*/
|
||||
export const ACCESS_POLICY_TEMPLATES = {
|
||||
levelAndActive: `{
|
||||
"logic": "and",
|
||||
"conditions": [
|
||||
{ "field": "trust_level", "op": "gte", "value": 2 },
|
||||
{ "field": "active", "op": "eq", "value": true }
|
||||
]
|
||||
}`,
|
||||
orgOrRole: `{
|
||||
"logic": "or",
|
||||
"conditions": [
|
||||
{ "field": "org", "op": "eq", "value": "core" },
|
||||
{ "field": "roles", "op": "contains", "value": "admin" }
|
||||
]
|
||||
}`,
|
||||
} as const
|
||||
|
||||
export const ACCESS_DENIED_MESSAGE_TEMPLATES = {
|
||||
level:
|
||||
'Requires level {{required}}; your current level is {{current}} (field: {{field}}).',
|
||||
org: 'Access is limited to approved organizations or roles. Organization: {{current.org}}; roles: {{current.roles}}.',
|
||||
} as const
|
||||
+76
-2
@@ -63,6 +63,10 @@ import {
|
||||
type CustomOAuthProvider,
|
||||
type CustomOAuthFormValues,
|
||||
} from '../types'
|
||||
import {
|
||||
ACCESS_DENIED_MESSAGE_TEMPLATES,
|
||||
ACCESS_POLICY_TEMPLATES,
|
||||
} from './access-policy-templates'
|
||||
import { DiscoveryButton } from './discovery-button'
|
||||
import { PresetSelector } from './preset-selector'
|
||||
|
||||
@@ -603,6 +607,11 @@ export function ProviderFormDialog(props: ProviderFormDialogProps) {
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>{t('Access Policy (JSON)')}</FormLabel>
|
||||
<FormDescription>
|
||||
{t(
|
||||
'Evaluate fields from the provider user info response. Conditions and nested groups use and/or logic.'
|
||||
)}
|
||||
</FormDescription>
|
||||
<FormControl>
|
||||
<JsonCodeEditor
|
||||
value={field.value || ''}
|
||||
@@ -618,9 +627,39 @@ export function ProviderFormDialog(props: ProviderFormDialogProps) {
|
||||
</FormControl>
|
||||
<FormDescription>
|
||||
{t(
|
||||
'JSON-based access control rules. Leave empty to allow all users.'
|
||||
'Supported operators: eq, ne, gt, gte, lt, lte, in, not_in, contains, not_contains, exists, not_exists. Leave empty to allow all users.'
|
||||
)}
|
||||
</FormDescription>
|
||||
<div className='flex flex-wrap gap-2'>
|
||||
<Button
|
||||
type='button'
|
||||
variant='outline'
|
||||
size='xs'
|
||||
onClick={() =>
|
||||
form.setValue(
|
||||
'access_policy',
|
||||
ACCESS_POLICY_TEMPLATES.levelAndActive,
|
||||
{ shouldDirty: true, shouldValidate: true }
|
||||
)
|
||||
}
|
||||
>
|
||||
{t('Fill template: level and active')}
|
||||
</Button>
|
||||
<Button
|
||||
type='button'
|
||||
variant='outline'
|
||||
size='xs'
|
||||
onClick={() =>
|
||||
form.setValue(
|
||||
'access_policy',
|
||||
ACCESS_POLICY_TEMPLATES.orgOrRole,
|
||||
{ shouldDirty: true, shouldValidate: true }
|
||||
)
|
||||
}
|
||||
>
|
||||
{t('Fill template: organization or role')}
|
||||
</Button>
|
||||
</div>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
@@ -635,11 +674,46 @@ export function ProviderFormDialog(props: ProviderFormDialogProps) {
|
||||
<FormControl>
|
||||
<Input
|
||||
placeholder={t(
|
||||
'Custom message shown when access is denied'
|
||||
'e.g. Requires level {{required}}; your current level is {{current}}'
|
||||
)}
|
||||
{...field}
|
||||
/>
|
||||
</FormControl>
|
||||
<FormDescription>
|
||||
{t(
|
||||
'Available variables: {{provider}}, {{field}}, {{op}}, {{required}}, {{current}}, and paths such as {{current.roles}}.'
|
||||
)}
|
||||
</FormDescription>
|
||||
<div className='flex flex-wrap gap-2'>
|
||||
<Button
|
||||
type='button'
|
||||
variant='outline'
|
||||
size='xs'
|
||||
onClick={() =>
|
||||
form.setValue(
|
||||
'access_denied_message',
|
||||
ACCESS_DENIED_MESSAGE_TEMPLATES.level,
|
||||
{ shouldDirty: true }
|
||||
)
|
||||
}
|
||||
>
|
||||
{t('Fill template: level message')}
|
||||
</Button>
|
||||
<Button
|
||||
type='button'
|
||||
variant='outline'
|
||||
size='xs'
|
||||
onClick={() =>
|
||||
form.setValue(
|
||||
'access_denied_message',
|
||||
ACCESS_DENIED_MESSAGE_TEMPLATES.org,
|
||||
{ shouldDirty: true }
|
||||
)
|
||||
}
|
||||
>
|
||||
{t('Fill template: organization message')}
|
||||
</Button>
|
||||
</div>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
|
||||
Reference in New Issue
Block a user