1
0
mirror of https://github.com/mainflux/mainflux.git synced 2025-04-24 13:48:49 +08:00

NOISSUE - Add Auth API Documentation (#1929)

* feat(api): aligns things api documentation

This commit addresses the following changes:
- Removes bulk provision of channels endpoint `/channels/bulk` to the OpenAPI specification file `api/openapi/things.yml`.
- Adds connect and disconnect API documentation for things

Note: No implementation changes have been made in this commit.
Signed-off-by: Rodney Osodo <28790446+rodneyosodo@users.noreply.github.com>

* Remove policies

Signed-off-by: Rodney Osodo <28790446+rodneyosodo@users.noreply.github.com>

* feat(api): update group members endpoint

This commit updates the group members endpoint in the users API. Instead of having a separate endpoint for /{groupID}/members, we can now use /{groupID}/users. This change simplifies the API structure and improves consistency.

Signed-off-by: Rodney Osodo <28790446+rodneyosodo@users.noreply.github.com>

* feat(api): add OpenAPI specification for Auth Service

This commit adds the OpenAPI 3.0 specification for the Auth Service. The `auth.yml` file contains the definition of the HTTP API for managing platform users. This specification will help in improving the API by allowing changes to be made to the definition.

Changes:
- Added `auth.yml` file with OpenAPI 3.0 specification
- Defined the title and description of the Auth Service in the `info` section

Note: This commit only includes the addition of the OpenAPI specification file and does not include any implementation changes.
Signed-off-by: Rodney Osodo <28790446+rodneyosodo@users.noreply.github.com>

* feat(auth): add new endpoint for deleting policies

- Updated the `MakeHandler` function in `auth/api/http/policies/transport.go` to add a new endpoint for deleting policies.
- Replaced the `mux.Put` method with `mux.Post` to match the HTTP verb for deleting policies.
- The new endpoint is now `/policies/delete`.

Signed-off-by: Rodney Osodo <28790446+rodneyosodo@users.noreply.github.com>

---------

Signed-off-by: Rodney Osodo <28790446+rodneyosodo@users.noreply.github.com>
Co-authored-by: Drasko DRASKOVIC <drasko.draskovic@gmail.com>
This commit is contained in:
b1ackd0t 2023-10-16 14:43:01 +03:00 committed by GitHub
parent ea851cf12c
commit 09236e87a7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 1002 additions and 816 deletions

312
api/openapi/auth.yml Normal file
View File

@ -0,0 +1,312 @@
openapi: 3.0.3
info:
title: Mainflux Auth Service
description: |
This is the Auth Server based on the OpenAPI 3.0 specification. It is the HTTP API for managing platform users. You can now help us improve the API whether it's by making changes to the definition itself or to the code.
Some useful links:
- [The Mainflux repository](https://github.com/mainflux/mainflux)
contact:
email: info@mainflux.com
license:
name: Apache 2.0
url: https://github.com/mainflux/mainflux/blob/master/LICENSE
version: 0.14.0
servers:
- url: http://localhost:8180
- url: https://localhost:8180
tags:
- name: Auth
description: Everything about your Authentication and Authorization.
externalDocs:
description: Find out more about auth
url: http://docs.mainflux.io/
- name: Keys
description: Everything about your Keys.
externalDocs:
description: Find out more about keys
url: http://docs.mainflux.io/
paths:
/keys:
post:
tags:
- Keys
summary: Issue API key
description: |
Generates a new API key. Thew new API key will
be uniquely identified by its ID.
requestBody:
$ref: "#/components/requestBodies/KeyRequest"
responses:
"201":
description: Issued new key.
"400":
description: Failed due to malformed JSON.
"409":
description: Failed due to using already existing ID.
"415":
description: Missing or invalid content type.
"500":
$ref: "#/components/responses/ServiceError"
/keys/{keyID}:
get:
summary: Gets API key details.
description: |
Gets API key details for the given key.
tags:
- Keys
parameters:
- $ref: "#/components/parameters/ApiKeyId"
responses:
"200":
$ref: "#/components/responses/KeyRes"
"400":
description: Failed due to malformed query parameters.
"401":
description: Missing or invalid access token provided.
"500":
$ref: "#/components/responses/ServiceError"
delete:
summary: Revoke API key
description: |
Revoke API key identified by the given ID.
tags:
- Keys
parameters:
- $ref: "#/components/parameters/ApiKeyId"
responses:
"204":
description: Key revoked.
"401":
description: Missing or invalid access token provided.
"500":
$ref: "#/components/responses/ServiceError"
/policies:
post:
summary: Creates new policies.
description: |
Creates new policies. Only admin can use this endpoint. Therefore, you need an authentication token for the admin.
Also, only policies defined on the system are allowed to add. For more details, please see the docs for Authorization.
tags:
- Auth
requestBody:
$ref: "#/components/requestBodies/PoliciesReq"
responses:
"201":
description: Policies created.
"400":
description: Failed due to malformed JSON.
"401":
description: Missing or invalid access token provided.
"403":
description: Unauthorized access token provided.
"409":
description: Failed due to using an existing email address.
"415":
description: Missing or invalid content type.
"500":
$ref: "#/components/responses/ServiceError"
/policies/delete:
post:
summary: Deletes policies.
description: |
Deletes policies. Only admin can use this endpoint. Therefore, you need an authentication token for the admin.
Also, only policies defined on the system are allowed to delete. For more details, please see the docs for Authorization.
tags:
- Auth
requestBody:
$ref: "#/components/requestBodies/PoliciesReq"
responses:
"204":
description: Policies deleted.
"400":
description: Failed due to malformed JSON.
"409":
description: Failed due to using an existing email address.
"415":
description: Missing or invalid content type.
"500":
$ref: "#/components/responses/ServiceError"
/health:
get:
summary: Retrieves service health check info.
tags:
- health
responses:
"200":
$ref: "#/components/responses/HealthRes"
"500":
$ref: "#/components/responses/ServiceError"
components:
schemas:
Key:
type: object
properties:
id:
type: string
format: uuid
example: "c5747f2f-2a7c-4fe1-b41a-51a5ae290945"
description: API key unique identifier
issuer_id:
type: string
format: uuid
example: "9118de62-c680-46b7-ad0a-21748a52833a"
description: In ID of the entity that issued the token.
type:
type: integer
example: 0
description: API key type. Keys of different type are processed differently.
subject:
type: string
format: string
example: "test@example.com"
description: User's email or service identifier of API key subject.
issued_at:
type: string
format: date-time
example: "2019-11-26 13:31:52"
description: Time when the key is generated.
expires_at:
type: string
format: date-time
example: "2019-11-26 13:31:52"
description: Time when the Key expires. If this field is missing,
that means that Key is valid indefinitely.
PoliciesReqSchema:
type: object
properties:
object:
type: string
description: |
Specifies an object field for the field.
Object indicates application objects such as ThingID.
subjects:
type: array
minItems: 1
uniqueItems: true
items:
type: string
policies:
type: array
minItems: 1
uniqueItems: true
items:
type: string
parameters:
ApiKeyId:
name: keyID
description: API Key ID.
in: path
schema:
type: string
format: uuid
required: true
Limit:
name: limit
description: Size of the subset to retrieve.
in: query
schema:
type: integer
default: 10
maximum: 100
minimum: 1
required: false
Offset:
name: offset
description: Number of items to skip during retrieval.
in: query
schema:
type: integer
default: 0
minimum: 0
required: false
Metadata:
name: metadata
description: Metadata filter. Filtering is performed matching the parameter with metadata on top level. Parameter is json.
in: query
required: false
schema:
type: object
additionalProperties: {}
Type:
name: type
description: The type of the API Key.
in: query
schema:
type: integer
default: 0
minimum: 0
required: false
Subject:
name: subject
description: The subject of an API Key
in: query
schema:
type: string
required: false
requestBodies:
KeyRequest:
description: JSON-formatted document describing key request.
required: true
content:
application/json:
schema:
type: object
properties:
type:
type: integer
example: 0
description: API key type. Keys of different type are processed differently.
duration:
type: number
format: integer
example: 23456
description: Number of seconds issued token is valid for.
PoliciesReq:
description: JSON-formatted document describing adding policies request.
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/PoliciesReqSchema"
responses:
ServiceError:
description: Unexpected server-side error occurred.
KeyRes:
description: Data retrieved.
content:
application/json:
schema:
$ref: "#/components/schemas/Key"
HealthRes:
description: Service Health Check.
content:
application/json:
schema:
$ref: "./schemas/HealthInfo.yml"
securitySchemes:
bearerAuth:
type: http
scheme: bearer
bearerFormat: JWT
description: |
* Users access: "Authorization: Bearer <user_token>"
security:
- bearerAuth: []

View File

@ -437,30 +437,6 @@ paths:
"500":
$ref: "#/components/responses/ServiceError"
/channels/bulk:
post:
summary: Bulk provisions new channels
description: |
Adds new channels to the list of channels owned by user identified using
the provided access token.
tags:
- Channels
requestBody:
$ref: "#/components/requestBodies/ChannelsCreateReq"
responses:
"201":
description: Channels registered.
"400":
description: Failed due to malformed JSON.
"401":
description: Missing or invalid access token provided.
"409":
description: Entity already exist.
"415":
description: Missing or invalid content type.
"500":
$ref: "#/components/responses/ServiceError"
/channels/{chanID}:
get:
summary: Retrieves channel info.
@ -854,48 +830,51 @@ paths:
"500":
$ref: "#/components/responses/ServiceError"
/channels/{chanID}/access:
/channels/{chanID}/things/{thingID}/connect:
post:
summary: Checks if thing has access to a channel.
summary: Connects a thing to a channel
description: |
Checks if a thing with a specified key has an access to a specified
channel and if it has, it returns that things id.
Connects a specific thing to a channel that is identifier by the channel ID.
tags:
- Policies
parameters:
- $ref: "#/components/parameters/chanID"
requestBody:
$ref: "#/components/requestBodies/AccessByIDReq"
- $ref: "#/components/parameters/ThingID"
responses:
"200":
$ref: "#/components/responses/AccessGrantedRes"
description: Thing connected.
"400":
description: Failed due to malformed thing's ID.
"401":
description: |
Thing and channel are not connected, or thing with specified key doesn't
exist.
"415":
description: Missing or invalid content type.
description: Missing or invalid access token provided.
"404":
description: A non-existent entity request.
"422":
description: Database can't process request.
"500":
$ref: "#/components/responses/ServiceError"
/identify:
/channels/{chanID}/things/{thingID}/disconnect:
post:
summary: Returns thing ID of the give thing secret.
summary: Disconnects a thing to a channel
description: |
Returns thing ID of the given thing secret, hence identifying the thing.
Disconnects a specific thing to a channel that is identifier by the channel ID.
tags:
- Policies
requestBody:
$ref: "#/components/requestBodies/IdentityReq"
parameters:
- $ref: "#/components/parameters/chanID"
- $ref: "#/components/parameters/ThingID"
responses:
"200":
$ref: "#/components/responses/IdentityRes"
description: Thing connected.
"400":
description: Failed due to malformed thing's ID.
"401":
description: |
Thing and channel are not connected, or thing with specified key doesn't
exist.
"415":
description: Missing or invalid content type.
description: Missing or invalid access token provided.
"404":
description: A non-existent entity request.
"422":
description: Database can't process request.
"500":
$ref: "#/components/responses/ServiceError"
@ -1431,17 +1410,6 @@ components:
- metadata
- description
Identity:
type: object
properties:
id:
type: string
format: uuid
description: Thing unique identifier. This can be either
provided by the user or left blank. If the user provides a UUID,
it would be validated. If there is not one provided then
the service will generate one in UUID format.
ConnectionReqSchema:
type: object
properties:
@ -1797,16 +1765,6 @@ components:
items:
$ref: "#/components/schemas/ThingReqObj"
ChannelsCreateReq:
description: JSON-formatted document describing the new channels.
required: true
content:
application/json:
schema:
type: array
items:
$ref: "#/components/schemas/ChannelReqObj"
ConnCreateReq:
description: JSON-formatted document describing the new connection.
required: true
@ -1823,42 +1781,6 @@ components:
schema:
$ref: "#/components/schemas/DisConnectionReqSchema"
IdentityReq:
description: JSON-formatted document that contains thing secret.
required: true
content:
application/json:
schema:
type: object
properties:
secret:
type: string
format: uuid
description: Thing Secret by which thing is uniquely identified.
AccessByIDReq:
description: JSON-formatted document that contains subject object and action.
required: true
content:
application/json:
schema:
type: object
properties:
subject:
type: string
format: uuid
description: Thing ID by which thing is uniquely identified.
action:
type: string
format: string
example: "publish"
description: Action you want to check access against.
entity_type:
type: string
format: string
example: group
description: Entity Type.
responses:
ThingCreateRes:
description: Registered new thing.
@ -1931,21 +1853,6 @@ components:
DisconnRes:
description: Things disconnected.
AccessGrantedRes:
description: |
Thing has access to the specified channel and the thing ID is returned.
content:
application/json:
schema:
$ref: "#/components/schemas/Identity"
IdentityRes:
description: Thing ID returned.
content:
application/json:
schema:
$ref: "#/components/schemas/Identity"
HealthRes:
description: Service Health Check.
content:

File diff suppressed because it is too large Load Diff

View File

@ -33,7 +33,7 @@ func MakeHandler(svc auth.Service, mux *bone.Mux, logger logger.Logger) *bone.Mu
opts...,
))
mux.Put("/policies", kithttp.NewServer(
mux.Post("/policies/delete", kithttp.NewServer(
(deletePoliciesEndpoint(svc)),
decodePoliciesRequest,
encodeResponse,
@ -43,7 +43,7 @@ func MakeHandler(svc auth.Service, mux *bone.Mux, logger logger.Logger) *bone.Mu
return mux
}
func decodePoliciesRequest(ctx context.Context, r *http.Request) (interface{}, error) {
func decodePoliciesRequest(_ context.Context, r *http.Request) (interface{}, error) {
if !strings.Contains(r.Header.Get("Content-Type"), contentType) {
return nil, errors.ErrUnsupportedContentType
}

View File

@ -83,32 +83,32 @@ func groupsHandler(svc groups.Service, r *chi.Mux, logger logger.Logger) http.Ha
opts...,
), "disable_group").ServeHTTP)
// Instead of this endpoint /{groupID}/members separately, we can simply use /{groupID}/users
// Instead of this endpoint /{groupID}/members/assign separately, we can simply use /{groupID}/users
// because this group is intended exclusively for users. No other entity could not be added
r.Post("/{groupID}/members", otelhttp.NewHandler(kithttp.NewServer(
r.Post("/{groupID}/members/assign", otelhttp.NewHandler(kithttp.NewServer(
gapi.AssignMembersEndpoint(svc, "", "users"),
gapi.DecodeAssignMembersRequest,
api.EncodeResponse,
opts...,
), "assign_members").ServeHTTP)
// Instead of maintaining this endpoint /{groupID}/members separately, we can simply use /{groupID}/users
// Instead of maintaining this endpoint /{groupID}/members/unassign separately, we can simply use /{groupID}/users
// because this group is intended exclusively for users. No other entity could not be added
r.Delete("/{groupID}/members", otelhttp.NewHandler(kithttp.NewServer(
r.Post("/{groupID}/members/unassign", otelhttp.NewHandler(kithttp.NewServer(
gapi.UnassignMembersEndpoint(svc, "", "users"),
gapi.DecodeUnassignMembersRequest,
api.EncodeResponse,
opts...,
), "unassign_members").ServeHTTP)
r.Post("/{groupID}/users", otelhttp.NewHandler(kithttp.NewServer(
r.Post("/{groupID}/users/assign", otelhttp.NewHandler(kithttp.NewServer(
assignUsersEndpoint(svc),
decodeAssignUsersRequest,
api.EncodeResponse,
opts...,
), "assign_users").ServeHTTP)
r.Delete("/{groupID}/users", otelhttp.NewHandler(kithttp.NewServer(
r.Post("/{groupID}/users/unassign", otelhttp.NewHandler(kithttp.NewServer(
unassignUsersEndpoint(svc),
decodeUnassignUsersRequest,
api.EncodeResponse,