Open API 3.0

- Added first draft of yaml file
- Added Python stubs generated by postman export tool
This commit is contained in:
Daniel Schick 2023-03-02 09:22:37 +01:00
parent 8af8e2b575
commit c69d13d1f3
17 changed files with 831 additions and 0 deletions

396
misc/index.yaml Normal file
View File

@ -0,0 +1,396 @@
openapi: '3.0.0'
info:
version: '1.0.0'
title: 'Bremen calling API'
description: Administer DEBRE ship calls, times and notifications
termsOfService: "https://www.bsmd.de/" # url to terms page
contact:
name: "Bremen calling API"
url: "https://www.textbausteine.net"
email: "info@textbausteine.net"
license:
name: "Use at your own risk"
url: "https://www.bsmd.de/license"
servers:
# tutorial: https://idratherbewriting.com/learnapidoc/pubapis_openapi_step3_servers_object.html
- url : "https://puls200.dyn-dns.org:8088/brecal/api"
description: "Test server self-hosted by yours truly"
paths:
# tutorial: https://idratherbewriting.com/learnapidoc/pubapis_openapi_step4_paths_object.html
/verify:
get:
summary: Get the user id if successful
responses:
200:
description: Successful response
content:
application/json:
schema:
title: Verify user token
type: integer
400:
$ref: '#/components/responses/400'
401:
$ref: '#/components/responses/401'
500:
$ref: '#/components/responses/500'
503:
$ref: '#/components/responses/503'
/shipcalls:
get:
summary: Gets a list of ship calls
parameters:
- name: participant_id
in: query
required: true
description: "**Id of participant**. *Example: 2*. Id of participant entity requesting ship calls"
schema:
type: integer
responses:
200:
description: ship call list
content:
application/json:
schema:
$ref: '#/components/schemas/shipcalls'
400:
$ref: '#/components/responses/400'
401:
$ref: '#/components/responses/401'
500:
$ref: '#/components/responses/500'
503:
$ref: '#/components/responses/503'
post:
summary: Create a new ship call
requestBody:
description: Creates a new ship call. **Do not** provide id parameter.
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/shipcall'
responses:
400:
$ref: '#/components/responses/400'
401:
$ref: '#/components/responses/401'
500:
$ref: '#/components/responses/500'
503:
$ref: '#/components/responses/503'
put:
summary: Updates a ship call
requestBody:
description: Creates a new ship call. The id parameter is **required**.
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/shipcall'
responses:
400:
$ref: '#/components/responses/400'
401:
$ref: '#/components/responses/401'
500:
$ref: '#/components/responses/500'
503:
$ref: '#/components/responses/503'
/participant:
get:
summary: gets a particular participant entry corresponding to user id
parameters:
- name: user_id
in: query
required: true
description: "**Id of user**. *Example: 2*. User id returned by verify call."
schema:
type: integer
responses:
200:
description: ship call list
content:
application/json:
schema:
$ref: '#/components/schemas/participant'
400:
$ref: '#/components/responses/400'
401:
$ref: '#/components/responses/401'
500:
$ref: '#/components/responses/500'
503:
$ref: '#/components/responses/503'
/times:
get:
summary: Get all recorded times for a a ship call
parameters:
- name: shipcall_id
in: query
description: "**Id**. *Example: 42*. Id of referenced ship call."
schema:
type: integer
responses:
200:
description: list of recorded times
content:
application/json:
schema:
$ref: '#/components/schemas/times_list'
400:
$ref: '#/components/responses/400'
401:
$ref: '#/components/responses/401'
500:
$ref: '#/components/responses/500'
503:
$ref: '#/components/responses/503'
post:
summary: Create a new times entry for a ship call
requestBody:
description: Times entry that will be added to the ship call. **Do not** provide id parameter.
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/times'
responses:
400:
$ref: '#/components/responses/400'
401:
$ref: '#/components/responses/401'
500:
$ref: '#/components/responses/500'
503:
$ref: '#/components/responses/503'
put:
summary: Update a times entry for a ship call
requestBody:
description: Times entry that will be added to the ship call. The id parameter is **required**.
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/times'
responses:
400:
$ref: '#/components/responses/400'
401:
$ref: '#/components/responses/401'
500:
$ref: '#/components/responses/500'
503:
$ref: '#/components/responses/503'
delete:
summary: Delete a times entry for a ship call.
parameters:
- name: id
in: query
required: true
schema:
$ref: '#/components/schemas/timesId'
responses:
400:
$ref: '#/components/responses/400'
401:
$ref: '#/components/responses/401'
500:
$ref: '#/components/responses/500'
503:
$ref: '#/components/responses/503'
/notifications:
get:
summary: Gets a list of notifications pursuant to a specified participant and ship call
parameters:
- name: participant_id
in: query
required: true
description: "**Id of participant**. *Example: 2*. Id returned through loading of participant"
schema:
type: integer
- name: shipcall_id
in: query
required: true
description: "**Id of ship call**. *Example: 52*. Id given in ship call list"
schema:
$ref: '#/components/schemas/shipcallId'
responses:
200:
description: notification list
content:
application/json:
schema:
$ref: '#/components/schemas/notification'
400:
$ref: '#/components/responses/400'
401:
$ref: '#/components/responses/401'
500:
$ref: '#/components/responses/500'
503:
$ref: '#/components/responses/503'
components:
schemas:
timesId:
description: The unique identifier for a times entry
type: integer
shipcallId:
description: The unique identifier of a ship call
type: integer
shipcall:
type: object
required:
- id
- ship_id
- type
- eta
- voyage
- etd
properties:
id:
$ref: '#/components/schemas/shipcallId'
type:
type: string
enum:
- incoming
- outgoing
- shifting
description:
type: string
shipcalls:
type: array
items:
$ref: '#/components/schemas/shipcall'
times:
type: object
description: the id parameter needs to be missing on POST and to be present on PUT (Update) calls, otherwise a 400 response will be generated
required:
- shipcall_id
- participant_id
properties:
id:
type: integer
start_planned:
type: string
format: date-time
end_planned:
type: string
format: date-time
duration_planned:
type: integer
start_actual:
type: string
format: date-time
end_actual:
type: string
format: date-time
shipcall_id:
type: integer
participant_id:
type: integer
times_list:
type: array
items:
$ref: '#/components/schemas/times'
notification:
type: object
description: a notification created by the engine if a times entry violates a rule
properties:
id:
type: integer
times_id:
type: integer
participant_id:
type: integer
notification_type:
type: string
enum: [undefined, email, push]
timestamp:
type: string
format: date-time
acknowledged:
type: boolean
notification_list:
type: array
items:
$ref: '#/components/schemas/notification'
participant:
type: object
description: A organisational entity that participates in Bremen Calling
properties:
id:
type: integer
name:
type: string
street:
type: string
postal code:
type: string
city:
type: string
Error:
type: object
required:
- message
properties:
message:
description: A human readable error message
type: string
securitySchemes:
ApiKey:
type: apiKey
in: header
name: X-Api-Key
responses:
400:
description: Invalid input
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
401:
description: Not authorized
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
500:
description: Unexpected error
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
503:
description: Not available
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
security:
- ApiKey: []
externalDocs:
url: http://textbausteine.net/
description: Extra documentation and conditions for Bremen Calling

