Updated openapi docs and generated some client code

This commit is contained in:
Tomas Groth 2024-04-22 22:33:51 +02:00
parent c02c3568da
commit 45b43324a8
15 changed files with 599 additions and 15 deletions

View File

@ -156,6 +156,7 @@ class SyncType(IntEnum):
Disabled = 0
Folder = 1
Ftp = 2
WebService = 3
@unique

View File

@ -0,0 +1,3 @@
from .api_config import *
from .models import *
from .services import *

View File

@ -0,0 +1,30 @@
import os
from typing import Optional, Union
from pydantic import BaseModel, Field
class APIConfig(BaseModel):
base_path: str = "http://localhost:8888/api/v1"
verify: Union[bool, str] = True
def get_access_token(self) -> Optional[str]:
try:
return os.environ["access_token"]
except KeyError:
return None
def set_access_token(self, value: str):
raise Exception(
"This client was generated with an environment variable for the access token. Please set the environment variable 'access_token' to the access token."
)
class HTTPException(Exception):
def __init__(self, status_code: int, message: str):
self.status_code = status_code
self.message = message
super().__init__(f"{status_code} {message}")
def __str__(self):
return f"{self.status_code} {self.message}"

View File

@ -0,0 +1,16 @@
from typing import *
from pydantic import BaseModel, Field
class ApiResponse(BaseModel):
"""
None model
"""
code: Optional[int] = Field(alias="code", default=None)
type: Optional[str] = Field(alias="type", default=None)
message: Optional[str] = Field(alias="message", default=None)

View File

@ -0,0 +1,18 @@
from typing import *
from pydantic import BaseModel, Field
class ItemInfo(BaseModel):
"""
None model
"""
uuid: Optional[str] = Field(alias="uuid", default=None)
version: Optional[int] = Field(alias="version", default=None)
created: Optional[str] = Field(alias="created", default=None)
updated: Optional[str] = Field(alias="updated", default=None)

View File

@ -0,0 +1,14 @@
from typing import *
from pydantic import BaseModel, Field
from .ItemInfo import ItemInfo
class ItemList(BaseModel):
"""
None model
"""
list: Optional[List[Optional[ItemInfo]]] = Field(alias="list", default=None)

View File

@ -0,0 +1,22 @@
from typing import *
from pydantic import BaseModel, Field
class TextItem(BaseModel):
"""
None model
"""
uuid: Optional[str] = Field(alias="uuid", default=None)
version: Optional[int] = Field(alias="version", default=None)
created: Optional[str] = Field(alias="created", default=None)
updated: Optional[str] = Field(alias="updated", default=None)
title: Optional[str] = Field(alias="title", default=None)
itemxml: Optional[str] = Field(alias="itemxml", default=None)

View File

@ -0,0 +1,4 @@
from .ApiResponse import *
from .ItemInfo import *
from .ItemList import *
from .TextItem import *

View File

@ -0,0 +1,3 @@
The restclient client was created using the OpenAPI python generator
See https://marcomuellner.github.io/openapi-python-generator/

View File

