diff --git a/docs/openapi.json b/docs/openapi.json new file mode 100644 index 00000000..c5570297 --- /dev/null +++ b/docs/openapi.json @@ -0,0 +1,382 @@ +{ + "openapi": "3.0.0", + "info": { + "version": "0.1.0", + "title": "mCaptcha/guard" + }, + "servers": [ + { + "url": "/" + } + ], + "paths": { + "/api//signup": { + "post": { + "summary": "Registration endpoint", + "operationId": "registerUser", + "tags": ["user"], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RegisterUser" + } + } + } + }, + "responses": { + "200": { + "description": "Successful registration" + }, + "400": { + "description": "Bad request: username contains profainity/blacklisted words or email not acceptable or password too long/short or duplicate username/password", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + } + } + }, + "/api//signin": { + "post": { + "summary": "Login endpoint", + "operationId": "loginUser", + "tags": ["user", "authentication"], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/LoginUser" + } + } + } + }, + "responses": { + "200": { + "description": "Successful authentication" + }, + "401": { + "description": "authentication failed, wrong password", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "username not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + } + } + }, + "/api//signout": { + "post": { + "security": [ + { + "cookieAuth": [] + } + ], + "summary": "Signout endpoint", + "operationId": "signoutUser", + "tags": ["user", "authentication"], + "responses": { + "200": { + "description": "OK" + } + } + } + }, + "/api//account/delete": { + "post": { + "security": [ + { + "cookieAuth": [] + } + ], + "summary": "Delete user account", + "operationId": "deleteUserAccount", + "tags": ["user"], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DeleteUser" + } + } + } + }, + "responses": { + "200": { + "description": "OK" + }, + "401": { + "description": "(cookie)authentication required or wrong password", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "username not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + } + } + }, + "/api//account/username/exists": { + "post": { + "summary": "Check if username exists", + "operationId": "usernameExists", + "tags": ["user"], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UserDetailCheck" + } + } + } + }, + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UserDetailCheckRes" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + } + } + }, + "/api//account/email/exists": { + "post": { + "summary": "Check if email exists", + "operationId": "emailExists", + "tags": ["user"], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UserDetailCheck" + } + } + } + }, + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UserDetailCheckRes" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + } + } + }, + "/api//meta/build": { + "post": { + "summary": "Check if email exists", + "operationId": "emailExists", + "tags": ["user"], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/BuildDetails" + } + } + } + } + } + } + }, + "components": { + "schemas": { + "RegisterUser": { + "type": "object", + "required": ["username", "password", "email"], + "properties": { + "username": { + "type": "string" + }, + "email": { + "type": "string" + }, + "password": { + "type": "string", + "format": "password" + } + } + }, + "LoginUser": { + "type": "object", + "required": ["username", "password"], + "properties": { + "username": { + "type": "string" + }, + "password": { + "type": "string", + "format": "password" + } + } + }, + "DeleteUser": { + "type": "object", + "required": ["password"], + "properties": { + "password": { + "type": "string", + "format": "password" + } + } + }, + "Error": { + "type": "object", + "required": ["error"], + "properties": { + "error": { + "type": "string" + } + } + }, + "User": { + "type": "object", + "required": ["id", "name"], + "properties": { + "id": { + "type": "integer", + "format": "int64" + }, + "name": { + "type": "string" + } + } + }, + "UserDetailCheck": { + "type": "object", + "required": ["val"], + "properties": { + "val": { + "type": "string" + } + } + }, + "UserDetailCheckRes": { + "type": "object", + "required": ["exists"], + "properties": { + "val": { + "type": "boolean" + } + } + } + }, + "BuildDetails": { + "type": "object", + "required": ["version", "git_commit_hash"], + "properties": { + "version": { + "type": "string" + }, + "git_commit_hash": { + "type": "string" + } + } + } + }, + + "securitySchemes": { + "cookieAuth": { + "type": "apiKey", + "in": "cookie", + "name": "Authorization" + } + } + } +} diff --git a/docs/swagger.json b/docs/swagger.json index 991e288c..474d0972 100644 --- a/docs/swagger.json +++ b/docs/swagger.json @@ -1,382 +1,410 @@ { - "openapi": "3.0.0", - "info": { - "version": "0.1.0", - "title": "mCaptcha/guard" - }, - "servers": [ - { - "url": "/" + "openapi": "3.0.0", + "info": { + "version": "0.1.0", + "title": "mCaptcha/guard" + }, + "servers": [ + { + "url": "/" + } + ], + "paths": { + "/api/v1/signup": { + "post": { + "summary": "Registration endpoint", + "operationId": "registerUser", + "tags": ["user"], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RegisterUser" + } + } + } + }, + "responses": { + "200": { + "description": "Successful registration" + }, + "400": { + "description": "Bad request: username contains profainity/blacklisted words or email not acceptable or password too long/short or duplicate username/password", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + } } - ], - "paths": { - "/api/v1/signup": { - "post": { - "summary": "Registration endpoint", - "operationId": "registerUser", - "tags": [ - "user" - ], - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/RegisterUser" - } - } - } - }, - "responses": { - "200": { - "description": "Successful registration" - }, - "400": { - "description": "Bad request: username contains profainity/blacklisted words or email not acceptable or password too long/short or duplicate username/password", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Error" - } - } - } - }, - "500": { - "description": "Internal server error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Error" - } - } - } - } + }, + "/api/v1/signin": { + "post": { + "summary": "Login endpoint", + "operationId": "loginUser", + "tags": ["user", "authentication"], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/LoginUser" + } } - } - }, - "/api/v1/signin": { - "post": { - "summary": "Login endpoint", - "operationId": "loginUser", - "tags": [ - "user", - "authentication" - ], - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LoginUser" - } - } - } - }, - "responses": { - "200": { - "description": "Successful authentication" - }, - "401": { - "description": "authentication failed, wrong password", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Error" - } - } - } - }, - "404": { - "description": "username not found", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Error" - } - } - } - }, - "500": { - "description": "Internal server error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Error" - } - } - } - } + } + }, + "responses": { + "200": { + "description": "Successful authentication" + }, + "401": { + "description": "authentication failed, wrong password", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } } - } - }, - "/api/v1/signout": { - "post": { - "security": [ - { - "cookieAuth": [] - } - ], - "summary": "Signout endpoint", - "operationId": "signoutUser", - "tags": [ - "user", - "authentication" - ], - "responses": { - "200": { - "description": "OK" - } + }, + "404": { + "description": "username not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } } - } - }, - "/api/v1/account/delete": { - "post": { - "security": [ - { - "cookieAuth": [] - } - ], - "summary": "Delete user account", - "operationId": "deleteUserAccount", - "tags": [ - "user" - ], - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/DeleteUser" - } - } - } - }, - "responses": { - "200": { - "description": "OK" - }, - "401": { - "description": "(cookie)authentication required or wrong password", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Error" - } - } - } - }, - "404": { - "description": "username not found", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Error" - } - } - } - }, - "500": { - "description": "Internal server error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Error" - } - } - } - } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } } - } - }, - "/api/v1/account/username/exists": { - "post": { - "summary": "Check if username exists", - "operationId": "usernameExists", - "tags": [ - "user" - ], - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/UserDetailCheck" - } - } - } - }, - "responses": { - "200": { - "description": "OK", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/UserDetailCheckRes" - } - } - } - }, - "500": { - "description": "Internal server error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Error" - } - } - } - } - } - } - }, - "/api/v1/account/email/exists": { - "post": { - "summary": "Check if email exists", - "operationId": "emailExists", - "tags": [ - "user" - ], - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/UserDetailCheck" - } - } - } - }, - "responses": { - "200": { - "description": "OK", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/UserDetailCheckRes" - } - } - } - }, - "500": { - "description": "Internal server error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Error" - } - } - } - } - } - } + } + } } - }, - "components": { - "schemas": { - "RegisterUser": { - "type": "object", - "required": [ - "username", - "password", - "email" - ], - "properties": { - "username": { - "type": "string" - }, - "email": { - "type": "string" - }, - "password": { - "type": "string", - "format": "password" - } - } - }, - "LoginUser": { - "type": "object", - "required": [ - "username", - "password" - ], - "properties": { - "username": { - "type": "string" - }, - "password": { - "type": "string", - "format": "password" - } - } - }, - "DeleteUser": { - "type": "object", - "required": [ - "password" - ], - "properties": { - "password": { - "type": "string", - "format": "password" - } - } - }, - "Error": { - "type": "object", - "required": [ - "error" - ], - "properties": { - "error": { - "type": "string" - } - } - }, - "User": { - "type": "object", - "required": [ - "id", - "name" - ], - "properties": { - "id": { - "type": "integer", - "format": "int64" - }, - "name": { - "type": "string" - } - } - }, - "UserDetailCheck": { - "type": "object", - "required": [ - "val" - ], - "properties": { - "val": { - "type": "string" - } - } - }, - "UserDetailCheckRes": { - "type": "object", - "required": [ - "exists" - ], - "properties": { - "val": { - "type": "boolean" - } - } - } - }, - "securitySchemes": { - "cookieAuth": { - "type": "apiKey", - "in": "cookie", - "name": "Authorization" - } + }, + "/api/v1/signout": { + "post": { + "security": [ + { + "cookieAuth": [] + } + ], + "summary": "Signout endpoint", + "operationId": "signoutUser", + "tags": ["user", "authentication"], + "responses": { + "200": { + "description": "OK" + } + } } - } + }, + "/api/v1/account/delete": { + "post": { + "security": [ + { + "cookieAuth": [] + } + ], + "summary": "Delete user account", + "operationId": "deleteUserAccount", + "tags": ["user"], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DeleteUser" + } + } + } + }, + "responses": { + "200": { + "description": "OK" + }, + "401": { + "description": "(cookie)authentication required or wrong password", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "404": { + "description": "username not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + } + } + }, + "/api/v1/account/username/exists": { + "post": { + "summary": "Check if username exists", + "operationId": "usernameExists", + "tags": ["user"], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UserDetailCheck" + } + } + } + }, + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UserDetailCheckRes" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + } + } + }, + "/api/v1/account/email/exists": { + "post": { + "summary": "Check if email exists", + "operationId": "emailExists", + "tags": ["user"], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UserDetailCheck" + } + } + } + }, + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UserDetailCheckRes" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + } + } + }, + "/api/v1/meta/health": { + "get": { + "summary": "Health check", + "operationId": "healthCheck", + "tags": ["meta","health"], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Health" + } + } + } + } + } + } + }, + + "/api/v1/meta/build": { + "get": { + "summary": "Get server binary build details", + "operationId": "buildDetails", + "tags": ["meta", "build"], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/BuildDetails" + } + } + } + } + } + } + } + }, + "components": { + "schemas": { + "RegisterUser": { + "type": "object", + "required": ["username", "password", "email"], + "properties": { + "username": { + "type": "string" + }, + "email": { + "type": "string" + }, + "password": { + "type": "string", + "format": "password" + } + } + }, + "LoginUser": { + "type": "object", + "required": ["username", "password"], + "properties": { + "username": { + "type": "string" + }, + "password": { + "type": "string", + "format": "password" + } + } + }, + "DeleteUser": { + "type": "object", + "required": ["password"], + "properties": { + "password": { + "type": "string", + "format": "password" + } + } + }, + "Error": { + "type": "object", + "required": ["error"], + "properties": { + "error": { + "type": "string" + } + } + }, + "User": { + "type": "object", + "required": ["id", "name"], + "properties": { + "id": { + "type": "integer", + "format": "int64" + }, + "name": { + "type": "string" + } + } + }, + "UserDetailCheck": { + "type": "object", + "required": ["val"], + "properties": { + "val": { + "type": "string" + } + } + }, + "Health": { + "type": "object", + "required": ["db"], + "properties": { + "db": { + "type": "boolean" + } + } + }, + "UserDetailCheckRes": { + "type": "object", + "required": ["exists"], + "properties": { + "val": { + "type": "boolean" + } + } + }, + "BuildDetails": { + "type": "object", + "required": ["version", "git_commit_hash"], + "properties": { + "version": { + "type": "string" + }, + "git_commit_hash": { + "type": "string" + } + } + } + }, + "securitySchemes": { + "cookieAuth": { + "type": "apiKey", + "in": "cookie", + "name": "Authorization" + } + } + } } diff --git a/mCaptcha-guard.postman_collection.json b/mCaptcha-guard.postman_collection.json new file mode 100644 index 00000000..5257a5c3 --- /dev/null +++ b/mCaptcha-guard.postman_collection.json @@ -0,0 +1,817 @@ +{ + "info": { + "_postman_id": "75a16c22-17aa-43ca-8906-0cc33844f77e", + "name": "mCaptcha/guard", + "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json" + }, + "item": [ + { + "name": "api/v1", + "item": [ + { + "name": "account", + "item": [ + { + "name": "Delete user account", + "request": { + "auth": { + "type": "apikey", + "apikey": [ + { + "key": "key", + "value": "Authorization", + "type": "string" + }, + { + "key": "value", + "value": true, + "type": "boolean" + }, + { + "key": "in", + "value": "header", + "type": "string" + } + ] + }, + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"password\": \"dolor aliquip laboris id\"\n}" + }, + "url": { + "raw": "{{baseUrl}}/api/v1/account/delete", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "api", + "v1", + "account", + "delete" + ] + } + }, + "response": [ + { + "name": "OK", + "originalRequest": { + "method": "POST", + "header": [ + { + "description": { + "content": "Added as a part of security scheme: apikey", + "type": "text/plain" + }, + "key": "Authorization", + "value": "" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"password\": \"dolor aliquip laboris id\"\n}" + }, + "url": { + "raw": "{{baseUrl}}/api/v1/account/delete", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "api", + "v1", + "account", + "delete" + ] + } + }, + "status": "OK", + "code": 200, + "_postman_previewlanguage": "text", + "header": [ + { + "key": "Content-Type", + "value": "text/plain" + } + ], + "cookie": [], + "body": "" + }, + { + "name": "(cookie)authentication required or wrong password", + "originalRequest": { + "method": "POST", + "header": [ + { + "description": { + "content": "Added as a part of security scheme: apikey", + "type": "text/plain" + }, + "key": "Authorization", + "value": "" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"password\": \"dolor aliquip laboris id\"\n}" + }, + "url": { + "raw": "{{baseUrl}}/api/v1/account/delete", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "api", + "v1", + "account", + "delete" + ] + } + }, + "status": "Unauthorized", + "code": 401, + "_postman_previewlanguage": "json", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + } + ], + "cookie": [], + "body": "{\n \"error\": \"elit enim fugiat\"\n}" + }, + { + "name": "username not found", + "originalRequest": { + "method": "POST", + "header": [ + { + "description": { + "content": "Added as a part of security scheme: apikey", + "type": "text/plain" + }, + "key": "Authorization", + "value": "" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"password\": \"dolor aliquip laboris id\"\n}" + }, + "url": { + "raw": "{{baseUrl}}/api/v1/account/delete", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "api", + "v1", + "account", + "delete" + ] + } + }, + "status": "Not Found", + "code": 404, + "_postman_previewlanguage": "json", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + } + ], + "cookie": [], + "body": "{\n \"error\": \"elit enim fugiat\"\n}" + }, + { + "name": "Internal server error", + "originalRequest": { + "method": "POST", + "header": [ + { + "description": { + "content": "Added as a part of security scheme: apikey", + "type": "text/plain" + }, + "key": "Authorization", + "value": "" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"password\": \"dolor aliquip laboris id\"\n}" + }, + "url": { + "raw": "{{baseUrl}}/api/v1/account/delete", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "api", + "v1", + "account", + "delete" + ] + } + }, + "status": "Internal Server Error", + "code": 500, + "_postman_previewlanguage": "json", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + } + ], + "cookie": [], + "body": "{\n \"error\": \"elit enim fugiat\"\n}" + } + ] + }, + { + "name": "Check if username exists", + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"val\": \"eiusmod irure s\"\n}" + }, + "url": { + "raw": "{{baseUrl}}/api/v1/account/username/exists", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "api", + "v1", + "account", + "username", + "exists" + ] + } + }, + "response": [ + { + "name": "OK", + "originalRequest": { + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\n \"val\": \"eiusmod irure s\"\n}" + }, + "url": { + "raw": "{{baseUrl}}/api/v1/account/username/exists", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "api", + "v1", + "account", + "username", + "exists" + ] + } + }, + "status": "OK", + "code": 200, + "_postman_previewlanguage": "json", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + } + ], + "cookie": [], + "body": "{\n \"val\": false\n}" + }, + { + "name": "Internal server error", + "originalRequest": { + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\n \"val\": \"eiusmod irure s\"\n}" + }, + "url": { + "raw": "{{baseUrl}}/api/v1/account/username/exists", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "api", + "v1", + "account", + "username", + "exists" + ] + } + }, + "status": "Internal Server Error", + "code": 500, + "_postman_previewlanguage": "json", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + } + ], + "cookie": [], + "body": "{\n \"error\": \"elit enim fugiat\"\n}" + } + ] + }, + { + "name": "Check if email exists", + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"val\": \"eiusmod irure s\"\n}" + }, + "url": { + "raw": "{{baseUrl}}/api/v1/account/email/exists", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "api", + "v1", + "account", + "email", + "exists" + ] + } + }, + "response": [ + { + "name": "OK", + "originalRequest": { + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\n \"val\": \"eiusmod irure s\"\n}" + }, + "url": { + "raw": "{{baseUrl}}/api/v1/account/email/exists", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "api", + "v1", + "account", + "email", + "exists" + ] + } + }, + "status": "OK", + "code": 200, + "_postman_previewlanguage": "json", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + } + ], + "cookie": [], + "body": "{\n \"val\": false\n}" + }, + { + "name": "Internal server error", + "originalRequest": { + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\n \"val\": \"eiusmod irure s\"\n}" + }, + "url": { + "raw": "{{baseUrl}}/api/v1/account/email/exists", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "api", + "v1", + "account", + "email", + "exists" + ] + } + }, + "status": "Internal Server Error", + "code": 500, + "_postman_previewlanguage": "json", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + } + ], + "cookie": [], + "body": "{\n \"error\": \"elit enim fugiat\"\n}" + } + ] + } + ] + }, + { + "name": "Registration endpoint", + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"username\": \"adipisicing\",\n \"password\": \"quis ut ipsum culpa\",\n \"email\": \"fugiat dolor ullamco magna\"\n}" + }, + "url": { + "raw": "{{baseUrl}}/api/v1/signup", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "api", + "v1", + "signup" + ] + } + }, + "response": [ + { + "name": "Bad request: username contains profainity/blacklisted words or email not acceptable or password too long/short or duplicate username/password", + "originalRequest": { + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\n \"username\": \"adipisicing\",\n \"password\": \"quis ut ipsum culpa\",\n \"email\": \"fugiat dolor ullamco magna\"\n}" + }, + "url": { + "raw": "{{baseUrl}}/api/v1/signup", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "api", + "v1", + "signup" + ] + } + }, + "status": "Bad Request", + "code": 400, + "_postman_previewlanguage": "json", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + } + ], + "cookie": [], + "body": "{\n \"error\": \"elit enim fugiat\"\n}" + }, + { + "name": "Successful registration", + "originalRequest": { + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\n \"username\": \"adipisicing\",\n \"password\": \"quis ut ipsum culpa\",\n \"email\": \"fugiat dolor ullamco magna\"\n}" + }, + "url": { + "raw": "{{baseUrl}}/api/v1/signup", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "api", + "v1", + "signup" + ] + } + }, + "status": "OK", + "code": 200, + "_postman_previewlanguage": "text", + "header": [ + { + "key": "Content-Type", + "value": "text/plain" + } + ], + "cookie": [], + "body": "" + }, + { + "name": "Internal server error", + "originalRequest": { + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\n \"username\": \"adipisicing\",\n \"password\": \"quis ut ipsum culpa\",\n \"email\": \"fugiat dolor ullamco magna\"\n}" + }, + "url": { + "raw": "{{baseUrl}}/api/v1/signup", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "api", + "v1", + "signup" + ] + } + }, + "status": "Internal Server Error", + "code": 500, + "_postman_previewlanguage": "json", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + } + ], + "cookie": [], + "body": "{\n \"error\": \"elit enim fugiat\"\n}" + } + ] + }, + { + "name": "Login endpoint", + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"username\": \"voluptate proident nulla cupidatat do\",\n \"password\": \"sint ut commodo\"\n}" + }, + "url": { + "raw": "{{baseUrl}}/api/v1/signin", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "api", + "v1", + "signin" + ] + } + }, + "response": [ + { + "name": "Successful authentication", + "originalRequest": { + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\n \"username\": \"voluptate proident nulla cupidatat do\",\n \"password\": \"sint ut commodo\"\n}" + }, + "url": { + "raw": "{{baseUrl}}/api/v1/signin", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "api", + "v1", + "signin" + ] + } + }, + "status": "OK", + "code": 200, + "_postman_previewlanguage": "text", + "header": [ + { + "key": "Content-Type", + "value": "text/plain" + } + ], + "cookie": [], + "body": "" + }, + { + "name": "Internal server error", + "originalRequest": { + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\n \"username\": \"voluptate proident nulla cupidatat do\",\n \"password\": \"sint ut commodo\"\n}" + }, + "url": { + "raw": "{{baseUrl}}/api/v1/signin", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "api", + "v1", + "signin" + ] + } + }, + "status": "Internal Server Error", + "code": 500, + "_postman_previewlanguage": "json", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + } + ], + "cookie": [], + "body": "{\n \"error\": \"elit enim fugiat\"\n}" + }, + { + "name": "username not found", + "originalRequest": { + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\n \"username\": \"voluptate proident nulla cupidatat do\",\n \"password\": \"sint ut commodo\"\n}" + }, + "url": { + "raw": "{{baseUrl}}/api/v1/signin", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "api", + "v1", + "signin" + ] + } + }, + "status": "Not Found", + "code": 404, + "_postman_previewlanguage": "json", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + } + ], + "cookie": [], + "body": "{\n \"error\": \"elit enim fugiat\"\n}" + }, + { + "name": "authentication failed, wrong password", + "originalRequest": { + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\n \"username\": \"voluptate proident nulla cupidatat do\",\n \"password\": \"sint ut commodo\"\n}" + }, + "url": { + "raw": "{{baseUrl}}/api/v1/signin", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "api", + "v1", + "signin" + ] + } + }, + "status": "Unauthorized", + "code": 401, + "_postman_previewlanguage": "json", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + } + ], + "cookie": [], + "body": "{\n \"error\": \"elit enim fugiat\"\n}" + } + ] + }, + { + "name": "Signout endpoint", + "request": { + "auth": { + "type": "apikey", + "apikey": [ + { + "key": "key", + "value": "Authorization", + "type": "string" + }, + { + "key": "value", + "value": true, + "type": "boolean" + }, + { + "key": "in", + "value": "header", + "type": "string" + } + ] + }, + "method": "POST", + "header": [], + "url": { + "raw": "{{baseUrl}}/api/v1/signout", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "api", + "v1", + "signout" + ] + } + }, + "response": [ + { + "name": "OK", + "originalRequest": { + "method": "POST", + "header": [ + { + "description": { + "content": "Added as a part of security scheme: apikey", + "type": "text/plain" + }, + "key": "Authorization", + "value": "" + } + ], + "url": { + "raw": "{{baseUrl}}/api/v1/signout", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "api", + "v1", + "signout" + ] + } + }, + "status": "OK", + "code": 200, + "_postman_previewlanguage": "text", + "header": [ + { + "key": "Content-Type", + "value": "text/plain" + } + ], + "cookie": [], + "body": "" + } + ] + } + ] + } + ], + "variable": [ + { + "key": "baseUrl", + "value": "http://localhost:3000", + "type": "string" + } + ] +} \ No newline at end of file diff --git a/openapi.yaml b/openapi.yaml index 9c401d26..e9d81e56 100644 --- a/openapi.yaml +++ b/openapi.yaml @@ -3,12 +3,11 @@ info: version: 0.1.0 title: mCaptcha/guard servers: - - url: 'http://localhost:3000' - + - url: / paths: /api/v1/signup: post: - summary: 'Registration endpoint' + summary: Registration endpoint operationId: registerUser tags: - user @@ -20,23 +19,25 @@ paths: $ref: '#/components/schemas/RegisterUser' responses: '200': - description: 'Successful registration' - '500': - description: 'Internal server error' + description: Successful registration + '400': + description: >- + Bad request: username contains profainity/blacklisted words or email + not acceptable or password too long/short or duplicate + username/password content: application/json: schema: - $ref: '#/components/schemas/Error' - '400': - description: 'Bad request: username contains profainity/blacklisted words or email not acceptable or password too long/short or duplicate username/password' + $ref: '#/components/schemas/Error' + '500': + description: Internal server error content: - application/json: - schema: - $ref: '#/components/schemas/Error' - + application/json: + schema: + $ref: '#/components/schemas/Error' /api/v1/signin: post: - summary: 'Login endpoint' + summary: Login endpoint operationId: loginUser tags: - user @@ -49,13 +50,7 @@ paths: $ref: '#/components/schemas/LoginUser' responses: '200': - description: 'Successful authentication' - '500': - description: 'Internal server error' - content: - application/json: - schema: - $ref: '#/components/schemas/Error' + description: Successful authentication '401': description: 'authentication failed, wrong password' content: @@ -63,31 +58,31 @@ paths: schema: $ref: '#/components/schemas/Error' '404': - description: 'username not found' - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - + description: username not found + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '500': + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' /api/v1/signout: post: security: - cookieAuth: [] - summary: 'Signout endpoint' + summary: Signout endpoint operationId: signoutUser tags: - user - authentication responses: '200': - description: 'OK' - + description: OK /api/v1/account/delete: post: - security: - - cookieAuth: [] - summary: 'Delete user account' - operationId: deleteUserAccount tags: - user requestBody: @@ -98,29 +93,28 @@ paths: $ref: '#/components/schemas/DeleteUser' responses: '200': - description: 'OK' - '500': - description: 'Internal server error' - content: - application/json: - schema: - $ref: '#/components/schemas/Error' + description: OK '401': - description: '(cookie)authentication required or wrong password' + description: (cookie)authentication required or wrong password content: application/json: schema: $ref: '#/components/schemas/Error' '404': - description: 'username not found' - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - + description: username not found + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '500': + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' /api/v1/account/username/exists: post: - summary: 'Check if username exists' + summary: Check if username exists operationId: usernameExists tags: - user @@ -132,22 +126,20 @@ paths: $ref: '#/components/schemas/UserDetailCheck' responses: '200': - description: 'OK' + description: OK content: application/json: schema: - $ref: '#/components/schemas/UserDetailCheckRes' + $ref: '#/components/schemas/UserDetailCheckRes' '500': - description: 'Internal server error' + description: Internal server error content: application/json: schema: - $ref: '#/components/schemas/Error' - - + $ref: '#/components/schemas/Error' /api/v1/account/email/exists: post: - summary: 'Check if email exists' + summary: Check if email exists operationId: emailExists tags: - user @@ -159,17 +151,168 @@ paths: $ref: '#/components/schemas/UserDetailCheck' responses: '200': - description: 'OK' + description: OK content: application/json: schema: - $ref: '#/components/schemas/UserDetailCheckRes' + $ref: '#/components/schemas/UserDetailCheckRes' '500': - description: 'Internal server error' + description: Internal server error content: application/json: schema: - $ref: '#/components/schemas/Error' + $ref: '#/components/schemas/Error' + /api/v1/meta/health: + get: + summary: Health check + operationId: healthCheck + tags: + - meta + - health + responses: + '200': + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/Health' + /api/v1/meta/build: + get: + summary: Get server binary build details + operationId: buildDetails + tags: + - meta + - build + responses: + '200': + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/BuildDetails' + /api/v1/mcaptcha/domain/add: + post: + security: + - cookieAuth: [] + summary: Add new domain to mCaptcha + operationId: addDomain + tags: + - mcaptcha + - domain + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/addDomain' + + responses: + '200': + description: OK + '400': + description: "Bad request: Submited domain name isn't a URI" + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '401': + description: 'authentication failed, wrong password' + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '500': + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + + /api/v1/mcaptcha/domain/domain/verify/challenge/get: + post: + security: + - cookieAuth: [] + summary: Get verification challenge for adding a domain + operationId: challengeDomain + tags: + - mcaptcha + - domain + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/addDomain' + + responses: + '200': + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/DomainVerificationChallenge' + '400': + description: "Bad request: Submited domain name isn't a URI" + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '401': + description: 'authentication failed, wrong password' + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '500': + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + + /api/v1/mcaptcha/domain/domain/verify/challenge/prove: + post: + security: + - cookieAuth: [] + summary: Verifiy domain + operationId: proveDomain + tags: + - mcaptcha + - domain + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/addDomain' + + responses: + '200': + description: OK + '400': + description: "Bad request: challenge is courrupt" + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '401': + description: 'authentication failed or challenge verification failure' + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '500': + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + '503': + description: Client server unavailable, please check if your server is online + content: + application/json: + schema: + $ref: '#/components/schemas/Error' components: schemas: @@ -196,7 +339,7 @@ components: username: type: string password: - type: string + type: string format: password DeleteUser: type: object @@ -204,7 +347,7 @@ components: - password properties: password: - type: string + type: string format: password Error: type: object @@ -231,13 +374,44 @@ components: properties: val: type: string + Health: + type: object + required: + - db + properties: + db: + type: boolean UserDetailCheckRes: type: object required: - - exists + - exists properties: - val: - type: boolean + val: + type: boolean + BuildDetails: + type: object + required: + - version + - git_commit_hash + properties: + version: + type: string + git_commit_hash: + type: string + AddDomain: + type: object + required: + - name + properties: + name: + type: string + DomainVerificationChallenge: + type: object + required: + - verification_challenge + properties: + verification_challenge: + type: string securitySchemes: cookieAuth: diff --git a/src/api/v1/meta.rs b/src/api/v1/meta.rs index b64af585..7268cf93 100644 --- a/src/api/v1/meta.rs +++ b/src/api/v1/meta.rs @@ -22,13 +22,20 @@ use serde::{Deserialize, Serialize}; use crate::Data; use crate::{GIT_COMMIT_HASH, VERSION}; +#[derive(Clone, Debug, Deserialize, Builder, Serialize)] +pub struct BuildDetails { + pub version: &'static str, + pub git_commit_hash: &'static str, +} + #[get("/api/v1/meta/build")] /// emmits build details of the bninary pub async fn build_details() -> impl Responder { - HttpResponse::Ok().content_type("text/html").body(format!( - "version: {}\ncommit: {}", - VERSION, *GIT_COMMIT_HASH - )) + let build = BuildDetails { + version: VERSION, + git_commit_hash: &GIT_COMMIT_HASH, + }; + HttpResponse::Ok().json(build) } #[derive(Clone, Debug, Deserialize, Builder, Serialize)] diff --git a/src/main.rs b/src/main.rs index 9cfde507..caeb15aa 100644 --- a/src/main.rs +++ b/src/main.rs @@ -55,7 +55,6 @@ pub static VERIFICATION_PATH: &str = "mcaptchaVerificationChallenge.json"; #[cfg(not(tarpaulin_include))] #[actix_web::main] async fn main() -> std::io::Result<()> { - use actix_web::web; use api::v1; use docs; pretty_env_logger::init(); @@ -70,9 +69,6 @@ async fn main() -> std::io::Result<()> { HttpServer::new(move || { let client = Client::default(); App::new() - .configure(v1::services) - .configure(docs::services) - //.service(web::resource("/dist/{_:.*}").route(web::get().to(docs::dist))) .wrap(middleware::Logger::default()) .wrap(get_identity_service()) .wrap(middleware::Compress::default()) @@ -81,6 +77,8 @@ async fn main() -> std::io::Result<()> { .wrap(middleware::NormalizePath::new( middleware::normalize::TrailingSlash::Trim, )) + .configure(v1::services) + .configure(docs::services) .app_data(get_json_err()) .service(Files::new("/", "./static")) })