1+ import React from "react"
2+ import PropTypes from "prop-types"
3+ import ImPropTypes from "react-immutable-proptypes"
4+
5+ export default class ScopeDisplay extends React . Component {
6+ static propTypes = {
7+ security : ImPropTypes . iterable ,
8+ authSelectors : PropTypes . object . isRequired ,
9+ authDefinitions : ImPropTypes . iterable ,
10+ specSelectors : PropTypes . object . isRequired
11+ }
12+
13+ extractSecurityRequirements = ( security ) => {
14+ if ( ! security || ! security . count ( ) ) {
15+ return null
16+ }
17+
18+ const requirements = [ ]
19+
20+ // Each item in security array represents an OR condition
21+ security . forEach ( ( requirement ) => {
22+ const schemes = [ ]
23+
24+ // Each entry in a requirement represents an AND condition
25+ requirement . forEach ( ( scopes , schemeName ) => {
26+ const schemeData = {
27+ name : schemeName ,
28+ scopes : [ ]
29+ }
30+
31+ // Handle different security scheme types
32+ if ( scopes && scopes . size > 0 ) {
33+ // For OAuth2, OpenID Connect, or any scheme with scopes
34+ schemeData . scopes = scopes . toJS ( )
35+ }
36+
37+ schemes . push ( schemeData )
38+ } )
39+
40+ requirements . push ( schemes )
41+ } )
42+
43+ return requirements
44+ }
45+
46+ formatNonOptionalRequirements = ( requirements ) => {
47+ return requirements . map ( ( requirementGroup , idx ) => {
48+ const isLastGroup = idx === requirements . length - 1
49+
50+ return (
51+ < span key = { idx } className = "opblock-security-requirement-group" >
52+ { requirementGroup . map ( ( scheme , schemeIdx ) => {
53+ const isLastInGroup = schemeIdx === requirementGroup . length - 1
54+
55+ return (
56+ < span key = { schemeIdx } className = "opblock-security-requirement" >
57+ < span className = "opblock-security-scheme-name" > { scheme . name } </ span >
58+ { scheme . scopes . length > 0 && (
59+ < span className = "opblock-security-scope-list" >
60+ { " (" }
61+ { scheme . scopes . map ( ( scope , scopeIdx ) => (
62+ < React . Fragment key = { scopeIdx } >
63+ < code className = "opblock-security-scope" >
64+ { scope }
65+ </ code >
66+ { scopeIdx < scheme . scopes . length - 1 ? ", " : "" }
67+ </ React . Fragment >
68+ ) ) }
69+ { ")" }
70+ </ span >
71+ ) }
72+ { ! isLastInGroup && (
73+ < span className = "opblock-security-operator" > + </ span >
74+ ) }
75+ </ span >
76+ )
77+ } ) }
78+ { ! isLastGroup && (
79+ < span className = "opblock-security-operator" > OR </ span >
80+ ) }
81+ </ span >
82+ )
83+ } )
84+ }
85+
86+ formatSecurityDisplay = ( requirements ) => {
87+ if ( ! requirements || requirements . length === 0 ) {
88+ return null
89+ }
90+
91+ // Check if this is optional security (empty object in array)
92+ if ( requirements . length === 1 && requirements [ 0 ] . length === 0 ) {
93+ return < span className = "opblock-security-requirement opblock-security-optional" > Optional</ span >
94+ }
95+
96+ // Check for optional security pattern (one empty and others with auth)
97+ const hasEmptyRequirement = requirements . some ( req => req . length === 0 )
98+ const hasNonEmptyRequirement = requirements . some ( req => req . length > 0 )
99+
100+ if ( hasEmptyRequirement && hasNonEmptyRequirement ) {
101+ // Filter out empty requirements and add optional label
102+ const nonEmptyRequirements = requirements . filter ( req => req . length > 0 )
103+ return (
104+ < React . Fragment >
105+ < span className = "opblock-security-requirement opblock-security-optional" > Optional</ span >
106+ < span className = "opblock-security-operator" > OR </ span >
107+ { this . formatNonOptionalRequirements ( nonEmptyRequirements ) }
108+ </ React . Fragment >
109+ )
110+ }
111+
112+ return this . formatNonOptionalRequirements ( requirements )
113+ }
114+
115+ render ( ) {
116+ const { security } = this . props
117+ const requirements = this . extractSecurityRequirements ( security )
118+ const display = this . formatSecurityDisplay ( requirements )
119+
120+ if ( ! display ) {
121+ return null
122+ }
123+
124+ return (
125+ < div className = "opblock-security-display" >
126+ { display }
127+ </ div >
128+ )
129+ }
130+ }
0 commit comments