598 lines
16 KiB
JSON
598 lines
16 KiB
JSON
|
{
|
||
|
"openapi": "3.1.0",
|
||
|
"info": {
|
||
|
"title": "Sync Node",
|
||
|
"summary": "A generic sync server",
|
||
|
"description": "This is a server intended to be a generic sync target. It enables client-powered apps to simply store their data in a location that's accessible across various devices and optionally share that data with other users.",
|
||
|
"license": {
|
||
|
"name": "GNU Affero General Public License v3.0",
|
||
|
"url": "https://www.gnu.org/licenses/agpl-3.0.txt"
|
||
|
},
|
||
|
"version": "1.0.0"
|
||
|
},
|
||
|
"paths": {
|
||
|
"/account": {
|
||
|
"get": {
|
||
|
"summary": "List current sessions",
|
||
|
"responses": {
|
||
|
"200": {
|
||
|
"content": {
|
||
|
"application/json": {
|
||
|
"schema": {
|
||
|
"$ref": "#/components/schemas/SessionArray"
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
},
|
||
|
"default": {
|
||
|
"$ref": "#/components/responses/ErrorResponse"
|
||
|
}
|
||
|
},
|
||
|
"security": [
|
||
|
{
|
||
|
"bearer": []
|
||
|
}
|
||
|
]
|
||
|
},
|
||
|
"post": {
|
||
|
"summary": "Create a new account",
|
||
|
"requestBody": {
|
||
|
"$ref": "#/components/requestBodies/Authentication"
|
||
|
},
|
||
|
"responses": {
|
||
|
"200": {
|
||
|
"description": "The account was created.",
|
||
|
"content": {
|
||
|
"application/json": {
|
||
|
"schema": {
|
||
|
"$ref": "#/components/schemas/Session"
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
},
|
||
|
"default": {
|
||
|
"$ref": "#/components/responses/ErrorResponse"
|
||
|
}
|
||
|
}
|
||
|
},
|
||
|
"delete": {
|
||
|
"summary": "Delete an account",
|
||
|
"responses": {
|
||
|
"204": {
|
||
|
"description": "The account was deleted."
|
||
|
},
|
||
|
"default": {
|
||
|
"$ref": "#/components/responses/ErrorResponse"
|
||
|
}
|
||
|
},
|
||
|
"security": [
|
||
|
{
|
||
|
"bearer": []
|
||
|
}
|
||
|
]
|
||
|
}
|
||
|
},
|
||
|
"/auth": {
|
||
|
"post": {
|
||
|
"summary": "Log in as an existing user",
|
||
|
"requestBody": {
|
||
|
"$ref": "#/components/requestBodies/Authentication"
|
||
|
},
|
||
|
"responses": {
|
||
|
"200": {
|
||
|
"$ref": "#/components/responses/AuthenticationSuccess"
|
||
|
},
|
||
|
"default": {
|
||
|
"$ref": "#/components/responses/ErrorResponse"
|
||
|
}
|
||
|
}
|
||
|
},
|
||
|
"delete": {
|
||
|
"summary": "Log out an existing user",
|
||
|
"responses": {
|
||
|
"204": {
|
||
|
"description": "The session was invalidated."
|
||
|
},
|
||
|
"default": {
|
||
|
"$ref": "#/components/responses/ErrorResponse"
|
||
|
}
|
||
|
},
|
||
|
"security": [
|
||
|
{
|
||
|
"bearer": []
|
||
|
}
|
||
|
]
|
||
|
}
|
||
|
},
|
||
|
"/health": {
|
||
|
"get": {
|
||
|
"summary": "Check the server health",
|
||
|
"responses": {
|
||
|
"200": {
|
||
|
"$ref": "#/components/responses/HealthResponse"
|
||
|
},
|
||
|
"500": {
|
||
|
"$ref": "#/components/responses/HealthResponse"
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
},
|
||
|
"/password": {
|
||
|
"post": {
|
||
|
"summary": "Update a user's password",
|
||
|
"requestBody": {
|
||
|
"required": true,
|
||
|
"content": {
|
||
|
"application/json": {
|
||
|
"schema": {
|
||
|
"$ref": "#/components/schemas/UpdatePasswordRequest"
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
},
|
||
|
"responses": {
|
||
|
"204": {
|
||
|
"description": "The user's password was updated"
|
||
|
},
|
||
|
"default": {
|
||
|
"$ref": "#/components/responses/ErrorResponse"
|
||
|
}
|
||
|
},
|
||
|
"security": [
|
||
|
{
|
||
|
"bearer": []
|
||
|
}
|
||
|
]
|
||
|
}
|
||
|
},
|
||
|
"/resetpassword": {
|
||
|
"post": {
|
||
|
"summary": "Request a password reset token",
|
||
|
"requestBody": {
|
||
|
"required": true,
|
||
|
"content": {
|
||
|
"application/json": {
|
||
|
"schema": {
|
||
|
"$ref": "#/components/schemas/ResetPasswordTokenRequest"
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
},
|
||
|
"responses": {
|
||
|
"204": {
|
||
|
"description": "A password reset request has been generated."
|
||
|
},
|
||
|
"default": {
|
||
|
"$ref": "#/components/responses/ErrorResponse"
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
},
|
||
|
"/store": {
|
||
|
"get": {
|
||
|
"summary": "Retrieve a list of keys to which the user has access.",
|
||
|
"responses": {
|
||
|
"200": {
|
||
|
"content": {
|
||
|
"application/json": {
|
||
|
"schema": {
|
||
|
"type": "array",
|
||
|
"items": {
|
||
|
"$ref": "#/components/schemas/StoreKey"
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
},
|
||
|
"default": {
|
||
|
"$ref": "#/components/responses/ErrorResponse"
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
},
|
||
|
"/permission/{key}": {
|
||
|
"parameters": [
|
||
|
{
|
||
|
"name": "key",
|
||
|
"in": "path",
|
||
|
"required": true,
|
||
|
"description": "The key for which to return the permissions.",
|
||
|
"schema": {
|
||
|
"type": "string"
|
||
|
}
|
||
|
}
|
||
|
],
|
||
|
"get": {
|
||
|
"summary": "Retrieve a list of users and their respective permissions for the given key",
|
||
|
"responses": {
|
||
|
"200": {
|
||
|
"description": "OK",
|
||
|
"content": {
|
||
|
"application/json": {
|
||
|
"schema": {
|
||
|
"type": "array",
|
||
|
"items": {
|
||
|
"$ref": "#/components/schemas/UserPermission"
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
},
|
||
|
"default": {
|
||
|
"$ref": "#/components/responses/ErrorResponse"
|
||
|
}
|
||
|
}
|
||
|
},
|
||
|
"put": {
|
||
|
"summary": "Create or update permissions for the given key",
|
||
|
"content": {
|
||
|
"application/json": {
|
||
|
"schema": {
|
||
|
"type": "array",
|
||
|
"items": {
|
||
|
"$ref": "#/components/schemas/UserPermission"
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
},
|
||
|
"responses": {
|
||
|
"204": {
|
||
|
"description": "The permissions were updated."
|
||
|
},
|
||
|
"default": {
|
||
|
"$ref": "#/components/responses/ErrorResponse"
|
||
|
}
|
||
|
}
|
||
|
},
|
||
|
"delete": {
|
||
|
"summary": "Delete permissions for the given users",
|
||
|
"parameters": [
|
||
|
{
|
||
|
"name": "users",
|
||
|
"in": "query",
|
||
|
"description": "The user identifiers for which to remove the permissions",
|
||
|
"schema": {
|
||
|
"type": "string"
|
||
|
}
|
||
|
}
|
||
|
],
|
||
|
"responses": {
|
||
|
"204": {
|
||
|
"description": "The permissions were removed."
|
||
|
},
|
||
|
"default": {
|
||
|
"$ref": "#/components/responses/ErrorResponse"
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
},
|
||
|
"/store/{key}": {
|
||
|
"parameters": [
|
||
|
{
|
||
|
"name": "key",
|
||
|
"in": "path",
|
||
|
"required": true,
|
||
|
"description": "The key for which to return the value.",
|
||
|
"schema": {
|
||
|
"type": "string"
|
||
|
}
|
||
|
}
|
||
|
],
|
||
|
"get": {
|
||
|
"summary": "Retrieve a value from the store by key",
|
||
|
"responses": {
|
||
|
"200": {
|
||
|
"description": "OK",
|
||
|
"headers": {
|
||
|
"X-Sync-Meta": {
|
||
|
"schema": {
|
||
|
"$ref": "#/components/schemas/StoreMeta"
|
||
|
}
|
||
|
},
|
||
|
"X-Sync-Token": {
|
||
|
"schema": {
|
||
|
"$ref": "#/components/schemas/StoreToken"
|
||
|
}
|
||
|
}
|
||
|
},
|
||
|
"content": {
|
||
|
"application/octet-stream": {
|
||
|
"schema": {
|
||
|
"type": "string",
|
||
|
"format": "binary"
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
},
|
||
|
"default": {
|
||
|
"$ref": "#/components/responses/ErrorResponse"
|
||
|
}
|
||
|
}
|
||
|
},
|
||
|
"put": {
|
||
|
"summary": "Create or update a value in the store by key",
|
||
|
"parameters": [
|
||
|
{
|
||
|
"name": "X-Sync-Meta",
|
||
|
"in": "header",
|
||
|
"schema": {
|
||
|
"$ref": "#/components/schemas/StoreMeta"
|
||
|
}
|
||
|
},
|
||
|
{
|
||
|
"name": "X-Sync-Token",
|
||
|
"in": "header",
|
||
|
"schema": {
|
||
|
"$ref": "#/components/schemas/StoreToken"
|
||
|
}
|
||
|
}
|
||
|
],
|
||
|
"content": {
|
||
|
"application/octet-stream": {
|
||
|
"schema": {
|
||
|
"type": "string",
|
||
|
"format": "binary"
|
||
|
}
|
||
|
}
|
||
|
},
|
||
|
"responses": {
|
||
|
"204": {
|
||
|
"description": "The data was updated."
|
||
|
},
|
||
|
"default": {
|
||
|
"$ref": "#/components/responses/ErrorResponse"
|
||
|
}
|
||
|
}
|
||
|
},
|
||
|
"delete": {
|
||
|
"summary": "Delete a value in the store by key",
|
||
|
"parameters": [
|
||
|
{
|
||
|
"name": "X-Sync-Token",
|
||
|
"in": "header",
|
||
|
"schema": {
|
||
|
"$ref": "#/components/schemas/StoreToken"
|
||
|
}
|
||
|
}
|
||
|
],
|
||
|
"responses": {
|
||
|
"204": {
|
||
|
"description": "The data was deleted."
|
||
|
},
|
||
|
"default": {
|
||
|
"$ref": "#/components/responses/ErrorResponse"
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
},
|
||
|
"components": {
|
||
|
"requestBodies": {
|
||
|
"Authentication": {
|
||
|
"required": true,
|
||
|
"content": {
|
||
|
"application/json": {
|
||
|
"schema": {
|
||
|
"$ref": "#/components/schemas/Credentials"
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
},
|
||
|
"responses": {
|
||
|
"AuthenticationSuccess": {
|
||
|
"description": "The user successfully authenticated.",
|
||
|
"content": {
|
||
|
"application/json": {
|
||
|
"schema": {
|
||
|
"$ref": "#/components/schemas/Session"
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
},
|
||
|
"ErrorResponse": {
|
||
|
"description": "An error occurred.",
|
||
|
"content": {
|
||
|
"application/json": {
|
||
|
"schema": {
|
||
|
"$ref": "#/components/schemas/Error"
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
},
|
||
|
"HealthResponse": {
|
||
|
"description": "The current statuses of server-side systems.",
|
||
|
"content": {
|
||
|
"application/json": {
|
||
|
"schema": {
|
||
|
"type": "object",
|
||
|
"properties": {
|
||
|
"database": {
|
||
|
"type": "boolean",
|
||
|
"description": "Whether or not the database is accessible"
|
||
|
},
|
||
|
"disk": {
|
||
|
"type": "boolean",
|
||
|
"description": "Whether or not the data directory is writeable and has sufficient free space"
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
},
|
||
|
"schemas": {
|
||
|
"Credentials": {
|
||
|
"title": "User Credentials",
|
||
|
"type": "object",
|
||
|
"description": "A credential pair used to authenticate a user.",
|
||
|
"properties": {
|
||
|
"id": {
|
||
|
"type": "string",
|
||
|
"description": "The identifier for the user."
|
||
|
},
|
||
|
"password": {
|
||
|
"type": "string",
|
||
|
"description": "The password for the user."
|
||
|
}
|
||
|
}
|
||
|
},
|
||
|
"Error": {
|
||
|
"type": "object",
|
||
|
"properties": {
|
||
|
"code": {
|
||
|
"type": "string",
|
||
|
"oneOf": [
|
||
|
{
|
||
|
"title": "AUTH01",
|
||
|
"const": "AUTH01",
|
||
|
"description": "The access token is missing or invalid."
|
||
|
},
|
||
|
{
|
||
|
"title": "ACCT01",
|
||
|
"const": "ACCT01",
|
||
|
"description": "Registration is disabled."
|
||
|
},
|
||
|
{
|
||
|
"title": "ACCT02",
|
||
|
"const": "ACCT02",
|
||
|
"description": "The user identifier and/or password do not meet the requirements."
|
||
|
},
|
||
|
{
|
||
|
"title": "ACCT03",
|
||
|
"const": "ACCT03",
|
||
|
"description": "The user identifier is already in use."
|
||
|
},
|
||
|
{
|
||
|
"title": "ERR01",
|
||
|
"const": "ERR01",
|
||
|
"description": "No data found for the given identifier."
|
||
|
},
|
||
|
{
|
||
|
"title": "ERR02",
|
||
|
"const": "ERR02",
|
||
|
"description": "The server encountered an unexpected error."
|
||
|
},
|
||
|
{
|
||
|
"title": "KEY01",
|
||
|
"const": "KEY01",
|
||
|
"description": "The store token is invalid or missing."
|
||
|
}
|
||
|
]
|
||
|
}
|
||
|
},
|
||
|
"required": [
|
||
|
"code"
|
||
|
]
|
||
|
},
|
||
|
"Permission": {
|
||
|
"type": "string",
|
||
|
"description": "The permission granted to the user for the associated key",
|
||
|
"enum": [
|
||
|
"READ",
|
||
|
"WRITE",
|
||
|
"OWN"
|
||
|
]
|
||
|
},
|
||
|
"ResetPasswordTokenRequest": {
|
||
|
"title": "Reset Password Token Request",
|
||
|
"type": "object",
|
||
|
"description": "A request for a token to reset the user's password.",
|
||
|
"properties": {
|
||
|
"id": {
|
||
|
"type": "string",
|
||
|
"description": "The identifier for the user."
|
||
|
}
|
||
|
},
|
||
|
"required": [
|
||
|
"id"
|
||
|
]
|
||
|
},
|
||
|
"Session": {
|
||
|
"title": "Session",
|
||
|
"type": "object",
|
||
|
"description": "A token and expiration date for a given session.",
|
||
|
"properties": {
|
||
|
"token": {
|
||
|
"type": "string",
|
||
|
"description": "A token with which to authenticate future requests."
|
||
|
},
|
||
|
"expiration": {
|
||
|
"type": "integer",
|
||
|
"description": "A timestamp in milliseconds since Unix Epoch"
|
||
|
}
|
||
|
}
|
||
|
},
|
||
|
"SessionArray": {
|
||
|
"title": "Session",
|
||
|
"type": "array",
|
||
|
"description": "A list of currently valid sessions.",
|
||
|
"items": {
|
||
|
"$ref": "#/components/schemas/Session"
|
||
|
}
|
||
|
},
|
||
|
"StoreKey": {
|
||
|
"title": "Store Key",
|
||
|
"type": "object",
|
||
|
"properties": {
|
||
|
"key": {
|
||
|
"type": "string",
|
||
|
"description": "The key in the store"
|
||
|
},
|
||
|
"permission": {
|
||
|
"schema": {
|
||
|
"$ref": "#/components/schemas/Permission"
|
||
|
}
|
||
|
},
|
||
|
"token": {
|
||
|
"schema": {
|
||
|
"$ref": "#/components/schemas/StoreToken"
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
},
|
||
|
"StoreMeta": {
|
||
|
"description": "Optional metadata associated with the data",
|
||
|
"type": "string"
|
||
|
},
|
||
|
"StoreToken": {
|
||
|
"description": "A token used to denote the version of the data. Newly updated data must send the same token that the backend has stored in order for it to be udpated.",
|
||
|
"type": "string"
|
||
|
},
|
||
|
"UpdatePasswordRequest": {
|
||
|
"title": "Update Password Token Request",
|
||
|
"type": "object",
|
||
|
"description": "A request to update the user's password.",
|
||
|
"properties": {
|
||
|
"password": {
|
||
|
"type": "string",
|
||
|
"description": "The new password for the user."
|
||
|
}
|
||
|
},
|
||
|
"required": [
|
||
|
"password"
|
||
|
]
|
||
|
},
|
||
|
"UserPermission": {
|
||
|
"title": "User-Permission Mapping",
|
||
|
"type": "object",
|
||
|
"properties": {
|
||
|
"user": {
|
||
|
"type": "string",
|
||
|
"description": "The user identifier."
|
||
|
},
|
||
|
"permission": {
|
||
|
"$ref": "#/components/schemas/Permission"
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
},
|
||
|
"securitySchemes": {
|
||
|
"bearer": {
|
||
|
"type": "http",
|
||
|
"scheme": "bearer"
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|