@ -0,0 +1,169 @@
import json
from typing import *
import requests
from ..api_config import APIConfig, HTTPException
from ..models import *
def getCustomslideList(churchId: str, api_config_override: Optional[APIConfig] = None) -> ItemList:
api_config = api_config_override if api_config_override else APIConfig()
base_path = api_config.base_path
path = f"/{churchId}/custom-list"
headers = {
"Content-Type": "application/json",
"Accept": "application/json",
"Authorization": f"Bearer { api_config.get_access_token() }",
}
query_params: Dict[str, Any] = {}
query_params = {key: value for (key, value) in query_params.items() if value is not None}
response = requests.request(
"get",
f"{base_path}{path}",
headers=headers,
params=query_params,
verify=api_config.verify,
)
if response.status_code != 200:
raise HTTPException(response.status_code, f" failed with status code: {response.status_code}")
return ItemList(**response.json()) if response.json() is not None else ItemList()
def getCustomslide(churchId: str, uuid: str, api_config_override: Optional[APIConfig] = None) -> TextItem:
api_config = api_config_override if api_config_override else APIConfig()
base_path = api_config.base_path
path = f"/{churchId}/custom/{uuid}"
headers = {
"Content-Type": "application/json",
"Accept": "application/json",
"Authorization": f"Bearer { api_config.get_access_token() }",
}
query_params: Dict[str, Any] = {}
query_params = {key: value for (key, value) in query_params.items() if value is not None}
response = requests.request(
"get",
f"{base_path}{path}",
headers=headers,
params=query_params,
verify=api_config.verify,
)
if response.status_code != 200:
raise HTTPException(response.status_code, f" failed with status code: {response.status_code}")
return TextItem(**response.json()) if response.json() is not None else TextItem()
def updateCustomslide(
churchId: str, uuid: str, data: TextItem, api_config_override: Optional[APIConfig] = None
) -> None:
api_config = api_config_override if api_config_override else APIConfig()
base_path = api_config.base_path
path = f"/{churchId}/custom/{uuid}"
headers = {
"Content-Type": "application/json",
"Accept": "application/json",
"Authorization": f"Bearer { api_config.get_access_token() }",
}
query_params: Dict[str, Any] = {}
query_params = {key: value for (key, value) in query_params.items() if value is not None}
response = requests.request(
"put", f"{base_path}{path}", headers=headers, params=query_params, verify=api_config.verify, json=data.dict()
)
if response.status_code != 200:
raise HTTPException(response.status_code, f" failed with status code: {response.status_code}")
return None
def deleteCustomslide(churchId: str, uuid: str, api_config_override: Optional[APIConfig] = None) -> None:
api_config = api_config_override if api_config_override else APIConfig()
base_path = api_config.base_path
path = f"/{churchId}/custom/{uuid}"
headers = {
"Content-Type": "application/json",
"Accept": "application/json",
"Authorization": f"Bearer { api_config.get_access_token() }",
}
query_params: Dict[str, Any] = {}
query_params = {key: value for (key, value) in query_params.items() if value is not None}
response = requests.request(
"delete",
f"{base_path}{path}",
headers=headers,
params=query_params,
verify=api_config.verify,
)
if response.status_code != 200:
raise HTTPException(response.status_code, f" failed with status code: {response.status_code}")
return None
def getCustomslideVersion(
churchId: str, uuid: str, version: int, api_config_override: Optional[APIConfig] = None
) -> TextItem:
api_config = api_config_override if api_config_override else APIConfig()
base_path = api_config.base_path
path = f"/{churchId}/custom/{uuid}/{version}"
headers = {
"Content-Type": "application/json",
"Accept": "application/json",
"Authorization": f"Bearer { api_config.get_access_token() }",
}
query_params: Dict[str, Any] = {}
query_params = {key: value for (key, value) in query_params.items() if value is not None}
response = requests.request(
"get",
f"{base_path}{path}",
headers=headers,
params=query_params,
verify=api_config.verify,
)
if response.status_code != 200:
raise HTTPException(response.status_code, f" failed with status code: {response.status_code}")
return TextItem(**response.json()) if response.json() is not None else TextItem()
def getCustomslideHistory(churchId: str, uuid: str, api_config_override: Optional[APIConfig] = None) -> TextItem:
api_config = api_config_override if api_config_override else APIConfig()
base_path = api_config.base_path
path = f"/{churchId}/custom-history/{uuid}"
headers = {
"Content-Type": "application/json",
"Accept": "application/json",
"Authorization": f"Bearer { api_config.get_access_token() }",
}
query_params: Dict[str, Any] = {}
query_params = {key: value for (key, value) in query_params.items() if value is not None}
response = requests.request(
"get",
f"{base_path}{path}",
headers=headers,
params=query_params,
verify=api_config.verify,
)
if response.status_code != 200:
raise HTTPException(response.status_code, f" failed with status code: {response.status_code}")
return TextItem(**response.json()) if response.json() is not None else TextItem()

