diff --git a/Cargo.lock b/Cargo.lock index fab4e3dd..db5989a4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -949,6 +949,12 @@ version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "77c90badedccf4105eca100756a0b1289e191f6fcbdadd3cee1d2f614f97da8f" +[[package]] +name = "dtoa" +version = "0.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56899898ce76aaf4a0f24d914c97ea6ed976d42fec6ad33fcbb0a1103e07b2b0" + [[package]] name = "either" version = "1.6.1" @@ -1229,9 +1235,11 @@ dependencies = [ "sailfish", "serde 1.0.125", "serde_json", + "serde_yaml", "sqlx", "url", "validator", + "yaml-rust", ] [[package]] @@ -2432,6 +2440,18 @@ dependencies = [ "serde 1.0.125", ] +[[package]] +name = "serde_yaml" +version = "0.8.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15654ed4ab61726bf918a39cb8d98a2e2995b002387807fa6ba58fdf7f59bb23" +dependencies = [ + "dtoa", + "linked-hash-map", + "serde 1.0.125", + "yaml-rust", +] + [[package]] name = "sha-1" version = "0.9.4" diff --git a/Cargo.toml b/Cargo.toml index da09f371..42ef51d4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -44,6 +44,7 @@ derive_more = "0.99" serde = "1" serde_json = "1" +serde_yaml = "0.8" url = "2.2" @@ -58,3 +59,8 @@ m_captcha = { version = "0.1.2", git = "https://github.com/mCaptcha/mCaptcha" } rand = "0.8" sailfish = "0.3.2" + +[build-dependencies] +serde_yaml = "0.8" +serde_json = "1" +yaml-rust = "0.4" diff --git a/build.rs b/build.rs index 22cd97d3..ee1a3459 100644 --- a/build.rs +++ b/build.rs @@ -16,6 +16,7 @@ */ use std::process::Command; + fn main() { // note: add error checking yourself. let output = Command::new("git") @@ -24,4 +25,11 @@ fn main() { .unwrap(); let git_hash = String::from_utf8(output.stdout).unwrap(); println!("cargo:rustc-env=GIT_HASH={}", git_hash); + + let yml = include_str!("./openapi.yaml"); + let api_json: serde_json::Value = serde_yaml::from_str(yml).unwrap(); + println!( + "cargo:rustc-env=OPEN_API_DOCS={}", + serde_json::to_string(&api_json).unwrap() + ); } diff --git a/docs/index.html b/docs/index.html index 5260c975..4116f441 100644 --- a/docs/index.html +++ b/docs/index.html @@ -39,7 +39,7 @@ window.onload = function() { // Begin Swagger UI call region const ui = SwaggerUIBundle({ - url: "/docs/swagger.json", + url: "/docs/openapi.json", dom_id: '#swagger-ui', deepLinking: true, presets: [ diff --git a/docs/openapi.json b/docs/openapi.json deleted file mode 100644 index c5570297..00000000 --- a/docs/openapi.json +++ /dev/null @@ -1,382 +0,0 @@ -{ - "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 deleted file mode 100644 index adfcff82..00000000 --- a/docs/swagger.json +++ /dev/null @@ -1 +0,0 @@ -{"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"},"example":{"username":"testuser","password":"mysuperlongandsecurepassword","email":"testuser@example.com"}}}},"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"},"example":{"username":"testuser","password":"mysuperlongandsecurepassword"}}}},"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/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 account","operationId":"deleteAccount","tags":["user"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeleteUser"},"example":{"password":"mysuperlongandsecurepassword"}}}},"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"},"example":{"val":"testuser"}}}},"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"},"example":{"val":"testuser@example.com"}}}},"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"}}}}}}},"/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"}}}}}}},"/api/v1/mcaptcha/domain/delete":{"post":{"security":[{"cookieAuth":[]}],"summary":"Delete domain from mcaptcha","operationId":"deleteDomain","tags":["mcaptcha","domain"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/addDomain"}}}},"responses":{"200":{"description":"OK"},"400":{"description":"Bad request: Submited URI is not a URI","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"authentication failed","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/token/add":{"post":{"security":[{"cookieAuth":[]}],"summary":"Add token for registered domain","operationId":"addToken","tags":["mcaptcha","domain","token"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MCaptchaID"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MCaptchaDetails"}}}},"400":{"description":"Bad request: Submited URI is not a URI or duplicate token name","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"authentication failed","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/token/update":{"post":{"security":[{"cookieAuth":[]}],"summary":"Update token key","operationId":"updateTokenKey","tags":["mcaptcha","domain","token"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MCaptchaID"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MCaptchaDetails"}}}},"400":{"description":"Bad request: Submited URI is not a URI or duplicate token name","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"authentication failed","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/token/get":{"post":{"security":[{"cookieAuth":[]}],"summary":"Get token key","operationId":"getTokenKey","tags":["mcaptcha","domain","token"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MCaptchaID"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MCaptchaDetails"}}}},"400":{"description":"Bad request: Submited URI is not a URI","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"authentication failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"token name 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/mcaptcha/domain/token/delete":{"post":{"security":[{"cookieAuth":[]}],"summary":"Delete token from mcaptcha","operationId":"deleteToken","tags":["mcaptcha","domain","token"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MCaptchaID"}}}},"responses":{"200":{"description":"OK"},"401":{"description":"authentication failed","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/token/levels/add":{"post":{"security":[{"cookieAuth":[]}],"summary":"Add levels to a token","operationId":"addTokenLevels","tags":["mcaptcha","domain","token","levels"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddLevels"}}}},"responses":{"200":{"description":"OK"},"400":{"description":"duplicate visitor count or difficulty_factor is zero or difficulty_factor decreases with increase in visitor count","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"authentication failed","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/token/levels/update":{"post":{"security":[{"cookieAuth":[]}],"summary":"Update levels of a token","operationId":"updateTokenLevels","tags":["mcaptcha","domain","token","levels"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddLevels"}}}},"responses":{"200":{"description":"OK"},"400":{"description":"duplicate visitor count or difficulty_factor is zero or difficulty_factor decreases with increase in visitor count","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"authentication failed","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/token/levels/delete":{"post":{"security":[{"cookieAuth":[]}],"tags":["mcaptcha","domain","token","levels"],"summary":"Delete levels of a token","operationId":"deleteTokenLevels","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddLevels"}}}},"responses":{"200":{"description":"OK"},"401":{"description":"(cookie)authentication required or 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/token/levels/get":{"post":{"security":[{"cookieAuth":[]}],"tags":["mcaptcha","domain","token","levels"],"summary":"Get levels of a token","operationId":"getTokenLevels","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddLevels"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Levels"}}}},"401":{"description":"(cookie)authentication required or 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/token/token/get":{"post":{"security":[{"cookieAuth":[]}],"tags":["mcaptcha","domain","token","levels","duration"],"summary":"Get duration of a token","operationId":"getTokenDuration","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetDuration"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Duration"}}}},"401":{"description":"(cookie)authentication required or 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/token/token/update":{"post":{"security":[{"cookieAuth":[]}],"tags":["mcaptcha","domain","token","levels","duration"],"summary":"update duration of a token","operationId":"updateTokenDuration","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateDuration"}}}},"responses":{"200":{"description":"OK"},"400":{"description":"Bad request: Duration must be greater than 0"},"401":{"description":"(cookie)authentication required or wrong password","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"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"}}},"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"}}},"AddDomain":{"type":"object","required":["name"],"properties":{"name":{"type":"string"}}},"DomainVerificationChallenge":{"type":"object","required":["verification_challenge"],"properties":{"verification_challenge":{"type":"string"}}},"MCaptchaID":{"type":"object","required":["name","domain"],"properties":{"name":{"type":"string"},"domain":{"type":"string"}}},"MCaptchaDetails":{"type":"object","required":["name","key"],"properties":{"name":{"type":"string"},"key":{"type":"string"}}},"Level":{"type":"object","required":["visitor_threshold","difficulty_factor"],"properties":{"visitor_threshold":{"type":"number","minimum":1,"maximum":2147483647},"difficulty_factor":{"type":"number","minimum":1}}},"GetLevels":{"type":"object","required":["token"],"properties":{"token":{"type":"string"}}},"Levels":{"type":"array","items":{"$ref":"#/components/schemas/Level"}},"AddLevels":{"type":"object","required":["name","levels"],"properties":{"name":{"type":"string"},"levels":{"type":"array","items":{"$ref":"#/components/schemas/Level"}}}},"GetDuration":{"type":"object","required":["token"],"properties":{"token":{"type":"string"}}},"Duration":{"type":"object","required":["duration"],"properties":{"duration":{"type":"number","minimum":1,"maximum":2147483647}}},"UpdateDuration":{"type":"object","required":["duration","token_name"],"properties":{"token_name":{"type":"string"},"duration":{"type":"number","minimum":1,"maximum":2147483647}}}},"securitySchemes":{"cookieAuth":{"type":"apiKey","in":"cookie","name":"Authorization"}}}} \ No newline at end of file diff --git a/src/docs.rs b/src/docs.rs index 2b64293c..119ceb66 100644 --- a/src/docs.rs +++ b/src/docs.rs @@ -46,12 +46,20 @@ async fn dist(path: web::Path) -> impl Responder { handle_embedded_file(&path.0) } +#[get("/docs/openapi.json")] +async fn spec() -> HttpResponse { + HttpResponse::Ok() + .content_type("appilcation/json") + .body(&*crate::OPEN_API_DOC) +} + #[get("/docs")] async fn index() -> HttpResponse { handle_embedded_file("index.html") } pub fn services(cfg: &mut web::ServiceConfig) { + cfg.service(spec); cfg.service(index); cfg.service(dist); } @@ -67,7 +75,8 @@ mod tests { #[actix_rt::test] async fn docs_work() { const INDEX: &str = "/docs"; - const FILE: &str = "/docs/swagger.json"; + const FILE: &str = "/docs/favicon-32x32.png"; + const SPEC: &str = "/docs/openapi.json"; let mut app = test::init_service(App::new().configure(services)).await; @@ -78,5 +87,9 @@ mod tests { let resp = test::call_service(&mut app, test::TestRequest::get().uri(FILE).to_request()).await; assert_eq!(resp.status(), StatusCode::OK); + + let resp = + test::call_service(&mut app, test::TestRequest::get().uri(SPEC).to_request()).await; + assert_eq!(resp.status(), StatusCode::OK); } } diff --git a/src/main.rs b/src/main.rs index caeb15aa..6d406fa3 100644 --- a/src/main.rs +++ b/src/main.rs @@ -43,6 +43,8 @@ pub use settings::Settings; lazy_static! { pub static ref SETTINGS: Settings = Settings::new().unwrap(); pub static ref GIT_COMMIT_HASH: String = env::var("GIT_HASH").unwrap(); + pub static ref OPEN_API_DOC: String = env::var("OPEN_API_DOCS").unwrap(); + pub static ref S: String = env::var("S").unwrap(); } pub static VERSION: &str = env!("CARGO_PKG_VERSION"); diff --git a/static/login/index.html b/static/login/index.html index bfc20b5d..950ae6b3 100644 --- a/static/login/index.html +++ b/static/login/index.html @@ -15,6 +15,7 @@ >Username New to mCaptcha? Create account

+ + -