View File

@ -0,0 +1,29 @@
from flask import Flask
import os
from .api import shipcalls
from .api import verify
def create_app(test_config=None):
app = Flask(__name__, instance_relative_config=True)
app.config.from_mapping(
SECRET_KEY='dev'
)
if test_config is None:
app.config.from_pyfile('config.py', silent=True)
else:
app.config.from_mapping(test_config)
try:
print(f'Instance path = {app.instance_path}')
os.makedirs(app.instance_path)
except OSError:
pass
# Add blueprints
app.register_blueprint(shipcalls.bp)
app.register_blueprint(verify.bp)
return app

View File

@ -0,0 +1,17 @@
from flask import Blueprint, request
from webargs.flaskparser import parser
from marshmallow import Schema, fields
from ..schemas import model
from .. import impl
bp = Blueprint('notifications', __name__)
@bp.route('/notifications', methods=['get'])
def GetNotifications():
options = {}
options["participant_id"] = request.args.get("participant_id")
options["shipcall_id"] = request.args.get("shipcall_id")
return impl.notifications.GetNotifications(options)

View File

@ -0,0 +1,16 @@
from flask import Blueprint, request
from webargs.flaskparser import parser
from marshmallow import Schema, fields
from ..schemas import model
from .. import impl
bp = Blueprint('participant', __name__)
@bp.route('/participant', methods=['get'])
def GetParticipant():
options = {}
options["user_id"] = request.args.get("user_id")
return impl.participant.GetParticipant(options)

