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