55use Illuminate \Foundation \Http \FormRequest ;
66use Illuminate \Routing \Route ;
77use Illuminate \Support \Str ;
8+ use Illuminate \Support \Arr ;
89use phpDocumentor \Reflection \DocBlockFactory ;
910use ReflectionMethod ;
1011
1112class Generator
1213{
14+ const SECURITY_DEFINITION_NAME = 'OAuth2 ' ;
1315 const OAUTH_TOKEN_PATH = '/oauth/token ' ;
1416 const OAUTH_AUTHORIZE_PATH = '/oauth/authorize ' ;
1517
@@ -20,18 +22,27 @@ class Generator
2022 protected $ originalUri ;
2123 protected $ method ;
2224 protected $ action ;
25+ protected $ middleware ;
26+ protected $ docParser ;
27+ protected $ hasSecurityDefinitions ;
2328
2429 public function __construct ($ config , $ routeFilter = null )
2530 {
2631 $ this ->config = $ config ;
2732 $ this ->routeFilter = $ routeFilter ;
2833 $ this ->docParser = DocBlockFactory::createInstance ();
34+ $ this ->hasSecurityDefinitions = false ;
2935 }
3036
3137 public function generate ()
3238 {
3339 $ this ->docs = $ this ->getBaseInfo ();
3440
41+ if ($ this ->config ['parseSecurity ' ] && $ this ->hasOauthRoutes ()) {
42+ $ this ->docs ['securityDefinitions ' ] = $ this ->generateSecurityDefinitions ();
43+ $ this ->hasSecurityDefinitions = true ;
44+ }
45+
3546 foreach ($ this ->getAppRoutes () as $ route ) {
3647 $ this ->originalUri = $ uri = $ this ->getRouteUri ($ route );
3748 $ this ->uri = strip_optional_char ($ uri );
@@ -40,11 +51,11 @@ public function generate()
4051 continue ;
4152 }
4253
43- if ($ this ->config ['parseSecurity ' ] && $ this ->isOauthRoute ()) {
44- $ this ->docs ['securityDefinitions ' ] = $ this ->generateSecurityDefinitions ();
45- }
54+ $ middleware = isset ($ route ->getAction ()['middleware ' ]) ? $ route ->getAction ()['middleware ' ] : [];
4655
4756 $ this ->action = $ route ->getAction ()['uses ' ];
57+ $ this ->middleware = $ this ->formatMiddleware ($ middleware );
58+
4859 $ methods = $ route ->methods ();
4960
5061 if (!isset ($ this ->docs ['paths ' ][$ this ->uri ])) {
@@ -118,22 +129,22 @@ protected function generateSecurityDefinitions()
118129 $ this ->validateAuthFlow ($ authFlow );
119130
120131 $ securityDefinition = [
121- ' OAuth2 ' => [
132+ self :: SECURITY_DEFINITION_NAME => [
122133 'type ' => 'oauth2 ' ,
123134 'flow ' => $ authFlow ,
124135 ]
125136 ];
126137
127138
128139 if (in_array ($ authFlow , ['implicit ' , 'accessCode ' ])) {
129- $ securityDefinition [' OAuth2 ' ]['authorizationUrl ' ] = $ this ->getEndpoint (self ::OAUTH_AUTHORIZE_PATH );
140+ $ securityDefinition [self :: SECURITY_DEFINITION_NAME ]['authorizationUrl ' ] = $ this ->getEndpoint (self ::OAUTH_AUTHORIZE_PATH );
130141 }
131142
132143 if (in_array ($ authFlow , ['password ' , 'application ' , 'accessCode ' ])) {
133- $ securityDefinition [' OAuth2 ' ]['tokenUrl ' ] = $ this ->getEndpoint (self ::OAUTH_TOKEN_PATH );
144+ $ securityDefinition [self :: SECURITY_DEFINITION_NAME ]['tokenUrl ' ] = $ this ->getEndpoint (self ::OAUTH_TOKEN_PATH );
134145 }
135146
136- $ securityDefinition [' OAuth2 ' ]['scopes ' ] = $ this ->generateOauthScopes ();
147+ $ securityDefinition [self :: SECURITY_DEFINITION_NAME ]['scopes ' ] = $ this ->generateOauthScopes ();
137148
138149 return $ securityDefinition ;
139150 }
@@ -157,6 +168,10 @@ protected function generatePath()
157168 ];
158169
159170 $ this ->addActionParameters ();
171+
172+ if ($ this ->hasSecurityDefinitions ) {
173+ $ this ->addActionScopes ();
174+ }
160175 }
161176
162177 protected function addActionParameters ()
@@ -176,6 +191,17 @@ protected function addActionParameters()
176191 }
177192 }
178193
194+ protected function addActionScopes ()
195+ {
196+ foreach ($ this ->middleware as $ middleware ) {
197+ if ($ middleware ['name ' ] === 'scope ' || $ middleware ['name ' ] === 'scopes ' ) {
198+ $ this ->docs ['paths ' ][$ this ->uri ][$ this ->method ]['security ' ] = [
199+ self ::SECURITY_DEFINITION_NAME => $ middleware ['parameters ' ]
200+ ];
201+ }
202+ }
203+ }
204+
179205 protected function getFormRules ()
180206 {
181207 if (!is_string ($ this ->action )) {
@@ -237,9 +263,20 @@ private function isFilteredRoute()
237263 return !preg_match ('/^ ' . preg_quote ($ this ->routeFilter , '/ ' ) . '/ ' , $ this ->uri );
238264 }
239265
240- private function isOauthRoute ()
266+ /**
267+ * Assumes routes have been created using Passport::routes()
268+ */
269+ private function hasOauthRoutes ()
241270 {
242- return $ this ->uri === self ::OAUTH_TOKEN_PATH || $ this ->uri === self ::OAUTH_AUTHORIZE_PATH ;
271+ foreach ($ this ->getAppRoutes () as $ route ) {
272+ $ uri = $ this ->getRouteUri ($ route );
273+
274+ if ($ uri === self ::OAUTH_TOKEN_PATH || $ uri === self ::OAUTH_AUTHORIZE_PATH ) {
275+ return true ;
276+ }
277+ }
278+
279+ return false ;
243280 }
244281
245282 private function getEndpoint (string $ path )
@@ -264,4 +301,17 @@ private function validateAuthFlow(string $flow)
264301 throw new LaravelSwaggerException ('Invalid OAuth flow passed ' );
265302 }
266303 }
304+
305+ private function formatMiddleware ($ middleware )
306+ {
307+ $ middleware = Arr::wrap ($ middleware );
308+
309+ return array_map (function ($ mw ) {
310+ $ tokens = explode (': ' , $ mw , 2 );
311+ $ name = $ tokens [0 ];
312+ $ parameters = isset ($ tokens [1 ]) ? explode (', ' , $ tokens [1 ]) : [];
313+
314+ return compact ('name ' , 'parameters ' );
315+ }, $ middleware );
316+ }
267317}
0 commit comments