diff --git a/public/swagger/swagger.html b/public/swagger/swagger.html index 1952a4a..b64f8cc 100644 --- a/public/swagger/swagger.html +++ b/public/swagger/swagger.html @@ -39,8 +39,7 @@ window.onload = function() { // Begin Swagger UI call region const ui = SwaggerUIBundle({ - //url: "https://petstore.swagger.io/v2/swagger.json", - url: "./swagger.yaml", + url: "./v1/swagger.yaml", dom_id: '#swagger-ui', deepLinking: true, presets: [ diff --git a/public/swagger/swagger-files.yaml b/public/swagger/v0/swagger-files.yaml similarity index 100% rename from public/swagger/swagger-files.yaml rename to public/swagger/v0/swagger-files.yaml diff --git a/public/swagger/swagger-port.yaml b/public/swagger/v0/swagger-port.yaml similarity index 100% rename from public/swagger/swagger-port.yaml rename to public/swagger/v0/swagger-port.yaml diff --git a/public/swagger/swagger-register.yaml b/public/swagger/v0/swagger-register.yaml similarity index 100% rename from public/swagger/swagger-register.yaml rename to public/swagger/v0/swagger-register.yaml diff --git a/public/swagger/swagger-who.yaml b/public/swagger/v0/swagger-who.yaml similarity index 100% rename from public/swagger/swagger-who.yaml rename to public/swagger/v0/swagger-who.yaml diff --git a/public/swagger/swagger.yaml b/public/swagger/v0/swagger.yaml similarity index 100% rename from public/swagger/swagger.yaml rename to public/swagger/v0/swagger.yaml diff --git a/public/swagger/v1/files.yaml b/public/swagger/v1/files.yaml new file mode 100644 index 0000000..ef3e997 --- /dev/null +++ b/public/swagger/v1/files.yaml @@ -0,0 +1,40 @@ +paths: + summary: "CRUD operations for namespace scoped hosted files" + get: + tags: + - files + parameters: + - $ref: "#/components/parameters/token" + - $ref: "#/components/parameters/path" + post: + tags: + - files + parameters: + - $ref: "#/components/parameters/token" + - $ref: "#/components/parameters/path" + requestBody: + $ref: "#/components/schemas/requestForm" + put: + tags: + - files + parameters: + - $ref: "#/components/parameters/token" + - $ref: "#/components/parameters/path" + requestBody: + $ref: "#/components/schemas/requestForm" + delete: + tags: + - files + parameters: + - $ref: "#/components/parameters/token" + - $ref: "#/components/parameters/path" + +components: + parameters: + token: + $ref: "./swagger.yaml#/components/parameters/token" + path: + $ref: "./swagger.yaml#/components/parameters/path" + schemas: + requestForm: + $ref: "./swagger.yaml#/components/schemas/requestForm" diff --git a/public/swagger/v1/swagger.yaml b/public/swagger/v1/swagger.yaml new file mode 100644 index 0000000..15c15dc --- /dev/null +++ b/public/swagger/v1/swagger.yaml @@ -0,0 +1,187 @@ +openapi: 3.0.2 +info: + title: DnDex + description: | + DnDex API, pronounced dee-IN-dex + + UI via htp://ui.dndex.lan:8080/, API via http://api.dndex.lan:8080/ + + Sources + * OpenAPI + * Swagger UI + version: 0.1.0 + +servers: +- url: http://api.dndex.lan:8080/ +- url: http://authapi.dndex.lan:8080/ + +paths: + /version: + $ref: "./version.yaml#/paths" + /files/{path}: + $ref: "./files.yaml#/paths" + /users/register: + $ref: "./users/register.yaml#/paths" + /users/login: + $ref: "./users/login.yaml#/paths" + #/entities: + # $ref: "./entities.yaml#/paths" + +components: + parameters: + path: + name: path + in: path + required: true + schema: + type: string + + token: + name: DnDex-Auth + in: cookie + required: true + schema: + type: string + + schemas: + responseOK: + content: + application/json: + properties: + ok: + type: boolean + example: true + + requestForm: + content: + application/x-www-form-urlencoded: + schema: + type: string + example: http://imgur.com/big-tiddy-goth-gf.jpg + + objectID: + title: "one ID" + type: string + example: "abc-123-def-456" + + objectOne: + title: "one entity" + type: object + properties: + _id: + $ref: "/components/schemas/objectID" + name: + type: string + example: "Jeff Snow" + type: + type: string + example: "doggo" + title: + type: string + example: "Meme Lord" + text: + type: string + example: "Lorem ipsum" + modified: + type: int + example: 8675309 + attachments: + type: object + additionalProperties: + type: object + properties: + location: + type: string + example: "/files/my/file.txt" + connections: + type: object + additionalProperties: + type: object + properties: + relationship: + type: string + example: "friendly" + + securitySchemes: + token: + name: DnDex-Auth + in: cookie + type: apiKey + description: | + Disabled by default but required by all endpoints when enabled + + Provided as AES-GCM 12-byte-padded ciphertext on all unauthorized requests via a response to a `/users/login` request. + +
+ + [Code example of decrypting a token in Javascript](https://notes-server.remote.blapointe.com/notes/disciplines/tech/languages/Encryption.md#toc_1) + + ```javascript + class NewAuthToken { + constructor(key) { + if (!key) { + throw "invalid key" + } + this.key = key.repeat(32).substr(0, 32) + } + + decode(b64, callback) { + var ciphertext = this.base64_decode(b64) + + var iv = ciphertext.substr(0, 12) + var encrypted = ciphertext.substr(iv.length, ciphertext.length-iv.length) + + this.get_crypto_key() + .then(function(crypto_key) { + NewAuthToken.decrypt(crypto_key, iv, encrypted, callback) + }) + } + + base64_decode(b64) { + return atob(b64) + } + + static to_buffer(s) { + var bytes = new Uint8Array(s.length) + for (var i = 0; i < s.length; i++) { + bytes[i] = s.charCodeAt(i) + } + return bytes.buffer + } + + static decrypt(crypto_key, iv, encrypted, callback) { + window.crypto.subtle.decrypt( + {name: "AES-GCM", iv: NewAuthToken.to_buffer(iv)}, + crypto_key, + NewAuthToken.to_buffer(encrypted), + ) + .then(function(decrypted) { + callback(String.fromCharCode.apply(null, new Uint8Array(decrypted))) + }) + } + + get_crypto_key() { + return crypto.subtle.importKey( + "raw", + NewAuthToken.to_buffer(this.key), + "AES-GCM", + false, + ["decrypt"] + ) + } + + set_token(encoded_token) { + this.decode(encoded_token, function (token) { + console.log("Set-Cookie DnDex-Auth="+token) + document.cookie = "DnDex-Auth=" + token + ";path=/" + }) + } + } + + authtoken = new NewAuthToken("123").set_token("SOY05yF/9iv3YG71sKkQPVaEwO53PCX8qZhDHS9JUohBgVl5Qr9/GTKK/TJ6OozhHN7QBIGmHNzQxTRRSLs4Lw==") + ``` +
+ +security: +- {} +- token: [] diff --git a/public/swagger/v1/users/login.yaml b/public/swagger/v1/users/login.yaml new file mode 100644 index 0000000..e7473e5 --- /dev/null +++ b/public/swagger/v1/users/login.yaml @@ -0,0 +1,15 @@ +paths: + summary: "Log in to namespaces" + post: + description: "Get an encrypted token and its salt as described in the security section" + tags: + - users + requestBody: + content: + application/x-www-form-urlencoded: + schema: + type: object + properties: + DnDex-User: + type: string + example: "namespace" diff --git a/public/swagger/v1/users/register.yaml b/public/swagger/v1/users/register.yaml new file mode 100644 index 0000000..6046c7b --- /dev/null +++ b/public/swagger/v1/users/register.yaml @@ -0,0 +1,17 @@ +paths: + summary: "Registering namespaces" + post: + tags: + - users + requestBody: + content: + application/x-www-form-urlencoded: + schema: + type: object + properties: + DnDex-User: + type: string + example: "namespace" + DnDex-Auth: + type: string + example: "password" diff --git a/public/swagger/v1/version.yaml b/public/swagger/v1/version.yaml new file mode 100644 index 0000000..c2de714 --- /dev/null +++ b/public/swagger/v1/version.yaml @@ -0,0 +1,15 @@ +paths: + get: + tags: + - version + summary: "Get the running server version" + responses: + 200: + content: + application/json: + schema: + type: object + properties: + version: + type: string + example: "02c5d795cf631a33528234a9cf52907c6cd34834"