saamfi-sdk 0.1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of saamfi-sdk might be problematic. Click here for more details.

@@ -0,0 +1,257 @@
1
+ Metadata-Version: 2.4
2
+ Name: saamfi-sdk
3
+ Version: 0.1.0
4
+ Summary: SDK de Python para conectarse a los servicios SAAMFI - Autenticacion y Autorizacion
5
+ Author-email: Universidad ICESI <dev@icesi.edu.co>
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/icesi-dev/saamfi-sdk-python
8
+ Project-URL: Documentation, https://saamfi-sdk-python.readthedocs.io
9
+ Project-URL: Repository, https://github.com/icesi-dev/saamfi-sdk-python.git
10
+ Project-URL: Issues, https://github.com/icesi-dev/saamfi-sdk-python/issues
11
+ Keywords: saamfi,authentication,authorization,jwt,security,sdk
12
+ Classifier: Development Status :: 3 - Alpha
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: License :: OSI Approved :: MIT License
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Python :: 3.8
17
+ Classifier: Programming Language :: Python :: 3.9
18
+ Classifier: Programming Language :: Python :: 3.10
19
+ Classifier: Programming Language :: Python :: 3.11
20
+ Classifier: Programming Language :: Python :: 3.12
21
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
22
+ Classifier: Topic :: Security
23
+ Requires-Python: >=3.8
24
+ Description-Content-Type: text/markdown
25
+ License-File: LICENSE
26
+ Requires-Dist: requests>=2.31.0
27
+ Requires-Dist: PyJWT>=2.8.0
28
+ Requires-Dist: cryptography>=41.0.0
29
+ Requires-Dist: pydantic>=2.5.0
30
+ Requires-Dist: python-dotenv>=1.0.0
31
+ Provides-Extra: dev
32
+ Requires-Dist: pytest>=7.4.0; extra == "dev"
33
+ Requires-Dist: pytest-cov>=4.1.0; extra == "dev"
34
+ Requires-Dist: pytest-asyncio>=0.21.0; extra == "dev"
35
+ Requires-Dist: black>=23.0.0; extra == "dev"
36
+ Requires-Dist: flake8>=6.0.0; extra == "dev"
37
+ Requires-Dist: mypy>=1.5.0; extra == "dev"
38
+ Requires-Dist: isort>=5.12.0; extra == "dev"
39
+ Provides-Extra: fastapi
40
+ Requires-Dist: fastapi>=0.104.0; extra == "fastapi"
41
+ Dynamic: license-file
42
+
43
+ ## Saamfi SDK para Python
44
+
45
+ Cliente oficial en Python para integrar sistemas con los servicios de autenticacion y autorizacion de Saamfi. Este SDK expone las mismas operaciones disponibles en la libreria Java (`SaamfiDelegate`) y simplifica la validacion de tokens JWT, la autenticacion de usuarios y la consulta de informacion institucional.
46
+
47
+ ---
48
+
49
+ ## Instalacion
50
+
51
+ - **Desde PyPI**
52
+ ```bash
53
+ pip install saamfi-sdk
54
+ ```
55
+ - **Desde el codigo fuente**
56
+ ```bash
57
+ git clone https://github.com/saamfi/saamfi-sdk-python.git
58
+ cd saamfi-sdk-python
59
+ pip install -e .
60
+ ```
61
+
62
+ Configura las siguientes variables de entorno antes de usar el cliente (por ejemplo en un archivo `.env`):
63
+
64
+ - `SAAMFI_BASE_URL`: URL base del servicio Saamfi (`https://api.saamfi.com`).
65
+ - `SAAMFI_SYS_ID`: Identificador del sistema o tenant asignado por Saamfi.
66
+ - `SAAMFI_TENANT_ID` *(opcional)*: Identificador de institución (para endpoints como `/institutions/{instid}/params`).
67
+ - `SAAMFI_CLIENT_ID` y `SAAMFI_CLIENT_SECRET` *(opcionales)*: Credenciales del sistema si tu integración las requiere.
68
+ - `SAAMFI_TEST_USERNAME` y `SAAMFI_TEST_PASSWORD` *(solo para pruebas locales)*: Usuario demo del sandbox.
69
+
70
+ > El cliente mantiene compatibilidad con las variables antiguas `SAAMFI_URL`, `SAAMFI_SYSTEM_ID` y `SAAMFI_INST_ID`.
71
+
72
+ ---
73
+
74
+ ## Quickstart
75
+
76
+ ```python
77
+ from saamfi_sdk import SaamfiClient
78
+
79
+ client = SaamfiClient() # Usa SAAMFI_BASE_URL y SAAMFI_SYS_ID desde el entorno
80
+
81
+ response = client.login("usuario@example.com", "clave-segura")
82
+ if response:
83
+ print(f"Token: {response.access_token}")
84
+ token_info = client.validate_token(response.access_token)
85
+ print(f"Roles: {token_info.roles}")
86
+ else:
87
+ print("Credenciales invalidas")
88
+ ```
89
+
90
+ ---
91
+
92
+ ## Sandbox local con docker compose
93
+
94
+ 1. Levanta el entorno local de Saamfi con `docker compose` (puerto `9091` según la configuración compartida).
95
+ 2. Crea un archivo `.env` junto al proyecto del SDK con las variables:
96
+ ```
97
+ SAAMFI_BASE_URL=http://localhost:9091/iaslab/saamfiapi
98
+ SAAMFI_SYS_ID=8
99
+ SAAMFI_CLIENT_ID=8
100
+ SAAMFI_CLIENT_SECRET=qYr6-CxZP9t4vN2eFM1sR4gL
101
+ SAAMFI_TENANT_ID=1
102
+ SAAMFI_TEST_USERNAME=testuser
103
+ SAAMFI_TEST_PASSWORD=password123
104
+ ```
105
+ 3. Ejecuta el script de ejemplo:
106
+ ```bash
107
+ python examples/sandbox_demo.py
108
+ ```
109
+ Verás el flujo completo: descarga de clave pública, descubrimiento de sistemas/instituciones, autenticación del usuario demo, validación del JWT y consultas protegidas.
110
+
111
+ > Consulta los logs del backend en `saamfi-rest/logs/saamfi.log` o mediante `GET /logs/` (requiere rol `Query-server-logs`) para corroborar las operaciones.
112
+
113
+ ---
114
+
115
+ ## Ejemplos por funcionalidad
116
+
117
+ Cada metodo del cliente refleja una operacion del servicio Saamfi. Los siguientes fragmentos muestran el flujo completo con un token valido (`token`):
118
+
119
+ - **Obtener llave publica**
120
+ ```python
121
+ public_key = client.get_public_key()
122
+ ```
123
+
124
+ - **Autenticar usuario**
125
+ ```python
126
+ login = client.login("usuario@example.com", "clave")
127
+ ```
128
+
129
+ - **Validar token y extraer datos**
130
+ ```python
131
+ token_info = client.validate_token(token)
132
+ print(token_info.username, token_info.roles)
133
+ ```
134
+
135
+ - **Roles desde un JWT**
136
+ ```python
137
+ roles = client.get_roles_from_jwt(token)
138
+ ```
139
+
140
+ - **Informacion detallada de usuario**
141
+ ```python
142
+ user = client.get_user_info(token, user_id=12345)
143
+ ```
144
+
145
+ - **Buscar usuario por username**
146
+ ```python
147
+ user = client.get_user_by_username(token, "john.doe")
148
+ ```
149
+
150
+ - **Buscar usuarios por documentos**
151
+ ```python
152
+ users = client.get_users_by_document(token, ["100200300", "999888777"])
153
+ ```
154
+
155
+ - **Obtener usuarios por lista de IDs**
156
+ ```python
157
+ users_json = client.get_users_from_list(token, [1, 2, 3])
158
+ ```
159
+
160
+ - **Busqueda generica por parametro y valor**
161
+ ```python
162
+ result_json = client.get_users_by_param_and_value(token, "email", "example.com")
163
+ ```
164
+
165
+ - **Consultar institucion por NIT**
166
+ ```python
167
+ institution_json = client.get_institution_by_nit(token, "900123456-7")
168
+ ```
169
+
170
+ - **Consultar instituciones por IDs**
171
+ ```python
172
+ institutions_json = client.get_institutions_by_ids(token, [10, 20, 30])
173
+ ```
174
+
175
+ - **Listado público de sistemas e instituciones**
176
+ ```python
177
+ systems = client.list_public_systems()
178
+ institutions = client.list_public_institutions()
179
+ ```
180
+
181
+ - **Parámetros de institución**
182
+ ```python
183
+ params = client.get_institution_params(token) # Usa SAAMFI_TENANT_ID por defecto
184
+ ```
185
+
186
+ - **Roles configurados para un sistema**
187
+ ```python
188
+ roles = client.get_system_roles(token) # Usa SAAMFI_SYS_ID por defecto
189
+ ```
190
+
191
+ ---
192
+
193
+ ## Referencia de API
194
+
195
+ ### Clases principales
196
+
197
+ | Clase | Descripcion |
198
+ | ----- | ----------- |
199
+ | `SaamfiClient` | Cliente principal; gestiona autenticacion, validacion y consultas. |
200
+ | `LoginBody` | Modelo para solicitudes de login. |
201
+ | `LoginResponse` | Respuesta de autenticacion exitosa. |
202
+ | `UserInfo` | Informacion detallada de usuario. |
203
+ | `UserDetailToken` | Datos extraidos de un JWT validado. |
204
+
205
+ ### Metodos clave de `SaamfiClient`
206
+
207
+ | Metodo | Entrada | Salida | Nota |
208
+ | ------ | ------- | ------ | ---- |
209
+ | `get_public_key()` | - | `RSAPublicKey` | Obtiene y cachea la llave publica. |
210
+ | `login(username, password)` | `str`, `str` | `LoginResponse | None` | Autentica usuario. |
211
+ | `get_roles_from_jwt(auth_token)` | `str` | `List[str]` | Extrae claim `role`. |
212
+ | `validate_token(auth_token)` | `str` | `UserDetailToken` | Valida firma y claims. |
213
+ | `get_user_info(auth_token, user_id)` | `str`, `int` | `UserInfo | None` | Consulta usuario por ID. |
214
+ | `get_user_by_username(auth_token, username)` | `str`, `str` | `dict | None` | Consulta POST por username. |
215
+ | `get_users_by_document(auth_token, user_documents)` | `str`, `List[str]` | `List[dict]` | Busca por multiples documentos. |
216
+ | `get_users_from_list(auth_token, user_ids)` | `str`, `List[int]` | `str | None` | JSON con usuarios por ID. |
217
+ | `get_users_by_param_and_value(auth_token, param, value)` | `str`, `str`, `str` | `str | None` | Filtro generico usando query string. |
218
+ | `get_institution_by_nit(auth_token, nit)` | `str`, `str` | `str | None` | Consulta institucion por NIT. |
219
+ | `get_institutions_by_ids(auth_token, institution_ids)` | `str`, `List[int]` | `str | None` | Consulta masiva por IDs. |
220
+ | `list_public_institutions()` | - | `List[dict] | None` | Descubrimiento de instituciones disponibles. |
221
+ | `get_institution_params(auth_token, institution_id=None)` | `str`, `Optional[int]` | `dict | None` | Obtiene parámetros de configuración institucional. |
222
+ | `list_public_systems()` | - | `List[dict] | None` | Descubrimiento de sistemas publicados. |
223
+ | `get_system_roles(auth_token, system_id=None)` | `str`, `Optional[int]` | `List[dict] | None` | Roles disponibles para un sistema. |
224
+
225
+ > Consulta los docstrings en `saamfi_sdk/client.py` para conocer detalles, equivalencias con la version Java y ejemplos adicionales.
226
+
227
+ ---
228
+
229
+ ## Manejo de errores
230
+
231
+ Todas las excepciones del SDK heredan de `SaamfiException`:
232
+
233
+ | Excepcion | Cuándo ocurre |
234
+ | --------- | ------------- |
235
+ | `SaamfiAuthenticationError` | Credenciales invalidas o token sin permisos. |
236
+ | `SaamfiTokenValidationError` | Token expirado, mal formado o con claims faltantes. |
237
+ | `SaamfiConnectionError` | Problemas de red o respuestas no exitosas del backend. |
238
+ | `SaamfiInvalidSystemError` | El token pertenece a otro `system_id`. |
239
+ | `SaamfiUnauthorizedError` | El usuario autenticado no tiene permisos para la operacion. |
240
+ | `SaamfiNotFoundError` | El recurso solicitado no existe. |
241
+
242
+ ```python
243
+ from saamfi_sdk import SaamfiClient
244
+ from saamfi_sdk.exceptions import SaamfiConnectionError, SaamfiAuthenticationError
245
+
246
+ client = SaamfiClient()
247
+
248
+ try:
249
+ login = client.login("usuario@example.com", "clave")
250
+ except SaamfiConnectionError as exc:
251
+ print(f"No es posible comunicar con Saamfi: {exc}")
252
+ except SaamfiAuthenticationError:
253
+ print("Credenciales invalidas")
254
+ ```
255
+
256
+ ---
257
+
@@ -0,0 +1,17 @@
1
+ saamfi_sdk/__init__.py,sha256=rC1tAAgJYOJAO1j3kGENyzqrtnXZH4GwyFyT_k4hmQA,1284
2
+ saamfi_sdk/client.py,sha256=Nwhv0giWBCyhs0GEeQUgbk6CuYe5yTn2sIt2562yPy8,11766
3
+ saamfi_sdk/exceptions.py,sha256=iVKCHbNlNEjw9foY0TV5PQMY0vrGDJY3KTLDw7oaCEo,2253
4
+ saamfi_sdk/models.py,sha256=shsY_Z-0Kp6Lle5TZr-PWZ4daZpbPVRwYkx2DyhJZiI,4602
5
+ saamfi_sdk/py.typed,sha256=daEdpEyAJIa8b2VkCqSKcw8PaExcB6Qro80XNes_sHA,2
6
+ saamfi_sdk/services/__init__.py,sha256=7xm0b5RLP6GNFXNj2bX7Yd16otGmffF9y_30B9jDZ6g,431
7
+ saamfi_sdk/services/auth.py,sha256=OLjRZOXiCh9L0yBaDioQ54s1yeFouG3_sRtyzvxeuUY,3171
8
+ saamfi_sdk/services/base.py,sha256=I4xqcOYup3unI5b9JnWbXHDE11vJfOhS8shw6zMFMA0,1555
9
+ saamfi_sdk/services/institutions.py,sha256=RmnhzrUkiO5Xc2hQ8Zkljaj472LuA-Bn8gvxlQBR9oY,3980
10
+ saamfi_sdk/services/systems.py,sha256=FD53D4b9smk_qzStyQsMJZfqUCaaSoyCUGLqPcxUd30,2053
11
+ saamfi_sdk/services/token.py,sha256=xE1pIdYb6voxI1pSeCap7ZBfj9T1kdKOFTSNM8pcvgE,6139
12
+ saamfi_sdk/services/users.py,sha256=bYWPcGOExtz0b4IZ3Ljuha2mX58j67ZmXkfznsY1QC4,5490
13
+ saamfi_sdk-0.1.0.dist-info/licenses/LICENSE,sha256=6iltbovbpbh9UIcMAQ4YaIe_XuhmiQHACLKGL5dXm70,1074
14
+ saamfi_sdk-0.1.0.dist-info/METADATA,sha256=-E-RGqe8R1nf81p2QrZfGkPMN1-ibIxRVWEGNWti4nE,9653
15
+ saamfi_sdk-0.1.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
16
+ saamfi_sdk-0.1.0.dist-info/top_level.txt,sha256=jF4kal_I5anaAgY1b4vS35XgME_BgJIPJK30WYndg9Q,11
17
+ saamfi_sdk-0.1.0.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (80.9.0)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Universidad ICESI
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1 @@
1
+ saamfi_sdk