Repository: RonasIT/laravel-swagger (php)

Issue:
Custom header key for security
I use custom key for token-header, how i can set this name in config? 
![image](https://github.com/RonasIT/laravel-swagger/assets/116457711/29a08027-4860-407f-8cdf-5e6ce1a9965d)

..jwt option give standart header name, but i need set another name

Pull request:
feat: add ability to select security in source key.
# Description

Add the ability to select security in the source key. It covers cases when you choose a different header name for the authorization bearer.

Fixes #97 

## Type of change

Please delete options that are not relevant.

- [x] New feature (non-breaking change which adds functionality)
- [x] This change requires a documentation update

# Checklist:

- [x] My code follows the style guidelines of this project
- [x] I have performed a self-review of my own code
- [x] I have commented my code, particularly in hard-to-understand areas
- [x] I have made corresponding changes to the documentation
- [x] My changes generate no new warnings
- [x] Any dependent changes have been merged and published in downstream modules

Patch:
diff --git a/config/auto-doc.php b/config/auto-doc.php
index f1ad137..aec6fb4 100644
--- a/config/auto-doc.php
+++ b/config/auto-doc.php
@@ -73,9 +73,22 @@ return [
     |--------------------------------------------------------------------------
     |
     | Library name, which used to secure the project.
-    | Available values: "jwt", "laravel", "null"
+    | Should have one of the key from the `security_drivers` config
     */
     'security' => '',
+    'security_drivers' => [
+        'jwt' => [
+            'type' => 'apiKey',
+            'name' => 'Authorization',
+            'in' => 'header'
+        ],
+        'laravel' => [
+            'type' => 'apiKey',
+            'name' => '__ym_uid',
+            'in' => 'cookie'
+        ]
+    ],
+
     'defaults' => [
 
         /*
@@ -171,5 +184,5 @@ return [
         'development'
     ],
 
-    'config_version' => '2.6'
+    'config_version' => '2.7'
 ];
diff --git a/src/Services/SwaggerService.php b/src/Services/SwaggerService.php
index 512565b..ad4b7d0 100755
--- a/src/Services/SwaggerService.php
+++ b/src/Services/SwaggerService.php
@@ -105,6 +105,12 @@ class SwaggerService
         if (!view()->exists("auto-doc::documentation-{$documentationViewer}")) {
             throw new UnsupportedDocumentationViewerException($documentationViewer);
         }
+
+        $securityDriver = Arr::get($this->config, 'security');
+
+        if ($securityDriver && !array_key_exists($securityDriver, Arr::get($this->config, 'security_drivers'))) {
+            throw new WrongSecurityConfigException();
+        }
     }
 
     protected function setDriver()
@@ -170,23 +176,11 @@ class SwaggerService
 
     protected function generateSecurityDefinitionObject($type): array
     {
-        switch ($type) {
-            case 'jwt':
-                return [
-                    'type' => 'apiKey',
-                    'name' => 'authorization',
-                    'in' => 'header'
-                ];
-
-            case 'laravel':
-                return [
-                    'type' => 'apiKey',
-                    'name' => 'Cookie',
-                    'in' => 'header'
-                ];
-            default:
-                throw new WrongSecurityConfigException();
-        }
+        return [
+            'type' => $this->config['security_drivers'][$type]['type'],
+            'name' => $this->config['security_drivers'][$type]['name'],
+            'in' => $this->config['security_drivers'][$type]['in']
+        ];
     }
 
     public function addData(Request $request, $response)
@@ -701,16 +695,27 @@ class SwaggerService
 
     protected function requestSupportAuth(): bool
     {
-        switch ($this->security) {
-            case 'jwt':
-                $header = $this->request->header('authorization');
+        $security = Arr::get($this->config, 'security');
+        $securityDriver = Arr::get($this->config, "security_drivers.{$security}");
+
+        switch (Arr::get($securityDriver, 'in')) {
+            case 'header':
+                // TODO Change this logic after migration on Swagger 3.0
+                // Swagger 2.0 does not support cookie authorization.
+                $securityToken = $this->request->hasHeader($securityDriver['name'])
+                    ? $this->request->header($securityDriver['name'])
+                    : $this->request->cookie($securityDriver['name']);
+
                 break;
-            case 'laravel':
-                $header = $this->request->cookie('__ym_uid');
+            case 'query':
+                $securityToken = $this->request->query($securityDriver['name']);
+
                 break;
+            default:
+                $securityToken = null;
         }
 
-        return !empty($header);
+        return !empty($securityToken);
     }
 
     protected function parseRequestName($request)


Test patch:
diff --git a/tests/SwaggerServiceTest.php b/tests/SwaggerServiceTest.php
index fb113f7..301a678 100644
--- a/tests/SwaggerServiceTest.php
+++ b/tests/SwaggerServiceTest.php
@@ -293,8 +293,11 @@ class SwaggerServiceTest extends TestCase
     }
 
     #[DataProvider('getConstructorInvalidTmpData')]
-    public function testGetDocFileContentInvalidTmpData(string $docFilePath, string $exception, string $exceptionMessage)
-    {
+    public function testGetDocFileContentInvalidTmpData(
+        string $docFilePath,
+        string $exception,
+        string $exceptionMessage
+    ) {
         $this->mockDriverGetDocumentation($this->getJsonFixture($docFilePath));
 
         $this->expectException($exception);
@@ -323,6 +326,10 @@ class SwaggerServiceTest extends TestCase
                 'security' => 'jwt',
                 'savedTmpDataFixture' => 'tmp_data_request_with_empty_data_jwt',
             ],
+            [
+                'security' => 'query',
+                'savedTmpDataFixture' => 'tmp_data_request_with_empty_data_query',
+            ],
         ];
     }
 
@@ -331,6 +338,23 @@ class SwaggerServiceTest extends TestCase
     {
         config([
             'auto-doc.security' => $security,
+            'auto-doc.security_drivers' => [
+                'laravel' => [
+                    'name' => 'laravel',
+                    'in' => 'cookie',
+                    'type' => 'apiKey'
+                ],
+                'jwt' => [
+                    'name' => 'Authorization',
+                    'in' => 'header',
+                    'type' => 'apiKey'
+                ],
+                'query' => [
+                    'name' => 'api_key',
+                    'in' => 'query',
+                    'type' => 'apiKey'
+                ]
+            ]
         ]);
 
         $this->mockDriverGetEmptyAndSaveTpmData([], $this->getJsonFixture($savedTmpDataFixture));
@@ -439,13 +463,36 @@ class SwaggerServiceTest extends TestCase
                 'security' => 'jwt',
                 'requestFixture' => 'tmp_data_search_roles_request_jwt_security',
             ],
+            [
+                'security' => 'query',
+                'requestFixture' => 'tmp_data_search_roles_request_query_security',
+            ],
         ];
     }
 
     #[DataProvider('addDataWithSecurity')]
-    public function testAddDataWithJWTSecurity(string $security, string $requestFixture)
+    public function testAddDataWithSecurity(string $security, string $requestFixture)
     {
-        config(['auto-doc.security' => $security]);
+        config([
+            'auto-doc.security' => $security,
+            'auto-doc.security_drivers' => [
+                'laravel' => [
+                    'name' => 'laravel',
+                    'in' => 'cookie',
+                    'type' => 'apiKey'
+                ],
+                'jwt' => [
+                    'name' => 'Authorization',
+                    'in' => 'header',
+                    'type' => 'apiKey'
+                ],
+                'query' => [
+                    'name' => 'api_key',
+                    'in' => 'query',
+                    'type' => 'apiKey'
+                ]
+            ]
+        ]);
 
         $this->mockDriverGetEmptyAndSaveTpmData($this->getJsonFixture($requestFixture));
 
@@ -458,7 +505,7 @@ class SwaggerServiceTest extends TestCase
         $service->addData($request, $response);
     }
 
-    public function testAddDataWithEmptySecurity()
+    public function testAddDataWithInvalidSecurity()
     {
         config(['auto-doc.security' => 'invalid']);
 
diff --git a/tests/fixtures/SwaggerServiceTest/tmp_data_request_with_empty_data_jwt.json b/tests/fixtures/SwaggerServiceTest/tmp_data_request_with_empty_data_jwt.json
index 43adab4..8e41bec 100644
--- a/tests/fixtures/SwaggerServiceTest/tmp_data_request_with_empty_data_jwt.json
+++ b/tests/fixtures/SwaggerServiceTest/tmp_data_request_with_empty_data_jwt.json
@@ -17,7 +17,7 @@
     "securityDefinitions": {
         "jwt": {
             "type": "apiKey",
-            "name": "authorization",
+            "name": "Authorization",
             "in": "header"
         }
     }
diff --git a/tests/fixtures/SwaggerServiceTest/tmp_data_request_with_empty_data_laravel.json b/tests/fixtures/SwaggerServiceTest/tmp_data_request_with_empty_data_laravel.json
index fe1aa15..12e360a 100644
--- a/tests/fixtures/SwaggerServiceTest/tmp_data_request_with_empty_data_laravel.json
+++ b/tests/fixtures/SwaggerServiceTest/tmp_data_request_with_empty_data_laravel.json
@@ -17,8 +17,8 @@
     "securityDefinitions": {
         "laravel": {
             "type": "apiKey",
-            "name": "Cookie",
-            "in": "header"
+            "name": "laravel",
+            "in": "cookie"
         }
     }
 }
\ No newline at end of file
diff --git a/tests/fixtures/SwaggerServiceTest/tmp_data_request_with_empty_data_query.json b/tests/fixtures/SwaggerServiceTest/tmp_data_request_with_empty_data_query.json
new file mode 100644
index 0000000..1e65a0d
--- /dev/null
+++ b/tests/fixtures/SwaggerServiceTest/tmp_data_request_with_empty_data_query.json
@@ -0,0 +1,24 @@
+{
+    "swagger": "2.0",
+    "host": "localhost",
+    "basePath": "\/",
+    "schemes": [],
+    "paths": [],
+    "definitions": [],
+    "info": {
+        "description": "This is automatically collected documentation",
+        "version": "0.0.0",
+        "title": "Name of Your Application",
+        "termsOfService": "",
+        "contact": {
+            "email": "your@mail.com"
+        }
+    },
+    "securityDefinitions": {
+        "query": {
+            "type": "apiKey",
+            "name": "api_key",
+            "in": "query"
+        }
+    }
+}
\ No newline at end of file
diff --git a/tests/fixtures/SwaggerServiceTest/tmp_data_search_roles_request_query_security.json b/tests/fixtures/SwaggerServiceTest/tmp_data_search_roles_request_query_security.json
new file mode 100644
index 0000000..c2ade21
--- /dev/null
+++ b/tests/fixtures/SwaggerServiceTest/tmp_data_search_roles_request_query_security.json
@@ -0,0 +1,110 @@
+{
+    "swagger": "2.0",
+    "host": "localhost",
+    "basePath": "/",
+    "schemes": [],
+    "paths": {
+        "/users/roles": {
+            "get": {
+                "tags": [
+                    "users"
+                ],
+                "consumes": [
+                    "application/json"
+                ],
+                "produces": [
+                    "application/json"
+                ],
+                "parameters": [
+                    {
+                        "in": "query",
+                        "name": "query",
+                        "description": "string, required",
+                        "type": "string",
+                        "required": true
+                    },
+                    {
+                        "in": "query",
+                        "name": "user_id",
+                        "description": "integer, with_to_array_rule_string_name",
+                        "type": "integer"
+                    },
+                    {
+                        "in": "query",
+                        "name": "is_email_enabled",
+                        "type": "string",
+                        "description": "test_rule_without_to_string"
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "Operation successfully done",
+                        "schema": {
+                            "example": [
+                                {
+                                    "id": 1,
+                                    "name": "admin",
+                                    "users": [
+                                        {
+                                            "id": 1,
+                                            "name": "admin"
+                                        }
+                                    ]
+                                },
+                                {
+                                    "id": 2,
+                                    "name": "client",
+                                    "users": [
+                                        {
+                                            "id": 2,
+                                            "name": "first_client"
+                                        },
+                                        {
+                                            "id": 3,
+                                            "name": "second_client"
+                                        }
+                                    ]
+                                }
+                            ],
+                            "$ref": "#/definitions/getUsersroles200ResponseObject"
+                        }
+                    }
+                },
+                "security": [],
+                "description": "",
+                "summary": "test",
+                "deprecated": false
+            }
+        }
+    },
+    "definitions": {
+        "getUsersroles200ResponseObject": {
+            "type": "array",
+            "properties": {
+                "items": {
+                    "allOf": [
+                        {
+                            "type": "array"
+                        }
+                    ]
+                }
+            }
+        }
+    },
+    "info": {
+        "description": "This is automatically collected documentation",
+        "version": "0.0.0",
+        "title": "Name of Your Application",
+        "termsOfService": "",
+        "contact": {
+            "email": "your@email.com"
+        }
+    },
+    "securityDefinitions": {
+        "query": {
+            "type": "apiKey",
+            "name": "authorization",
+            "in": "header"
+        }
+    }
+}