Cat Feeder  1.0.0
The Cat feeder project
Loading...
Searching...
No Matches
responses.py
Go to the documentation of this file.
1r"""
2# +==== BEGIN CatFeeder =================+
3# LOGO:
4# ..............(..../\
5# ...............)..(.')
6# ..............(../..)
7# ...............\‍(__)|
8# Inspired by Joan Stark
9# source https://www.asciiart.eu/
10# animals/cats
11# /STOP
12# PROJECT: CatFeeder
13# FILE: responses.py
14# CREATION DATE: 11-10-2025
15# LAST Modified: 16:8:51 22-01-2026
16# DESCRIPTION:
17# This is the backend server in charge of making the actual website work.
18# /STOP
19# COPYRIGHT: (c) Cat Feeder
20# PURPOSE: File containing boilerplate responses that could be used by the server in it's endpoints_initialised.
21# // AR
22# +==== END CatFeeder =================+
23"""
24
25from typing import Union, Dict, Any, Optional
26from fastapi import Response
27from display_tty import Disp, initialise_logger
28from .non_web import BoilerplateNonHTTP
29from ..core import FinalSingleton
30from ..utils import constants as CONST
31from ..core.runtime_manager import RuntimeManager, RI
32from ..server_header import ServerHeaders
33from ..http_codes import HCI, HTTP_DEFAULT_TYPE
34
35
37 """_summary_
38 """
39
40 disp: Disp = initialise_logger(__qualname__, False)
41
42 def __init__(self, debug: bool = False) -> None:
43 """_summary_
44
45 Args:
46 debug (bool, optional): _description_. Defaults to False.
47 """
48 super().__init__()
49 # ------------------------ The logging function ------------------------
50 self.disp.update_disp_debug(debug)
51 self.disp.log_debug("Initialising...")
52 # -------------------------- Inherited values --------------------------
53 self.debug: bool = debug
54 self.runtime_manager: RuntimeManager = RI
55 # -------------------------- Shared instances --------------------------
56 self.boilerplate_non_http_initialised: Optional[BoilerplateNonHTTP] = self.runtime_manager.get_if_exists(
57 BoilerplateNonHTTP, None)
58 self.server_headers_initialised: ServerHeaders = self.runtime_manager.get(
59 ServerHeaders)
60
61 self.disp.log_debug("Initialised")
62
63 def build_response_body(self, title: str, message: str, resp: Any, token: Optional[str], error: bool = False) -> Dict[str, Any]:
64 """_summary_
65 This is a function that will create a response body for the queries of the server.
66 Args:
67 title (str): _description_: The title of the message in the body
68 message (any): _description_: The actual message you wish to send (this is so that it is human friendly [i.e. "You have successfully logged in"])
69 resp (any): _description_: The section where you can put more coder side data.
70 token Union[str, None]: _description_: The user token or None if not present
71 error (bool, optional): _description_: If this is an error message or not. Defaults to False.
72
73 Returns:
74 Dict[str, any]: _description_: the final version of the body message
75 """
76 func_title = "build_response_body"
77 json_body = {}
78 msg = f"title={title}, message={message}, resp={resp},"
79 msg += f"token={token}, error={error}"
80 self.disp.log_debug(msg, func_title)
81
82 json_body[CONST.JSON_TITLE] = title
83 json_body[CONST.JSON_MESSAGE] = message
84 if error is False:
85 json_body[CONST.JSON_RESP] = resp
86 else:
87 json_body[CONST.JSON_ERROR] = resp
88 self.disp.log_debug(f"token = {token}", func_title)
89 self.boilerplate_non_http_initialised = self.runtime_manager.get_if_exists(
90 BoilerplateNonHTTP,
92 )
94 self.disp.log_warning(
95 "Token validation service unavailable, unable to verify authentication status",
96 func_title
97 )
98 json_body[CONST.JSON_LOGGED_IN] = None
99 else:
100 self.disp.log_debug(
101 "self.boilerplate_non_http_initialised is initialised"
102 )
103 if token:
104 self.disp.log_debug("Token is present")
105 json_body[CONST.JSON_LOGGED_IN] = self.boilerplate_non_http_initialised.is_token_correct(
106 token
107 )
108 else:
109 self.disp.log_debug("Token is absent")
110 json_body[CONST.JSON_LOGGED_IN] = False
111 self.disp.log_debug(
112 f"Valid token? {json_body[CONST.JSON_LOGGED_IN]}")
113 self.disp.log_debug(f"Final response: {json_body}")
114 return json_body
115
116 def invalid_token(self, title: str) -> Response:
117 """_summary_
118 This is a function that will return an invalid token response.
119
120 Args:
121 title (str): _description_: The title of the called endpoint
122
123 Returns:
124 Response: _description_: The response ready to be sent back to the user
125 """
126 body = self.build_response_body(
127 title=title,
128 message="The token you entered is invalid.",
129 resp="Invalid token",
130 token="",
131 error=True
132 )
133 return HCI.invalid_token(content=body, content_type=HTTP_DEFAULT_TYPE, headers=self.server_headers_initialised.for_json())
134
135 def no_access_token(self, title: str, token: Union[str, None] = None) -> Response:
136 """_summary_
137 This is a function that will return a no access token response.
138
139 Args:
140 title (str): _description_: The name of the endpoint that is concerned
141 token (str): _description_: The token corresponding to the user being logged in
142
143 Returns:
144 Response: _description_: A pre-made http response ready to go.
145 """
146 body = self.build_response_body(
147 title=title,
148 message="Access token not found.",
149 resp="No access token",
150 token=token,
151 error=True
152 )
153 return HCI.bad_request(content=body, content_type=HTTP_DEFAULT_TYPE, headers=self.server_headers_initialised.for_json())
154
155 def provider_not_found(self, title: str, token: Union[str, None] = None) -> Response:
156 """_summary_
157 This is a function that will return a provider not found response.
158
159 Args:
160 title (str): _description_: The title of the called endpoint
161 token (Union[str, None], optional): _description_. Defaults to None.: The token provided by the user of the called endpoint
162
163 Returns:
164 Response: _description_: The response ready to be sent back to the user
165 """
166 body = self.build_response_body(
167 title=title,
168 message="The provider you are looking for was not found.",
169 resp="Provider not found",
170 token=token,
171 error=True
172 )
173 return HCI.not_found(content=body, content_type=HTTP_DEFAULT_TYPE, headers=self.server_headers_initialised.for_json())
174
175 def provider_not_given(self, title: str, token: Union[str, None] = None) -> Response:
176 """_summary_
177 This is a function that will return a provider not found response.
178
179 Args:
180 title (str): _description_: The title of the called endpoint
181 token (Union[str, None], optional): _description_. Defaults to None.: The token provided by the user of the called endpoint
182
183 Returns:
184 Response: _description_: The response ready to be sent back to the user
185 """
186 body = self.build_response_body(
187 title=title,
188 message="You have not given a provider.",
189 resp="Provider missing",
190 token=token,
191 error=True
192 )
193 return HCI.bad_request(content=body, content_type=HTTP_DEFAULT_TYPE, headers=self.server_headers_initialised.for_json())
194
195 def not_logged_in(self, title: str) -> Response:
196 """_summary_
197 This is a function that will return a not logged in response.
198
199 Args:
200 title (str): _description_: The title of the called endpoint
201
202 Returns:
203 Response: _description_: The response ready to be sent back to the user
204 """
205 body = self.build_response_body(
206 title=title,
207 message="You need to be logged in to be able to run this endpoint.",
208 resp="User not logged in",
209 token="",
210 error=True
211 )
212 return HCI.unauthorized(content=body, content_type=HTTP_DEFAULT_TYPE, headers=self.server_headers_initialised.for_json())
213
214 def login_failed(self, title: str) -> Response:
215 """_summary_
216 This is a function that will return a failed login response.
217
218 Args:
219 title (str): _description_: The title of the called endpoint
220
221 Returns:
222 Response: _description_: The response ready to be sent back to the user
223 """
224 body = self.build_response_body(
225 title=title,
226 message="Login failed, invalid credentials or username.",
227 resp="Invalid credentials or username.",
228 token="",
229 error=True
230 )
231 return HCI.unauthorized(content=body, content_type=HTTP_DEFAULT_TYPE, headers=self.server_headers_initialised.for_json())
232
233 def insuffisant_rights(self, title: str, token: Union[str, None] = None) -> Response:
234 """_summary_
235 This is a function that will return an insuffisant rights response.
236
237 Args:
238 title (str): _description_: The title of the called endpoint
239 token (Union[str, None], optional): _description_. Defaults to None.: The token provided by the user of the called endpoint
240
241 Returns:
242 Response: _description_: The response ready to be sent back to the user
243 """
244 body = self.build_response_body(
245 title=title,
246 message="You do not have enough permissions to execute this endpoint.",
247 resp="Insufficient rights for given account.",
248 token=token,
249 error=True
250 )
251 return HCI.forbidden(content=body, content_type=HTTP_DEFAULT_TYPE, headers=self.server_headers_initialised.for_json())
252
253 def bad_request(self, title: str, token: Union[str, None] = None) -> Response:
254 """_summary_
255 This is a function that will return a bad request response.
256
257 Args:
258 title (str): _description_: The title of the called endpoint
259 token (Union[str, None], optional): _description_. Defaults to None.: The token provided by the user of the called endpoint
260
261 Returns:
262 Response: _description_: The response ready to be sent back to the user
263 """
264 body = self.build_response_body(
265 title=title,
266 message="The request was not formatted correctly.",
267 resp="Bad request",
268 token=token,
269 error=True
270 )
271 return HCI.bad_request(content=body, content_type=HTTP_DEFAULT_TYPE, headers=self.server_headers_initialised.for_json())
272
273 def internal_server_error(self, title: str, token: Union[str, None] = None) -> Response:
274 """_summary_
275 This is a function that will return an internal server error response.
276
277 Args:
278 title (str): _description_: The title of the called endpoint
279 token (Union[str, None], optional): _description_. Defaults to None.: The token provided by the user of the called endpoint
280
281 Returns:
282 Response: _description_: The response ready to be sent back to the user
283 """
284 body = self.build_response_body(
285 title=title,
286 message="The server has encountered an error.",
287 resp="Internal server error",
288 token=token,
289 error=True
290 )
291 return HCI.internal_server_error(content=body, content_type=HTTP_DEFAULT_TYPE, headers=self.server_headers_initialised.for_json())
292
293 def update_failed(self, title: str, token: Union[str, None] = None) -> Response:
294 """Return an HTTP 500 (Internal Server Error) response for update failures.
295
296 This function is intended as a catch-all for unexpected server-side
297 failures that occur during update operations (for example: database
298 errors, unhandled exceptions, or other transient errors). It returns an
299 HTTP 500 response via `HCI.internal_server_error(...)` with a short
300 `resp` token ("update_failed") and a user-friendly message.
301
302 When the failure reason is known and predictable, prefer a more
303 specific HTTP status code (use the corresponding helper on this class):
304 - Validation / malformed input: `bad_request` (HTTP 400) or an `unprocessable_entity`/validation helper (HTTP 422) if present.
305 - Conflict (concurrent edit): use a 409 Conflict response (implement a `update_conflict` helper if you need this commonly).
306 - Authentication/authorization: `unauthorized` (401) or `insuffisant_rights`/`forbidden` (403) as appropriate.
307
308 Args:
309 title (str): The title of the called endpoint (used in the response body).
310 token (Optional[str]): User token to allow `build_response_body` to include logged-in status information.
311
312 Returns:
313 Response: The HTTP response produced by `HCI.internal_server_error(content=body, content_type=..., headers=...)`.
314 """
315 body = self.build_response_body(
316 title=title,
317 message="The server failed to update the requested content.",
318 resp="update_failed",
319 token=token,
320 error=True,
321 )
322 return HCI.internal_server_error(
323 content=body,
324 content_type=HTTP_DEFAULT_TYPE,
325 headers=self.server_headers_initialised.for_json(),
326 )
327
328 def unauthorized(self, title: str, token: Union[str, None] = None) -> Response:
329 """_summary_
330 This is a function that will return an unauthorized response.
331
332 Args:
333 title (str): _description_: The title of the called endpoint
334 token (Union[str, None], optional): _description_. Defaults to None.: The token provided by the user of the called endpoint
335
336 Returns:
337 Response: _description_: The response ready to be sent back to the user
338 """
339 body = self.build_response_body(
340 title=title,
341 message="You do not have permission to run this endpoint.",
342 resp="Access denied",
343 token=token,
344 error=True
345 )
346 return HCI.unauthorized(content=body, content_type=HTTP_DEFAULT_TYPE, headers=self.server_headers_initialised.for_json())
347
348 def invalid_verification_code(self, title: str, token: Union[str, None] = None) -> Response:
349 """_summary_
350 This is a function that will return an invalid verification code response.
351
352 Args:
353 title (str): _description_: The title of the called endpoint
354 token (Union[str, None], optional): _description_. Defaults to None.: The token provided by the user of the called endpoint
355
356 Returns:
357 Response: _description_: The response ready to be sent back to the user
358 """
359 body = self.build_response_body(
360 title=title,
361 message="The verification code you have entered is incorrect.",
362 resp="Invalid verification code",
363 token=token,
364 error=True
365 )
366 return HCI.bad_request(content=body, content_type=HTTP_DEFAULT_TYPE, headers=self.server_headers_initialised.for_json())
367
368 def user_not_found(self, title: str, token: Union[str, None] = None) -> Response:
369 """_summary_
370 Function that will return a user not found error.
371
372 Args:
373 title (str): _description_: The title of the endpoint
374 token (Union[str, None], optional): _description_. Defaults to None.: The token if present.
375
376 Returns:
377 Response: _description_: The pre-compiled response (ready to go)
378 """
379 body = self.build_response_body(
380 title=title,
381 message="The current user was not found.",
382 resp="Not found",
383 token=token,
384 error=True
385 )
386 return HCI.not_found(content=body, content_type=HTTP_DEFAULT_TYPE, headers=self.server_headers_initialised.for_json())
387
388 def missing_variable_in_body(self, title: str, token: Union[str, None] = None, variable_name: str = "") -> Response:
389 """_summary_
390 Function that will return a message saying that there is a missing variable in the provided body.
391
392 Args:
393 title (str): _description_: The name of the endpoint
394 token (Union[str, None], optional): _description_. Defaults to None.: The token of the account.
395
396 Returns:
397 Response: _description_: The pre-compiled response (ready to go)
398 """
399 body = self.build_response_body(
400 title=title,
401 message=f"A variable ('{variable_name}') is missing in the body of the request.",
402 resp="Missing variable",
403 token=token,
404 error=True
405 )
406 return HCI.bad_request(body, content_type=HTTP_DEFAULT_TYPE, headers=self.server_headers_initialised.for_json())
407
408 def missing_variable_in_query(self, title: str, token: Union[str, None] = None) -> Response:
409 """_summary_
410 Function that will return a message saying that there is a missing variable in the provided query.
411
412 Args:
413 title (str): _description_: The name of the endpoint
414 token (Union[str, None], optional): _description_. Defaults to None.: The token of the account.
415 Returns:
416 Response: _description_: The pre-compiled response (ready to go)
417 """
418 body = self.build_response_body(
419 title=title,
420 message="A variable is missing in the query of the request.",
421 resp="Missing variable",
422 token=token,
423 error=True
424 )
425 return HCI.bad_request(body, content_type=HTTP_DEFAULT_TYPE, headers=self.server_headers_initialised.for_json())
426
427 def missing_resource(self, title: str, token: Union[str, None] = None) -> Response:
428 """_summary_
429 Function that will return a message saying that a resource is missing.
430
431 Args:
432 title (str): _description_: The name of the endpoint
433 token (Union[str, None], optional): _description_. Defaults to None.: The token of the account.
434 Returns:
435 Response: _description_: The pre-compiled response (ready to go)
436 """
437 body = self.build_response_body(
438 title=title,
439 message="The requested resource is missing.",
440 resp="Missing resource",
441 token=token,
442 error=True
443 )
444 return HCI.not_found(body, content_type=HTTP_DEFAULT_TYPE, headers=self.server_headers_initialised.for_json())
445
446 def service_unavailable(self, service: str = "<not specified>", title: str = "<not specified>", token: Union[str, None] = None) -> Response:
447 """_summary_
448 Function that will return a message saying that the service is unavailable.
449
450 Args:
451 title (str): _description_: The name of the endpoint
452 token (Union[str, None], optional): _description_. Defaults to None.: The token of the account.
453 Returns:
454 Response: _description_: The pre-compiled response (ready to go)
455 """
456 body = self.build_response_body(
457 title=title,
458 message=f"The service ({service}) is currently unavailable.",
459 resp="Service unavailable",
460 token=token,
461 error=True
462 )
463 return HCI.service_unavailable(body, content_type=HTTP_DEFAULT_TYPE, headers=self.server_headers_initialised.for_json())
Response provider_not_found(self, str title, Union[str, None] token=None)
Definition responses.py:155
Response unauthorized(self, str title, Union[str, None] token=None)
Definition responses.py:328
Response no_access_token(self, str title, Union[str, None] token=None)
Definition responses.py:135
Response invalid_verification_code(self, str title, Union[str, None] token=None)
Definition responses.py:348
Response missing_resource(self, str title, Union[str, None] token=None)
Definition responses.py:427
Response bad_request(self, str title, Union[str, None] token=None)
Definition responses.py:253
Response provider_not_given(self, str title, Union[str, None] token=None)
Definition responses.py:175
Response missing_variable_in_body(self, str title, Union[str, None] token=None, str variable_name="")
Definition responses.py:388
Dict[str, Any] build_response_body(self, str title, str message, Any resp, Optional[str] token, bool error=False)
Definition responses.py:63
Response missing_variable_in_query(self, str title, Union[str, None] token=None)
Definition responses.py:408
Response user_not_found(self, str title, Union[str, None] token=None)
Definition responses.py:368
Optional[BoilerplateNonHTTP] boilerplate_non_http_initialised
Definition responses.py:56
Response internal_server_error(self, str title, Union[str, None] token=None)
Definition responses.py:273
Response update_failed(self, str title, Union[str, None] token=None)
Definition responses.py:293
Response insuffisant_rights(self, str title, Union[str, None] token=None)
Definition responses.py:233
Response service_unavailable(self, str service="<not specified>", str title="<not specified>", Union[str, None] token=None)
Definition responses.py:446