Cat Feeder  1.0.0
The Cat feeder project
Loading...
Searching...
No Matches
security.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: security.py
14# CREATION DATE: 23-01-2026
15# LAST Modified: 1:12:17 24-01-2026
16# DESCRIPTION:
17# This is the project in charge of making the connected cat feeder project work.
18# /STOP
19# COPYRIGHT: (c) Cat Feeder
20# PURPOSE: Security decorators for API endpoint authentication and authorization.
21# /STOP
22# // AR
23# +==== END CatFeeder =================+
24"""
25
26from functools import wraps
27from typing import Callable
28
29from .decorator_constants import SecurityLevel, Environment
30
31
33 security_level: SecurityLevel = SecurityLevel.AUTHENTICATED,
34 environment: Environment = Environment.ALL
35) -> Callable:
36 """Mark endpoint as requiring authentication.
37
38 Args:
39 security_level: Level of security required (default: AUTHENTICATED).
40 environment: Environment where this applies (default: ALL).
41
42 Returns:
43 Decorator function.
44 """
45 def decorator(func: Callable) -> Callable:
46 @wraps(func)
47 def wrapper(*args, **kwargs):
48 return func(*args, **kwargs)
49
50 setattr(wrapper, "_requires_auth", True)
51 setattr(wrapper, "_security_level", security_level.value)
52 setattr(wrapper, "_environment", environment.value)
53
54 # Preserve existing metadata
55 _preserve_metadata(func, wrapper)
56 return wrapper
57 return decorator
58
59
61 security_level: SecurityLevel = SecurityLevel.ADMIN,
62 environment: Environment = Environment.ALL
63) -> Callable:
64 """Mark endpoint as requiring admin privileges.
65
66 Args:
67 security_level: Level of admin access required (default: ADMIN).
68 environment: Environment where this applies (default: ALL).
69
70 Returns:
71 Decorator function.
72 """
73 def decorator(func: Callable) -> Callable:
74 @wraps(func)
75 def wrapper(*args, **kwargs):
76 return func(*args, **kwargs)
77
78 setattr(wrapper, "_requires_admin", True)
79 setattr(wrapper, "_security_level", security_level.value)
80 setattr(wrapper, "_environment", environment.value)
81
82 # Preserve existing metadata
83 _preserve_metadata(func, wrapper)
84 return wrapper
85 return decorator
86
87
88def public_endpoint(environment: Environment = Environment.ALL) -> Callable:
89 """Mark endpoint as public (no authentication required).
90
91 Args:
92 environment: Environment where this applies (default: ALL).
93
94 Returns:
95 Decorator function.
96 """
97 def decorator(func: Callable) -> Callable:
98 @wraps(func)
99 def wrapper(*args, **kwargs):
100 return func(*args, **kwargs)
101
102 setattr(wrapper, "_public", True)
103 setattr(wrapper, "_security_level", SecurityLevel.PUBLIC.value)
104 setattr(wrapper, "_environment", environment.value)
105
106 # Preserve existing metadata
107 _preserve_metadata(func, wrapper)
108 return wrapper
109 return decorator
110
111
112def test_endpoint(environment: Environment = Environment.TESTING) -> Callable:
113 """Mark endpoint as testing-only.
114
115 Args:
116 environment: Environment where this applies (default: TESTING).
117
118 Returns:
119 Decorator function.
120 """
121 def decorator(func: Callable) -> Callable:
122 @wraps(func)
123 def wrapper(*args, **kwargs):
124 return func(*args, **kwargs)
125
126 setattr(wrapper, "_testing_only", True)
127 setattr(wrapper, "_environment", environment.value)
128
129 # Preserve existing metadata
130 _preserve_metadata(func, wrapper)
131 return wrapper
132 return decorator
133
134
135def _preserve_metadata(func: Callable, wrapper: Callable) -> None:
136 """Helper function to preserve existing metadata attributes."""
137 metadata_attrs = [
138 '_requires_auth', '_requires_admin', '_public', '_testing_only',
139 '_security_level', '_environment', '_description', '_summary',
140 '_response_model', '_tags'
141 ]
142
143 for attr in metadata_attrs:
144 if hasattr(func, attr):
145 setattr(wrapper, attr, getattr(func, attr))
Callable admin_endpoint(SecurityLevel security_level=SecurityLevel.ADMIN, Environment environment=Environment.ALL)
Definition security.py:63
Callable public_endpoint(Environment environment=Environment.ALL)
Definition security.py:88
Callable auth_endpoint(SecurityLevel security_level=SecurityLevel.AUTHENTICATED, Environment environment=Environment.ALL)
Definition security.py:35
Callable test_endpoint(Environment environment=Environment.TESTING)
Definition security.py:112
None _preserve_metadata(Callable func, Callable wrapper)
Definition security.py:135