View File

@ -0,0 +1,36 @@
from flask import Blueprint, request
from webargs.flaskparser import parser
from marshmallow import Schema, fields
from ..schemas import model
from .. import impl
bp = Blueprint('shipcalls', __name__)
@bp.route('/shipcalls', methods=['get'])
def GetShipcalls():
options = {}
options["participant_id"] = request.args.get("participant_id")
return impl.shipcalls.GetShipcalls(options)
@bp.route('/shipcalls', methods=['post'])
def PostShipcalls():
schema = model.Shipcall()
body = parser.parse(schema, request, location='json')
return impl.shipcalls.PostShipcalls(body)
@bp.route('/shipcalls', methods=['put'])
def PutShipcalls():
schema = model.Shipcall()
body = parser.parse(schema, request, location='json')
return impl.shipcalls.PutShipcalls(body)

View File

@ -0,0 +1,45 @@
from flask import Blueprint, request
from webargs.flaskparser import parser
from marshmallow import Schema, fields
from ..schemas import model
from .. import impl
bp = Blueprint('times', __name__)
@bp.route('/times', methods=['get'])
def GetTimes():
options = {}
options["shipcall_id"] = request.args.get("shipcall_id")
return impl.times.GetTimes(options)
@bp.route('/times', methods=['post'])
def PostTimes():
schema = model.Times()
body = parser.parse(schema, request, location='json')
return impl.times.PostTimes(body)
@bp.route('/times', methods=['put'])
def PutTimes():
schema = model.Times()
body = parser.parse(schema, request, location='json')
return impl.times.PutTimes(body)
@bp.route('/times', methods=['delete'])
def DeleteTimes():
options = {}
options["id"] = request.args.get("id")
return impl.times.DeleteTimes(options)

View File

@ -0,0 +1,13 @@
from flask import Blueprint, request
from webargs.flaskparser import parser
from marshmallow import Schema, fields
from ..schemas import model
from .. import impl
bp = Blueprint('verify', __name__)
@bp.route('/verify', methods=['get'])
def GetVerify():
return impl.verify.GetVerify()

View File

@ -0,0 +1,5 @@
from . import notifications
from . import participant
from . import shipcalls
from . import times
from . import verify

View File

@ -0,0 +1,25 @@
import json
def GetNotifications(options):
"""
:param options: A dictionary containing all the paramters for the Operations
options["participant_id"]: **Id of participant**. *Example: 2*. Id returned through loading of participant
options["shipcall_id"]: **Id of ship call**. *Example: 52*. Id given in ship call list
"""
# Implement your business logic here
# All the parameters are present in the options argument
return json.dumps({
"acknowledged": "<boolean>",
"id": "<integer>",
"notification_type": "<string>",
"participant_id": "<integer>",
"times_id": "<integer>",
"timestamp": "<date-time>",
}), 200

View File

@ -0,0 +1,23 @@
import json
def GetParticipant(options):
"""
:param options: A dictionary containing all the paramters for the Operations
options["user_id"]: **Id of user**. *Example: 2*. User id returned by verify call.
"""
# Implement your business logic here
# All the parameters are present in the options argument
return json.dumps({
"city": "<string>",
"id": "<integer>",
"name": "<string>",
"postal code": "<string>",
"street": "<string>",
}), 200

View File

