Skip to content

Instantly share code, notes, and snippets.

@Zeitwaechter
Last active September 16, 2023 16:27
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Zeitwaechter/e299ee0d6af88f30dbf76104ae7da5b3 to your computer and use it in GitHub Desktop.
Save Zeitwaechter/e299ee0d6af88f30dbf76104ae7da5b3 to your computer and use it in GitHub Desktop.
Laravel Auth / Sanctum routes are not annotated by default, right? So here we go - with a bit extra...
<?php
namespace App\Helpers\Traits\OpenApi\Routes\Auth;
use OpenApi\Attributes as OAT;
#[OAT\Post(
path: '/v1/auth/login',
operationId: 'v1-auth-login',
description: <<<'NOW'
After you have set your XSRF-Token you can now try to login with your user.
**Copy** the **CSRF Token's value** of the Cookie into the `csrfAuthHeader`
authorization and do not forget to replace the `0%30` with `0=`.
After you have successfully logged in, your CSRF Token is now invalid.
NOW,
summary: 'Login with your user credentials',
security: [
[
'csrfAuthHeader' => [],
],
],
tags: ['api/v1'],
parameters: [
new OAT\Parameter(
name: 'email',
description: 'The email address for user login',
in: 'query',
required: true,
schema: new OAT\Schema(
type: 'string'
),
example: 'john@doe.tld',
),
new OAT\Parameter(
name: 'password',
description: 'The password for user login, in clear text',
in: 'query',
required: true,
schema: new OAT\Schema(
type: 'string',
),
example: 'password',
),
],
responses: [
new OAT\Response(
response: 200,
description: 'successful operation',
headers: [
new OAT\Header(
header: 'x-ratelimit-limit',
description: 'calls per minute allowed by the user',
schema: new OAT\Schema(
type: 'integer',
format: 'int32',
),
),
new OAT\Header(
header: 'x-ratelimit-remaining',
description: 'count of remaining calls per minute allowed by the user',
schema: new OAT\Schema(
type: 'integer',
format: 'int32',
),
),
],
content: new OAT\JsonContent(
properties: [
new OAT\Property(
property: 'message',
type: 'string',
example: 'OK',
),
new OAT\Property(
property: 'data',
properties: [
new OAT\Property(
property: 'user',
properties: [
new OAT\Property(
property: 'uuid',
type: 'uuid',
example: 'd299c116-4af6-41cc-a297-eabf7cd3ed87',
),
new OAT\Property(
property: 'attributes',
properties: [
new OAT\Property(
property: 'name',
type: 'string',
example: 'John Doe',
),
new OAT\Property(
property: 'email',
type: 'string',
example: 'john@doe.tld',
),
new OAT\Property(
property: 'created_at',
type: 'date-time',
example: '2023-09-02T12:05:11.000000Z',
),
new OAT\Property(
property: 'updated_at',
type: 'date-time',
example: '2023-09-02T12:05:11.000000Z',
),
],
type: 'object',
),
],
type: 'object',
),
new OAT\Property(
property: 'token',
type: 'string',
example: '0|laravel_sanctum_t9Xl5BZjoQuLFJcZG4lojGiLBTbZOlHgA117DyYF7f1c9817',
),
],
type: 'object',
),
],
type: 'object',
),
),
new OAT\Response(
response: 403,
description: 'csrf token mismatch / expired / missing / already authenticated',
headers: [
new OAT\Header(
header: 'x-ratelimit-limit',
description: 'calls per minute allowed by the user',
schema: new OAT\Schema(
type: 'integer',
format: 'int32',
),
),
new OAT\Header(
header: 'x-ratelimit-remaining',
description: 'count of remaining calls per minute allowed by the user',
schema: new OAT\Schema(
type: 'integer',
format: 'int32',
),
),
],
content: new OAT\JsonContent(
properties: [
new OAT\Property(
property: 'message',
type: 'string',
example: <<<'NOW'
You are already logged in or your Token is mismatching. Is your CSRF Token attached as X-XSRF-TOKEN header param?
NOW
),
new OAT\Property(
property: 'data',
type: 'array',
items: new OAT\Items(),
example: [],
),
],
),
),
new OAT\Response(
response: 401,
description: <<<'NOW'
incorrect credentials / user does not exist
**When you have reached this point, delete all your
Cookies and Sessions for this Swagger UI page.**
Start anew with requesting another CSRF-Token.
NOW,
content: new OAT\JsonContent(
properties: [
new OAT\Property(
property: 'message',
type: 'string',
example: 'Credentials do not match',
),
new OAT\Property(
property: 'data',
type: 'array',
items: new OAT\Items(),
example: [],
),
],
type: 'object',
),
),
new OAT\Response(
response: 500,
description: 'Server Error',
headers: [
new OAT\Header(
header: 'x-ratelimit-limit',
description: 'calls per minute allowed by the user',
schema: new OAT\Schema(
type: 'integer',
format: 'int32',
),
),
new OAT\Header(
header: 'x-ratelimit-remaining',
description: 'count of remaining calls per minute allowed by the user',
schema: new OAT\Schema(
type: 'integer',
format: 'int32',
),
),
],
content: new OAT\JsonContent(
properties: [
new OAT\Property(
property: 'message',
type: 'string',
example: 'Screw up from our side. Server will be right back...',
),
new OAT\Property(
property: 'data',
type: 'array',
items: new OAT\Items(),
example: [],
),
],
type: 'object',
),
),
],
deprecated: false,
)]
#[OAT\Post(
path: '/v1/auth/register',
operationId: 'v1-auth-register',
description: 'After you have set your XSRF-Token you can now try to register your user.',
summary: 'Register your user',
security: [
[
'csrfAuthHeader' => [],
],
],
tags: ['api/v1'],
parameters: [
new OAT\Parameter(
name: 'email',
description: 'The email address for user login',
in: 'query',
required: true,
schema: new OAT\Schema(
type: 'string',
),
example: 'john@doe.tld',
),
new OAT\Parameter(
name: 'password',
description: 'The password for user login, in clear text',
in: 'query',
required: true,
schema: new OAT\Schema(
type: 'string',
),
example: 'password',
),
],
responses: [
new OAT\Response(
response: 200,
description: 'successful operation',
headers: [
new OAT\Header(
header: 'x-ratelimit-limit',
description: 'calls per minute allowed by the user',
schema: new OAT\Schema(
type: 'integer',
format: 'int32',
),
),
new OAT\Header(
header: 'x-ratelimit-remaining',
description: 'count of remaining calls per minute allowed by the user',
schema: new OAT\Schema(
type: 'integer',
format: 'int32',
),
),
],
content: new OAT\JsonContent(
properties: [
new OAT\Property(
property: 'message',
type: 'string',
example: 'OK',
),
new OAT\Property(
property: 'data',
properties: [
new OAT\Property(
property: 'user',
properties: [
new OAT\Property(
property: 'uuid',
type: 'uuid',
example: 'd299c116-4af6-41cc-a297-eabf7cd3ed87',
),
new OAT\Property(
property: 'attributes',
properties: [
new OAT\Property(
property: 'name',
type: 'string',
example: 'John Doe',
),
new OAT\Property(
property: 'email',
type: 'string',
example: 'john@doe.tld',
),
new OAT\Property(
property: 'created_at',
type: 'date-time',
example: '2023-09-02T12:05:11.000000Z',
),
new OAT\Property(
property: 'updated_at',
type: 'date-time',
example: '2023-09-02T12:05:11.000000Z',
),
],
type: 'object',
),
],
type: 'object',
),
new OAT\Property(
property: 'token',
type: 'string',
),
],
type: 'object',
),
],
type: 'object',
),
),
new OAT\Response(
response: 403,
description: 'csrf token mismatch / expired / missing',
headers: [
new OAT\Header(
header: 'x-ratelimit-limit',
description: 'calls per minute allowed by the user',
schema: new OAT\Schema(
type: 'integer',
format: 'int32',
),
),
new OAT\Header(
header: 'x-ratelimit-remaining',
description: 'count of remaining calls per minute allowed by the user',
schema: new OAT\Schema(
type: 'integer',
format: 'int32',
),
),
],
content: new OAT\JsonContent(
properties: [
new OAT\Property(
property: 'message',
type: 'string',
example: <<<'NOW'
You are already logged in or your Token is mismatching. Is your CSRF Token attached as X-XSRF-TOKEN header param?
NOW
),
new OAT\Property(
property: 'data',
type: 'array',
items: new OAT\Items(),
example: [],
),
],
),
),
new OAT\Response(
response: 422,
description: 'error, user record might already exist',
headers: [
new OAT\Header(
header: 'x-ratelimit-limit',
description: 'calls per minute allowed by the user',
schema: new OAT\Schema(
type: 'integer',
format: 'int32',
),
),
new OAT\Header(
header: 'x-ratelimit-remaining',
description: 'count of remaining calls per minute allowed by the user',
schema: new OAT\Schema(
type: 'integer',
format: 'int32',
),
),
],
content: new OAT\JsonContent(
properties: [
new OAT\Property(
property: 'message',
type: 'string',
example: 'The email has already been taken'
),
new OAT\Property(
property: 'errors',
properties: [
new OAT\Property(
'email',
type: 'array',
items: new OAT\Items(
type: 'string',
example: 'The email has already been taken',
),
),
],
type: 'object',
),
],
),
),
new OAT\Response(
response: 500,
description: 'Server Error',
headers: [
new OAT\Header(
header: 'x-ratelimit-limit',
description: 'calls per minute allowed by the user',
schema: new OAT\Schema(
type: 'integer',
format: 'int32',
),
),
new OAT\Header(
header: 'x-ratelimit-remaining',
description: 'count of remaining calls per minute allowed by the user',
schema: new OAT\Schema(
type: 'integer',
format: 'int32',
),
),
],
content: new OAT\JsonContent(
properties: [
new OAT\Property(
property: 'message',
type: 'string',
example: 'Screw up from our side. Server will be right back...',
),
new OAT\Property(
property: 'data',
type: 'array',
items: new OAT\Items(),
example: [],
),
],
type: 'object',
),
),
],
deprecated: false,
)]
#[OAT\Post(
path: '/v1/auth/logout',
operationId: 'v1-auth-logout',
description: 'Say goodbye to your current session, friend.',
summary: 'Logout the current, authenticated User',
security: [
[
'bearerAuthHeader' => [],
],
],
tags: ['api/v1'],
responses: [
new OAT\Response(
response: 200,
description: 'logging out was correctly handled.',
headers: [
new OAT\Header(
header: 'x-ratelimit-limit',
description: 'calls per minute allowed by the user',
schema: new OAT\Schema(
type: 'integer',
format: 'int32',
),
),
new OAT\Header(
header: 'x-ratelimit-remaining',
description: 'count of remaining calls per minute allowed by the user',
schema: new OAT\Schema(
type: 'integer',
format: 'int32',
),
),
],
content: new OAT\JsonContent(
properties: [
new OAT\Property(
property: 'message',
type: 'string',
example: 'Bearer Token annihilated.',
),
new OAT\Property(
property: 'data',
type: 'array',
items: new OAT\Items(),
example: [],
),
],
type: 'object',
),
),
new OAT\Response(
response: 401,
description: 'unauthorized / already logged out',
content: new OAT\JsonContent(
properties: [
new OAT\Property(
property: 'message',
type: 'string',
example: 'You are not authorized to use this route. Are you logged in?',
),
new OAT\Property(
property: 'data',
type: 'array',
items: new OAT\Items(),
example: [],
),
],
type: 'object',
),
),
new OAT\Response(
response: 500,
description: 'Server Error',
headers: [
new OAT\Header(
header: 'x-ratelimit-limit',
description: 'calls per minute allowed by the user',
schema: new OAT\Schema(
type: 'integer',
format: 'int32',
),
),
new OAT\Header(
header: 'x-ratelimit-remaining',
description: 'count of remaining calls per minute allowed by the user',
schema: new OAT\Schema(
type: 'integer',
format: 'int32',
),
),
],
content: new OAT\JsonContent(
properties: [
new OAT\Property(
property: 'message',
type: 'string',
example: 'Screw up from our side. Server will be right back...',
),
new OAT\Property(
property: 'data',
type: 'array',
items: new OAT\Items(),
example: [],
),
],
type: 'object',
),
),
],
deprecated: false,
)]
#[OAT\Get(
path: '/v1/user',
operationId: 'v1-user-show',
description: 'Returns some meta information about the current, authenticated User',
summary: 'Get the current authenticated User',
security: [
[
'bearerAuthHeader' => [],
],
],
tags: ['api/v1'],
responses: [
new OAT\Response(
response: 200,
description: 'successful operation',
headers: [
new OAT\Header(
header: 'x-ratelimit-limit',
description: 'calls per minute allowed by the user',
schema: new OAT\Schema(
type: 'integer',
format: 'int32',
),
),
new OAT\Header(
header: 'x-ratelimit-remaining',
description: 'count of remaining calls per minute allowed by the user',
schema: new OAT\Schema(
type: 'integer',
format: 'int32',
),
),
],
content: new OAT\JsonContent(
properties: [
new OAT\Property(
property: 'message',
type: 'string',
example: 'OK',
),
new OAT\Property(
property: 'data',
properties: [
new OAT\Property(
property: 'user',
properties: [
new OAT\Property(
property: 'uuid',
type: 'uuid',
example: 'd299c116-4af6-41cc-a297-eabf7cd3ed87',
),
new OAT\Property(
property: 'attributes',
properties: [
new OAT\Property(
property: 'name',
type: 'string',
example: 'John Doe',
),
new OAT\Property(
property: 'email',
type: 'string',
example: 'john@doe.tld',
),
new OAT\Property(
property: 'created_at',
type: 'date-time',
example: '2023-09-02T12:05:11.000000Z',
),
new OAT\Property(
property: 'updated_at',
type: 'date-time',
example: '2023-09-02T12:05:11.000000Z',
),
],
type: 'object',
),
],
type: 'object',
),
],
type: 'object',
),
],
type: 'object',
),
),
new OAT\Response(
response: 401,
description: 'Error: Unauthorized',
headers: [
new OAT\Header(
header: 'x-ratelimit-limit',
description: 'calls per minute allowed by the user',
schema: new OAT\Schema(
type: 'integer',
format: 'int32',
),
),
new OAT\Header(
header: 'x-ratelimit-remaining',
description: 'count of remaining calls per minute allowed by the user',
schema: new OAT\Schema(
type: 'integer',
format: 'int32',
),
),
],
content: new OAT\JsonContent(
properties: [
new OAT\Property(
property: 'message',
type: 'string',
example: 'You are not authorized to use this route. Are you logged in?',
),
new OAT\Property(
property: 'data',
type: 'array',
items: new OAT\Items(),
example: [],
),
],
type: 'object',
),
),
new OAT\Response(
response: 500,
description: 'Server Error',
headers: [
new OAT\Header(
header: 'x-ratelimit-limit',
description: 'calls per minute allowed by the user',
schema: new OAT\Schema(
type: 'integer',
format: 'int32',
),
),
new OAT\Header(
header: 'x-ratelimit-remaining',
description: 'count of remaining calls per minute allowed by the user',
schema: new OAT\Schema(
type: 'integer',
format: 'int32',
),
),
],
content: new OAT\JsonContent(
properties: [
new OAT\Property(
property: 'message',
type: 'string',
example: 'Screw up from our side. Server will be right back...',
),
new OAT\Property(
property: 'data',
type: 'array',
items: new OAT\Items(),
example: [],
),
],
type: 'object',
),
),
],
deprecated: false,
)]
/**
* Trait HasAuthOpenApiDescriptors
*/
trait HasAuthOpenApiVersion1Descriptors
{
//
}
<?php
namespace App\Helpers\Traits\OpenApi\Routes\Auth;
use OpenApi\Attributes as OAT;
#[OAT\Post(
path: '/v2/auth/login',
operationId: 'v2-auth-login',
description: <<<'NOW'
After you have set your XSRF-Token you can now try to login with your user.
**Copy** the **CSRF Token's value** of the Cookie into the `csrfAuthHeader`
authorization and do not forget to replace the `0%30` with `0=`.
After you have successfully logged in, your CSRF Token is now invalid.
NOW,
summary: 'Login with your user credentials',
security: [
[
'csrfAuthHeader' => [],
],
],
tags: ['api/v2'],
parameters: [
new OAT\Parameter(
name: 'email',
description: 'The email address for user login',
in: 'query',
required: true,
schema: new OAT\Schema(
type: 'string'
),
example: 'john@doe.tld',
),
new OAT\Parameter(
name: 'password',
description: 'The password for user login, in clear text',
in: 'query',
required: true,
schema: new OAT\Schema(
type: 'string',
),
example: 'password',
),
],
responses: [
new OAT\Response(
response: 200,
description: 'successful operation',
headers: [
new OAT\Header(
header: 'x-ratelimit-limit',
description: 'calls per minute allowed by the user',
schema: new OAT\Schema(
type: 'integer',
format: 'int32',
),
),
new OAT\Header(
header: 'x-ratelimit-remaining',
description: 'count of remaining calls per minute allowed by the user',
schema: new OAT\Schema(
type: 'integer',
format: 'int32',
),
),
],
content: new OAT\JsonContent(
properties: [
new OAT\Property(
property: 'message',
type: 'string',
example: 'OK',
),
new OAT\Property(
property: 'data',
properties: [
new OAT\Property(
property: 'user',
properties: [
new OAT\Property(
property: 'uuid',
type: 'uuid',
example: 'd299c116-4af6-41cc-a297-eabf7cd3ed87',
),
new OAT\Property(
property: 'attributes',
properties: [
new OAT\Property(
property: 'name',
type: 'string',
example: 'John Doe',
),
new OAT\Property(
property: 'email',
type: 'string',
example: 'john@doe.tld',
),
new OAT\Property(
property: 'created_at',
type: 'date-time',
example: '2023-09-02T12:05:11.000000Z',
),
new OAT\Property(
property: 'updated_at',
type: 'date-time',
example: '2023-09-02T12:05:11.000000Z',
),
],
type: 'object',
),
],
type: 'object',
),
new OAT\Property(
property: 'token',
type: 'string',
example: '0|laravel_sanctum_t9Xl5BZjoQuLFJcZG4lojGiLBTbZOlHgA117DyYF7f1c9817',
),
],
type: 'object',
),
],
type: 'object',
),
),
new OAT\Response(
response: 403,
description: 'csrf token mismatch / expired / missing / already authenticated',
headers: [
new OAT\Header(
header: 'x-ratelimit-limit',
description: 'calls per minute allowed by the user',
schema: new OAT\Schema(
type: 'integer',
format: 'int32',
),
),
new OAT\Header(
header: 'x-ratelimit-remaining',
description: 'count of remaining calls per minute allowed by the user',
schema: new OAT\Schema(
type: 'integer',
format: 'int32',
),
),
],
content: new OAT\JsonContent(
properties: [
new OAT\Property(
property: 'message',
type: 'string',
example: <<<'NOW'
You are already logged in or your Token is mismatching. Is your CSRF Token attached as X-XSRF-TOKEN header param?
NOW
),
new OAT\Property(
property: 'data',
type: 'array',
items: new OAT\Items(),
example: [],
),
],
),
),
new OAT\Response(
response: 401,
description: <<<'NOW'
incorrect credentials / user does not exist
**When you have reached this point, delete all your
Cookies and Sessions for this Swagger UI page.**
Start anew with requesting another CSRF-Token.
NOW,
content: new OAT\JsonContent(
properties: [
new OAT\Property(
property: 'message',
type: 'string',
example: 'Credentials do not match',
),
new OAT\Property(
property: 'data',
type: 'array',
items: new OAT\Items(),
example: [],
),
],
type: 'object',
),
),
new OAT\Response(
response: 500,
description: 'Server Error',
headers: [
new OAT\Header(
header: 'x-ratelimit-limit',
description: 'calls per minute allowed by the user',
schema: new OAT\Schema(
type: 'integer',
format: 'int32',
),
),
new OAT\Header(
header: 'x-ratelimit-remaining',
description: 'count of remaining calls per minute allowed by the user',
schema: new OAT\Schema(
type: 'integer',
format: 'int32',
),
),
],
content: new OAT\JsonContent(
properties: [
new OAT\Property(
property: 'message',
type: 'string',
example: 'Screw up from our side. Server will be right back...',
),
new OAT\Property(
property: 'data',
type: 'array',
items: new OAT\Items(),
example: [],
),
],
type: 'object',
),
),
],
deprecated: false,
)]
#[OAT\Post(
path: '/v2/auth/register',
operationId: 'v2-auth-register',
description: 'After you have set your XSRF-Token you can now try to register your user.',
summary: 'Register your user',
security: [
[
'csrfAuthHeader' => [],
],
],
tags: ['api/v2'],
parameters: [
new OAT\Parameter(
name: 'email',
description: 'The email address for user login',
in: 'query',
required: true,
schema: new OAT\Schema(
type: 'string',
),
example: 'john@doe.tld',
),
new OAT\Parameter(
name: 'password',
description: 'The password for user login, in clear text',
in: 'query',
required: true,
schema: new OAT\Schema(
type: 'string',
),
example: 'password',
),
],
responses: [
new OAT\Response(
response: 200,
description: 'successful operation',
headers: [
new OAT\Header(
header: 'x-ratelimit-limit',
description: 'calls per minute allowed by the user',
schema: new OAT\Schema(
type: 'integer',
format: 'int32',
),
),
new OAT\Header(
header: 'x-ratelimit-remaining',
description: 'count of remaining calls per minute allowed by the user',
schema: new OAT\Schema(
type: 'integer',
format: 'int32',
),
),
],
content: new OAT\JsonContent(
properties: [
new OAT\Property(
property: 'message',
type: 'string',
example: 'OK',
),
new OAT\Property(
property: 'data',
properties: [
new OAT\Property(
property: 'user',
properties: [
new OAT\Property(
property: 'uuid',
type: 'uuid',
example: 'd299c116-4af6-41cc-a297-eabf7cd3ed87',
),
new OAT\Property(
property: 'attributes',
properties: [
new OAT\Property(
property: 'name',
type: 'string',
example: 'John Doe',
),
new OAT\Property(
property: 'email',
type: 'string',
example: 'john@doe.tld',
),
new OAT\Property(
property: 'created_at',
type: 'date-time',
example: '2023-09-02T12:05:11.000000Z',
),
new OAT\Property(
property: 'updated_at',
type: 'date-time',
example: '2023-09-02T12:05:11.000000Z',
),
],
type: 'object',
),
],
type: 'object',
),
new OAT\Property(
property: 'token',
type: 'string',
),
],
type: 'object',
),
],
type: 'object',
),
),
new OAT\Response(
response: 403,
description: 'csrf token mismatch / expired / missing / already authenticated',
headers: [
new OAT\Header(
header: 'x-ratelimit-limit',
description: 'calls per minute allowed by the user',
schema: new OAT\Schema(
type: 'integer',
format: 'int32',
),
),
new OAT\Header(
header: 'x-ratelimit-remaining',
description: 'count of remaining calls per minute allowed by the user',
schema: new OAT\Schema(
type: 'integer',
format: 'int32',
),
),
],
content: new OAT\JsonContent(
properties: [
new OAT\Property(
property: 'message',
type: 'string',
example: <<<'NOW'
You are already logged in or your Token is mismatching. Is your CSRF Token attached as X-XSRF-TOKEN header param?
NOW
),
new OAT\Property(
property: 'data',
type: 'array',
items: new OAT\Items(),
example: [],
),
],
),
),
new OAT\Response(
response: 422,
description: 'error, user record might already exist',
headers: [
new OAT\Header(
header: 'x-ratelimit-limit',
description: 'calls per minute allowed by the user',
schema: new OAT\Schema(
type: 'integer',
format: 'int32',
),
),
new OAT\Header(
header: 'x-ratelimit-remaining',
description: 'count of remaining calls per minute allowed by the user',
schema: new OAT\Schema(
type: 'integer',
format: 'int32',
),
),
],
content: new OAT\JsonContent(
properties: [
new OAT\Property(
property: 'message',
type: 'string',
example: 'The email has already been taken'
),
new OAT\Property(
property: 'errors',
properties: [
new OAT\Property(
'email',
type: 'array',
items: new OAT\Items(
type: 'string',
example: 'The email has already been taken',
),
),
],
type: 'object',
),
],
),
),
new OAT\Response(
response: 500,
description: 'Server Error',
headers: [
new OAT\Header(
header: 'x-ratelimit-limit',
description: 'calls per minute allowed by the user',
schema: new OAT\Schema(
type: 'integer',
format: 'int32',
),
),
new OAT\Header(
header: 'x-ratelimit-remaining',
description: 'count of remaining calls per minute allowed by the user',
schema: new OAT\Schema(
type: 'integer',
format: 'int32',
),
),
],
content: new OAT\JsonContent(
properties: [
new OAT\Property(
property: 'message',
type: 'string',
example: 'Screw up from our side. Server will be right back...',
),
new OAT\Property(
property: 'data',
type: 'array',
items: new OAT\Items(),
example: [],
),
],
type: 'object',
),
),
],
deprecated: false,
)]
#[OAT\Post(
path: '/v2/auth/logout',
operationId: 'v2-auth-logout',
description: 'Say goodbye to your current session, friend.',
summary: 'Logout the current, authenticated User',
security: [
[
'bearerAuthHeader' => [],
],
],
tags: ['api/v2'],
responses: [
new OAT\Response(
response: 200,
description: 'logging out was correctly handled.',
headers: [
new OAT\Header(
header: 'x-ratelimit-limit',
description: 'calls per minute allowed by the user',
schema: new OAT\Schema(
type: 'integer',
format: 'int32',
),
),
new OAT\Header(
header: 'x-ratelimit-remaining',
description: 'count of remaining calls per minute allowed by the user',
schema: new OAT\Schema(
type: 'integer',
format: 'int32',
),
),
],
content: new OAT\JsonContent(
properties: [
new OAT\Property(
property: 'message',
type: 'string',
example: 'Bearer Token annihilated.',
),
new OAT\Property(
property: 'data',
type: 'array',
items: new OAT\Items(),
example: [],
),
],
type: 'object',
),
),
new OAT\Response(
response: 401,
description: 'unauthorized / already logged out',
content: new OAT\JsonContent(
properties: [
new OAT\Property(
property: 'message',
type: 'string',
example: 'You are not authorized to use this route. Are you logged in?',
),
new OAT\Property(
property: 'data',
type: 'array',
items: new OAT\Items(),
example: [],
),
],
type: 'object',
),
),
new OAT\Response(
response: 500,
description: 'Server Error',
headers: [
new OAT\Header(
header: 'x-ratelimit-limit',
description: 'calls per minute allowed by the user',
schema: new OAT\Schema(
type: 'integer',
format: 'int32',
),
),
new OAT\Header(
header: 'x-ratelimit-remaining',
description: 'count of remaining calls per minute allowed by the user',
schema: new OAT\Schema(
type: 'integer',
format: 'int32',
),
),
],
content: new OAT\JsonContent(
properties: [
new OAT\Property(
property: 'message',
type: 'string',
example: 'Screw up from our side. Server will be right back...',
),
new OAT\Property(
property: 'data',
type: 'array',
items: new OAT\Items(),
example: [],
),
],
type: 'object',
),
),
],
deprecated: false,
)]
#[OAT\Get(
path: '/v2/user',
operationId: 'v2-user-show',
description: 'Returns some meta information about the current, authenticated User',
summary: 'Get the current authenticated User',
security: [
[
'bearerAuthHeader' => [],
],
],
tags: ['api/v2'],
responses: [
new OAT\Response(
response: 200,
description: 'successful operation',
headers: [
new OAT\Header(
header: 'x-ratelimit-limit',
description: 'calls per minute allowed by the user',
schema: new OAT\Schema(
type: 'integer',
format: 'int32',
),
),
new OAT\Header(
header: 'x-ratelimit-remaining',
description: 'count of remaining calls per minute allowed by the user',
schema: new OAT\Schema(
type: 'integer',
format: 'int32',
),
),
],
content: new OAT\JsonContent(
properties: [
new OAT\Property(
property: 'message',
type: 'string',
example: 'OK',
),
new OAT\Property(
property: 'data',
properties: [
new OAT\Property(
property: 'user',
properties: [
new OAT\Property(
property: 'uuid',
type: 'uuid',
example: 'd299c116-4af6-41cc-a297-eabf7cd3ed87',
),
new OAT\Property(
property: 'attributes',
properties: [
new OAT\Property(
property: 'name',
type: 'string',
example: 'John Doe',
),
new OAT\Property(
property: 'email',
type: 'string',
example: 'john@doe.tld',
),
new OAT\Property(
property: 'created_at',
type: 'date-time',
example: '2023-09-02T12:05:11.000000Z',
),
new OAT\Property(
property: 'updated_at',
type: 'date-time',
example: '2023-09-02T12:05:11.000000Z',
),
],
type: 'object',
),
],
type: 'object',
),
],
type: 'object',
),
],
type: 'object',
),
),
new OAT\Response(
response: 401,
description: 'Error: Unauthorized',
headers: [
new OAT\Header(
header: 'x-ratelimit-limit',
description: 'calls per minute allowed by the user',
schema: new OAT\Schema(
type: 'integer',
format: 'int32',
),
),
new OAT\Header(
header: 'x-ratelimit-remaining',
description: 'count of remaining calls per minute allowed by the user',
schema: new OAT\Schema(
type: 'integer',
format: 'int32',
),
),
],
content: new OAT\JsonContent(
properties: [
new OAT\Property(
property: 'message',
type: 'string',
example: 'You are not authorized to use this route. Are you logged in?',
),
new OAT\Property(
property: 'data',
type: 'array',
items: new OAT\Items(),
example: [],
),
],
type: 'object',
),
),
new OAT\Response(
response: 500,
description: 'Server Error',
headers: [
new OAT\Header(
header: 'x-ratelimit-limit',
description: 'calls per minute allowed by the user',
schema: new OAT\Schema(
type: 'integer',
format: 'int32',
),
),
new OAT\Header(
header: 'x-ratelimit-remaining',
description: 'count of remaining calls per minute allowed by the user',
schema: new OAT\Schema(
type: 'integer',
format: 'int32',
),
),
],
content: new OAT\JsonContent(
properties: [
new OAT\Property(
property: 'message',
type: 'string',
example: 'Screw up from our side. Server will be right back...',
),
new OAT\Property(
property: 'data',
type: 'array',
items: new OAT\Items(),
example: [],
),
],
type: 'object',
),
),
],
deprecated: false,
)]
/**
* Trait HasAuthOpenApiDescriptors
*/
trait HasAuthOpenApiVersion2Descriptors
{
//
}
<?php
namespace App\Helpers\Traits\OpenApi;
use OpenApi\Attributes as OAT;
#[OAT\Info(
version: '1.0.0',
description: <<<'NOW'
[This](https://gitlab.com/zw-learning/laravel-farmstall-api) is a rebuild of
'[Designing APIs with Swagger and OpenAPI](https://www.manning.com/books/designing-apis-with-swagger-and-openapi)'s
1st API, the FarmStall API.
Their API was written in GO, so to add more flavor to it, here is a variation with
PHP/[Laravel](https://laravel.com/docs/10.x).
It was created by [Joshua S. Ponelat](https://github.com/ponelat) and
[Lukas L. Rosenstock](https://github.com/LukasRos),
their book was published by Manning Publications Co.
---
To authenticate, you first need to get a **CSRF**-Token/Cookie, via Laravel Sanctum.
This you will need to send as `X-XSRF-TOKEN` header afterwards,
until you have registered and authenticated yourself.
When that time arrives, you will be presented with a Bearer Token.
The Bearer Token will be what we need to authenticate against user-only routes.
NOW,
title: 'Laravel port of FarmStall API',
license: new OAT\License(
name: 'MIT',
url: 'https://spdx.org/licenses/MIT.html',
),
x: [
'logo' => [
'url' => 'https://via.placeholder.com/190x90.png?text=Laravel-FarmStall-API',
],
],
)]
#[OAT\Components(
securitySchemes: [
new OAT\SecurityScheme(
securityScheme: 'csrfAuthHeader',
type: 'apiKey',
name: 'X-XSRF-TOKEN',
in: 'header',
),
new OAT\SecurityScheme(
securityScheme: 'bearerAuthHeader',
type: 'http',
in: 'header',
bearerFormat: 'JWT',
scheme: 'bearer',
),
],
)]
#[OAT\Server(
// sadly here we cannot use env vars, it seems
url: 'https://api.farmstall.test:443',
description: 'Local Development Server',
variables: [
new OAT\ServerVariable(
serverVariable: 'schema',
default: 'https',
enum: ['https'],
),
],
)]
#[OAT\ExternalDocumentation(
description: 'Find out more about the OpenAPI v3.0.0 specification',
url: 'https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.0.md'
)]
/**
* Trait HasCoreOpenApiDescriptors
*/
trait HasCoreOpenApiDescriptors
{
//
}
<?php
namespace App\Helpers\Traits\OpenApi\Routes;
use OpenApi\Attributes as OAT;
#[OAT\Get(
path: '/',
operationId: 'index',
description: 'If consumers are not familiar with API versioning they need to be taught',
summary: 'Get hint for API versioning',
tags: ['api/v1', 'api/v2'],
responses: [
new OAT\Response(
response: 200,
description: 'successful operation',
headers: [
new OAT\Header(
header: 'x-ratelimit-limit',
description: 'calls per minute allowed by the user',
schema: new OAT\Schema(
type: 'integer',
format: 'int32',
),
),
new OAT\Header(
header: 'x-ratelimit-remaining',
description: 'count of remaining calls per minute allowed by the user',
schema: new OAT\Schema(
type: 'integer',
format: 'int32',
),
),
],
content: new OAT\JsonContent(
properties: [
new OAT\Property(
property: 'message',
type: 'string',
example: "Please add '/v1'(, '/v2', ...) to the URL path; '/v0/docs' for Swagger UI view",
),
new OAT\Property(
property: 'data',
type: 'array',
items: new OAT\Items(),
example: [],
),
],
type: 'object',
),
),
new OAT\Response(
response: 500,
description: 'Server Error',
headers: [
new OAT\Header(
header: 'x-ratelimit-limit',
description: 'calls per minute allowed by the user',
schema: new OAT\Schema(
type: 'integer',
format: 'int32',
),
),
new OAT\Header(
header: 'x-ratelimit-remaining',
description: 'count of remaining calls per minute allowed by the user',
schema: new OAT\Schema(
type: 'integer',
format: 'int32',
),
),
],
content: new OAT\JsonContent(
properties: [
new OAT\Property(
property: 'message',
type: 'string',
example: 'Screw up from our side. Server will be right back...',
),
new OAT\Property(
property: 'data',
type: 'array',
items: new OAT\Items(),
example: [],
),
],
type: 'object',
),
),
],
deprecated: false,
)]
#[OAT\Get(
path: '/v1',
operationId: 'v1-index',
description: 'Returns some meta information about the environment of API v1',
summary: 'Get API v1 environment information',
tags: ['api/v1'],
responses: [
new OAT\Response(
response: 200,
description: 'successful operation',
headers: [
new OAT\Header(
header: 'x-ratelimit-limit',
description: 'calls per minute allowed by the user',
schema: new OAT\Schema(
type: 'integer',
format: 'int32',
),
),
new OAT\Header(
header: 'x-ratelimit-remaining',
description: 'count of remaining calls per minute allowed by the user',
schema: new OAT\Schema(
type: 'integer',
format: 'int32',
),
),
],
content: new OAT\JsonContent(
properties: [
new OAT\Property(
property: 'message',
type: 'string',
example: 'OK',
),
new OAT\Property(
property: 'data',
properties: [
new OAT\Property(
property: 'arch',
type: 'string',
example: 'Laravel Framework',
),
new OAT\Property(
property: 'env',
type: 'string',
example: 'local',
),
new OAT\Property(
property: 'released_at',
type: 'date-time',
example: '2023-09-01',
),
],
type: 'object',
),
],
type: 'object',
),
),
new OAT\Response(
response: 500,
description: 'Server Error',
headers: [
new OAT\Header(
header: 'x-ratelimit-limit',
description: 'calls per minute allowed by the user',
schema: new OAT\Schema(
type: 'integer',
format: 'int32',
),
),
new OAT\Header(
header: 'x-ratelimit-remaining',
description: 'count of remaining calls per minute allowed by the user',
schema: new OAT\Schema(
type: 'integer',
format: 'int32',
),
),
],
content: new OAT\JsonContent(
properties: [
new OAT\Property(
property: 'message',
type: 'string',
example: 'Screw up from our side. Server will be right back...',
),
new OAT\Property(
property: 'data',
type: 'array',
items: new OAT\Items(),
example: [],
),
],
type: 'object',
),
),
],
deprecated: false,
)]
#[OAT\Get(
path: '/v1/healthz',
operationId: 'v1-health-index',
description: 'Returns some meta information about the environment of API v1',
summary: 'Get API v1 up & running check resolution',
tags: ['api/v1'],
responses: [
new OAT\Response(
response: 200,
description: 'successful operation',
headers: [
new OAT\Header(
header: 'x-ratelimit-limit',
description: 'calls per minute allowed by the user',
schema: new OAT\Schema(
type: 'integer',
format: 'int32',
),
),
new OAT\Header(
header: 'x-ratelimit-remaining',
description: 'count of remaining calls per minute allowed by the user',
schema: new OAT\Schema(
type: 'integer',
format: 'int32',
),
),
],
content: new OAT\JsonContent(
properties: [
new OAT\Property(
property: 'message',
type: 'string',
example: 'OK',
),
new OAT\Property(
property: 'data',
properties: [],
type: 'object',
example: [],
),
],
type: 'object',
),
),
new OAT\Response(
response: 500,
description: 'Server Error',
headers: [
new OAT\Header(
header: 'x-ratelimit-limit',
description: 'calls per minute allowed by the user',
schema: new OAT\Schema(
type: 'integer',
format: 'int32',
),
),
new OAT\Header(
header: 'x-ratelimit-remaining',
description: 'count of remaining calls per minute allowed by the user',
schema: new OAT\Schema(
type: 'integer',
format: 'int32',
),
),
],
content: new OAT\JsonContent(
properties: [
new OAT\Property(
property: 'message',
type: 'string',
example: 'Screw up from our side. Server will be right back...',
),
new OAT\Property(
property: 'data',
type: 'array',
items: new OAT\Items(),
example: [],
),
],
type: 'object',
),
),
],
deprecated: false,
)]
#[OAT\Get(
path: '/v2',
operationId: 'v2-index',
description: 'Returns some meta information about the environment of API v2',
summary: 'Get API v2 environment information',
tags: ['api/v2'],
responses: [
new OAT\Response(
response: 200,
description: 'successful operation',
headers: [
new OAT\Header(
header: 'x-ratelimit-limit',
description: 'calls per minute allowed by the user',
schema: new OAT\Schema(
type: 'integer',
format: 'int32',
),
),
new OAT\Header(
header: 'x-ratelimit-remaining',
description: 'count of remaining calls per minute allowed by the user',
schema: new OAT\Schema(
type: 'integer',
format: 'int32',
),
),
],
content: new OAT\JsonContent(
properties: [
new OAT\Property(
property: 'message',
type: 'string',
example: 'OK',
),
new OAT\Property(
property: 'data',
properties: [
new OAT\Property(
property: 'arch',
type: 'string',
example: 'Laravel Framework',
),
new OAT\Property(
property: 'env',
type: 'string',
example: 'local',
),
new OAT\Property(
property: 'released_at',
type: 'date-time',
example: '2023-09-01',
),
],
type: 'object',
),
],
type: 'object',
),
),
new OAT\Response(
response: 500,
description: 'Server Error',
headers: [
new OAT\Header(
header: 'x-ratelimit-limit',
description: 'calls per minute allowed by the user',
schema: new OAT\Schema(
type: 'integer',
format: 'int32',
),
),
new OAT\Header(
header: 'x-ratelimit-remaining',
description: 'count of remaining calls per minute allowed by the user',
schema: new OAT\Schema(
type: 'integer',
format: 'int32',
),
),
],
content: new OAT\JsonContent(
properties: [
new OAT\Property(
property: 'message',
type: 'string',
example: 'Screw up from our side. Server will be right back...',
),
new OAT\Property(
property: 'data',
type: 'array',
items: new OAT\Items(),
example: [],
),
],
type: 'object',
),
),
],
deprecated: false,
)]
#[OAT\Get(
path: '/v2/healthz',
operationId: 'v2-health-index',
description: 'Returns some meta information about the environment of API v2',
summary: 'Get API v2 up & running check resolution',
tags: ['api/v2'],
responses: [
new OAT\Response(
response: 200,
description: 'successful operation',
headers: [
new OAT\Header(
header: 'x-ratelimit-limit',
description: 'calls per minute allowed by the user',
schema: new OAT\Schema(
type: 'integer',
format: 'int32',
),
),
new OAT\Header(
header: 'x-ratelimit-remaining',
description: 'count of remaining calls per minute allowed by the user',
schema: new OAT\Schema(
type: 'integer',
format: 'int32',
),
),
],
content: new OAT\JsonContent(
properties: [
new OAT\Property(
property: 'message',
type: 'string',
example: 'OK',
),
new OAT\Property(
property: 'data',
properties: [],
type: 'object',
example: [],
),
],
type: 'object',
),
),
new OAT\Response(
response: 500,
description: 'Server Error',
headers: [
new OAT\Header(
header: 'x-ratelimit-limit',
description: 'calls per minute allowed by the user',
schema: new OAT\Schema(
type: 'integer',
format: 'int32',
),
),
new OAT\Header(
header: 'x-ratelimit-remaining',
description: 'count of remaining calls per minute allowed by the user',
schema: new OAT\Schema(
type: 'integer',
format: 'int32',
),
),
],
content: new OAT\JsonContent(
properties: [
new OAT\Property(
property: 'message',
type: 'string',
example: 'Screw up from our side. Server will be right back...',
),
new OAT\Property(
property: 'data',
type: 'array',
items: new OAT\Items(),
example: [],
),
],
type: 'object',
),
),
],
deprecated: false,
)]
/**
* Trait HasGeneralRoutesOpenApiDescriptors
*/
trait HasGeneralRoutesOpenApiDescriptors
{
//
}
<?php
namespace App\Helpers\Traits\OpenApi\Routes\Auth;
use OpenApi\Attributes as OAT;
#[OAT\Get(
path: '/sanctum/csrf-cookie',
operationId: 'auth-csrf-token',
description: <<<'NOW'
Without the CSRF token, which is provided by the Laravel (Sanctum) API,
you won't make many requests.
Next, you need to add the CSRF Token to your subsequent requests, before being really
logged into the application.
> Currently, it's not possible to use the CSRF Token / Cookie we get from the API directly,
> via Swagger UI.
>
> You **need** to _manually_ copy+paste the CSRF Token out of your Storage / Cookie Tab within
> your Browser's Dev Console.
>
> Beware that the Cookie's value is encoded.
>
> You need to change the `0%30` to `0=`, **at the end of it**, when you use the Token via
> Swagger UI `csrfAuthHeader` authorization.<br>
> For this, see **Authorize** button.
NOW,
summary: 'Get your much needed CSRF token',
tags: ['auth'],
responses: [
new OAT\Response(
response: 204,
description: 'successful csrf token retrieval',
headers: [
new OAT\Header(
header: 'Set-Cookie',
description: 'Attach CSRF Token to Headers',
schema: new OAT\Schema(
type: 'string',
example: <<<'NOW'
eyJpdiI6ImNqdW1MbE5teHhvWUgxekZjZFFqcEE9PSIsInZhbHVlIjoiZWx5cFVqbVNWTjJINFY1ekVDdEdja2w5UnBBZzg
yMU85Nkw5RGtNTDdrdUlkRHNhclF3MXFjL3pOU0VGcVl4Y2ZtM3V3Rlp5TjdtRnNlZCtSMWtjUU1Vd2FGZlVCRmxkVVE5Wj
Vqdm40WnV0SmdxZ3BUdUE3dUlBOGhnQUJuZG8iLCJtYWMiOiI2OWNmMjE5NzFmZmJmMDFkNzlhZmY1Njk1N2M4M2Y1YTRlZ
WQ4ZWM5OWZmNjhiMGJmMGRjNTg1NWE0MTY3NjIyIiwidGFnIjoiIn0=
NOW,
)
),
],
content: new OAT\MediaType(
mediaType: 'application/json',
),
),
new OAT\Response(
response: 500,
description: 'Server Error',
headers: [
new OAT\Header(
header: 'x-ratelimit-limit',
description: 'calls per minute allowed by the user',
schema: new OAT\Schema(
type: 'integer',
format: 'int32',
),
),
new OAT\Header(
header: 'x-ratelimit-remaining',
description: 'count of remaining calls per minute allowed by the user',
schema: new OAT\Schema(
type: 'integer',
format: 'int32',
),
),
],
content: new OAT\JsonContent(
properties: [
new OAT\Property(
property: 'message',
type: 'string',
example: 'Screw up from our side. Server will be right back...',
),
new OAT\Property(
property: 'data',
type: 'array',
items: new OAT\Items(),
example: [],
),
],
type: 'object',
),
),
],
deprecated: false,
)]
/**
* Trait HasSanctumOpenApiDescriptors
*/
trait HasSanctumOpenApiDescriptors
{
//
}
<?php
namespace App\Helpers\Traits\OpenApi;
use OpenApi\Attributes as OAT;
#[OAT\Tag(
name: 'auth',
description: <<<'NOW'
For unauthenticated POST requests to work, your first need to
get your CSRF-Token from Laravel Sanctum.
Every other/next step can be found within each of the api/vXY sections.
NOW,
)]
#[OAT\Tag(
name: 'api/v1',
description: 'All requests related to API V1',
)]
#[OAT\Tag(
name: 'api/v2',
description: 'All requests related to API V2',
)]
/**
* Trait HasTagOpenApiDescriptors
*/
trait HasTagOpenApiDescriptors
{
//
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment