jedoist-client/src/main.py
2024-10-11 23:08:51 +03:00

183 lines
6.3 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import falcon
import json
import os
from typing import Optional
# https://falcon.readthedocs.io/en/stable/user/quickstart.html#learning-by-example
class AuthMiddleware:
def process_request(self, req, resp):
token = req.get_header('Authorization')
account_id = req.get_header('Account-ID')
challenges = ['Token type="Fernet"']
if token is None:
description = 'Please provide an auth token as part of the request.'
raise falcon.HTTPUnauthorized(
title='Auth token required',
description=description,
challenges=challenges,
href='http://docs.example.com/auth',
)
if not self._token_is_valid(token, account_id):
description = (
'The provided auth token is not valid. '
'Please request a new token and try again.'
)
raise falcon.HTTPUnauthorized(
title='Authentication required',
description=description,
challenges=challenges,
href='http://docs.example.com/auth',
)
def _token_is_valid(self, token, account_id):
return os.environ["TOKEN"] # Suuuuuure it's valid...
class RequireJSON:
def process_request(self, req, resp):
if not req.client_accepts_json:
raise falcon.HTTPNotAcceptable(
description='This API only supports responses encoded as JSON.',
href='http://docs.examples.com/api/json',
)
if req.method in ('POST', 'PUT'):
if req.content_type is None or 'application/json' not in req.content_type:
raise falcon.HTTPUnsupportedMediaType(
title='This API only supports requests encoded as JSON.',
href='http://docs.examples.com/api/json',
)
class JSONTranslator:
# NOTE: Normally you would simply use req.media and resp.media for
# this particular use case; this example serves only to illustrate
# what is possible.
def process_request(self, req, resp):
# req.stream corresponds to the WSGI wsgi.input environ variable,
# and allows you to read bytes from the request body.
#
# See also: PEP 3333
if req.content_length in (None, 0):
# Nothing to do
return
body = req.stream.read()
if not body:
raise falcon.HTTPBadRequest(
title='Empty request body',
description='A valid JSON document is required.',
)
try:
req.context.doc = json.loads(body.decode('utf-8'))
except (ValueError, UnicodeDecodeError):
description = (
'Could not decode the request body. The '
'JSON was incorrect or not encoded as '
'UTF-8.'
)
raise falcon.HTTPBadRequest(title='Malformed JSON', description=description)
def process_response(self, req, resp, resource, req_succeeded):
if not hasattr(resp.context, 'result'):
return
resp.text = json.dumps(resp.context.result)
def max_body(limit):
def hook(req, resp, resource, params):
length = req.content_length
if length is not None and length > limit:
msg = (
'The size of the request is too large. The body must not '
'exceed ' + str(limit) + ' bytes in length.'
)
raise falcon.HTTPPayloadTooLarge(
title='Request body is too large', description=msg
)
return hook
########################################################################################################
class CreateTaskResource:
TODO_HEADER = '# ToDo'
def __init__(self, config_file: str, todos_path: str) -> None:
self.__todos_path = todos_path
self.__config = self.__read_config_file(config_file)
def on_post(self, req, resp):
params = req.params
list_id = 'default'
if 'list' in params:
list_id = params['list']
file_path = self.__detect_todo_file_path(list_id)
if file_path == None:
quote = {
'title': 'Ошибка настройки',
'description': 'В URL не указан параметр "list"'
}
resp.media = quote
resp.status = falcon.HTTP_500
else:
task = req.context.doc['task']
self.__create_task(task, file_path)
quote = {
'title': 'Получена задача',
'description': task
}
resp.media = quote
resp.status = falcon.HTTP_201
def __read_config_file(self, config_file: str) -> None:
with open(config_file, 'r') as f:
return json.load(f)
def __detect_todo_file_path(self, todo_list_id) -> Optional[str]:
if not 'lists' in self.__config or not todo_list_id in self.__config['lists']:
return None
return "{0}/{1}".format(self.__todos_path, self.__config['lists'][todo_list_id])
def __create_task(self, text: str, file_path: str) -> None:
content = []
section_found = False
is_waiting_empty_line = False
with open(file_path, 'r', encoding='UTF-8') as file:
while line := file.readline():
if not section_found:
if line.strip() == CreateTaskResource.TODO_HEADER:
section_found = True
is_waiting_empty_line = True
content.append(line)
if section_found and is_waiting_empty_line == True and line.strip() == '':
content.append("- [ ] {0}\n".format(text))
is_waiting_empty_line = False
with open(file_path, 'w', encoding='utf-8') as file:
file.writelines(content)
########################################################################################################
app = falcon.App(
middleware=[
AuthMiddleware(),
RequireJSON(),
JSONTranslator()
]
)
app.add_route('/create-task', CreateTaskResource(config_file=os.environ['CONFIG_FILE'],
todos_path=os.environ['TODOS_PATH']))