View File

@ -0,0 +1,165 @@
import json
from typing import *
import requests
from ..api_config import APIConfig, HTTPException
from ..models import *
def getSongList(churchId: str, api_config_override: Optional[APIConfig] = None) -> ItemList:
api_config = api_config_override if api_config_override else APIConfig()
base_path = api_config.base_path
path = f"/{churchId}/song-list"
headers = {
"Content-Type": "application/json",
"Accept": "application/json",
"Authorization": f"Bearer { api_config.get_access_token() }",
}
query_params: Dict[str, Any] = {}
query_params = {key: value for (key, value) in query_params.items() if value is not None}
response = requests.request(
"get",
f"{base_path}{path}",
headers=headers,
params=query_params,
verify=api_config.verify,
)
if response.status_code != 200:
raise HTTPException(response.status_code, f" failed with status code: {response.status_code}")
return ItemList(**response.json()) if response.json() is not None else ItemList()
def getSong(churchId: str, uuid: str, api_config_override: Optional[APIConfig] = None) -> TextItem:
api_config = api_config_override if api_config_override else APIConfig()
base_path = api_config.base_path
path = f"/{churchId}/song/{uuid}"
headers = {
"Content-Type": "application/json",
"Accept": "application/json",
"Authorization": f"Bearer { api_config.get_access_token() }",
}
query_params: Dict[str, Any] = {}
query_params = {key: value for (key, value) in query_params.items() if value is not None}
response = requests.request(
"get",
f"{base_path}{path}",
headers=headers,
params=query_params,
verify=api_config.verify,
)
if response.status_code != 200:
raise HTTPException(response.status_code, f" failed with status code: {response.status_code}")
return TextItem(**response.json()) if response.json() is not None else TextItem()
def updateSong(churchId: str, uuid: str, data: TextItem, api_config_override: Optional[APIConfig] = None) -> None:
api_config = api_config_override if api_config_override else APIConfig()
base_path = api_config.base_path
path = f"/{churchId}/song/{uuid}"
headers = {
"Content-Type": "application/json",
"Accept": "application/json",
"Authorization": f"Bearer { api_config.get_access_token() }",
}
query_params: Dict[str, Any] = {}
query_params = {key: value for (key, value) in query_params.items() if value is not None}
response = requests.request(
"put", f"{base_path}{path}", headers=headers, params=query_params, verify=api_config.verify, json=data.dict()
)
if response.status_code != 200:
raise HTTPException(response.status_code, f" failed with status code: {response.status_code}")
return None
def deleteSong(churchId: str, uuid: str, api_config_override: Optional[APIConfig] = None) -> None:
api_config = api_config_override if api_config_override else APIConfig()
base_path = api_config.base_path
path = f"/{churchId}/song/{uuid}"
headers = {
"Content-Type": "application/json",
"Accept": "application/json",
"Authorization": f"Bearer { api_config.get_access_token() }",
}
query_params: Dict[str, Any] = {}
query_params = {key: value for (key, value) in query_params.items() if value is not None}
response = requests.request(
"delete",
f"{base_path}{path}",
headers=headers,
params=query_params,
verify=api_config.verify,
)
if response.status_code != 200:
raise HTTPException(response.status_code, f" failed with status code: {response.status_code}")
return None
def getSongVersion(churchId: str, uuid: str, version: int, api_config_override: Optional[APIConfig] = None) -> TextItem:
api_config = api_config_override if api_config_override else APIConfig()
base_path = api_config.base_path
path = f"/{churchId}/song/{uuid}/{version}"
headers = {
"Content-Type": "application/json",
"Accept": "application/json",
"Authorization": f"Bearer { api_config.get_access_token() }",
}
query_params: Dict[str, Any] = {}
query_params = {key: value for (key, value) in query_params.items() if value is not None}
response = requests.request(
"get",
f"{base_path}{path}",
headers=headers,
params=query_params,
verify=api_config.verify,
)
if response.status_code != 200:
raise HTTPException(response.status_code, f" failed with status code: {response.status_code}")
return TextItem(**response.json()) if response.json() is not None else TextItem()
def getSongHistory(churchId: str, uuid: str, api_config_override: Optional[APIConfig] = None) -> TextItem:
api_config = api_config_override if api_config_override else APIConfig()
base_path = api_config.base_path
path = f"/{churchId}/song-history/{uuid}"
headers = {
"Content-Type": "application/json",
"Accept": "application/json",
"Authorization": f"Bearer { api_config.get_access_token() }",
}
query_params: Dict[str, Any] = {}
query_params = {key: value for (key, value) in query_params.items() if value is not None}
response = requests.request(
"get",
f"{base_path}{path}",
headers=headers,
params=query_params,
verify=api_config.verify,
)
if response.status_code != 200:
raise HTTPException(response.status_code, f" failed with status code: {response.status_code}")
return TextItem(**response.json()) if response.json() is not None else TextItem()

