iatoolkit 0.11.0__py3-none-any.whl → 0.71.2__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.
- iatoolkit/__init__.py +2 -6
- iatoolkit/base_company.py +9 -29
- iatoolkit/cli_commands.py +1 -1
- iatoolkit/common/routes.py +96 -52
- iatoolkit/common/session_manager.py +2 -1
- iatoolkit/common/util.py +17 -27
- iatoolkit/company_registry.py +1 -2
- iatoolkit/iatoolkit.py +97 -53
- iatoolkit/infra/llm_client.py +15 -20
- iatoolkit/infra/llm_proxy.py +38 -10
- iatoolkit/infra/openai_adapter.py +1 -1
- iatoolkit/infra/redis_session_manager.py +48 -2
- iatoolkit/locales/en.yaml +167 -0
- iatoolkit/locales/es.yaml +163 -0
- iatoolkit/repositories/database_manager.py +23 -3
- iatoolkit/repositories/document_repo.py +1 -1
- iatoolkit/repositories/models.py +35 -10
- iatoolkit/repositories/profile_repo.py +3 -2
- iatoolkit/repositories/vs_repo.py +26 -20
- iatoolkit/services/auth_service.py +193 -0
- iatoolkit/services/branding_service.py +70 -25
- iatoolkit/services/company_context_service.py +155 -0
- iatoolkit/services/configuration_service.py +133 -0
- iatoolkit/services/dispatcher_service.py +80 -105
- iatoolkit/services/document_service.py +5 -2
- iatoolkit/services/embedding_service.py +146 -0
- iatoolkit/services/excel_service.py +30 -26
- iatoolkit/services/file_processor_service.py +4 -12
- iatoolkit/services/history_service.py +7 -16
- iatoolkit/services/i18n_service.py +104 -0
- iatoolkit/services/jwt_service.py +18 -29
- iatoolkit/services/language_service.py +83 -0
- iatoolkit/services/load_documents_service.py +100 -113
- iatoolkit/services/mail_service.py +9 -4
- iatoolkit/services/profile_service.py +152 -76
- iatoolkit/services/prompt_manager_service.py +20 -16
- iatoolkit/services/query_service.py +208 -96
- iatoolkit/services/search_service.py +11 -4
- iatoolkit/services/sql_service.py +57 -25
- iatoolkit/services/tasks_service.py +1 -1
- iatoolkit/services/user_feedback_service.py +72 -34
- iatoolkit/services/user_session_context_service.py +112 -54
- iatoolkit/static/images/fernando.jpeg +0 -0
- iatoolkit/static/js/chat_feedback_button.js +80 -0
- iatoolkit/static/js/chat_help_content.js +124 -0
- iatoolkit/static/js/chat_history_button.js +110 -0
- iatoolkit/static/js/chat_logout_button.js +36 -0
- iatoolkit/static/js/chat_main.js +135 -222
- iatoolkit/static/js/chat_onboarding_button.js +103 -0
- iatoolkit/static/js/chat_prompt_manager.js +94 -0
- iatoolkit/static/js/chat_reload_button.js +35 -0
- iatoolkit/static/styles/chat_iatoolkit.css +289 -210
- iatoolkit/static/styles/chat_modal.css +63 -77
- iatoolkit/static/styles/chat_public.css +107 -0
- iatoolkit/static/styles/landing_page.css +182 -0
- iatoolkit/static/styles/onboarding.css +176 -0
- iatoolkit/system_prompts/query_main.prompt +5 -22
- iatoolkit/templates/_company_header.html +20 -0
- iatoolkit/templates/_login_widget.html +42 -0
- iatoolkit/templates/base.html +40 -20
- iatoolkit/templates/change_password.html +57 -36
- iatoolkit/templates/chat.html +180 -86
- iatoolkit/templates/chat_modals.html +138 -68
- iatoolkit/templates/error.html +44 -8
- iatoolkit/templates/forgot_password.html +40 -23
- iatoolkit/templates/index.html +145 -0
- iatoolkit/templates/login_simulation.html +45 -0
- iatoolkit/templates/onboarding_shell.html +107 -0
- iatoolkit/templates/signup.html +63 -65
- iatoolkit/views/base_login_view.py +91 -0
- iatoolkit/views/change_password_view.py +56 -31
- iatoolkit/views/embedding_api_view.py +65 -0
- iatoolkit/views/external_login_view.py +61 -28
- iatoolkit/views/{file_store_view.py → file_store_api_view.py} +10 -3
- iatoolkit/views/forgot_password_view.py +27 -21
- iatoolkit/views/help_content_api_view.py +54 -0
- iatoolkit/views/history_api_view.py +56 -0
- iatoolkit/views/home_view.py +50 -23
- iatoolkit/views/index_view.py +14 -0
- iatoolkit/views/init_context_api_view.py +74 -0
- iatoolkit/views/llmquery_api_view.py +58 -0
- iatoolkit/views/login_simulation_view.py +93 -0
- iatoolkit/views/login_view.py +130 -37
- iatoolkit/views/logout_api_view.py +49 -0
- iatoolkit/views/profile_api_view.py +46 -0
- iatoolkit/views/{prompt_view.py → prompt_api_view.py} +10 -10
- iatoolkit/views/signup_view.py +41 -36
- iatoolkit/views/{tasks_view.py → tasks_api_view.py} +10 -36
- iatoolkit/views/tasks_review_api_view.py +55 -0
- iatoolkit/views/user_feedback_api_view.py +60 -0
- iatoolkit/views/verify_user_view.py +34 -29
- {iatoolkit-0.11.0.dist-info → iatoolkit-0.71.2.dist-info}/METADATA +41 -23
- iatoolkit-0.71.2.dist-info/RECORD +122 -0
- iatoolkit-0.71.2.dist-info/licenses/LICENSE +21 -0
- iatoolkit/common/auth.py +0 -200
- iatoolkit/static/images/arrow_up.png +0 -0
- iatoolkit/static/images/diagrama_iatoolkit.jpg +0 -0
- iatoolkit/static/images/logo_clinica.png +0 -0
- iatoolkit/static/images/logo_iatoolkit.png +0 -0
- iatoolkit/static/images/logo_maxxa.png +0 -0
- iatoolkit/static/images/logo_notaria.png +0 -0
- iatoolkit/static/images/logo_tarjeta.png +0 -0
- iatoolkit/static/images/logo_umayor.png +0 -0
- iatoolkit/static/images/upload.png +0 -0
- iatoolkit/static/js/chat_feedback.js +0 -115
- iatoolkit/static/js/chat_history.js +0 -117
- iatoolkit/static/styles/chat_info.css +0 -53
- iatoolkit/templates/header.html +0 -31
- iatoolkit/templates/home.html +0 -199
- iatoolkit/templates/login.html +0 -43
- iatoolkit/templates/test.html +0 -9
- iatoolkit/views/chat_token_request_view.py +0 -98
- iatoolkit/views/chat_view.py +0 -58
- iatoolkit/views/download_file_view.py +0 -58
- iatoolkit/views/external_chat_login_view.py +0 -95
- iatoolkit/views/history_view.py +0 -57
- iatoolkit/views/llmquery_view.py +0 -65
- iatoolkit/views/tasks_review_view.py +0 -83
- iatoolkit/views/user_feedback_view.py +0 -74
- iatoolkit-0.11.0.dist-info/RECORD +0 -110
- {iatoolkit-0.11.0.dist-info → iatoolkit-0.71.2.dist-info}/WHEEL +0 -0
- {iatoolkit-0.11.0.dist-info → iatoolkit-0.71.2.dist-info}/top_level.txt +0 -0
|
@@ -4,52 +4,57 @@
|
|
|
4
4
|
# IAToolkit is open source software.
|
|
5
5
|
|
|
6
6
|
from flask.views import MethodView
|
|
7
|
-
from flask import render_template
|
|
7
|
+
from flask import render_template, url_for, redirect, session, flash
|
|
8
8
|
from iatoolkit.services.profile_service import ProfileService
|
|
9
9
|
from itsdangerous import URLSafeTimedSerializer, SignatureExpired
|
|
10
|
+
from iatoolkit.services.branding_service import BrandingService
|
|
11
|
+
from iatoolkit.services.i18n_service import I18nService
|
|
10
12
|
from injector import inject
|
|
11
13
|
import os
|
|
12
14
|
|
|
13
15
|
|
|
14
16
|
class VerifyAccountView(MethodView):
|
|
15
17
|
@inject
|
|
16
|
-
def __init__(self,
|
|
18
|
+
def __init__(self,
|
|
19
|
+
profile_service: ProfileService,
|
|
20
|
+
branding_service: BrandingService,
|
|
21
|
+
i18n_service: I18nService):
|
|
17
22
|
self.profile_service = profile_service
|
|
23
|
+
self.branding_service = branding_service
|
|
24
|
+
self.i18n_service = i18n_service
|
|
18
25
|
self.serializer = URLSafeTimedSerializer(os.getenv("USER_VERIF_KEY"))
|
|
19
26
|
|
|
20
27
|
def get(self, company_short_name: str, token: str):
|
|
21
|
-
# get company info
|
|
22
|
-
company = self.profile_service.get_company_by_short_name(company_short_name)
|
|
23
|
-
if not company:
|
|
24
|
-
return render_template('error.html', message="Empresa no encontrada"), 404
|
|
25
|
-
|
|
26
28
|
try:
|
|
27
|
-
#
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
29
|
+
# get company info
|
|
30
|
+
company = self.profile_service.get_company_by_short_name(company_short_name)
|
|
31
|
+
if not company:
|
|
32
|
+
return render_template('error.html',
|
|
33
|
+
message=self.i18n_service.t('errors.templates.company_not_found')), 404
|
|
34
|
+
|
|
35
|
+
branding_data = self.branding_service.get_company_branding(company_short_name)
|
|
36
|
+
try:
|
|
37
|
+
# decode the token from the URL
|
|
38
|
+
email = self.serializer.loads(token, salt='email-confirm', max_age=3600*5)
|
|
39
|
+
except SignatureExpired:
|
|
40
|
+
flash(self.i18n_service.t('errors.verification.token_expired'), 'error')
|
|
41
|
+
return render_template('signup.html',
|
|
42
|
+
company_short_name=company_short_name,
|
|
43
|
+
branding=branding_data,
|
|
44
|
+
token=token), 400
|
|
35
45
|
|
|
36
|
-
try:
|
|
37
46
|
response = self.profile_service.verify_account(email)
|
|
38
47
|
if "error" in response:
|
|
48
|
+
flash(response["error"], 'error')
|
|
39
49
|
return render_template(
|
|
40
50
|
'signup.html',
|
|
41
|
-
company=company,
|
|
42
51
|
company_short_name=company_short_name,
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
alert_icon='success',
|
|
50
|
-
alert_message=response['message'])
|
|
52
|
+
branding=branding_data,
|
|
53
|
+
token=token), 400
|
|
54
|
+
|
|
55
|
+
flash(response['message'], 'success')
|
|
56
|
+
return redirect(url_for('home', company_short_name=company_short_name))
|
|
57
|
+
|
|
51
58
|
except Exception as e:
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
company_short_name=company_short_name,
|
|
55
|
-
message="Ha ocurrido un error inesperado."), 500
|
|
59
|
+
flash(self.i18n_service.t('errors.general.unexpected_error', error=str(e)), 'error')
|
|
60
|
+
return redirect(url_for('home', company_short_name=company_short_name))
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: iatoolkit
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.71.2
|
|
4
4
|
Summary: IAToolkit
|
|
5
5
|
Author: Fernando Libedinsky
|
|
6
6
|
License-Expression: MIT
|
|
7
|
-
Requires-Python: >=3.
|
|
7
|
+
Requires-Python: >=3.12
|
|
8
8
|
Description-Content-Type: text/markdown
|
|
9
|
+
License-File: LICENSE
|
|
9
10
|
Requires-Dist: aiohappyeyeballs==2.4.4
|
|
10
11
|
Requires-Dist: aiohttp==3.11.9
|
|
11
12
|
Requires-Dist: aiosignal==1.3.1
|
|
@@ -206,47 +207,64 @@ Requires-Dist: wrapt==1.17.0
|
|
|
206
207
|
Requires-Dist: yarl==1.18.3
|
|
207
208
|
Requires-Dist: zipp==3.21.0
|
|
208
209
|
Requires-Dist: zstandard==0.23.0
|
|
210
|
+
Dynamic: license-file
|
|
209
211
|
|
|
210
212
|
|
|
211
213
|
<div align="center">
|
|
212
|
-
|
|
214
|
+
<h1>
|
|
215
|
+
IAToolkit
|
|
216
|
+
</h1>
|
|
217
|
+
|
|
213
218
|
<p><strong>The Open-Source Framework for Building AI Chatbots on Your Private Data.</strong></p>
|
|
219
|
+
<h4>
|
|
220
|
+
<a href="https://www.iatoolkit.com" target="_blank" style="text-decoration: none; color: inherit;">
|
|
221
|
+
www.iatoolkit.com
|
|
222
|
+
</a>
|
|
223
|
+
</h4>
|
|
214
224
|
</div>
|
|
215
225
|
|
|
216
|
-
IAToolkit is a comprehensive, open-source framework designed for building enterprise-grade
|
|
217
|
-
AI chatbots and conversational applications.
|
|
226
|
+
IAToolkit is a comprehensive, Python open-source framework designed for building enterprise-grade
|
|
227
|
+
AI chatbots and conversational applications. It bridges the gap between the power of
|
|
228
|
+
Large Language Models (LLMs) and the valuable,
|
|
229
|
+
private data locked within your organization's databases and documents.
|
|
230
|
+
|
|
218
231
|
With IAToolkit, you can build production-ready, context-aware chatbots and agents that
|
|
219
232
|
can query relational databases, perform semantic searches on documents,
|
|
220
233
|
and connect to your internal APIs in minutes.
|
|
221
234
|
|
|
222
|
-
|
|
235
|
+
Create secure, branded chat interfaces that can reason over your data, answer questions, and execute custom business logic,
|
|
236
|
+
all powered by leading models from OpenAI, Google Gemini, and more.
|
|
223
237
|
|
|
224
238
|
|
|
225
239
|
## 🚀 Key Features
|
|
226
240
|
|
|
227
|
-
*
|
|
228
|
-
*
|
|
229
|
-
*
|
|
241
|
+
* **🔗 Unified Data Connection**
|
|
242
|
+
* **Natural Language to SQL**: Let your chatbot query relational databases (PostgreSQL, MySQL, SQLite) using everyday language.
|
|
243
|
+
* **Semantic Document Search**: Automatically chunk, embed, and search across your private documents (PDFs, Word, etc.) to provide contextually accurate answers.
|
|
230
244
|
|
|
231
|
-
*
|
|
232
|
-
*
|
|
245
|
+
* **🏢 Enterprise-Ready Multi-Tenancy**
|
|
246
|
+
* Deploy isolated "Company" modules, each with its own data, tools, and context.
|
|
247
|
+
* Perfect for SaaS products or internal departmental agents.
|
|
233
248
|
|
|
234
|
-
*
|
|
235
|
-
*
|
|
249
|
+
* **🎨 Fully Brandable UI**
|
|
250
|
+
* Customize the look and feel for each "Company" with its own logos, colors, and even language settings (i18n).
|
|
251
|
+
* Provides a white-labeled experience for your users.
|
|
236
252
|
|
|
237
|
-
*
|
|
238
|
-
*
|
|
239
|
-
*
|
|
240
|
-
* Powerful Flask-based **CLI** for database setup, API key generation, and more.
|
|
253
|
+
* **🧠 LLM Agnostic**
|
|
254
|
+
* Switch between **OpenAI (GPT-*)** and **Google (Gemini-*)** with a single line change in your configuration.
|
|
255
|
+
* No code refactoring needed.
|
|
241
256
|
|
|
242
|
-
*
|
|
243
|
-
*
|
|
244
|
-
*
|
|
257
|
+
* **🛠️ Developer-First Experience**
|
|
258
|
+
* Built with a clean **Dependency Injection** architecture.
|
|
259
|
+
* High-quality code base with **90%+ test coverage**.
|
|
245
260
|
|
|
246
|
-
|
|
261
|
+
* **🔒 Security & Observability Built-In**
|
|
262
|
+
* Comes with integrated user authentication, API keys, and secure session handling out of the box.
|
|
263
|
+
* Full traceability with detailed logging of all queries, function calls, token usage, and costs.
|
|
264
|
+
## ⚡ Quick Start: Try our 'hello world' example
|
|
247
265
|
|
|
248
|
-
|
|
249
|
-
|
|
266
|
+
Ready to see it in action? Our Quickstart Guide will walk you through downloading, configuring, and launching your first AI assistant in just a few minutes.
|
|
267
|
+
It's the best way to experience the toolkit's capabilities firsthand.
|
|
250
268
|
|
|
251
269
|
## 🤝 Contributing
|
|
252
270
|
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
iatoolkit/__init__.py,sha256=lWMmZiXzVqOAD2cnLZTjoX5_EMoDljjU7oAZTQbKu5c,951
|
|
2
|
+
iatoolkit/base_company.py,sha256=U0KWZf7zLrJCw87NrEt2MCCHfd78HS22D7ht_BLeoL0,3522
|
|
3
|
+
iatoolkit/cli_commands.py,sha256=bTn4iXiDM4P2Nyn6oPT2wCL4pUQy34hVTL6c4fyEQdY,2303
|
|
4
|
+
iatoolkit/company_registry.py,sha256=NAsrCJyvgkdG8yGfqA7EdPUTHDzzcPzKu0PKXniub50,2490
|
|
5
|
+
iatoolkit/iatoolkit.py,sha256=Z5aPSnKlepfqWqsChSju4aQVZttDI-hxUy1p0Eo1WIc,19439
|
|
6
|
+
iatoolkit/common/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
7
|
+
iatoolkit/common/exceptions.py,sha256=EXx40n5htp7UiOM6P1xfJ9U6NMcADqm62dlFaKz7ICU,1154
|
|
8
|
+
iatoolkit/common/routes.py,sha256=oFL8ivzenGpNgiDjV0pda_NRZ5XrlEHSIHPWW53zj8k,6529
|
|
9
|
+
iatoolkit/common/session_manager.py,sha256=OUYMzT8hN1U-NCUidR5tUAXB1drd8nYTOpo60rUNYeY,532
|
|
10
|
+
iatoolkit/common/util.py,sha256=lwMhQ2gT1DPzJ3mmL9xw3uobWJFIapAw50ks6mCvV60,15028
|
|
11
|
+
iatoolkit/infra/__init__.py,sha256=5JqK9sZ6jBuK83zDQokUhxQ0wuJJJ9DXB8pYCLkX7X4,102
|
|
12
|
+
iatoolkit/infra/call_service.py,sha256=iRk9VxbXaAwlLIl8fUzGDWIAdzwfsbs1MtP84YeENxg,4929
|
|
13
|
+
iatoolkit/infra/gemini_adapter.py,sha256=kXV-t5i9GmWBafUPX2kAyiqvcT7GPoxHylcCUWG_c_U,15051
|
|
14
|
+
iatoolkit/infra/google_chat_app.py,sha256=_uKWxeacHH6C5a4FVx0YZjBn1tL-x_MIQV9gqgWGAjo,1937
|
|
15
|
+
iatoolkit/infra/llm_client.py,sha256=Jt7CWX-RlBANvwnAuIIQscHPQVuWrxC8Jn7YjUuYs5A,18297
|
|
16
|
+
iatoolkit/infra/llm_proxy.py,sha256=TJti_mkdeFfsl4oGd5gTB7gaxF6bNG_rwqchkDiubw0,6933
|
|
17
|
+
iatoolkit/infra/llm_response.py,sha256=YUUQPBHzmP3Ce6-t0kKMRIpowvh7de1odSoefEByIvI,904
|
|
18
|
+
iatoolkit/infra/mail_app.py,sha256=PLGZdEs7LQ_9bmMRRxz0iqQdNa4xToAFyf9tg75wK8U,6103
|
|
19
|
+
iatoolkit/infra/openai_adapter.py,sha256=tbzd8aPAH5cQOJT-sD4ypqq2fWB6WiEIGuGesUDnQNk,3550
|
|
20
|
+
iatoolkit/infra/redis_session_manager.py,sha256=EPr3E_g7LHxn6U4SV5lT_L8WQsAwg8VzA_WIEZ3TwOw,3667
|
|
21
|
+
iatoolkit/infra/connectors/__init__.py,sha256=5JqK9sZ6jBuK83zDQokUhxQ0wuJJJ9DXB8pYCLkX7X4,102
|
|
22
|
+
iatoolkit/infra/connectors/file_connector.py,sha256=HOjRTFd-WfDOcFyvHncAhnGNZuFgChIwC-P6osPo9ZM,352
|
|
23
|
+
iatoolkit/infra/connectors/file_connector_factory.py,sha256=3qvyfH4ZHKuiMxJFkawOxhW2-TGKKtsBYHgoPpZMuKU,2118
|
|
24
|
+
iatoolkit/infra/connectors/google_cloud_storage_connector.py,sha256=IXpL3HTo7Ft4EQsYiQq5wXRRQK854jzOEB7ZdWjLa4U,2050
|
|
25
|
+
iatoolkit/infra/connectors/google_drive_connector.py,sha256=WR1AlO5-Bl3W89opdja0kKgHTJzVOjTsy3H4SlIvwVg,2537
|
|
26
|
+
iatoolkit/infra/connectors/local_file_connector.py,sha256=hrzIgpMJOTuwTqzlQeTIU_50ZbZ6yl8lcWPv6hMnoqI,1739
|
|
27
|
+
iatoolkit/infra/connectors/s3_connector.py,sha256=Nj4_YaLobjfcnbZewJf21_K2EXohgcc3mJll1Pzn4zg,1123
|
|
28
|
+
iatoolkit/locales/en.yaml,sha256=uEwOksWcaXyluj9aYW_yYSCbwqd84Kio2Z4lHaWyi_s,7674
|
|
29
|
+
iatoolkit/locales/es.yaml,sha256=HbszlQ2Xqx82hpcbMYtgWtSw3KUdMpUEIjl__BYIX8I,8690
|
|
30
|
+
iatoolkit/repositories/__init__.py,sha256=5JqK9sZ6jBuK83zDQokUhxQ0wuJJJ9DXB8pYCLkX7X4,102
|
|
31
|
+
iatoolkit/repositories/database_manager.py,sha256=IyqokOXhYydTGC859wDvu6jvJAK_Rgs16YdpDTuaF3k,3889
|
|
32
|
+
iatoolkit/repositories/document_repo.py,sha256=vhFc0hu9GK6yoKJHs2dLaAoQ9ZJaf9GEOsD2yWuVuNw,1130
|
|
33
|
+
iatoolkit/repositories/llm_query_repo.py,sha256=YT_t7cYGQk8rwzH_17-28aTzO-e2jUfa2rvXy8tugvA,3612
|
|
34
|
+
iatoolkit/repositories/models.py,sha256=9UijNdpZnX6yzHOj5ReYJckRz01gIXmIetBJ7nBOES0,14287
|
|
35
|
+
iatoolkit/repositories/profile_repo.py,sha256=zM68DvI3J3aSFt8yMuOpqy3v9_xJ2j86cmspD87gLK8,4139
|
|
36
|
+
iatoolkit/repositories/tasks_repo.py,sha256=icVO_r2oPagGnnBhwVFzznnvEEU2EAx-2dlWuWvoDC4,1745
|
|
37
|
+
iatoolkit/repositories/vs_repo.py,sha256=Iwbx9G-N05NEYTkZD2GP5mKWHcp_3D7h8VAhS0XGSv0,5824
|
|
38
|
+
iatoolkit/services/__init__.py,sha256=5JqK9sZ6jBuK83zDQokUhxQ0wuJJJ9DXB8pYCLkX7X4,102
|
|
39
|
+
iatoolkit/services/auth_service.py,sha256=ErP0CC2MpGJthIOMuYBbRdFsQQKpEQQ0Uu9_wT90yJI,7744
|
|
40
|
+
iatoolkit/services/benchmark_service.py,sha256=CdbFYyS3FHFhNzWQEa9ZNjUlmON10DT1nKNbZQ1EUi8,5880
|
|
41
|
+
iatoolkit/services/branding_service.py,sha256=GCUxchW6cAbYogCRVw3KGF-Zmi8v99yHiiDUYBxaD5Q,8141
|
|
42
|
+
iatoolkit/services/company_context_service.py,sha256=ME9dshCY1J1L6Kz_anrvoSfWy2Zutk4PtnMkyjbq_d4,6986
|
|
43
|
+
iatoolkit/services/configuration_service.py,sha256=TmWRqne9M9vf06c9_Hlfc8VMB--s99iK39hf8JSyO3k,5746
|
|
44
|
+
iatoolkit/services/dispatcher_service.py,sha256=wHZV4AU4okYKuFwH5afB3ktYDE2Ej4XVvxmUlL-IsmM,12635
|
|
45
|
+
iatoolkit/services/document_service.py,sha256=whW3B9g7lCaNOqezYmoHkSAov0K7EH90u-KVANO0mPg,6057
|
|
46
|
+
iatoolkit/services/embedding_service.py,sha256=AxcNVEhUeUXXYU80kafS70D-kFBlnN2_EnR6doae-cE,6110
|
|
47
|
+
iatoolkit/services/excel_service.py,sha256=MGVFjSo1NOL8PL7_hVgEEFzvXfA4NmF-JFEr8FBSjOA,4090
|
|
48
|
+
iatoolkit/services/file_processor_service.py,sha256=h8Tg2Xwvjv_HOIUo51Rnu5H4tUmkJ8W9tKvmFfgKPms,3792
|
|
49
|
+
iatoolkit/services/history_service.py,sha256=HoJs5CRpXturrdycznlalL6TOPbzC2npziTs86mOIkg,1375
|
|
50
|
+
iatoolkit/services/i18n_service.py,sha256=mR4pS0z56NgZLeSnEvDXiMvVBeOCl5CkUWdYBTVEhyM,3941
|
|
51
|
+
iatoolkit/services/jwt_service.py,sha256=EXpc1cZAak2nQ3cXIopm5nFTqevzINToWRYk22gJNjo,2933
|
|
52
|
+
iatoolkit/services/language_service.py,sha256=6l5ooiFXXRIF2gdKySR_7sj5IkJg-PYmwTMhdBcJHBM,3245
|
|
53
|
+
iatoolkit/services/load_documents_service.py,sha256=04XZmn6AWOK0wiRU7QDu2VYRekOK7fD19H-mC4FiMjA,7908
|
|
54
|
+
iatoolkit/services/mail_service.py,sha256=R_5zOSXMGOdn3pSCyUFCOUmQumXoiKEgmg78H_rxcP8,2366
|
|
55
|
+
iatoolkit/services/profile_service.py,sha256=sjE9cFz8fDRClYTXs1LLkPGfDlbzrV6TYx_DYJM6VW8,21969
|
|
56
|
+
iatoolkit/services/prompt_manager_service.py,sha256=o0SBO3k_VHaPxPcaM5oeq7Y2rOlFr7FCp_cIcpcU8qY,8415
|
|
57
|
+
iatoolkit/services/query_service.py,sha256=4g_rzRmAh-X4_6FsJgBoM7RQ0CV7FOWfGoxILDBk-8U,20704
|
|
58
|
+
iatoolkit/services/search_service.py,sha256=Omx7tXit5V9o_HdIEFs24Hmaz382CxuphfFzvige4Uo,2188
|
|
59
|
+
iatoolkit/services/sql_service.py,sha256=Eyyi1uY4o3szSO06nxURHUGTWp2N631kdWXZSEOho2E,3455
|
|
60
|
+
iatoolkit/services/tasks_service.py,sha256=itREO5rDnUIgsqtyCOBKDtH30QL5v1egs4qPTiBK8xU,6865
|
|
61
|
+
iatoolkit/services/user_feedback_service.py,sha256=4hftNzE69kiaJYjhxgPmiDAVu3399DiIgCbzg6DQ7Rc,4966
|
|
62
|
+
iatoolkit/services/user_session_context_service.py,sha256=vYF_vWM37tPB_ZyPBJ6f6WTJVjT2j-4L8JfZbqbI93k,6775
|
|
63
|
+
iatoolkit/static/images/fernando.jpeg,sha256=W68TYMuo5hZVpbP-evwH6Nu4xWFv2bc8pJzSKDoLTeQ,100612
|
|
64
|
+
iatoolkit/static/js/chat_feedback_button.js,sha256=Wzb2l3jmpZNwY2KYQQDuBmFKS4oU9WteB9s4U-bEqb4,2429
|
|
65
|
+
iatoolkit/static/js/chat_filepond.js,sha256=mzXafm7a506EpM37KATTK3zvAswO1E0KSUY1vKbwuRc,3163
|
|
66
|
+
iatoolkit/static/js/chat_help_content.js,sha256=N9APsdNoPWWyC1aMLjfq-xFfFYZ5g8ZefUGTkYt75DY,5211
|
|
67
|
+
iatoolkit/static/js/chat_history_button.js,sha256=i9EBAWWW2XyQnAuj1b-c8102EG_gDkQ2ElbA8_Nu0yo,3491
|
|
68
|
+
iatoolkit/static/js/chat_logout_button.js,sha256=Of9H6IbAboSBmeqRaurEVW6_dL752L0UeDcDLNBD5Z0,1335
|
|
69
|
+
iatoolkit/static/js/chat_main.js,sha256=MmoagngCFqzjWVUewq9ZOE2RgATKoyuy351aQ0ezVco,12504
|
|
70
|
+
iatoolkit/static/js/chat_onboarding_button.js,sha256=MyNpqqc4BGPZL5MMJTqi6OLFjQKKrJ9eNT1nOsTbvIw,3353
|
|
71
|
+
iatoolkit/static/js/chat_prompt_manager.js,sha256=QYki28CpyM2Chn82dnOP2eH6FObxH8eChGFyUxukv1M,3319
|
|
72
|
+
iatoolkit/static/js/chat_reload_button.js,sha256=FHMm5sLdn2HuWDq66wphNuRcltjLG-aADp0yTwEbnQw,1256
|
|
73
|
+
iatoolkit/static/styles/chat_iatoolkit.css,sha256=b25ahyuEKRLQArOhyIgnMxWAxy2vATk8-iVlebl6PrY,13808
|
|
74
|
+
iatoolkit/static/styles/chat_modal.css,sha256=9rwWrzL4Vq7AsdiGb3qczyOUf2PJEgLjSLCkSns8dQA,3031
|
|
75
|
+
iatoolkit/static/styles/chat_public.css,sha256=4EHN_VvURQYlooCmNB-UHIhvMsn4GFm7tKtr4VKpCNE,3830
|
|
76
|
+
iatoolkit/static/styles/landing_page.css,sha256=E6VRI5dko_naloH_FmNAHpjzxz4NZbrbzKwYLw4fYJA,4297
|
|
77
|
+
iatoolkit/static/styles/llm_output.css,sha256=AlxgRSOleeCk2dLAqFWVaQ-jwZiJjcpC5rHuUv3T6VU,2312
|
|
78
|
+
iatoolkit/static/styles/onboarding.css,sha256=fNiqT_MMJ6gGhNzfbSZhJwvcCZ_8gibL-MWZwxyAgAs,3749
|
|
79
|
+
iatoolkit/system_prompts/format_styles.prompt,sha256=MSMe1qvR3cF_0IbFshn8R0z6Wx6VCHQq1p37rpu5wwk,3576
|
|
80
|
+
iatoolkit/system_prompts/query_main.prompt,sha256=zcXM8nNyxvtbWevNkFAgBbSdLkzvLPxKQx9kj8NvfFA,2077
|
|
81
|
+
iatoolkit/system_prompts/sql_rules.prompt,sha256=y4nURVnb9AyFwt-lrbMNBHHtZlhk6kC9grYoOhRnrJo,59174
|
|
82
|
+
iatoolkit/templates/_company_header.html,sha256=wrwDftsSVu1uMPchsweAPLupsPkmLIPQBQ0xpIIyxjA,747
|
|
83
|
+
iatoolkit/templates/_login_widget.html,sha256=mheHpa_mcGK7UYSYdzxyD_n97MnJXJE19IcFxxUQYTY,1952
|
|
84
|
+
iatoolkit/templates/about.html,sha256=ciC08grUVz5qLzdzDDqDX31xirg5PrJIRYabWpV9oA8,294
|
|
85
|
+
iatoolkit/templates/base.html,sha256=xOox6JJEd6dHBlw6DBrFDJTXtAKCaXZc3Ffrufa-GDk,3042
|
|
86
|
+
iatoolkit/templates/change_password.html,sha256=p0GWZ9gldluYQM8OPSz2Q4CYhU8UJmb-72iz_Sl_6Ho,3485
|
|
87
|
+
iatoolkit/templates/chat.html,sha256=fT85IZMJZwWrhmI_5rTpdTCmyda19SwK8inMZmtDA44,13283
|
|
88
|
+
iatoolkit/templates/chat_modals.html,sha256=x0Do7I7X9cfgZFHSAwWreIN55nYPCpZK7PTBxGXjrYY,8501
|
|
89
|
+
iatoolkit/templates/error.html,sha256=4aT6cIYQUILciekAceHEiUuZxcAqkmNPUMnB9CD4BNA,1778
|
|
90
|
+
iatoolkit/templates/forgot_password.html,sha256=RPV_fDCzEdSQpA0qM8RNSCsNlhUhgp9sRGUHpMMBQ10,2247
|
|
91
|
+
iatoolkit/templates/index.html,sha256=mOuHePAmQ5PaMwqkJf7HU5oIL_lh8iKBKFng6d-QVzA,8017
|
|
92
|
+
iatoolkit/templates/login_simulation.html,sha256=2_f-rTEf3yuCaTFwrQlY3XxHljbp34KHPffHRuUkCyY,1459
|
|
93
|
+
iatoolkit/templates/onboarding_shell.html,sha256=ozjzzHfu63Ovgk295rE-sRvI4Z9Ecpk-SuDcV8Gs7lA,4678
|
|
94
|
+
iatoolkit/templates/signup.html,sha256=u2wiahk_d_BfooknSCcgcgAaQqIfas2aj6fe0cG3jzE,4174
|
|
95
|
+
iatoolkit/views/__init__.py,sha256=5JqK9sZ6jBuK83zDQokUhxQ0wuJJJ9DXB8pYCLkX7X4,102
|
|
96
|
+
iatoolkit/views/base_login_view.py,sha256=yu3dzY3CSA13voplE2AJ6uUz0X51diRuHSjvIEx2_pw,3691
|
|
97
|
+
iatoolkit/views/change_password_view.py,sha256=sTtjvLsGrZPt38gVzqABSB9EUEWIx3o4lFKYYGK79fc,4951
|
|
98
|
+
iatoolkit/views/embedding_api_view.py,sha256=9n5utihq8zHiG0V2sVCOYQ72wOKa4denqE951gqaJWo,2371
|
|
99
|
+
iatoolkit/views/external_login_view.py,sha256=H83jtiHXQCL0yP0ULBF0O_fxh-WU6XMz-YMJXEcSuDY,2864
|
|
100
|
+
iatoolkit/views/file_store_api_view.py,sha256=pkGYtSKaIH0S9qGEMYvELoJmNKmlVnyDZfJEqYYAWYA,2307
|
|
101
|
+
iatoolkit/views/forgot_password_view.py,sha256=M4w2UpEU3DFQXMOvyp3HqIKHs0PUPWzFZtVezmlhr14,3121
|
|
102
|
+
iatoolkit/views/help_content_api_view.py,sha256=8EUw2iSE6X-Lm2dGlYZxSp-29HzaAGwD3CpL4Otqp5k,2011
|
|
103
|
+
iatoolkit/views/history_api_view.py,sha256=CrfHmdIx4pB41KC_mbvEpv33zkPeKuBmlfGI2kc1ZvM,1988
|
|
104
|
+
iatoolkit/views/home_view.py,sha256=f3KLPr5Pv4utVSDK5ImjMIovDi5J0cta8ZQ_hjGpJpc,2579
|
|
105
|
+
iatoolkit/views/index_view.py,sha256=OsykSlXLB-TpFAPkDlsMna6bi3Ie5PXL303Hsg3WwUM,329
|
|
106
|
+
iatoolkit/views/init_context_api_view.py,sha256=SZ71RkMirbzvnSF0upUznwmn9id8W82PA1SuYYkynxo,2948
|
|
107
|
+
iatoolkit/views/llmquery_api_view.py,sha256=zjNVAvFI62xj4fBDaTWY6uqtlkoopCwizCX7KtvX_c8,2233
|
|
108
|
+
iatoolkit/views/login_simulation_view.py,sha256=xZ6GH7AfqNAK-0Cpf0RRD5Bdm3SsWkfNyx2PohV3_Uk,4034
|
|
109
|
+
iatoolkit/views/login_view.py,sha256=zdqwljOl4xGYoUbDYR-ucxBUF6nROTyvVFW8OGGE6Bw,6443
|
|
110
|
+
iatoolkit/views/logout_api_view.py,sha256=tvk4sCCXOFsk6qfGsrwY-pDKHL4ET30tL7ncTG-PT8A,1733
|
|
111
|
+
iatoolkit/views/profile_api_view.py,sha256=qhlmhyygIs5h-OyNDwq1uGUS8S-GxB2zOYY51Hs5prY,1645
|
|
112
|
+
iatoolkit/views/prompt_api_view.py,sha256=zumYnC_LWq_IeLraoL24YrY87U6a7iC6maY1PN-IP6U,1263
|
|
113
|
+
iatoolkit/views/signup_view.py,sha256=UIRsiZ_rCJprWy58UAsiVTUcPWnIdU7UyayJwoWaq28,3917
|
|
114
|
+
iatoolkit/views/tasks_api_view.py,sha256=wGnuwuuL83ByQ1Yre6ytRVztA0OGQjGrwMjB1_G830U,2630
|
|
115
|
+
iatoolkit/views/tasks_review_api_view.py,sha256=wsCpzqyRyUdCXWAhyGlBe3eNZZ6A1DQG7TblN_GZNfM,1894
|
|
116
|
+
iatoolkit/views/user_feedback_api_view.py,sha256=QOTBtpNqYAmewXDgVAoaIprnVjvf1xM0ExWxSFp3ICI,2098
|
|
117
|
+
iatoolkit/views/verify_user_view.py,sha256=TTC9BNjyjT8ZT5KnQ2f5-8UF1Y_sJII2wJ501xWSFvY,2653
|
|
118
|
+
iatoolkit-0.71.2.dist-info/licenses/LICENSE,sha256=5tOLQdjoCvSXEx_7Lr4bSab3ha4NSwzamvua0fwCXi8,1075
|
|
119
|
+
iatoolkit-0.71.2.dist-info/METADATA,sha256=en0VLL6vKIP1H7lXkakyLlzXotm7FNDJZqStOOHfvt0,9963
|
|
120
|
+
iatoolkit-0.71.2.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
121
|
+
iatoolkit-0.71.2.dist-info/top_level.txt,sha256=V_w4QvDx0b1RXiy8zTCrD1Bp7AZkFe3_O0-9fMiwogg,10
|
|
122
|
+
iatoolkit-0.71.2.dist-info/RECORD,,
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Fernando Libedinsky
|
|
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
|
|
13
|
+
all 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
|
|
21
|
+
THE SOFTWARE.
|
iatoolkit/common/auth.py
DELETED
|
@@ -1,200 +0,0 @@
|
|
|
1
|
-
# Copyright (c) 2024 Fernando Libedinsky
|
|
2
|
-
# Product: IAToolkit
|
|
3
|
-
#
|
|
4
|
-
# IAToolkit is open source software.
|
|
5
|
-
|
|
6
|
-
from flask import redirect, url_for
|
|
7
|
-
from iatoolkit.common.session_manager import SessionManager
|
|
8
|
-
from datetime import datetime, timezone
|
|
9
|
-
from injector import inject
|
|
10
|
-
from iatoolkit.repositories.profile_repo import ProfileRepo
|
|
11
|
-
from iatoolkit.services.jwt_service import JWTService
|
|
12
|
-
import logging
|
|
13
|
-
from flask import request
|
|
14
|
-
from typing import Optional
|
|
15
|
-
|
|
16
|
-
MAX_INACTIVITY_SECONDS = 60*30
|
|
17
|
-
|
|
18
|
-
class IAuthentication:
|
|
19
|
-
@inject
|
|
20
|
-
|
|
21
|
-
def __init__(self,
|
|
22
|
-
profile_repo: ProfileRepo,
|
|
23
|
-
jwt_service: JWTService):
|
|
24
|
-
self.profile_repo = profile_repo
|
|
25
|
-
self.jwt_service = jwt_service
|
|
26
|
-
|
|
27
|
-
def verify(self, company_short_name: str, body_external_user_id: str = None) -> dict:
|
|
28
|
-
# authentication is in this orden: JWT, API Key, Sesión
|
|
29
|
-
local_user_id = None
|
|
30
|
-
company_id = None
|
|
31
|
-
auth_method = None
|
|
32
|
-
external_user_id = None # for JWT or API Key
|
|
33
|
-
|
|
34
|
-
# 1. try auth via JWT
|
|
35
|
-
jwt_company_id, jwt_external_user_id, jwt_error_info = self._authenticate_via_chat_jwt(company_short_name)
|
|
36
|
-
|
|
37
|
-
if jwt_company_id is not None and jwt_external_user_id is not None:
|
|
38
|
-
auth_method = "JWT"
|
|
39
|
-
company_id = jwt_company_id
|
|
40
|
-
external_user_id = jwt_external_user_id
|
|
41
|
-
local_user_id = 0
|
|
42
|
-
elif jwt_error_info is not None:
|
|
43
|
-
# explicit error in JWT (inválido, expirado, etc.)
|
|
44
|
-
logging.warning(f"Fallo de autenticación JWT: {jwt_error_info}")
|
|
45
|
-
return {"error_message": "Fallo de autenticación JWT"}
|
|
46
|
-
else:
|
|
47
|
-
# 2. JWT not apply, try by API Key
|
|
48
|
-
api_key_company_id, api_key_error_info = self._authenticate_via_api_key(company_short_name)
|
|
49
|
-
|
|
50
|
-
if api_key_company_id is not None:
|
|
51
|
-
auth_method = "API Key"
|
|
52
|
-
company_id = api_key_company_id
|
|
53
|
-
external_user_id = body_external_user_id # API Key usa external_user_id del body
|
|
54
|
-
local_user_id = 0
|
|
55
|
-
elif api_key_error_info is not None:
|
|
56
|
-
# explicit error in API Key (inválida, incorrecta, error interno)
|
|
57
|
-
logging.warning(f"Fallo de autenticación API Key: {api_key_error_info}")
|
|
58
|
-
return {"error_message": "Fallo de autenticación API Key"}
|
|
59
|
-
else:
|
|
60
|
-
# 3. no JWT and API Key auth, try by Session
|
|
61
|
-
self.check_if_user_is_logged_in(company_short_name) # raise exception or redirect if not logged in
|
|
62
|
-
|
|
63
|
-
# In case not logged in check_if_user_is_logged_in redirects to login page
|
|
64
|
-
auth_method = "Session"
|
|
65
|
-
local_user_id = SessionManager.get('user_id')
|
|
66
|
-
company_id = SessionManager.get('company_id')
|
|
67
|
-
external_user_id = ""
|
|
68
|
-
|
|
69
|
-
if not company_id or not local_user_id:
|
|
70
|
-
logging.error(
|
|
71
|
-
f"Sesión válida para {company_short_name} pero falta company_id o user_id en SessionManager.")
|
|
72
|
-
return {"error_message": "Fallo interno en la autenticación o no autenticado"}
|
|
73
|
-
|
|
74
|
-
# last verification of authentication
|
|
75
|
-
if company_id is None or auth_method is None or local_user_id is None:
|
|
76
|
-
# this condition should never happen,
|
|
77
|
-
logging.error(
|
|
78
|
-
f"Fallo inesperado en la lógica de autenticación para {company_short_name}. Ningún método tuvo éxito o devolvió error.")
|
|
79
|
-
return {"error_message": "Fallo interno en la autenticación o no autenticado"}
|
|
80
|
-
|
|
81
|
-
return {
|
|
82
|
-
'success': True,
|
|
83
|
-
"auth_method": auth_method,
|
|
84
|
-
"company_id": company_id,
|
|
85
|
-
"auth_method": auth_method,
|
|
86
|
-
"local_user_id": local_user_id,
|
|
87
|
-
"external_user_id": external_user_id
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
def _authenticate_via_api_key(self, company_short_name_from_url: str):
|
|
91
|
-
"""
|
|
92
|
-
try to authenticate using an API Key from the header 'Authorization'.
|
|
93
|
-
Retorna (company_id, None) en éxito.
|
|
94
|
-
Retorna (None, error_message) en fallo.
|
|
95
|
-
"""
|
|
96
|
-
api_key_header = request.headers.get('Authorization')
|
|
97
|
-
api_key_value = None
|
|
98
|
-
|
|
99
|
-
# extract the key
|
|
100
|
-
if api_key_header and api_key_header.startswith('Bearer '):
|
|
101
|
-
api_key_value = api_key_header.split('Bearer ')[1]
|
|
102
|
-
else:
|
|
103
|
-
# there is no key in the headers expected
|
|
104
|
-
return None, None
|
|
105
|
-
|
|
106
|
-
# validate the api-key using ProfileRepo
|
|
107
|
-
try:
|
|
108
|
-
api_key_entry = self.profile_repo.get_active_api_key_entry(api_key_value)
|
|
109
|
-
if not api_key_entry:
|
|
110
|
-
logging.warning(f"Intento de acceso con API Key inválida o inactiva: {api_key_value[:5]}...")
|
|
111
|
-
return None, "API Key inválida o inactiva"
|
|
112
|
-
|
|
113
|
-
# check that the key belongs to the company
|
|
114
|
-
# api_key_entry.company already loaded by joinedload
|
|
115
|
-
if not api_key_entry.company or api_key_entry.company.short_name != company_short_name_from_url:
|
|
116
|
-
return None, f"API Key no es válida para la compañía {company_short_name_from_url}"
|
|
117
|
-
|
|
118
|
-
# successfull auth by API Key
|
|
119
|
-
company_id = api_key_entry.company_id
|
|
120
|
-
|
|
121
|
-
return company_id, None
|
|
122
|
-
|
|
123
|
-
except Exception as e:
|
|
124
|
-
logging.exception(f"Error interno durante validación de API Key: {e}")
|
|
125
|
-
return None, "Error interno del servidor al validar API Key"
|
|
126
|
-
|
|
127
|
-
def _authenticate_via_chat_jwt(self, company_short_name_from_url: str) -> tuple[
|
|
128
|
-
Optional[int], Optional[str], Optional[str]]:
|
|
129
|
-
"""
|
|
130
|
-
authenticate using an JWT chat session in the del header 'X-Chat-Token'.
|
|
131
|
-
Return (company_id, external_user_id, None) on exit
|
|
132
|
-
Returns (None, None, error_message) on fail.
|
|
133
|
-
"""
|
|
134
|
-
chat_jwt = request.headers.get('X-Chat-Token')
|
|
135
|
-
if not chat_jwt:
|
|
136
|
-
return None, None, None
|
|
137
|
-
|
|
138
|
-
# open the jwt token and retrieve the payload
|
|
139
|
-
jwt_payload = self.jwt_service.validate_chat_jwt(chat_jwt, company_short_name_from_url)
|
|
140
|
-
if not jwt_payload:
|
|
141
|
-
# validation fails (token expired, incorrect signature, company , etc.)
|
|
142
|
-
# validate_chat_jwt logs the specific failure
|
|
143
|
-
return None, None, "Token de chat expirado, debes reingresar al chat"
|
|
144
|
-
|
|
145
|
-
# JWT is validated: extract the company_id and external_user_id
|
|
146
|
-
company_id = jwt_payload.get('company_id')
|
|
147
|
-
external_user_id = jwt_payload.get('external_user_id')
|
|
148
|
-
|
|
149
|
-
# Sanity check aditional, should never happen
|
|
150
|
-
if not isinstance(company_id, int) or not external_user_id:
|
|
151
|
-
logging.error(
|
|
152
|
-
f"LLMQuery: JWT payload incompleto tras validación exitosa. CompanyID: {company_id}, UserID: {external_user_id}")
|
|
153
|
-
return None, None, "Token de chat con formato interno incorrecto"
|
|
154
|
-
|
|
155
|
-
return company_id, external_user_id, None
|
|
156
|
-
|
|
157
|
-
def check_if_user_is_logged_in(self, company_short_name: str):
|
|
158
|
-
if not SessionManager.get('user'):
|
|
159
|
-
if company_short_name:
|
|
160
|
-
return redirect(url_for('login', company_short_name=company_short_name))
|
|
161
|
-
else:
|
|
162
|
-
return redirect(url_for('home'))
|
|
163
|
-
|
|
164
|
-
if company_short_name != SessionManager.get('company_short_name'):
|
|
165
|
-
return redirect(url_for('login', company_short_name=company_short_name))
|
|
166
|
-
|
|
167
|
-
# check session timeout
|
|
168
|
-
if not self.check_session_timeout():
|
|
169
|
-
SessionManager.clear()
|
|
170
|
-
return redirect(url_for('login', company_short_name=company_short_name))
|
|
171
|
-
|
|
172
|
-
# update last_activity
|
|
173
|
-
SessionManager.set('last_activity', datetime.now(timezone.utc).timestamp())
|
|
174
|
-
|
|
175
|
-
def check_session_timeout(self):
|
|
176
|
-
# get last activity from session manager
|
|
177
|
-
last_activity = SessionManager.get('last_activity')
|
|
178
|
-
if not last_activity:
|
|
179
|
-
return False
|
|
180
|
-
|
|
181
|
-
# Tiempo actual en timestamp
|
|
182
|
-
current_time = datetime.now(timezone.utc).timestamp()
|
|
183
|
-
|
|
184
|
-
# get inactivity duration
|
|
185
|
-
inactivity_duration = current_time - last_activity
|
|
186
|
-
|
|
187
|
-
# verify if inactivity duration is greater than MAX_INACTIVITY_SECONDS
|
|
188
|
-
if inactivity_duration > MAX_INACTIVITY_SECONDS:
|
|
189
|
-
# close session
|
|
190
|
-
return False
|
|
191
|
-
|
|
192
|
-
# update last activity timestamp
|
|
193
|
-
SessionManager.set('last_activity', current_time)
|
|
194
|
-
|
|
195
|
-
return True # session is active
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|