@ -0,0 +1,45 @@
import json
def GetShipcalls(options):
"""
:param options: A dictionary containing all the paramters for the Operations
options["participant_id"]: **Id of participant**. *Example: 2*. Id of participant entity requesting ship calls
"""
# Implement your business logic here
# All the parameters are present in the options argument
return json.dumps([{
"description": "<string>",
"id": "<ShipcallId>",
"type": "<string>",
}]), 200
def PostShipcalls(body):
"""
:param body: The parsed body of the request
"""
# Implement your business logic here
# All the parameters are present in the options argument
return 400
def PutShipcalls(body):
"""
:param body: The parsed body of the request
"""
# Implement your business logic here
# All the parameters are present in the options argument
return 400

View File

@ -0,0 +1,63 @@
import json
def GetTimes(options):
"""
:param options: A dictionary containing all the paramters for the Operations
options["shipcall_id"]: **Id**. *Example: 42*. Id of referenced ship call.
"""
# Implement your business logic here
# All the parameters are present in the options argument
return json.dumps([{
"duration_planned": "<integer>",
"end_actual": "<date-time>",
"end_planned": "<date-time>",
"id": "<integer>",
"participant_id": "<integer>",
"shipcall_id": "<integer>",
"start_actual": "<date-time>",
"start_planned": "<date-time>",
}]), 200
def PostTimes(body):
"""
:param body: The parsed body of the request
"""
# Implement your business logic here
# All the parameters are present in the options argument
return 400
def PutTimes(body):
"""
:param body: The parsed body of the request
"""
# Implement your business logic here
# All the parameters are present in the options argument
return 400
def DeleteTimes(options):
"""
:param options: A dictionary containing all the paramters for the Operations
options["id"]
"""
# Implement your business logic here
# All the parameters are present in the options argument
return 400

View File

@ -0,0 +1,15 @@
import json
def GetVerify():
"""
"""
# Implement your business logic here
# All the parameters are present in the options argument
return json.dumps("<integer>"), 200

View File

@ -0,0 +1,69 @@
from marshmallow import Schema, fields
class Error(Schema):
message = fields.String(required=True,)
class GetVerifyInlineResp(Schema):
pass
class Notification(Schema):
acknowledged = fields.Boolean()
id = fields.Int()
notification_type = fields.String()
participant_id = fields.Int()
times_id = fields.Int()
timestamp = fields.DateTime()
class Participant(Schema):
city = fields.String()
id = fields.Int()
name = fields.String()
postal_code = fields.String(data_key="postal code",)
street = fields.String()
class Shipcall(Schema):
description = fields.String()
id = fields.Raw(required=True,)
type = fields.String(required=True,)
class ShipcallId(Schema):
pass
class Times(Schema):
duration_planned = fields.Int()
end_actual = fields.DateTime()
end_planned = fields.DateTime()
id = fields.Int()
participant_id = fields.Int(required=True,)
shipcall_id = fields.Int(required=True,)
start_actual = fields.DateTime()
start_planned = fields.DateTime()
class TimesId(Schema):
pass
class NotificationList(Notification):
pass
class Shipcalls(Shipcall):
pass
class TimesList(Times):
pass

14
src/server/README.md Normal file
View File

@ -0,0 +1,14 @@
# BreCal
## OpenAPI 3.0 Generated Flask project
All the routes are defined in 'project/api' folder.
Each route parses the request and calls the corresponding function in the 'project/impl' directory passing all the parameters and request body as function arguments.
To run this project:
```
pip install -r requirements.txt
export FLASK_APP='BreCal'
export FLASK_ENV=development
flask run
```

View File

@ -0,0 +1,8 @@
click==7.1.2
Flask==1.1.2
itsdangerous==1.1.0
Jinja2==2.11.2
MarkupSafe==1.1.1
marshmallow==3.9.1
webargs==6.1.1
Werkzeug==1.0.1

12
src/server/setup.py Normal file
View File

@ -0,0 +1,12 @@
from setuptools import find_packages, setup
setup(
name='BreCal',
version='1.0.0',
packages=find_packages(),
include_package_data=True,
zip_safe=False,
install_requires=[
'flask'
]
)