Full-Stack Ruby on Rails application running the Pen&PaperBox
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

1272 lines
41 KiB

openapi: 3.0.0
info:
title: "Pen&PaperBox API"
version: 1.0.0
servers:
- url: https://penpaperbox.com/api
description: Production server
- url: http://localhost:3000/api
description: Local development sever
components:
securitySchemes:
bearer:
type: http
scheme: bearer
description: Bearer token that can be obtained via `/1.0/login`
schemas:
TimestampCreated:
type: object
properties:
created:
type: integer
description: Unix epoch seconds when the entity was first created
example: 1653112526
Timestamps:
allOf:
- $ref: '#/components/schemas/TimestampCreated'
- type: object
properties:
updated:
type: integer
description: Unix epoch seconds when the entity was last updated
example: 1653132603
Error:
type: object
properties:
error:
type: string
description: Machine-readable error type
example: validation_error
error_description:
type: string
description: Human-readable error type
ErrorWithFields:
allOf:
- $ref: '#/components/schemas/Error'
- type: object
properties:
field_errors:
type: array
items:
type: object
properties:
field:
type: string
description: Name of the field that failed the validation
error:
type: string
description: Description of the failed validation
File:
type: object
writeOnly: true
properties:
data:
type: string
description: Base64 encoded content of the file
filename:
type: string
description: Name of the file
example: 'image.jpg'
content_type:
type: string
description: Content type of the file
example: 'image/jpeg'
Image:
type: object
readOnly: true
properties:
original:
type: string
description: URL to the original version of the image
inline:
type: string
description: URL to a small version of the image
thumb:
type: string
description: URL to a thumbnail version of the image
medium:
type: string
description: URL to a medium-sized version of the image
CharacterWOPlayer:
allOf:
- $ref: '#/components/schemas/Timestamps'
- type: object
properties:
id:
type: integer
description: ID of the character
example: 1
readOnly: true
name:
type: string
description: (Current) name of the character
example: Groot
is_private:
type: boolean
description: Is this character only visible for it's owner?
avatar:
$ref: '#/components/schemas/Image'
avatar_file:
$ref: '#/components/schemas/File'
avatar_attribution:
type: string
description: Attribution for the character image, formatted in Markdown
example: CC-BY-SA [xx](https://example.com)
rpg_system:
type: string
description: Name of the RPG system the character belongs to (if any)
example: Cryptomancer
session_character:
type: boolean
description: Is the character a session character? Session characters exist only for a single session. It's most likely a copy of a regular character that go assigned to a player during a session.
readOnly: true
PlayerModel:
type: object
properties:
id:
type: integer
description: ID of the player
example: 23
readOnly: true
name:
type: string
description: Name of the player
example: Bob
is_admin:
type: boolean
description: Has the player administrator rights?
avatar:
$ref: '#/components/schemas/Image'
avatar_file:
$ref: '#/components/schemas/File'
PlayerReference:
# Need to duplicate this because of this https://stackoverflow.com/a/51402417
readOnly: true
type: object
properties:
id:
type: integer
description: ID of the player
example: 23
readOnly: true
name:
type: string
description: Name of the player
example: Bob
is_admin:
type: boolean
description: Has the player administrator rights?
avatar:
$ref: '#/components/schemas/Image'
avatar_file:
$ref: '#/components/schemas/File'
PlayerDetailsModel:
allOf:
- $ref: '#/components/schemas/PlayerModel'
- type: object
properties:
email:
type: string
example: bob@example.com
description: Player's email-address. Only present when it's your own information or you have admin rights.
email_validated:
type: boolean
readOnly: true
description: Was the player's email address successfully validated. Only present when it's your own information or you have admin rights.
profile_text:
type: string
description: A self-description of the player with Markdown formatting
gender:
type: string
example: f
description: Players preferred pronouns. 'm' or 'f' Only present when it's your own info or player has enabled sharing this information
characters:
type: array
readOnly: true
items:
$ref: '#/components/schemas/CharacterWOPlayer'
experienced_systems:
type: array
items:
type: string
description: Array of Rpg system names the player is interested in.
interested_systems:
type: array
items:
type: string
description: Array of Rpg systems names the player is interested in.
PlayerOwnModel:
allOf:
- $ref: '#/components/schemas/PlayerDetailsModel'
- type: object
properties:
show_gender:
type: boolean
description: Should your preferred pronouns be publicly displayed?
theme:
type: string
example: ppb_light
description: Your preferred display theme
locale:
type: string
example: de
description: Your display locale
password:
type: string
description: Provide to update your password
writeOnly: true
password_confirmation:
type: string
description: Confirmation of the password, must be the same as password
writeOnly: true
terms_of_service:
type: boolean
description: Has the user accepted the terms of service? Only needed for registration
writeOnly: true
calendar_token:
type: string
description: Token to be used to retrieve calendar by url.
required: false
readOnly: true
CharacterModel:
allOf:
- $ref: '#/components/schemas/CharacterWOPlayer'
- type: object
properties:
player:
$ref: '#/components/schemas/PlayerReference'
latest_revision:
type: integer
description: Latest revision number of the character's CML
example: 5
readOnly: true
CharacterDetailsModel:
allOf:
- $ref: '#/components/schemas/CharacterModel'
- type: object
properties:
description:
type: string
description: A description of the character, formatted in Markdown
example: I am Groot
cml_revision:
type: integer
description: Revision number of the provided CML. Might differ from latest_revision
readOnly: true
cml:
type: string
description: XML (CML) containing the character information
example: <character></character>
CharacterRevision:
allOf:
- $ref: '#/components/schemas/TimestampCreated'
type: object
properties:
revision:
type: integer
description: Revision number
example: 5
comment:
type: string
description: Commit comment, Markdown formatted.
example: Leveled up!
security:
- bearer: [ ]
tags:
- name: Server Information
description: Information about the used API endpoint
- name: Authorization
description: Endpoints to authenticate a user
- name: Players
description: Endpoint for player registration and self-service
- name: Characters
description: Endpoint for Character browsing and management
- name: Rpg Systems
- name: Admin
description: Endpoints at which admins can use their privileges over normal users
paths:
/info:
get:
operationId: getInfo
tags:
- "Server Information"
description: Provides information about the server running this API
responses:
200:
description: Sever information
content:
'application/json':
schema:
type: object
properties:
url:
type: string
description: URL of the server to be used by humans
example: "https://penpaperbox.com"
terms_of_service:
type: string
description: URL proving human-readable terms of service for this server
example: "https://penpaperbox.com/tos"
privacy_policy:
type: string
description: URL proving human-readable privacy policy for this server
example: "https://penpaperbox.com/privacy"
server_version:
type: string
description: Version of the server software
example: "0.12.3"
api_version:
type: string
description: Version of the API that the server is using
example: "1.0.1"
/1.0/login:
post:
operationId: login
tags:
- "Authorization"
description: Generates a bearer token to be used in the `Authorization` header to authenticate the client, similar to [OAuth 2.0 Implicit Grant](https://datatracker.ietf.org/doc/html/rfc6749#section-4.2)
parameters:
- name: response_type
in: query
required: true
description: Must be set to `token`
example: token
schema:
type: string
- name: client_id
in: query
required: true
description: Will be ignored
schema:
type: string
- name: state
in: query
description: Can be provided and will be included in response in order to associate the response with the request
schema:
type: string
requestBody:
content:
'application/json':
schema:
type: object
properties:
user_name:
type: string
description: The player's email address
format: email
example: "bob@example.com"
password:
type: string
description: Player's password
responses:
200:
description: New token was issued. Response follows [RFC 6750](https://datatracker.ietf.org/doc/html/rfc6750#section-4)
content:
'application/json':
schema:
type: object
properties:
access_token:
type: string
description: The bearer token you can use in the `Authorization` header to authenticate as this user
token_type:
type: string
example: bearer
expires_in:
type: integer
description: Number of seconds until the token expires
example: 2592000
state:
type: string
description: The state provided in the request if any.
400:
description: Invalid credentials
content:
'application/json':
schema:
type: object
properties:
error:
type: string
description: Error string according to RFC6749
example: "access_denied"
error_description:
type: string
description: Human-readable description of the error
example: "Invalid email/password combination"
state:
type: string
description: The state provided in the request if any.
/1.0/logout:
post:
operationId: logout
tags:
- "Authorization"
description: Delete the currently used bearer token in the `Authorization` header, therefore performing a log out
responses:
200:
description: Access token was invalidated, therefore the session is logged out
content:
'application/json':
schema:
type: object
properties:
access_token:
type: string
description: The access token that was invalidated.
400:
description: An invalid token was provided.
content:
'application/json':
schema:
type: object
properties:
error:
type: string
description: Will be `invalid_token`
access_token:
type: string
description: The invalid access token you tried to invalidate
/1.0/players:
get:
operationId: GetPlayers
tags:
- "Players"
description: Search for players
parameters:
- name: q
in: query
description: Query string to search for in player names
schema:
type: string
- name: limit
in: query
description: Maximum number of fount players to be returned
schema:
type: integer
minimum: 1
maximum: 100
default: 10
- name: offset
in: query
description: Offset of the provided results from the first result, used for pagination of the results
schema:
type: integer
minimum: 0
default: 0
responses:
200:
description: Known Players
content:
'application/json':
schema:
type: object
properties:
offset:
type: integer
description: Offset of the first returned result from the first result in the database
query:
type: string
description: Query string used
players:
type: array
items:
$ref: '#/components/schemas/PlayerModel'
post:
operationId: CreatePlayer
tags:
- "Players"
description: Registers a new player.
requestBody:
content:
'application/json':
schema:
$ref: '#/components/schemas/PlayerOwnModel'
responses:
201:
description: Player was successfully created. The player should receive an email asking to validate the email address.
content:
'application/json':
schema:
$ref: '#/components/schemas/PlayerOwnModel'
400:
description: There is something wrong in the provided data model
content:
'application/json':
schema:
$ref: '#/components/schemas/ErrorWithFields'
/1.0/players/me:
get:
operationId: GetSelf
tags:
- "Players"
description: Get your own information
responses:
200:
description: Your own information
content:
'application/json':
schema:
$ref: '#/components/schemas/PlayerOwnModel'
401:
description: You don't have a valid bearer token so there is nothing that can be displayed
content:
'application/json':
schema:
$ref: '#/components/schemas/Error'
patch:
operationId: UpdateSelf
tags:
- "Players"
description: Update Player Information. You only need to provide the fields you want to update in your request.
requestBody:
content:
'application/json':
schema:
$ref: '#/components/schemas/PlayerOwnModel'
responses:
200:
description: Information has been updated.
content:
'application/json':
schema:
$ref: '#/components/schemas/PlayerOwnModel'
400:
description: There is something wrong with the model you have provided.
content:
'application/json':
schema:
$ref: '#/components/schemas/ErrorWithFields'
401:
description: Your provided bearer token does not indicate that you are either an admin or the user itself.
content:
'application/json':
schema:
$ref: '#/components/schemas/Error'
/1.0/players/me/resend_validation:
post:
operationId: ResendValidation
tags:
- "Players"
description: Trigger a new email to validate the player's email address
responses:
200:
description: Validation email sent
content:
'application/json':
schema:
type: object
properties:
email:
type: string
description: Address to which the validation email was sent
example: bob@example.com
400:
description: You are already validated
content:
'application/json':
schema:
$ref: '#/components/schemas/Error'
401:
description: You are not authorized
content:
'application/json':
schema:
$ref: '#/components/schemas/Error'
/1.0/players/{id}:
get:
operationId: GetPlayer
tags:
- "Players"
description: Get Detailed information on a single player
parameters:
- name: id
in: path
required: true
description: ID of the player
schema:
type: integer
responses:
200:
description: Detailed information on a single player
content:
'application/json':
schema:
$ref: '#/components/schemas/PlayerDetailsModel'
404:
description: No player found for provided ID
content:
'application/json':
schema:
$ref: '#/components/schemas/Error'
patch:
operationId: UpdatePlayer
tags:
- "Players"
- "Admin"
description: Update Player Information. You only need to provide the fields you want to update in your request.
parameters:
- name: id
in: path
required: true
description: ID of the player
schema:
type: integer
requestBody:
content:
'application/json':
schema:
$ref: '#/components/schemas/PlayerOwnModel'
responses:
200:
description: Information has been updated.
content:
'application/json':
schema:
$ref: '#/components/schemas/PlayerOwnModel'
400:
description: There is something wrong with the model you have provided.
content:
'application/json':
schema:
$ref: '#/components/schemas/ErrorWithFields'
401:
description: Your provided bearer token does not indicate that you are either an admin or the user itself.
content:
'application/json':
schema:
$ref: '#/components/schemas/Error'
/1.0/players/{id}/validate:
post:
operationId: ValidatePlayer
tags:
- "Players"
parameters:
- name: id
in: path
required: true
schema:
type: integer
description: ID of the player to validate
- name: token
in: query
required: true
schema:
type: string
description: Token received with validation email
responses:
200:
description: Player was validated
content:
'application/json':
schema:
$ref: '#/components/schemas/PlayerModel'
400:
description: Provided validation token was wrong
content:
'application/json':
schema:
$ref: '#/components/schemas/Error'
404:
description: No player found for ID
content:
'application/json':
schema:
$ref: '#/components/schemas/Error'
/1.0/players/{player_id}/calendar:
get:
operationId: GetPlayerCalendar
tags:
- "Players"
parameters:
- name: player_id
in: path
required: true
schema:
type: integer
description: ID of the player whose calendar shall be retrieved.
- name: token
in: query
required: true
schema:
type: string
description: The secret calendar token needed to access the calendar
responses:
200:
description: Returns the player's calender as iCal file
content:
'text/calendar':
schema:
type: string
400:
description: Provided calendar token not provided
403:
description: Token not valid
404:
description: No player found with this ID
post:
operationId: CreatePlayerCalendarToken
tags:
- "Players"
description: Create a new calendar access token for the player. If one already exists, it becomes invalid.
parameters:
- name: player_id
in: path
required: true
description: ID of the player
schema:
type: integer
responses:
201:
description: New Calendar access token was created
content:
'application/json':
schema:
$ref: '#/components/schemas/PlayerOwnModel'
401:
description: You are not logged in
content:
'application/json':
schema:
$ref: '#/components/schemas/Error'
403:
description: You are not this player
content:
'application/json':
schema:
$ref: '#/components/schemas/Error'
delete:
operationId: DeletePlayerCalendarToken
tags:
- "Players"
description: Invalidates this player's calendar token
parameters:
- name: player_id
in: path
required: true
description: ID of the player
schema:
type: integer
responses:
200:
description: Token was invalidated
content:
'application/json':
schema:
$ref: '#/components/schemas/PlayerOwnModel'
401:
description: You are not logged in
content:
'application/json':
schema:
$ref: '#/components/schemas/Error'
403:
description: You are not this player
content:
'application/json':
schema:
$ref: '#/components/schemas/Error'
/1.0/characters:
get:
operationId: GetCharacters
tags:
- "Characters"
description: Search for characters
parameters:
- name: q
in: query
description: Query string to search for in character names
schema:
type: string
- name: limit
in: query
description: Maximum number of found characters to be returned
schema:
type: integer
minimum: 1
maximum: 100
default: 10
- name: offset
in: query
description: Offset of the provided results from the first result, used for pagination of the results
schema:
type: integer
minimum: 0
default: 0
responses:
200:
description: Characters found in search. Private characters are not displayed unless they belong to the current player. Session characters are never displayed.
content:
'application/json':
schema:
type: object
properties:
offset:
type: integer
description: Offset of the first returned result from the first result in the database
query:
type: string
description: Query string used
characters:
type: array
items:
$ref: '#/components/schemas/CharacterModel'
post:
operationId: CreateCharacter
tags:
- "Characters"
description: Create a new character
requestBody:
content:
'application/json':
schema:
allOf:
- $ref: '#/components/schemas/CharacterDetailsModel'
- type: object
properties:
comment:
type: string
description: Optional commit comment for first revision, Markdown formatted
responses:
201:
description: Character was created
content:
'application/json':
schema:
$ref: '#/components/schemas/CharacterDetailsModel'
400:
description: Something is wrong with the provided character
content:
'application/json':
schema:
$ref: '#/components/schemas/ErrorWithFields'
401:
description: You are not logged in
content:
'application/json':
schema:
$ref: '#/components/schemas/Error'
/1.0/characters/{id}:
get:
operationId: GetCharacter
tags:
- "Characters"
- "Admin"
description: Get a details on a single character
parameters:
- name: id
in: path
schema:
type: integer
description: ID of the character
required: true
- name: rev
in: query
schema:
type: integer
description: Revision number of the character. If omnitted, the most recent version of the character is returned.
required: false
responses:
200:
description: The details of the character
content:
'application/json':
schema:
$ref: '#/components/schemas/CharacterDetailsModel'
400:
description: Requested revision does not exist within character
content:
'application/json':
schema:
$ref: '#/components/schemas/Error'
401:
description: This is a private character and you are not logged in
content:
'application/json':
schema:
$ref: '#/components/schemas/Error'
403:
description: This is a private character and you are neither the owner nor an admin
content:
'application/json':
schema:
$ref: '#/components/schemas/Error'
404:
description: There is no character with this ID
content:
'application/json':
schema:
$ref: '#/components/schemas/Error'
patch:
operationId: UpdateCharacter
tags:
- "Characters"
description: Update a character. You can also upload an XSLT document to patch the character CML.
parameters:
- name: id
in: path
schema:
type: integer
description: ID of the character
required: true
- name: comment
in: query
schema:
type: string
description: Optional commit comment, Markdown formatted
requestBody:
content:
'application/json':
schema:
allOf:
- $ref: '#/components/schemas/CharacterDetailsModel'
- type: object
properties:
latest_revision:
type: integer
description: The latest know revision of the character known to you. The request will be rejected with a 400 if this does not match the latest revision known to the database.
'application/xslt+xml':
schema:
type: string
example: |
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns="http://www.w3.org/TR/REC-html40">
<xsl:output method="xml"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="@value[parent::attribute and ../@name='attr']">
<xsl:attribute name="value">
<xsl:value-of select="'23'"/>
</xsl:attribute>
</xsl:template>
</xsl:stylesheet>
responses:
200:
description: Character was successfully updated
content:
'application/json':
schema:
$ref: '#/components/schemas/CharacterDetailsModel'
400:
description: There is something wrong with the data you provided
content:
'application/json':
schema:
$ref: '#/components/schemas/ErrorWithFields'
401:
description: You are not logged in
content:
'application/json':
schema:
$ref: '#/components/schemas/Error'
403:
description: You are not the owner of the character
content:
'application/json':
schema:
$ref: '#/components/schemas/Error'
404:
description: There is no character with this ID
content:
'application/json':
schema:
$ref: '#/components/schemas/Error'
delete:
operationId: DeleteCharacter
tags:
- "Characters"
- "Admin"
description: Deletes a character
parameters:
- name: id
in: path
schema:
type: integer
description: ID of the character
required: true
responses:
200:
description: Character was deleted
content:
'application/json':
schema:
$ref: '#/components/schemas/CharacterModel'
401:
description: You are not logged in
content:
'application/json':
schema:
$ref: '#/components/schemas/Error'
403:
description: You are neither the character's owner nor an admin
content:
'application/json':
schema:
$ref: '#/components/schemas/Error'
404:
description: There is no character with this ID
content:
'application/json':
schema:
$ref: '#/components/schemas/Error'
/1.0/characters/{id}/history:
get:
operationId: getCharacterHistory
tags:
- "Characters"
description: Gets information about character revisions
parameters:
- name: id
in: path
schema:
type: integer
description: ID of the character
required: true
responses:
200:
description: Information about the character's revisions, latest revision first
content:
'application/json':
schema:
type: array
items:
$ref: '#/components/schemas/CharacterRevision'
401:
description: This is a private character and you are not logged in
content:
'application/json':
schema:
$ref: '#/components/schemas/Error'
403:
description: This is a private character and you are neither the owner nor the admin
content:
'application/json':
schema:
$ref: '#/components/schemas/Error'
404:
description: There is no character with this ID
content:
'application/json':
schema:
$ref: '#/components/schemas/Error'
/1.0/characters/{id}/history/{revision}:
delete:
operationId: DeleteCharacterRevision
tags:
- "Characters"
description: Deletes a single revision from a character. This will not affect previous nor later revisions. Think of a character revision as a snapshot rather than a set of changes. You cannot delete the last remaining revision of a character.
parameters:
- name: id
in: path
schema:
type: integer
description: ID of the character
required: true
- name: revision
in: path
schema:
type: integer
description: Revision number within character to delete
required: true
responses:
200:
description: Revision was deleted
content:
'application/json':
schema:
$ref: '#/components/schemas/CharacterRevision'
400:
description: Revision does not exist within character or this is the last remaining revision of this character
content:
'application/json':
schema:
$ref: '#/components/schemas/Error'
401:
description: You are not logged in.
content:
'application/json':
schema:
$ref: '#/components/schemas/Error'
403:
description: You are not the owner of the character
content:
'application/json':
schema:
$ref: '#/components/schemas/Error'
404:
description: There is no character with this ID
content:
'application/json':
schema:
$ref: '#/components/schemas/Error'
/1.0/systems/:
get:
operationId: GetSystems
tags:
- "Rpg Systems"
description: Search for rpg systems
parameters:
- name: q
in: query
description: Query string to search for in character names
schema:
type: string
- name: limit
in: query
description: Maximum number of found characters to be returned
schema:
type: integer
minimum: 1
maximum: 100
default: 10
- name: offset
in: query
description: Offset of the provided results from the first result, used for pagination of the results
schema:
type: integer
minimum: 0
default: 0
responses:
200:
description: "A list of all systems that match the query"
content:
'application/json':
schema:
type: object
properties:
offset:
type: integer
description: Offset of the first returned result from the first result in the database
query:
type: string
description: Query string used
systems:
type: array
items:
type: object
properties:
name:
type: string
description: Name of the System
interested_players:
type: integer
description: Number of players interested in the system
experienced_players:
type: integer
description: Number of players experienced in the system
campaigns:
type: integer
description: Number of campaigns running this system
characters:
type: integer
description: Number of characters using this system
/1.0/systems/{name}:
patch:
operationId: UpdateSystem
tags:
- "Rpg Systems"
- "Admin"
description: Rename a system. Must be an admin.
parameters:
- name: name
in: path
required: true
schema:
type: string
requestBody:
content:
'application/json':
schema:
type: object
properties:
new_name:
type: string
description: "New name for the system"
example: "Shadowrun 6"
responses:
200:
description: System has been renamed
content:
'application/json':
schema:
type: string
description: New name
example: "Shadowrun 6"
400:
description: Missing new_name parameter
content:
'application/json':
schema:
$ref: '#/components/schemas/Error'
401:
description: You are not logged in.
content:
'application/json':
schema:
$ref: '#/components/schemas/Error'
403:
description: You are not an administrator
content:
'application/json':
schema:
$ref: '#/components/schemas/Error'
404:
description: No system with that name
content:
'application/json':
schema:
$ref: '#/components/schemas/Error'
delete:
operationId: DeleteSystem
tags:
- "Rpg Systems"
- "Admin"
description: Delete a system. Must be admin
parameters:
- name: name
in: path
required: true
schema:
type: string
description: Name of the system
example: "Shadowrun 6"
responses:
200:
description: System deleted
content:
'application/json':
schema:
type: object
properties:
name:
type: string
description: Name of the deleted system
example: "Shadowrun 6"
401:
description: You are not logged in
content:
'application/json':
schema:
$ref: '#/components/schemas/Error'
403:
description: Your are not an admin
content:
'application/json':
schema:
$ref: '#/components/schemas/Error'
404:
description: There is no system with that name
content:
'application/json':
schema:
$ref: '#/components/schemas/Error'