Skip to content

Commit 8d073a7

Browse files
codeRabbitai suggestions
1 parent 4adaddd commit 8d073a7

File tree

4 files changed

+131
-75
lines changed

4 files changed

+131
-75
lines changed

admin-ui/app/routes/Apps/Gluu/GluuCommitDialog.tsx

Lines changed: 89 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,28 @@ import customColors from '@/customColors'
2525

2626
const USER_MESSAGE = 'user_action_message'
2727

28+
type JsonValue = string | number | boolean | null | { [key: string]: JsonValue } | JsonValue[]
29+
30+
type GluuInputType = 'text' | 'textarea' | 'password' | 'email' | 'number' | 'search' | 'url'
31+
32+
interface GluuCommitDialogProps {
33+
handler: () => void
34+
modal: boolean
35+
onAccept: (message: string) => void
36+
formik?: {
37+
setFieldValue: (field: string, value: string) => void
38+
}
39+
operations?: Array<{
40+
path?: string
41+
value?: JsonValue | JsonValue[]
42+
}>
43+
label?: string
44+
placeholderLabel?: string
45+
inputType?: GluuInputType
46+
feature?: string
47+
isLicenseLabel?: boolean
48+
}
49+
2850
const GluuCommitDialog = ({
2951
handler,
3052
modal,
@@ -36,16 +58,19 @@ const GluuCommitDialog = ({
3658
inputType,
3759
feature,
3860
isLicenseLabel = false,
39-
}: any) => {
61+
}: GluuCommitDialogProps) => {
4062
const { t } = useTranslation()
4163
const { hasCedarReadPermission, authorizeHelper } = useCedarling()
4264

43-
const theme: any = useContext(ThemeContext)
44-
const selectedTheme = theme.state.theme
65+
const theme = useContext(ThemeContext)
66+
const selectedTheme = theme?.state.theme || 'light'
4567
const [active, setActive] = useState(false)
46-
const [isOpen, setIsOpen] = useState(null)
68+
const [isOpen, setIsOpen] = useState<number | null>(null)
4769
const [userMessage, setUserMessage] = useState('')
48-
const { loadingWebhooks, webhookModal } = useSelector((state: any) => state.webhookReducer)
70+
const { loadingWebhooks, webhookModal } = useSelector(
71+
(state: { webhookReducer: { loadingWebhooks: boolean; webhookModal: boolean } }) =>
72+
state.webhookReducer,
73+
)
4974

5075
const webhookResourceId = useMemo(() => ADMIN_UI_RESOURCES.Webhooks, [])
5176
const webhookScopes = useMemo(
@@ -91,13 +116,10 @@ const GluuCommitDialog = ({
91116
onCloseModal()
92117
}
93118

94-
if (!modal) {
95-
return <></>
96-
}
97-
const renderBadges = (values: any) => {
119+
const renderBadges = (values: JsonValue[]) => {
98120
return (
99121
<div className="d-flex flex-column gap-1 align-items-start">
100-
{values.map((data: any) => (
122+
{values.map((data) => (
101123
<Badge
102124
color={`primary-${selectedTheme} `}
103125
style={{ width: 'fit-content' }}
@@ -109,6 +131,32 @@ const GluuCommitDialog = ({
109131
</div>
110132
)
111133
}
134+
135+
const renderArrayValue = (values: JsonValue[], key: number) => {
136+
if (!values.length) {
137+
return <Badge color={`primary-${selectedTheme}`}>&quot;&quot;</Badge>
138+
}
139+
140+
return (
141+
<div className="d-flex flex-column gap-1 align-items-start">
142+
{isOpen === key ? (
143+
<Collapse isOpen={isOpen === key}>{renderBadges(values)}</Collapse>
144+
) : (
145+
renderBadges(values.slice(0, 2))
146+
)}
147+
{values.length > 2 && (
148+
<Button color="link" onClick={() => setIsOpen(isOpen !== key ? key : null)} size="sm">
149+
{isOpen === key ? 'Show Less' : 'Show More'}
150+
{isOpen === key ? <KeyboardArrowUpIcon /> : <KeyboardArrowDownIcon />}
151+
</Button>
152+
)}
153+
</div>
154+
)
155+
}
156+
157+
if (!modal) {
158+
return <></>
159+
}
112160
return (
113161
<>
114162
{(webhookModal || loadingWebhooks) && canReadWebhooks ? (
@@ -155,63 +203,39 @@ const GluuCommitDialog = ({
155203
</FormGroup>
156204
) : null}
157205
{operations &&
158-
operations.map((item: any, key: any) => (
159-
<FormGroup row key={key}>
160-
<Col sm={1} style={{ fontWeight: 'bold' }}>
161-
Set
162-
</Col>
163-
<Col
164-
sm={5}
165-
style={{
166-
overflow: 'auto',
167-
width: 300,
168-
paddingBottom: 10,
169-
}}
170-
>
171-
<Badge color={`primary-${selectedTheme}`}>{item.path}</Badge>
172-
</Col>
173-
<Col sm={1} style={{ fontWeight: 'bold' }}>
174-
to
175-
</Col>
176-
<Col sm={5} style={{ overflow: 'auto' }}>
177-
{Array.isArray(item.value) ? (
178-
item.value.length === 0 ? (
206+
operations.map(
207+
(item: { path?: string; value?: JsonValue | JsonValue[] }, key: number) => (
208+
<FormGroup row key={key}>
209+
<Col sm={1} style={{ fontWeight: 'bold' }}>
210+
Set
211+
</Col>
212+
<Col
213+
sm={5}
214+
style={{
215+
overflow: 'auto',
216+
width: 300,
217+
paddingBottom: 10,
218+
}}
219+
>
220+
<Badge color={`primary-${selectedTheme}`}>{item.path}</Badge>
221+
</Col>
222+
<Col sm={1} style={{ fontWeight: 'bold' }}>
223+
to
224+
</Col>
225+
<Col sm={5} style={{ overflow: 'auto' }}>
226+
{Array.isArray(item.value) ? (
227+
renderArrayValue(item.value, key)
228+
) : typeof item.value === 'boolean' ? (
229+
<Badge color={`primary-${selectedTheme}`}>{String(item.value)}</Badge>
230+
) : item.value === '' || item.value === null || item.value === undefined ? (
179231
<Badge color={`primary-${selectedTheme}`}>&quot;&quot;</Badge>
180232
) : (
181-
<div className="d-flex flex-column gap-1 align-items-start">
182-
{isOpen === key ? (
183-
<Collapse isOpen={isOpen === key}>
184-
{renderBadges(item.value)}
185-
</Collapse>
186-
) : (
187-
renderBadges(item.value.slice(0, 2))
188-
)}
189-
{item.value.length > 2 && (
190-
<Button
191-
color="link"
192-
onClick={() => setIsOpen(isOpen !== key ? key : null)}
193-
size="sm"
194-
>
195-
{isOpen === key ? 'Show Less' : 'Show More'}
196-
{isOpen === key ? (
197-
<KeyboardArrowUpIcon />
198-
) : (
199-
<KeyboardArrowDownIcon />
200-
)}
201-
</Button>
202-
)}
203-
</div>
204-
)
205-
) : typeof item.value === 'boolean' ? (
206-
<Badge color={`primary-${selectedTheme}`}>{String(item.value)}</Badge>
207-
) : item.value === '' || item.value === null || item.value === undefined ? (
208-
<Badge color={`primary-${selectedTheme}`}>&quot;&quot;</Badge>
209-
) : (
210-
<Badge color={`primary-${selectedTheme}`}>{String(item.value)}</Badge>
211-
)}
212-
</Col>
213-
</FormGroup>
214-
))}
233+
<Badge color={`primary-${selectedTheme}`}>{String(item.value)}</Badge>
234+
)}
235+
</Col>
236+
</FormGroup>
237+
),
238+
)}
215239
</div>
216240
<div>
217241
<FormGroup row>

admin-ui/plugins/user-management/helper/userAuditHelpers.ts

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,15 @@ export interface AuthState {
3838
}
3939
}
4040

41+
const SENSITIVE_CUSTOM_ATTRS: string[] = [USER_PASSWORD_ATTR]
42+
43+
const isSensitiveCustomAttr = (name?: string): boolean => {
44+
return !!name && SENSITIVE_CUSTOM_ATTRS.includes(name)
45+
}
46+
47+
type CustomAttributeValueItem = CustomObjectAttribute['values'] extends (infer T)[] ? T : never
48+
4149
export interface AuditPayload extends CustomUser {
42-
customAttributes?: CustomObjectAttribute[]
4350
modifiedFields?: Record<string, unknown>
4451
performedOn?: {
4552
user_inum?: string
@@ -64,16 +71,21 @@ function redactSensitiveData(payload: AuditPayload): void {
6471
payload.jsonPatchString = '[{"op":"replace","path":"/userPassword","value":"[REDACTED]"}]'
6572
}
6673

67-
if (Array.isArray(payload.customAttributes)) {
74+
if (payload.customAttributes && payload.customAttributes.length > 0) {
6875
payload.customAttributes = payload.customAttributes.map((attr) => {
69-
if (attr.name === USER_PASSWORD_ATTR) {
70-
const redactedValues = Array.isArray(attr.values)
71-
? attr.values.map(() => '[REDACTED]')
72-
: ['[REDACTED]']
73-
return { ...attr, values: redactedValues }
76+
if (isSensitiveCustomAttr(attr.name)) {
77+
const redactedValue = '[REDACTED]' as CustomAttributeValueItem
78+
const redactedValues =
79+
attr.values && Array.isArray(attr.values)
80+
? (attr.values.map(() => redactedValue) as CustomObjectAttribute['values'])
81+
: undefined
82+
return {
83+
...attr,
84+
values: redactedValues,
85+
}
7486
}
7587
return attr
76-
}) as typeof payload.customAttributes
88+
}) as CustomUser['customAttributes']
7789
}
7890
}
7991

admin-ui/plugins/user-management/utils/attributeTransformUtils.ts

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,8 +63,24 @@ export const normalizeBooleanValue = (rawValue: FormValueEntry | boolean): boole
6363
}
6464

6565
export const normalizeFieldValue = (value: FormValueEntry): string => {
66-
if (Array.isArray(value)) return (value[0] as string) || ''
67-
return typeof value === 'string' ? value : ''
66+
if (Array.isArray(value)) {
67+
const first = value[0]
68+
return first != null ? String(first) : ''
69+
}
70+
71+
if (typeof value === 'string') {
72+
return value
73+
}
74+
75+
if (typeof value === 'boolean') {
76+
return value ? 'true' : 'false'
77+
}
78+
79+
if (value == null) {
80+
return ''
81+
}
82+
83+
return String(value)
6884
}
6985

7086
export const createCustomAttribute = (

admin-ui/plugins/user-management/utils/userFormUtils.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,10 @@ export const validatePassword = (password: string): boolean => {
1616
}
1717

1818
export const getStringValue = (value: string | string[] | boolean | null | undefined): string => {
19+
if (Array.isArray(value)) {
20+
return value[0] ?? ''
21+
}
22+
1923
if (typeof value === 'string') return value
2024
if (typeof value === 'boolean') return ''
2125
return ''

0 commit comments

Comments
 (0)