OAS: yaml to json

This commit is contained in:
realaravinth 2021-04-01 15:23:36 +05:30
parent 55dd3fffe5
commit e83ed3d8ea
No known key found for this signature in database
GPG key ID: AD9F0F08E855ED88
9 changed files with 92 additions and 424 deletions

20
Cargo.lock generated
View file

@ -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"

View file

@ -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"

View file

@ -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()
);
}

View file

@ -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: [

View file

@ -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"
}
}
}
}

File diff suppressed because one or more lines are too long

View file

@ -46,12 +46,20 @@ async fn dist(path: web::Path<String>) -> 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);
}
}

View file

@ -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");

View file

@ -15,6 +15,7 @@
>Username
<input
class="form__in-field"
id="username"
type="text"
name="username"
id="username"
@ -27,6 +28,7 @@
<input
class="form__in-field"
type="password"
id="password"
name="password"
id="password"
required
@ -45,6 +47,45 @@
<p class="form__secondary-action__banner">New to mCaptcha? <a href="/signup" class="form__secondary-action__link">Create account</a></p>
</div>
</div>
<script>
export const SUBMIT = '/';
export const isBlankString = (event, value, field) => {
if (!value.replace(/\s/g, '').length) {
event.preventDefautl()
alert(`${field} can't be empty`);
}
};
const genJsonPayload = payload => {
let value = {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(payload),
};
return value;
};
const submit = async e => {
let name = document.getElementById('username').value;
isBlankString(e, name, 'username');
let password = document.getElementById('password').value;
isBlankString(e, email, 'email');
let payload = {
username,
}
};
let form = document.getElementById('form');
form.addEventListener('submit', submit, true);
</script>
</body>
<style>
* {
@ -141,43 +182,4 @@
}
</style>
<script>
export const SUBMIT = '/';
export const isBlankString = (event, value, field) => {
if (!value.replace(/\s/g, '').length) {
event.preventDefautl()
alert(`${field} can't be empty`);
}
};
export const genJsonPayload = payload => {
let value = {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(payload),
};
return value;
};
const submit = async e => {
let name = document.getElementById('name').value;
isBlankString(e, name, 'Name');
let registration_number = document.getElementById('email').value;
isBlankString(e, registration_number, 'Registration number');
let email = document.getElementById('email').value;
isBlankString(e, email, 'email');
console.log(`from signup: PoW: ${pow}`);
};
let form = document.getElementById('form');
form.addEventListener('submit', submit, true);
</script>
</html>