Created
May 12, 2024 23:07
-
-
Save helmturner/2f0c98a090c8ca819b80d7a65551b189 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| { | |
| "openapi": "3.1.0", | |
| "info": { | |
| "title": "Tulsa WebDevs Voting Service", | |
| "description": "API for casting votes on various topics/projects and submitting and managing proposals with a ranking and voting system.", | |
| "version": "0.0.2" | |
| }, | |
| "servers": [ | |
| { | |
| "url": "http://vote.tulsawebdevs. org", | |
| "description": "Voting Service API" | |
| }, | |
| { | |
| "url": "http://localhost:8080", | |
| "description": "Local development server" | |
| } | |
| ], | |
| "paths": { | |
| "/drafts": { | |
| "summary": "Manage the current user's proposal drafts", | |
| "parameters": [ | |
| { "$ref": "#/components/parameters/AuthorizationRequired" } | |
| ], | |
| "get": { | |
| "operationId": "listDrafts", | |
| "summary": "Get a list of the current user's drafts with pagination, filtering, and sorting", | |
| "parameters": [ | |
| { "$ref": "#/components/parameters/PaginationParams" }, | |
| { "$ref": "#/components/parameters/ProposalTypeFilter" } | |
| ], | |
| "responses": { | |
| "200": { | |
| "description": "OK", | |
| "content": { | |
| "application/json": { | |
| "schema": { "$ref": "#/components/schemas/DraftIndex" } | |
| } | |
| } | |
| }, | |
| "401": { "$ref": "#/components/responses/401" }, | |
| "404": { "$ref": "#/components/responses/404" }, | |
| "default": { "$ref": "#/components/responses/500" } | |
| } | |
| }, | |
| "post": { | |
| "summary": "Create a new draft", | |
| "requestBody": { | |
| "required": true, | |
| "content": { | |
| "application/json": { | |
| "schema": { "$ref": "#/components/schemas/Draft" } | |
| } | |
| } | |
| }, | |
| "responses": { | |
| "201": { | |
| "description": "Created", | |
| "content": { | |
| "application/json": { | |
| "schema": { | |
| "allOf": [ | |
| { "$ref": "#/components/schemas/Draft" }, | |
| { "$ref": "#/components/schemas/DatabaseObject" } | |
| ] | |
| } | |
| } | |
| } | |
| }, | |
| "401": { "$ref": "#/components/responses/401" }, | |
| "default": { "$ref": "#/components/responses/500" } | |
| } | |
| }, | |
| "put": { | |
| "summary": "Replace an existing draft", | |
| "parameters": [{ "$ref": "#/components/parameters/RecordId" }], | |
| "requestBody": { | |
| "required": true, | |
| "content": { | |
| "application/json": { | |
| "schema": { "$ref": "#/components/schemas/Draft" } | |
| } | |
| } | |
| }, | |
| "responses": { | |
| "200": { | |
| "description": "OK", | |
| "content": { | |
| "application/json": { | |
| "schema": { | |
| "allOf": [ | |
| { "$ref": "#/components/schemas/Draft" }, | |
| { "$ref": "#/components/schemas/DatabaseObject" } | |
| ] | |
| } | |
| } | |
| } | |
| }, | |
| "401": { "$ref": "#/components/responses/401" }, | |
| "404": { "$ref": "#/components/responses/404" }, | |
| "default": { "$ref": "#/components/responses/500" } | |
| } | |
| }, | |
| "patch": { | |
| "summary": "Update an existing draft", | |
| "parameters": [{ "$ref": "#/components/parameters/RecordId" }], | |
| "requestBody": { | |
| "required": true, | |
| "content": { | |
| "application/json": { | |
| "schema": { "$ref": "#/components/schemas/Draft" } | |
| } | |
| } | |
| }, | |
| "responses": { | |
| "200": { | |
| "description": "OK", | |
| "content": { | |
| "application/json": { | |
| "schema": { | |
| "allOf": [ | |
| { "$ref": "#/components/schemas/Draft" }, | |
| { "$ref": "#/components/schemas/DatabaseObject" } | |
| ] | |
| } | |
| } | |
| } | |
| }, | |
| "401": { "$ref": "#/components/responses/401" }, | |
| "404": { "$ref": "#/components/responses/404" }, | |
| "default": { "$ref": "#/components/responses/500" } | |
| } | |
| }, | |
| "delete": { | |
| "summary": "Delete a draft by ID", | |
| "parameters": [{ "$ref": "#/components/parameters/RecordId" }], | |
| "responses": { | |
| "204": { "description": "No Content" }, | |
| "401": { "$ref": "#/components/responses/401" }, | |
| "404": { "$ref": "#/components/responses/404" }, | |
| "default": { "$ref": "#/components/responses/500" } | |
| } | |
| } | |
| }, | |
| "/proposals": { | |
| "summary": "Create or list proposals", | |
| "get": { | |
| "summary": "Get a list of the proposals with pagination, filtering, and sorting", | |
| "parameters": [ | |
| { "$ref": "#/components/parameters/AuthorizationOptional" }, | |
| { "$ref": "#/components/parameters/PaginationParams" }, | |
| { "$ref": "#/components/parameters/ProposalTypeFilter" }, | |
| { "$ref": "#/components/parameters/ProposalStatusFilter" } | |
| ], | |
| "responses": { | |
| "200": { | |
| "description": "OK", | |
| "content": { | |
| "application/json": { | |
| "schema": { "$ref": "#/components/schemas/ProposalIndex" } | |
| } | |
| } | |
| }, | |
| "404": { "$ref": "#/components/responses/404" }, | |
| "default": { "$ref": "#/components/responses/500" } | |
| } | |
| }, | |
| "post": { | |
| "summary": "Create a new proposal", | |
| "parameters": [ | |
| { "$ref": "#/components/parameters/AuthorizationRequired" } | |
| ], | |
| "requestBody": { | |
| "required": true, | |
| "content": { | |
| "application/json": { | |
| "schema": { "$ref": "#/components/schemas/Proposal" } | |
| } | |
| } | |
| }, | |
| "responses": { | |
| "201": { | |
| "description": "Created", | |
| "content": { | |
| "application/json": { | |
| "schema": { | |
| "allOf": [ | |
| { "$ref": "#/components/schemas/Proposal" }, | |
| { "$ref": "#/components/schemas/ProposalState" }, | |
| { "$ref": "#/components/schemas/DatabaseObject" } | |
| ] | |
| } | |
| } | |
| } | |
| }, | |
| "401": { "$ref": "#/components/responses/401" }, | |
| "default": { "$ref": "#/components/responses/500" } | |
| } | |
| } | |
| }, | |
| "/{recordId}": { | |
| "summary": "Manage a user's vote on a proposal", | |
| "parameters": [ | |
| { "$ref": "#/components/parameters/AuthorizationRequired" }, | |
| { "$ref": "#/components/parameters/RecordId" } | |
| ], | |
| "post": { | |
| "summary": "Submit (or update) a vote on a proposal", | |
| "requestBody": { | |
| "required": true, | |
| "content": { | |
| "application/json": { | |
| "schema": { "$ref": "#/components/schemas/Vote" } | |
| } | |
| } | |
| }, | |
| "responses": { | |
| "201": { | |
| "description": "Created", | |
| "content": { | |
| "application/json": { | |
| "schema": { | |
| "allOf": [ | |
| { "$ref": "#/components/schemas/Vote" }, | |
| { "$ref": "#/components/schemas/DatabaseObject" } | |
| ] | |
| } | |
| } | |
| } | |
| }, | |
| "401": { "$ref": "#/components/responses/401" }, | |
| "default": { "$ref": "#/components/responses/500" } | |
| } | |
| }, | |
| "delete": { | |
| "summary": "Delete a user's proposal vote", | |
| "responses": { | |
| "204": { "description": "No Content" }, | |
| "401": { "$ref": "#/components/responses/401" }, | |
| "404": { "$ref": "#/components/responses/404" }, | |
| "default": { "$ref": "#/components/responses/500" } | |
| } | |
| } | |
| } | |
| }, | |
| "components": { | |
| "parameters": { | |
| "PaginationParams": { | |
| "name": "pagination", | |
| "in": "query", | |
| "required": false, | |
| "schema": { "$ref": "#/components/schemas/Paginated" } | |
| }, | |
| "ProposalTypeFilter": { | |
| "name": "type", | |
| "in": "query", | |
| "required": false, | |
| "schema": { | |
| "type": "string", | |
| "enum": ["topic", "project"] | |
| }, | |
| "description": "Filter items by type" | |
| }, | |
| "ProposalStatusFilter": { | |
| "name": "status", | |
| "in": "query", | |
| "required": false, | |
| "schema": { | |
| "type": "string", | |
| "enum": ["open", "closed"] | |
| }, | |
| "description": "Filter items by status" | |
| }, | |
| "AuthorizationRequired": { | |
| "name": "Authorization", | |
| "in": "header", | |
| "required": true, | |
| "schema": { | |
| "type": "string" | |
| } | |
| }, | |
| "AuthorizationOptional": { | |
| "name": "Authorization", | |
| "in": "header", | |
| "required": false, | |
| "schema": { | |
| "type": "string" | |
| } | |
| }, | |
| "RecordId": { | |
| "name": "recordId", | |
| "in": "query", | |
| "required": true, | |
| "description": "ID of the record to get, update, or delete", | |
| "schema": { | |
| "type": "integer", | |
| "format": "int32" | |
| } | |
| } | |
| }, | |
| "responses": { | |
| "401": { | |
| "description": "Unauthorized", | |
| "content": { | |
| "application/json": { | |
| "schema": { "$ref": "#/components/schemas/Error" } | |
| } | |
| } | |
| }, | |
| "404": { | |
| "description": "Not Found", | |
| "content": { | |
| "application/json": { | |
| "schema": { "$ref": "#/components/schemas/Error" } | |
| } | |
| } | |
| }, | |
| "500": { | |
| "description": "Internal Server Error", | |
| "content": { | |
| "application/json": { | |
| "schema": { "$ref": "#/components/schemas/Error" } | |
| } | |
| } | |
| } | |
| }, | |
| "schemas": { | |
| "DatabaseObject": { | |
| "type": "object", | |
| "required": ["id", "created"], | |
| "properties": { | |
| "id": { | |
| "type": "integer", | |
| "format": "int32" | |
| }, | |
| "created": { | |
| "type": "string", | |
| "format": "date-time" | |
| }, | |
| "updated": { | |
| "type": "string", | |
| "format": "date-time" | |
| } | |
| } | |
| }, | |
| "Draft": { | |
| "type": "object", | |
| "properties": { | |
| "title": { | |
| "type": "string", | |
| "maxLength": 48 | |
| }, | |
| "summary": { | |
| "type": "string", | |
| "maxLength": 255 | |
| }, | |
| "description": { | |
| "type": "string", | |
| "maxLength": 2048 | |
| }, | |
| "type": { | |
| "type": "string", | |
| "enum": ["topic", "project"] | |
| } | |
| } | |
| }, | |
| "DraftIndex": { | |
| "allOf": [ | |
| { "$ref": "#/components/schemas/Paginated" }, | |
| { | |
| "type": "object", | |
| "required": ["drafts"], | |
| "properties": { | |
| "drafts": { | |
| "type": "array", | |
| "items": { | |
| "allOf": [ | |
| { "$ref": "#/components/schemas/Draft" }, | |
| { "$ref": "#/components/schemas/DatabaseObject" } | |
| ] | |
| } | |
| } | |
| } | |
| } | |
| ] | |
| }, | |
| "Proposal": { | |
| "allOf": [ | |
| { "$ref": "#/components/schemas/Draft" }, | |
| { | |
| "type": "object", | |
| "required": ["type", "title", "summary"], | |
| "properties": { | |
| "title": { | |
| "type": "string", | |
| "minLength": 8 | |
| }, | |
| "summary": { | |
| "type": "string", | |
| "minLength": 30 | |
| } | |
| } | |
| } | |
| ] | |
| }, | |
| "ProposalState": { | |
| "oneOf": [ | |
| { | |
| "type": "object", | |
| "required": ["status", "results", "authorName"], | |
| "properties": { | |
| "authorName": { "type": "string" }, | |
| "status": { "type": "string", "enum": ["closed"] }, | |
| "userVote": { "$ref": "#/components/schemas/Vote" }, | |
| "results": { | |
| "type": "array", | |
| "items": { "$ref": "#/components/schemas/Vote" } | |
| } | |
| } | |
| }, | |
| { | |
| "type": "object", | |
| "required": ["status", "authorName"], | |
| "properties": { | |
| "authorName": { "type": "string", "minLength": 4 }, | |
| "status": { "type": "string", "enum": ["open"] }, | |
| "userVote": { "$ref": "#/components/schemas/Vote" } | |
| } | |
| } | |
| ] | |
| }, | |
| "ProposalIndex": { | |
| "allOf": [ | |
| { "$ref": "#/components/schemas/Paginated" }, | |
| { | |
| "type": "object", | |
| "required": ["proposals"], | |
| "properties": { | |
| "proposals": { | |
| "type": "array", | |
| "items": { | |
| "allOf": [ | |
| { "$ref": "#/components/schemas/Proposal" }, | |
| { "$ref": "#/components/schemas/ProposalState" }, | |
| { "$ref": "#/components/schemas/DatabaseObject" } | |
| ] | |
| } | |
| } | |
| } | |
| } | |
| ] | |
| }, | |
| "Vote": { | |
| "type": "object", | |
| "required": ["value"], | |
| "properties": { | |
| "value": { | |
| "description": "Ranking values: -2 (strong disinterest), -1 (slight disinterest), 0 (neutral), 1 (slight interest), 2 (strong interest)", | |
| "type": "string", | |
| "enum": ["-2", "-1", "0", "1", "2"] | |
| }, | |
| "comment": { | |
| "type": "string", | |
| "maxLength": 255 | |
| } | |
| } | |
| }, | |
| "Expirable": { | |
| "type": "object", | |
| "required": ["expires"], | |
| "properties": { | |
| "expires": { | |
| "type": "string", | |
| "format": "date-time" | |
| } | |
| } | |
| }, | |
| "Paginated": { | |
| "type": "object", | |
| "description": "Controls pagination of results", | |
| "properties": { | |
| "cursor": { | |
| "description": "Cursor for paginating through a list of items", | |
| "type": "integer", | |
| "format": "int32" | |
| }, | |
| "limit": { | |
| "description": "In a request, the maximum number of items to return. In a response, the total number of items available, if known.", | |
| "type": "integer", | |
| "format": "int32" | |
| } | |
| } | |
| }, | |
| "Error": { | |
| "type": "object", | |
| "required": ["message"], | |
| "properties": { | |
| "message": { | |
| "type": "string" | |
| } | |
| } | |
| } | |
| } | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment