Procházet zdrojové kódy

Add `auth.default` field to set default status for all endpoints

shalvah před 4 roky
rodič
revize
4c84107846

+ 7 - 1
config/scribe.php

@@ -46,10 +46,16 @@ return [
      */
     'auth' => [
         /*
-         * Set this to true if your API is authenticated.
+         * Set this to true if any endpoints in your API are authenticated.
          */
         'enabled' => false,
 
+        /*
+         * Set this to true if your API is authenticated by default.
+         * You can also use @unauthenticated or @authenticated on individual methods to change their status.
+         */
+        'default' => false,
+
         /*
          * Where is the auth value meant to be sent in a request?
          * Options: query, body, query_or_body, basic, bearer, header (for custom header)

+ 3 - 1
docs/config.md

@@ -91,7 +91,9 @@ Authentication information about your API. This information will be used:
 - to set the auth headers/query parameters/body parameters for response calls
 
 Here are the available settings:
-- `enabled`: Set this to `true` if your API requires authentication. Default: `false`.
+- `enabled`: Set this to `true` if any endpoints in your API use authentication. Default: `false`.
+
+- `default`: Specify the default behaviour of your API. If you set this to `true`, your endpoints will be authenticated by default, and you can opt out individually with the `@unauthenticated` tag. If you set this to `false`, your endpoints will NOT be authenticated by default, and you can turn on auth individually with the `@authenticated` tag. Don't forget to set `auth.enabled` to `true`!  Default: `false`.
 
 - `in`: Where is the auth value meant to be sent in a request? Options:
   - `query` (for a query parameter)

+ 6 - 2
docs/documenting/documenting-api-information.md

@@ -7,8 +7,8 @@ You can add authentication information for your API using the `auth` section in
 .. Important:: Scribe uses your specified authentication information in three places:
 
    - Generating an "Authentication" section in your docs
-   - Adding authentication parameters to your example requests (only for endpoints marked as :code:`@authenticated`)
-   - Adding the necessary auth parameters with the specified value to response calls (only for endpoints marked as :code:`@authenticated`)
+   - Adding authentication parameters to your example requests for endpoints marked as :code:`@authenticated` (or if you have with :code:`auth.default` = true)
+   - Adding the necessary auth parameters with the specified value to response calls only for endpoints marked as :code:`@authenticated` (or if you have with :code:`auth.default` = true)
 ```
 
 Here's how you'd configure auth with a query parameter named `apiKey`:
@@ -16,6 +16,7 @@ Here's how you'd configure auth with a query parameter named `apiKey`:
 ```php
     'auth' => [
         'enabled' => true,
+        'default' => false,
         'in' => 'query',
         'name' => 'apiKey',
         'use_value' => env('SCRIBE_API_KEY'),
@@ -32,6 +33,7 @@ Here's an example with a bearer token (also applies to basic auth, if you change
 ```php
     'auth' => [
         'enabled' => true,
+        'default' => false,
         'in' => 'bearer',
         'name' => 'hahaha', // <--- This value is ignored for bearer and basic auth
         'use_value' => env('SCRIBE_AUTH_KEY'),
@@ -46,6 +48,7 @@ And here's an example with a custom header:
 ```php
     'auth' => [
         'enabled' => true,
+        'default' => false,
         'in' => 'header',
         'name' => 'Api-Key', // <--- The name of the header
         'use_value' => env('SCRIBE_AUTH_KEY'),
@@ -53,6 +56,7 @@ And here's an example with a custom header:
         'extra_info' => 'You can retrieve your token by visiting your dashboard and clicking <b>Generate API token</b>.',
     ],
 ```
+The `default` field is the default behaviour of our API. If your endpoints are authenticated by default, set this to `true`, then use `@unauthenticated` on the method doc block if you need to turn off auth for specific endpoints. If your endpoints are open by default, leave this as `false`, then use `@authenticated` on the method doc block if you need to turn on auth for specific endpoints.
 
 You can set whatever you want as the `extra_info`. A good idea would be to tell your users where to get their auth key. 
 

+ 6 - 2
docs/documenting/documenting-endpoint-metadata.md

@@ -73,10 +73,12 @@ class UserController extends Controller
 Grouping endpoints is optional. Any endpoints not in a group will be placed in a default group, "Endpoints".
 
 ## Indicating authentication status
-You can use the `@authenticated` annotation on a method to indicate if the endpoint is authenticated. A "Requires authentication" badge will be added to that route in the generated documentation. 
+If you have `auth.default` set to `false` in your config, your endpoints will be treated as open by default. You can use the `@authenticated` annotation on a method to indicate that the endpoint is authenticated.
+
+Similarly, if you have `auth.default` set to `true` in your config, your endpoints will be treated as authenticated by default. You can use the `@unauthenticated` annotation on a method to indicate that the endpoint is unauthenticated. 
 
 ```eval_rst
-.. Tip:: If all the routes in a controller are authenticated, you can specify `@authenticated` in the controller doc block instead. 
+.. Tip:: You can also specify `@authenticated` or `@unauthenticated` in a controller doc block instead to override the status for all the routes in that controller. 
 ```
 
 ```php
@@ -92,4 +94,6 @@ You can use the `@authenticated` annotation on a method to indicate if the endpo
      }
 ```
 
+A "Requires authentication" badge will be added to that route in the generated documentation. 
+
 ![](../images/endpoint-auth.png)

+ 17 - 9
src/Extracting/Strategies/Metadata/GetFromDocBlocks.php

@@ -33,23 +33,31 @@ class GetFromDocBlocks extends Strategy
             'groupDescription' => $routeGroupDescription,
             'title' => $routeTitle ?: $methodDocBlock->getShortDescription(),
             'description' => $methodDocBlock->getLongDescription()->getContents(),
-            'authenticated' => $this->getAuthStatusFromDocBlock($classDocBlock->getTags()) ?: $this->getAuthStatusFromDocBlock($methodDocBlock->getTags()),
+            'authenticated' => $this->getAuthStatusFromDocBlock($methodDocBlock, $classDocBlock),
         ];
     }
 
     /**
-     * @param array $tags Tags in the method doc block
+     * @param DocBlock $methodDocBlock Method docblock
+     * @param DocBlock $classDocBlock Class docblock
      *
      * @return bool
      */
-    protected function getAuthStatusFromDocBlock(array $tags)
+    protected function getAuthStatusFromDocBlock(DocBlock $methodDocBlock, DocBlock $classDocBlock = null)
     {
-        $authTag = collect($tags)
-            ->first(function ($tag) {
-                return $tag instanceof Tag && strtolower($tag->getName()) === 'authenticated';
-            });
+        foreach ($methodDocBlock->getTags() as $tag) {
+            if (strtolower($tag->getName()) === 'authenticated') {
+                return true;
+            }
+
+            if (strtolower($tag->getName()) === 'unauthenticated') {
+                return false;
+            }
+        }
 
-        return (bool) $authTag;
+        return $classDocBlock
+            ? $this->getAuthStatusFromDocBlock($classDocBlock)
+            : $this->config->get('auth.default', false);
     }
 
     /**
@@ -61,7 +69,7 @@ class GetFromDocBlocks extends Strategy
     protected function getRouteGroupDescriptionAndTitle(DocBlock $methodDocBlock, DocBlock $controllerDocBlock)
     {
         // @group tag on the method overrides that on the controller
-        if (! empty($methodDocBlock->getTags())) {
+        if (!empty($methodDocBlock->getTags())) {
             foreach ($methodDocBlock->getTags() as $tag) {
                 if ($tag->getName() === 'group') {
                     $routeGroupParts = explode("\n", trim($tag->getContent()));

+ 1 - 1
tests/GenerateDocumentationTest.php

@@ -39,7 +39,7 @@ class GenerateDocumentationTest extends TestCase
 
     public function tearDown(): void
     {
-        // Utils::deleteDirectoryAndContents('/public/docs');
+        Utils::deleteDirectoryAndContents('/public/docs');
         Utils::deleteDirectoryAndContents('/resources/docs');
     }
 

+ 1 - 0
tests/Unit/PostmanCollectionWriterTest.php

@@ -227,6 +227,7 @@ class PostmanCollectionWriterTest extends TestCase
     {
         config(['scribe.base_url' => 'fake.localhost']);
         config(['scribe.auth.enabled' => true]);
+        config(['scribe.auth.default' => false]);
 
         $route1 = $this->createMockRouteData('some/path');
         $route1['metadata']['authenticated'] = true;