View File

@ -26,6 +26,7 @@ from openlp.core.common import Settings, registry
from openlp.core.lib.db import Manager
from openlp.plugins.remotesync.lib.backends.synchronizer import Synchronizer
from openlp.plugins.songs.lib.db import init_schema, Song
from openlp.plugins.remotesync.lib.backends.restclient.services import song_service, custom_service
class WebServiceSynchronizer(Synchronizer):

View File

@ -6,13 +6,12 @@ info:
Some useful links:
- [The OpenLP remotesync MR](https://gitlab.com/openlp/openlp/-/merge_requests/9)
termsOfService: http://swagger.io/terms/
contact:
email: dev@openlp.io
license:
name: Apache 2.0
url: http://www.apache.org/licenses/LICENSE-2.0.html
version: 1.0.11
version: 0.9.1
externalDocs:
description: Find out more about Swagger
url: http://swagger.io
@ -21,6 +20,8 @@ servers:
tags:
- name: song
description: Operations about songs
- name: custom
description: Operations about custom slides
paths:
/{churchId}/song-list:
get:
@ -50,12 +51,55 @@ paths:
description: Invalid uuid supplied
'404':
description: Song not found
security:
- openlp_auth:
- write:song
- read:song
/{churchId}/song-list/changes/{sinceDateTime}:
get:
tags:
- song
summary: Get list of songs changed since given timestamp
description: ''
operationId: getSongListChangesSince
parameters:
- name: churchId
in: path
description: The id of the church.
required: true
schema:
type: string
- name: sinceDateTime
in: path
description: The timestamp to look for changes after
required: true
schema:
type: string
format: date-time
responses:
'200':
description: successful operation
content:
application/json:
schema:
$ref: '#/components/schemas/ItemList'
application/xml:
schema:
$ref: '#/components/schemas/ItemList'
'400':
description: Invalid uuid supplied
'404':
description: Song not found
security:
- openlp_auth:
- write:song
- read:song
/{churchId}/song/{uuid}:
get:
tags:
- song
summary: Get song by uuid
description: fwef
description: Get song by uuid
operationId: getSong
parameters:
- name: churchId
@ -84,6 +128,10 @@ paths:
description: Invalid uuid supplied
'404':
description: Song not found
security:
- openlp_auth:
- write:song
- read:song
put:
tags:
- song
@ -116,8 +164,14 @@ paths:
schema:
$ref: '#/components/schemas/TextItem'
responses:
default:
'200':
description: successful operation
'409':
description: A conflict occured. The version requested to be saved is not the newest.
security:
- openlp_auth:
- write:song
- read:song
delete:
tags:
- song
@ -142,6 +196,10 @@ paths:
description: Invalid uuid supplied
'404':
description: Song not found
security:
- openlp_auth:
- write:song
- read:song
/{churchId}/song/{uuid}/{version}:
get:
tags:
@ -182,6 +240,10 @@ paths:
description: Invalid uuid supplied
'404':
description: Song not found
security:
- openlp_auth:
- write:song
- read:song
/{churchId}/song-history/{uuid}:
get:
tags:
@ -216,6 +278,10 @@ paths:
description: Invalid uuid supplied
'404':
description: Song not found
security:
- openlp_auth:
- write:song
- read:song
/{churchId}/custom-list:
get:
tags:
@ -244,6 +310,49 @@ paths:
description: Invalid uuid supplied
'404':
description: Custom slide not found
security:
- openlp_auth:
- write:custom
- read:custom
/{churchId}/custom-list/changes/{sinceDateTime}:
get:
tags:
- song
summary: Get list of custom slides changed since given timestamp
description: ''
operationId: getCustomSlideListChangesSince
parameters:
- name: churchId
in: path
description: The id of the church.
required: true
schema:
type: string
- name: sinceDateTime
in: path
description: The timestamp to look for changes after
required: true
schema:
type: string
format: date-time
responses:
'200':
description: successful operation
content:
application/json:
schema:
$ref: '#/components/schemas/ItemList'
application/xml:
schema:
$ref: '#/components/schemas/ItemList'
'400':
description: Invalid uuid supplied
'404':
description: Song not found
security:
- openlp_auth:
- write:song
- read:song
/{churchId}/custom/{uuid}:
get:
tags:
@ -278,6 +387,10 @@ paths:
description: Invalid uuid supplied
'404':
description: Custom slide not found
security:
- openlp_auth:
- write:custom
- read:custom
put:
tags:
- custom
@ -310,8 +423,14 @@ paths:
schema:
$ref: '#/components/schemas/TextItem'
responses:
default:
'200':
description: successful operation
'409':
description: A conflict occured. The version requested to be saved is not the newest.
security:
- openlp_auth:
- write:custom
- read:custom
delete:
tags:
- custom
@ -336,6 +455,10 @@ paths:
description: Invalid uuid supplied
'404':
description: Custom slide not found
security:
- openlp_auth:
- write:custom
- read:custom
/{churchId}/custom/{uuid}/{version}:
get:
tags:
@ -376,6 +499,10 @@ paths:
description: Invalid uuid supplied
'404':
description: Custom slide not found
security:
- openlp_auth:
- write:custom
- read:custom
/{churchId}/custom-history/{uuid}:
get:
tags:
@ -410,6 +537,10 @@ paths:
description: Invalid uuid supplied
'404':
description: Custom slide not found
security:
- openlp_auth:
- write:custom
- read:custom
components:
schemas:
TextItem:
@ -422,10 +553,10 @@ components:
type: integer
format: int32
examples: [2]
created:
user:
type: string
format: date-time
updated:
examples: ['user1', '354364']
timestamp:
type: string
format: date-time
title:
@ -454,12 +585,15 @@ components:
type: integer
format: int32
examples: [2]
created:
user:
type: string
examples: ['user1', '354364']
timestamp:
type: string
format: date-time
updated:
title:
type: string
format: date-time
examples: ['Text item title']
ApiResponse:
type: object
properties:
@ -483,14 +617,16 @@ components:
schema:
$ref: '#/components/schemas/TextItem'
securitySchemes:
petstore_auth:
openlp_auth:
type: oauth2
flows:
implicit:
authorizationUrl: https://petstore3.swagger.io/oauth/authorize
authorizationUrl: http://localhost:8888/oauth/authorize
scopes:
write:pets: modify pets in your account
read:pets: read your pets
write:songs: modify songs in your account
read:songs: read your songs
write:customs: modify custom slides in your account
read:customs: read your custom slides
api_key:
type: apiKey
name: api_key

View File

@ -117,6 +117,8 @@ class RemoteSyncPlugin(Plugin):
Settings().value('remotesync/ftp server'),
Settings().value('remotesync/ftp username'),
Settings().value('remotesync/ftp password'))
elif sync_type == SyncType.WebService:
self.synchronizer = WebServiceSynchronizer()
else:
self.synchronizer = None
if self.synchronizer and not self.synchronizer.check_connection():