iatoolkit 0.8.1__py3-none-any.whl → 0.63.4__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 iatoolkit might be problematic. Click here for more details.
- iatoolkit/__init__.py +8 -34
- iatoolkit/base_company.py +14 -3
- iatoolkit/common/routes.py +83 -52
- iatoolkit/common/session_manager.py +0 -1
- iatoolkit/common/util.py +0 -27
- iatoolkit/iatoolkit.py +61 -46
- iatoolkit/infra/llm_client.py +7 -8
- iatoolkit/infra/openai_adapter.py +1 -1
- iatoolkit/infra/redis_session_manager.py +48 -2
- iatoolkit/repositories/database_manager.py +17 -2
- iatoolkit/repositories/models.py +31 -6
- iatoolkit/repositories/profile_repo.py +7 -2
- iatoolkit/services/auth_service.py +188 -0
- iatoolkit/services/branding_service.py +147 -0
- iatoolkit/services/dispatcher_service.py +10 -40
- iatoolkit/services/excel_service.py +15 -15
- iatoolkit/services/history_service.py +3 -12
- iatoolkit/services/jwt_service.py +15 -24
- iatoolkit/services/onboarding_service.py +43 -0
- iatoolkit/services/profile_service.py +97 -44
- iatoolkit/services/query_service.py +124 -81
- iatoolkit/services/tasks_service.py +1 -1
- iatoolkit/services/user_feedback_service.py +67 -31
- iatoolkit/services/user_session_context_service.py +112 -54
- iatoolkit/static/images/fernando.jpeg +0 -0
- iatoolkit/static/js/{chat_feedback.js → chat_feedback_button.js} +6 -11
- iatoolkit/static/js/chat_history_button.js +126 -0
- iatoolkit/static/js/chat_logout_button.js +36 -0
- iatoolkit/static/js/chat_main.js +130 -220
- iatoolkit/static/js/chat_onboarding_button.js +97 -0
- iatoolkit/static/js/chat_prompt_manager.js +94 -0
- iatoolkit/static/js/chat_reload_button.js +52 -0
- iatoolkit/static/styles/chat_iatoolkit.css +329 -507
- iatoolkit/static/styles/chat_modal.css +95 -56
- iatoolkit/static/styles/landing_page.css +182 -0
- iatoolkit/static/styles/onboarding.css +169 -0
- iatoolkit/system_prompts/query_main.prompt +3 -12
- iatoolkit/templates/_company_header.html +20 -0
- iatoolkit/templates/_login_widget.html +40 -0
- iatoolkit/templates/base.html +8 -3
- iatoolkit/templates/change_password.html +54 -37
- iatoolkit/templates/chat.html +149 -66
- iatoolkit/templates/chat_modals.html +47 -18
- iatoolkit/templates/error.html +41 -8
- iatoolkit/templates/forgot_password.html +37 -24
- iatoolkit/templates/index.html +140 -0
- iatoolkit/templates/login_simulation.html +34 -0
- iatoolkit/templates/onboarding_shell.html +105 -0
- iatoolkit/templates/signup.html +64 -66
- iatoolkit/views/base_login_view.py +81 -0
- iatoolkit/views/change_password_view.py +23 -12
- iatoolkit/views/external_login_view.py +61 -28
- iatoolkit/views/{file_store_view.py → file_store_api_view.py} +9 -2
- iatoolkit/views/forgot_password_view.py +23 -13
- iatoolkit/views/history_api_view.py +52 -0
- iatoolkit/views/home_view.py +58 -25
- iatoolkit/views/index_view.py +14 -0
- iatoolkit/views/init_context_api_view.py +68 -0
- iatoolkit/views/llmquery_api_view.py +45 -0
- iatoolkit/views/login_simulation_view.py +81 -0
- iatoolkit/views/login_view.py +118 -34
- iatoolkit/views/logout_api_view.py +45 -0
- iatoolkit/views/{prompt_view.py → prompt_api_view.py} +7 -7
- iatoolkit/views/signup_view.py +38 -29
- iatoolkit/views/{tasks_view.py → tasks_api_view.py} +10 -36
- iatoolkit/views/tasks_review_api_view.py +55 -0
- iatoolkit/views/{user_feedback_view.py → user_feedback_api_view.py} +16 -31
- iatoolkit/views/verify_user_view.py +13 -8
- {iatoolkit-0.8.1.dist-info → iatoolkit-0.63.4.dist-info}/METADATA +2 -2
- iatoolkit-0.63.4.dist-info/RECORD +113 -0
- {iatoolkit-0.8.1.dist-info → iatoolkit-0.63.4.dist-info}/top_level.txt +0 -1
- 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_history.js +0 -117
- iatoolkit/templates/home.html +0 -201
- iatoolkit/templates/login.html +0 -43
- iatoolkit/views/chat_token_request_view.py +0 -98
- iatoolkit/views/chat_view.py +0 -51
- iatoolkit/views/download_file_view.py +0 -58
- iatoolkit/views/external_chat_login_view.py +0 -88
- iatoolkit/views/history_view.py +0 -57
- iatoolkit/views/llmquery_view.py +0 -65
- iatoolkit/views/tasks_review_view.py +0 -83
- iatoolkit-0.8.1.dist-info/RECORD +0 -175
- tests/__init__.py +0 -5
- tests/common/__init__.py +0 -0
- tests/common/test_auth.py +0 -279
- tests/common/test_routes.py +0 -42
- tests/common/test_session_manager.py +0 -59
- tests/common/test_util.py +0 -444
- tests/companies/__init__.py +0 -5
- tests/conftest.py +0 -36
- tests/infra/__init__.py +0 -5
- tests/infra/connectors/__init__.py +0 -5
- tests/infra/connectors/test_google_drive_connector.py +0 -107
- tests/infra/connectors/test_local_file_connector.py +0 -85
- tests/infra/connectors/test_s3_connector.py +0 -95
- tests/infra/test_call_service.py +0 -92
- tests/infra/test_database_manager.py +0 -59
- tests/infra/test_gemini_adapter.py +0 -137
- tests/infra/test_google_chat_app.py +0 -68
- tests/infra/test_llm_client.py +0 -165
- tests/infra/test_llm_proxy.py +0 -122
- tests/infra/test_mail_app.py +0 -94
- tests/infra/test_openai_adapter.py +0 -105
- tests/infra/test_redis_session_manager_service.py +0 -117
- tests/repositories/__init__.py +0 -5
- tests/repositories/test_database_manager.py +0 -87
- tests/repositories/test_document_repo.py +0 -76
- tests/repositories/test_llm_query_repo.py +0 -340
- tests/repositories/test_models.py +0 -38
- tests/repositories/test_profile_repo.py +0 -142
- tests/repositories/test_tasks_repo.py +0 -76
- tests/repositories/test_vs_repo.py +0 -107
- tests/services/__init__.py +0 -5
- tests/services/test_dispatcher_service.py +0 -274
- tests/services/test_document_service.py +0 -181
- tests/services/test_excel_service.py +0 -208
- tests/services/test_file_processor_service.py +0 -121
- tests/services/test_history_service.py +0 -164
- tests/services/test_jwt_service.py +0 -255
- tests/services/test_load_documents_service.py +0 -112
- tests/services/test_mail_service.py +0 -70
- tests/services/test_profile_service.py +0 -379
- tests/services/test_prompt_manager_service.py +0 -190
- tests/services/test_query_service.py +0 -243
- tests/services/test_search_service.py +0 -39
- tests/services/test_sql_service.py +0 -160
- tests/services/test_tasks_service.py +0 -252
- tests/services/test_user_feedback_service.py +0 -389
- tests/services/test_user_session_context_service.py +0 -132
- tests/views/__init__.py +0 -5
- tests/views/test_change_password_view.py +0 -191
- tests/views/test_chat_token_request_view.py +0 -188
- tests/views/test_chat_view.py +0 -98
- tests/views/test_download_file_view.py +0 -149
- tests/views/test_external_chat_login_view.py +0 -120
- tests/views/test_external_login_view.py +0 -102
- tests/views/test_file_store_view.py +0 -128
- tests/views/test_forgot_password_view.py +0 -142
- tests/views/test_history_view.py +0 -336
- tests/views/test_home_view.py +0 -61
- tests/views/test_llm_query_view.py +0 -154
- tests/views/test_login_view.py +0 -114
- tests/views/test_prompt_view.py +0 -111
- tests/views/test_signup_view.py +0 -140
- tests/views/test_tasks_review_view.py +0 -104
- tests/views/test_tasks_view.py +0 -130
- tests/views/test_user_feedback_view.py +0 -214
- tests/views/test_verify_user_view.py +0 -110
- {iatoolkit-0.8.1.dist-info → iatoolkit-0.63.4.dist-info}/WHEEL +0 -0
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
iatoolkit/__init__.py,sha256=4PWjMJjktixtrxF6BY405qyA50Sv967kEP2x-oil6qk,1120
|
|
2
|
+
iatoolkit/base_company.py,sha256=vU4ki-wB3PWIn3_Bvehfh0TfBH_XNC614tRBKNmEd84,4718
|
|
3
|
+
iatoolkit/cli_commands.py,sha256=G5L9xQXZ0lVFXQWBaE_KEZHyfuiT6PL1nTQRoSdnBzc,2302
|
|
4
|
+
iatoolkit/company_registry.py,sha256=tduqt3oV8iDX_IB1eA7KIgvIxE4edTcy-3qZIXh3Lzw,2549
|
|
5
|
+
iatoolkit/iatoolkit.py,sha256=nFc0wvDX4za2R81QnF0uUMmX8MyGAF4JZWKiuLb1c_M,17616
|
|
6
|
+
iatoolkit/common/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
7
|
+
iatoolkit/common/exceptions.py,sha256=EXx40n5htp7UiOM6P1xfJ9U6NMcADqm62dlFaKz7ICU,1154
|
|
8
|
+
iatoolkit/common/routes.py,sha256=XwhbXupwnYqZ2F4Ec28o9W0LmUUHzpc0QDLQttl4Dwc,5843
|
|
9
|
+
iatoolkit/common/session_manager.py,sha256=UeKfD15bcEA3P5e0WSURfotLqpsiIMp3AXxAMhtgHs0,471
|
|
10
|
+
iatoolkit/common/util.py,sha256=dlSDxnN3g-GOjK3YsPggzQG7VsZWarIMCzUkV9FBAIw,14442
|
|
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=clTYqV_0a2VD2vVH3j6AWqd1gVUmeg-fU3_myizmjQc,18543
|
|
16
|
+
iatoolkit/infra/llm_proxy.py,sha256=cHyNxUpVE4UDoWUfvSGfGCrIUFPTrpWZOixELQTsGFY,5744
|
|
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/repositories/__init__.py,sha256=5JqK9sZ6jBuK83zDQokUhxQ0wuJJJ9DXB8pYCLkX7X4,102
|
|
29
|
+
iatoolkit/repositories/database_manager.py,sha256=QgV8hNnVv9RmeOvUdomdj_mfk0bf3Rl8Ti41a-5zIAY,3700
|
|
30
|
+
iatoolkit/repositories/document_repo.py,sha256=Y7bF1kZB1HWJsAGjWdF7P2aVYeTYNufq9ngQXp7mDkY,1124
|
|
31
|
+
iatoolkit/repositories/llm_query_repo.py,sha256=YT_t7cYGQk8rwzH_17-28aTzO-e2jUfa2rvXy8tugvA,3612
|
|
32
|
+
iatoolkit/repositories/models.py,sha256=6KQpyCtp2l-ExfbeoPmoqc2V5qlTmSmEbzHYISZtu6g,14288
|
|
33
|
+
iatoolkit/repositories/profile_repo.py,sha256=21am3GP7XCG0nq6i3pArQ7mfGsrRn8rdcWT98fsdwlU,4397
|
|
34
|
+
iatoolkit/repositories/tasks_repo.py,sha256=icVO_r2oPagGnnBhwVFzznnvEEU2EAx-2dlWuWvoDC4,1745
|
|
35
|
+
iatoolkit/repositories/vs_repo.py,sha256=UkpmQQiocgM5IwRBmmWhw3HHzHP6zK1nN3J3TcQgjhc,5300
|
|
36
|
+
iatoolkit/services/__init__.py,sha256=5JqK9sZ6jBuK83zDQokUhxQ0wuJJJ9DXB8pYCLkX7X4,102
|
|
37
|
+
iatoolkit/services/auth_service.py,sha256=so6031zc9BTrLYskSrOpi1Cplu23_biPnTb-UgcDG4s,7495
|
|
38
|
+
iatoolkit/services/benchmark_service.py,sha256=CdbFYyS3FHFhNzWQEa9ZNjUlmON10DT1nKNbZQ1EUi8,5880
|
|
39
|
+
iatoolkit/services/branding_service.py,sha256=aCdfn6TVAYab8YcaIALGpqnvx3ObizBTEIcYWs-UVIU,7790
|
|
40
|
+
iatoolkit/services/dispatcher_service.py,sha256=Qdn2x4cozpgpKg2448sUxkhO6tuplzb8xPWUxdTTFBE,12772
|
|
41
|
+
iatoolkit/services/document_service.py,sha256=nMXrNtbHQuc9pSaten0LvKY0kT8_WngBDmZJUP3jNPw,5936
|
|
42
|
+
iatoolkit/services/excel_service.py,sha256=JdAcg7_vPz3J16cf2chC6j7WYVpiT55tDX9667tfMUc,3764
|
|
43
|
+
iatoolkit/services/file_processor_service.py,sha256=B1sUUhZNFf-rT4_1wrD38GKNoBFMp2g0dYrXYMCWe2E,4122
|
|
44
|
+
iatoolkit/services/history_service.py,sha256=3IxcdpKV1mHBGIiv2KIYV3LsVQJ0GPdFuCOiGYRszMU,1255
|
|
45
|
+
iatoolkit/services/jwt_service.py,sha256=W2kQVNQheQSLkNLS7RZ4jd3hmySBPLbHAS5hvBrUI10,3244
|
|
46
|
+
iatoolkit/services/load_documents_service.py,sha256=ZpB0BZ3qX1fGJGBtZtMLbFdWWx0hkPoeCS3OqJKwCTs,7291
|
|
47
|
+
iatoolkit/services/mail_service.py,sha256=2h-fcF3swZDya_o7IpgXkmuj3iEVHVCiHi7oVxU99sQ,2182
|
|
48
|
+
iatoolkit/services/onboarding_service.py,sha256=cMO2Ho1-G3wAeVNl-j25LwCMJjRwj3yKHpYKnZUFLDE,2001
|
|
49
|
+
iatoolkit/services/profile_service.py,sha256=cOjGJvrH9f3DRoXrhs4vZEqG7dzwrl_GnOcwxyaSX18,20301
|
|
50
|
+
iatoolkit/services/prompt_manager_service.py,sha256=U-XmSpkeXvv1KRN4dytdMxSYBMRSB7y-UHcb18mk0nA,8342
|
|
51
|
+
iatoolkit/services/query_service.py,sha256=gtMEAQ7IRVrFAMq4h_Pc_lHlMlXFI6heLSuBYHenkfs,17502
|
|
52
|
+
iatoolkit/services/search_service.py,sha256=i1xGWu7ORKIIDH0aAQBkF86dVVbLQ0Yrooz5TiZ6aGo,1823
|
|
53
|
+
iatoolkit/services/sql_service.py,sha256=MIslAtpJWnTMgSD74nnqTvQj27p-lHiyRXc6OiA2C_c,2172
|
|
54
|
+
iatoolkit/services/tasks_service.py,sha256=itREO5rDnUIgsqtyCOBKDtH30QL5v1egs4qPTiBK8xU,6865
|
|
55
|
+
iatoolkit/services/user_feedback_service.py,sha256=Bb6PVWcxzoQ3awev_k4MI0BQhkMh6iLPGC8_CK02t5g,4986
|
|
56
|
+
iatoolkit/services/user_session_context_service.py,sha256=vYF_vWM37tPB_ZyPBJ6f6WTJVjT2j-4L8JfZbqbI93k,6775
|
|
57
|
+
iatoolkit/static/images/fernando.jpeg,sha256=W68TYMuo5hZVpbP-evwH6Nu4xWFv2bc8pJzSKDoLTeQ,100612
|
|
58
|
+
iatoolkit/static/js/chat_feedback_button.js,sha256=j3BIyxcgyDuDDBn3vxxe0DV4evQabj3xb6XF28OWwCs,4220
|
|
59
|
+
iatoolkit/static/js/chat_filepond.js,sha256=mzXafm7a506EpM37KATTK3zvAswO1E0KSUY1vKbwuRc,3163
|
|
60
|
+
iatoolkit/static/js/chat_history_button.js,sha256=miPQOtG8m_w_TP6mhiM3PUZdIZITUJFJTchvNi7_fs4,4332
|
|
61
|
+
iatoolkit/static/js/chat_logout_button.js,sha256=Of9H6IbAboSBmeqRaurEVW6_dL752L0UeDcDLNBD5Z0,1335
|
|
62
|
+
iatoolkit/static/js/chat_main.js,sha256=TELqxzMg-qe-XbI-9-tj-CLEcrkZY8ANuQ4XggjCnow,12466
|
|
63
|
+
iatoolkit/static/js/chat_onboarding_button.js,sha256=vjvEloJ9PA9D7jOGca0QjS3J_7bU97R71L7kSyY3wOI,3153
|
|
64
|
+
iatoolkit/static/js/chat_prompt_manager.js,sha256=QYki28CpyM2Chn82dnOP2eH6FObxH8eChGFyUxukv1M,3319
|
|
65
|
+
iatoolkit/static/js/chat_reload_button.js,sha256=f8f_qRnZTNr_DwbcmafTHIuBLmiCoypYAKGQc472AOs,2393
|
|
66
|
+
iatoolkit/static/styles/chat_iatoolkit.css,sha256=sr4O4_9hpbCBtcPFaN-JQeAgEEbe0s9tEe9D7NNyKcQ,15081
|
|
67
|
+
iatoolkit/static/styles/chat_info.css,sha256=17DbgoNYE21VYWfb5L9-QLCpD2R1idK4imKRLwXtJLY,1058
|
|
68
|
+
iatoolkit/static/styles/chat_modal.css,sha256=2AAwfH88v_sqcJ_2pBrYm4_UIRsVmgf-JrVaoTkQ1no,3973
|
|
69
|
+
iatoolkit/static/styles/landing_page.css,sha256=E6VRI5dko_naloH_FmNAHpjzxz4NZbrbzKwYLw4fYJA,4297
|
|
70
|
+
iatoolkit/static/styles/llm_output.css,sha256=AlxgRSOleeCk2dLAqFWVaQ-jwZiJjcpC5rHuUv3T6VU,2312
|
|
71
|
+
iatoolkit/static/styles/onboarding.css,sha256=Bo0hd8ngVy404_a-gtNFi-hzljhIAnpE-1oQJGnj0F0,3655
|
|
72
|
+
iatoolkit/system_prompts/format_styles.prompt,sha256=MSMe1qvR3cF_0IbFshn8R0z6Wx6VCHQq1p37rpu5wwk,3576
|
|
73
|
+
iatoolkit/system_prompts/query_main.prompt,sha256=D2Wjf0uunQIQsQiJVrY-BTQz6PemM5En6ftmw_c5t4E,2808
|
|
74
|
+
iatoolkit/system_prompts/sql_rules.prompt,sha256=y4nURVnb9AyFwt-lrbMNBHHtZlhk6kC9grYoOhRnrJo,59174
|
|
75
|
+
iatoolkit/templates/_company_header.html,sha256=wrwDftsSVu1uMPchsweAPLupsPkmLIPQBQ0xpIIyxjA,747
|
|
76
|
+
iatoolkit/templates/_login_widget.html,sha256=E0ly8eGKDVfUCaOkFYYbRaPlZ4gDQUWIBTdCciN9cHw,1854
|
|
77
|
+
iatoolkit/templates/about.html,sha256=ciC08grUVz5qLzdzDDqDX31xirg5PrJIRYabWpV9oA8,294
|
|
78
|
+
iatoolkit/templates/base.html,sha256=y6YnYM1w2YXOuU0HcC9oE-o7UjFEBgusJqDxHEWazHI,2361
|
|
79
|
+
iatoolkit/templates/change_password.html,sha256=VObsXwjEzMkKkzIv-M2voDazPZkW_07Ye_RovTx62bw,3284
|
|
80
|
+
iatoolkit/templates/chat.html,sha256=6i01YQUSfWeehJ8FV1u3DDM6salIbrf3G52eDKIS6TM,12343
|
|
81
|
+
iatoolkit/templates/chat_modals.html,sha256=FImo_xrN3FS4xpTnWbHWde0eSOi9gAMQkAUCz6PArys,6801
|
|
82
|
+
iatoolkit/templates/error.html,sha256=tmN4tLx_WfgfFizvMWZJFd6_qeBTAiEnQB_Kz_AP38Q,1655
|
|
83
|
+
iatoolkit/templates/forgot_password.html,sha256=iJ4qgC8NMpalmO2g6sxUrPznSAy6aN0bi10EB1WldGE,2165
|
|
84
|
+
iatoolkit/templates/header.html,sha256=179agI7rnYwP_rvJNXIiVde5E8Ec5649_XKq6eew2Hk,1263
|
|
85
|
+
iatoolkit/templates/index.html,sha256=DZZ9WK0jQ9bCbCDkukNt_jWYII7ISxQtNxn4vHQNwz8,7808
|
|
86
|
+
iatoolkit/templates/login_simulation.html,sha256=1svwCBPrJ3Gy6bD9WMuz25NBSdFgZt4j8_sC7HE6MFU,1270
|
|
87
|
+
iatoolkit/templates/onboarding_shell.html,sha256=exSGckoPeE-ID9ym3B4TLh5hULpR7N1X6LeuSNmiUL0,4666
|
|
88
|
+
iatoolkit/templates/signup.html,sha256=ZX1Ufj-W5efOqiBG_7SIxUZcKonffsdRaWdEQYTFuqs,4262
|
|
89
|
+
iatoolkit/templates/test.html,sha256=rwNtxC83tbCl5COZFXYvmRBxxmgFJtPNuVBd_nq9KWY,133
|
|
90
|
+
iatoolkit/views/__init__.py,sha256=5JqK9sZ6jBuK83zDQokUhxQ0wuJJJ9DXB8pYCLkX7X4,102
|
|
91
|
+
iatoolkit/views/base_login_view.py,sha256=qoMMrAezCJvzjcfNzIbd2vwHhksALIQfNK8f_9E8m0o,3241
|
|
92
|
+
iatoolkit/views/change_password_view.py,sha256=NIUxvOz6rs2PpFvAjd-_UE9m4XQCrcxJicgxSXu7434,4582
|
|
93
|
+
iatoolkit/views/external_login_view.py,sha256=d4gUQbxFsThGbbAUdtFn7AMgPJjeb7_8KFFoH3vspVA,2853
|
|
94
|
+
iatoolkit/views/file_store_api_view.py,sha256=UvtZWOG-rLQMLfs8igOIYoQ-tkkEg5baMjqCJdKxaRQ,2300
|
|
95
|
+
iatoolkit/views/forgot_password_view.py,sha256=46AQ9bNXUESkFUYYcb_oIP1FukE5WyN2-MTwNgcqCu0,3349
|
|
96
|
+
iatoolkit/views/history_api_view.py,sha256=0YChbss0ae05KHzni2p3d4bGS2_yKAbjALk1OBeQk50,1867
|
|
97
|
+
iatoolkit/views/home_view.py,sha256=poAUAmaXNbf-bcuxmQg7XZ1yQQAbvlyCE2YkzwDS5wg,2733
|
|
98
|
+
iatoolkit/views/index_view.py,sha256=OsykSlXLB-TpFAPkDlsMna6bi3Ie5PXL303Hsg3WwUM,329
|
|
99
|
+
iatoolkit/views/init_context_api_view.py,sha256=YTjpT4xdtm1knUhelDj-VbV4EK6o_qGAgwwDhFmIOlg,2716
|
|
100
|
+
iatoolkit/views/llmquery_api_view.py,sha256=v_KxR6w-TrCVR2fMFHZCz3_v4o42CXb1Yvd-R1hSJHg,1662
|
|
101
|
+
iatoolkit/views/login_simulation_view.py,sha256=0Qt-puRnltI2HZxlfdyJmOf26-hQp3xjknGV_jkwV7E,3484
|
|
102
|
+
iatoolkit/views/login_view.py,sha256=XP_OkkpWEzPfY6LpPDGeZtsnNBMbliopi6k67tOwSD4,5843
|
|
103
|
+
iatoolkit/views/logout_api_view.py,sha256=wpiWLNkgypOOy7L75_tCJLv1gvcITgmd_hK2ipb9024,1505
|
|
104
|
+
iatoolkit/views/prompt_api_view.py,sha256=S_4-qAD5knh8Esae1AczEYGdXy_AuU7LMOmnUPej4jQ,1294
|
|
105
|
+
iatoolkit/views/signup_view.py,sha256=EWvkptFQ9g_DZZepo3lJ0-R2fgrVMq5ocxw0GFfxr9k,4112
|
|
106
|
+
iatoolkit/views/tasks_api_view.py,sha256=wGnuwuuL83ByQ1Yre6ytRVztA0OGQjGrwMjB1_G830U,2630
|
|
107
|
+
iatoolkit/views/tasks_review_api_view.py,sha256=wsCpzqyRyUdCXWAhyGlBe3eNZZ6A1DQG7TblN_GZNfM,1894
|
|
108
|
+
iatoolkit/views/user_feedback_api_view.py,sha256=-Ngex8SPf0mPvPNqwE_GUcRErLpOL49yJ43o5Y4Qhqo,1992
|
|
109
|
+
iatoolkit/views/verify_user_view.py,sha256=iFEVc-hFh5qOBy3T93ckM6-V2_mcomk-M4TVFl2D3Pw,2690
|
|
110
|
+
iatoolkit-0.63.4.dist-info/METADATA,sha256=9iwHUs3ntkAULZTRIUYe1NSjktISGnNrn_XCxdObwdY,9301
|
|
111
|
+
iatoolkit-0.63.4.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
112
|
+
iatoolkit-0.63.4.dist-info/top_level.txt,sha256=V_w4QvDx0b1RXiy8zTCrD1Bp7AZkFe3_O0-9fMiwogg,10
|
|
113
|
+
iatoolkit-0.63.4.dist-info/RECORD,,
|
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
|
|
@@ -1,117 +0,0 @@
|
|
|
1
|
-
$(document).ready(function () {
|
|
2
|
-
// Evento para abrir el modal de historial
|
|
3
|
-
$('#history-button').on('click', function() {
|
|
4
|
-
loadHistory();
|
|
5
|
-
$('#historyModal').modal('show');
|
|
6
|
-
});
|
|
7
|
-
|
|
8
|
-
// Variables globales para el historial
|
|
9
|
-
let historyData = [];
|
|
10
|
-
|
|
11
|
-
// Función para cargar el historial
|
|
12
|
-
async function loadHistory() {
|
|
13
|
-
const historyLoading = $('#history-loading');
|
|
14
|
-
const historyError = $('#history-error');
|
|
15
|
-
const historyContent = $('#history-content');
|
|
16
|
-
|
|
17
|
-
// Mostrar loading
|
|
18
|
-
historyLoading.show();
|
|
19
|
-
historyError.hide();
|
|
20
|
-
historyContent.hide();
|
|
21
|
-
|
|
22
|
-
try {
|
|
23
|
-
const data = {
|
|
24
|
-
external_user_id: window.externalUserId
|
|
25
|
-
};
|
|
26
|
-
|
|
27
|
-
const responseData = await callLLMAPI("/history", data, "POST");
|
|
28
|
-
|
|
29
|
-
if (responseData && responseData.history) {
|
|
30
|
-
// Guardar datos globalmente
|
|
31
|
-
historyData = responseData.history;
|
|
32
|
-
|
|
33
|
-
// Mostrar todos los datos
|
|
34
|
-
displayAllHistory();
|
|
35
|
-
|
|
36
|
-
// Mostrar contenido
|
|
37
|
-
historyContent.show();
|
|
38
|
-
} else {
|
|
39
|
-
throw new Error('No se recibieron datos del historial');
|
|
40
|
-
}
|
|
41
|
-
} catch (error) {
|
|
42
|
-
console.error("Error al cargar historial:", error);
|
|
43
|
-
const errorHtml = `
|
|
44
|
-
<div class="alert alert-danger alert-dismissible show" role="alert">
|
|
45
|
-
<strong>Error al cargar el historial:</strong> ${error.message}
|
|
46
|
-
<button type="button" class="close" data-dismiss="alert">
|
|
47
|
-
<span>×</span>
|
|
48
|
-
</button>
|
|
49
|
-
</div>
|
|
50
|
-
`;
|
|
51
|
-
historyError.html(errorHtml).show();
|
|
52
|
-
} finally {
|
|
53
|
-
historyLoading.hide();
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
// Función para mostrar todo el historial
|
|
58
|
-
function displayAllHistory() {
|
|
59
|
-
const historyTableBody = $('#history-table-body');
|
|
60
|
-
|
|
61
|
-
// Limpiar tabla
|
|
62
|
-
historyTableBody.empty();
|
|
63
|
-
|
|
64
|
-
// Filtrar solo consultas que son strings simples (no objetos JSON)
|
|
65
|
-
const filteredHistory = historyData.filter(item => {
|
|
66
|
-
try {
|
|
67
|
-
// Intentar parsear como JSON
|
|
68
|
-
const parsed = JSON.parse(item.query);
|
|
69
|
-
// Si se puede parsear y es un objeto, filtrarlo
|
|
70
|
-
return false;
|
|
71
|
-
} catch (e) {
|
|
72
|
-
// Si no se puede parsear, es un string simple, incluirlo
|
|
73
|
-
return true;
|
|
74
|
-
}
|
|
75
|
-
});
|
|
76
|
-
|
|
77
|
-
// Poblar tabla solo con las consultas filtradas
|
|
78
|
-
filteredHistory.forEach((item, index) => {
|
|
79
|
-
const row = $(`
|
|
80
|
-
<tr>
|
|
81
|
-
<td>${index + 1}</td>
|
|
82
|
-
<td>${formatDate(item.created_at)}</td>
|
|
83
|
-
<td class="query-cell" style="cursor: pointer;" title="Haz clic para copiar esta consulta al chat">${item.query}</td>
|
|
84
|
-
</tr>
|
|
85
|
-
`);
|
|
86
|
-
historyTableBody.append(row);
|
|
87
|
-
});
|
|
88
|
-
|
|
89
|
-
// Agregar evento de clic a las celdas de consulta
|
|
90
|
-
historyTableBody.on('click', '.query-cell', function() {
|
|
91
|
-
const queryText = $(this).text();
|
|
92
|
-
|
|
93
|
-
// Copiar el texto al textarea del chat
|
|
94
|
-
$('#question').val(queryText);
|
|
95
|
-
|
|
96
|
-
// Cerrar el modal
|
|
97
|
-
$('#historyModal').modal('hide');
|
|
98
|
-
|
|
99
|
-
// Hacer focus en el textarea para que el usuario pueda editar si lo desea
|
|
100
|
-
$('#question').focus();
|
|
101
|
-
});
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
// Función para formatear fecha
|
|
105
|
-
function formatDate(dateString) {
|
|
106
|
-
const date = new Date(dateString);
|
|
107
|
-
return date.toLocaleDateString('es-CL', {
|
|
108
|
-
day: '2-digit',
|
|
109
|
-
month: '2-digit',
|
|
110
|
-
year: 'numeric',
|
|
111
|
-
hour: '2-digit',
|
|
112
|
-
minute: '2-digit'
|
|
113
|
-
});
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
});
|
|
117
|
-
|
iatoolkit/templates/home.html
DELETED
|
@@ -1,201 +0,0 @@
|
|
|
1
|
-
{% extends "base.html" %}
|
|
2
|
-
|
|
3
|
-
{% block title %}Inicio - IAToolkit{% endblock %}
|
|
4
|
-
|
|
5
|
-
{% block content %}
|
|
6
|
-
|
|
7
|
-
<!-- Contenido principal con espaciado adicional respecto al header -->
|
|
8
|
-
<div class="row flex-fill mt-5 flex-wrap">
|
|
9
|
-
|
|
10
|
-
{% if not user or user_company != company_short_name %}
|
|
11
|
-
<!-- Sección de login (se coloca primero en el HTML para mobile) -->
|
|
12
|
-
<div class="col-12 col-lg-5 offset-lg-1">
|
|
13
|
-
<div class="border rounded p-4 shadow-sm bg-light">
|
|
14
|
-
<h4 class="text-muted fw-semibold text-start mb-3">login integrado (IAToolkit)</h4>
|
|
15
|
-
<form id="login-form"
|
|
16
|
-
action="{{ url_for('home', company_short_name=company_short_name) }}"
|
|
17
|
-
method="post">
|
|
18
|
-
<div class="mb-3">
|
|
19
|
-
<label for="company_short_name" class="form-label d-block text-muted">Empresa</label>
|
|
20
|
-
<select id="company_short_name" name="company_short_name" class="form-select" required>
|
|
21
|
-
<option value="" disabled selected>Selecciona una empresa</option>
|
|
22
|
-
{% for company in companies %}
|
|
23
|
-
<option value="{{ company.short_name }}"
|
|
24
|
-
{% if company.short_name == company_short_name %}selected{% endif %}>
|
|
25
|
-
{{ company.short_name }}
|
|
26
|
-
</option>
|
|
27
|
-
{% endfor %}
|
|
28
|
-
</select>
|
|
29
|
-
</div>
|
|
30
|
-
|
|
31
|
-
<div class="mb-3">
|
|
32
|
-
<label for="email" class="form-label d-block text-muted">Correo Electrónico</label>
|
|
33
|
-
<input type="email" id="email" name="email" class="form-control" required>
|
|
34
|
-
</div>
|
|
35
|
-
<div class="mb-3">
|
|
36
|
-
<label for="password" class="form-label d-block text-muted">Contraseña</label>
|
|
37
|
-
<input type="password" id="password" name="password" class="form-control" required>
|
|
38
|
-
</div>
|
|
39
|
-
<button type="submit" class="btn btn-primary w-100">
|
|
40
|
-
Iniciar Sesión</button>
|
|
41
|
-
</form>
|
|
42
|
-
|
|
43
|
-
<div class="text-center mt-3">
|
|
44
|
-
<a href="{% if company_short_name %}{{ url_for('signup', company_short_name=company_short_name) }}{% else %}#{% endif %}"
|
|
45
|
-
id="signup-link"
|
|
46
|
-
class="btn btn-outline-primary w-100">Registrarse</a>
|
|
47
|
-
</div>
|
|
48
|
-
<div class="text-center mt-3">
|
|
49
|
-
<a href="{{ url_for('forgot_password', company_short_name=company_short_name) }}" class="text-decoration-none text-muted fw-semibold">
|
|
50
|
-
¿Olvidaste tu contraseña?
|
|
51
|
-
</a>
|
|
52
|
-
</div>
|
|
53
|
-
</div>
|
|
54
|
-
</div>
|
|
55
|
-
{% endif %}
|
|
56
|
-
|
|
57
|
-
<!-- Sección de JWT -->
|
|
58
|
-
<div class="col-12 col-lg-5 offset-lg-1">
|
|
59
|
-
<div class="border rounded p-4 shadow-sm bg-light">
|
|
60
|
-
<h4 class="text-muted fw-semibold text-start mb-3">login externo (api-key)</h4>
|
|
61
|
-
<form id="jwt-form" method="post">
|
|
62
|
-
<div class="mb-3">
|
|
63
|
-
<label for="company_name" class="form-label d-block text-muted">Empresa</label>
|
|
64
|
-
<select id="company_name" name="company_short_name" class="form-select" required>
|
|
65
|
-
<option value="" disabled selected>Selecciona una empresa</option>
|
|
66
|
-
{% for company in companies %}
|
|
67
|
-
{% if company.allow_jwt %}
|
|
68
|
-
<option value="{{ company.short_name }}"> {{ company.short_name }}
|
|
69
|
-
</option>
|
|
70
|
-
{% endif %}
|
|
71
|
-
{% endfor %}
|
|
72
|
-
</select>
|
|
73
|
-
</div>
|
|
74
|
-
|
|
75
|
-
<div class="mb-3">
|
|
76
|
-
<label for="external_user_id" class="form-label d-block text-muted">External user ID</label>
|
|
77
|
-
<input type="text" id="external_user_id" name="external_user_id" class="form-control" required>
|
|
78
|
-
</div>
|
|
79
|
-
|
|
80
|
-
<button type="button"
|
|
81
|
-
id="initiateJwtChatButton"
|
|
82
|
-
class="ml-5 btn btn-primary">
|
|
83
|
-
<span class="spinner-border spinner-border-sm d-none" role="status" aria-hidden="true"></span>
|
|
84
|
-
Iniciar Sesión JWT
|
|
85
|
-
</button>
|
|
86
|
-
</form>
|
|
87
|
-
</div>
|
|
88
|
-
</div>
|
|
89
|
-
|
|
90
|
-
</div>
|
|
91
|
-
|
|
92
|
-
{% endblock %}
|
|
93
|
-
|
|
94
|
-
{% block scripts %}
|
|
95
|
-
|
|
96
|
-
<script>
|
|
97
|
-
// Variables pasadas desde Flask (HomeView)
|
|
98
|
-
const CHAT_TOKEN_REQUEST_URL = "{{ chat_token_request_url|safe }}";
|
|
99
|
-
const PUBLIC_CHAT_URL_TEMPLATE = "{{ public_chat_url_template|safe }}";
|
|
100
|
-
const API_KEY = "{{ api_key|safe }}";
|
|
101
|
-
|
|
102
|
-
$(document).ready(function () {
|
|
103
|
-
// Función para actualizar el enlace de "Registrarse" y el action del formulario "Iniciar Sesión"
|
|
104
|
-
function updateLinksAndForm() {
|
|
105
|
-
const selectedCompany = $('#company_short_name').val(); // Obtenemos el valor del select
|
|
106
|
-
|
|
107
|
-
// Actualizar enlace "Registrarse"
|
|
108
|
-
if (selectedCompany && selectedCompany.trim() !== '') {
|
|
109
|
-
const signupUrl = '/' + selectedCompany + '/signup';
|
|
110
|
-
$('#signup-link').attr('href', signupUrl); // Actualizamos el href del botón "Registrarse"
|
|
111
|
-
} else {
|
|
112
|
-
$('#signup-link').attr('href', '#'); // Enlace a "#" si no hay empresa seleccionada
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
// Actualizar action del formulario "Iniciar Sesión"
|
|
116
|
-
if (selectedCompany && selectedCompany.trim() !== '') {
|
|
117
|
-
const loginAction = '/' + selectedCompany + '/login';
|
|
118
|
-
$('#login-form').attr('action', loginAction); // Actualizamos la URL del form
|
|
119
|
-
} else {
|
|
120
|
-
$('#login-form').attr('action', '#'); // URL genérica si no hay selección
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
// Actualizamos al cargar la página
|
|
125
|
-
updateLinksAndForm();
|
|
126
|
-
|
|
127
|
-
// Escuchamos el evento de cambio en el dropdown para actualizar dinámicamente
|
|
128
|
-
$('#company_short_name').on('change', function () {
|
|
129
|
-
updateLinksAndForm();
|
|
130
|
-
});
|
|
131
|
-
|
|
132
|
-
// Interceptamos el click en "Registrarse"
|
|
133
|
-
$('#signup-link').on('click', function (e) {
|
|
134
|
-
const selectedCompany = $('#company_short_name').val();
|
|
135
|
-
|
|
136
|
-
if (!selectedCompany || selectedCompany.trim() === '') {
|
|
137
|
-
e.preventDefault(); // evitar navegación al #
|
|
138
|
-
Swal.fire({
|
|
139
|
-
icon: 'warning',
|
|
140
|
-
title: 'Empresa no seleccionada',
|
|
141
|
-
text: 'Por favor, selecciona una empresa antes de registrarte.'
|
|
142
|
-
});
|
|
143
|
-
}
|
|
144
|
-
});
|
|
145
|
-
|
|
146
|
-
// Event listener para el botón de "Abrir Chat (JWT)"
|
|
147
|
-
$('#initiateJwtChatButton').on('click', function() {
|
|
148
|
-
|
|
149
|
-
const selectedCompany = $('#company_name').val();
|
|
150
|
-
const externalUserId = $('#external_user_id').val();
|
|
151
|
-
|
|
152
|
-
if (!selectedCompany || !externalUserId.trim()) {
|
|
153
|
-
Swal.fire({ icon: 'warning', title: 'Campos Requeridos', text: 'Por favor, selecciona una empresa e ingresa un ID de usuario.' });
|
|
154
|
-
return;
|
|
155
|
-
}
|
|
156
|
-
if (!API_KEY || API_KEY.includes("defecto")) {
|
|
157
|
-
Swal.fire({ icon: 'error', title: 'Error de Configuración', text: 'La API Key de la aplicación no está disponible.' });
|
|
158
|
-
return;
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
const $button = $(this);
|
|
162
|
-
const $spinner = $button.find('.spinner-border');
|
|
163
|
-
$button.prop('disabled', true);
|
|
164
|
-
$spinner.removeClass('d-none');
|
|
165
|
-
|
|
166
|
-
fetch(`/${selectedCompany}/chat_login`, {
|
|
167
|
-
method: 'POST',
|
|
168
|
-
headers: {
|
|
169
|
-
'Content-Type': 'application/json',
|
|
170
|
-
'Authorization': `Bearer ${API_KEY}`
|
|
171
|
-
},
|
|
172
|
-
body: JSON.stringify({
|
|
173
|
-
external_user_id: externalUserId
|
|
174
|
-
})
|
|
175
|
-
})
|
|
176
|
-
.then(async response => {
|
|
177
|
-
if (response.ok) { // Si el status es 200, la respuesta es el HTML
|
|
178
|
-
return response.text();
|
|
179
|
-
} else { // Si hay un error, el cuerpo es JSON
|
|
180
|
-
const errorData = await response.json();
|
|
181
|
-
throw new Error(errorData.error || 'Ocurrió un error desconocido.');
|
|
182
|
-
}
|
|
183
|
-
})
|
|
184
|
-
.then(htmlContent => {
|
|
185
|
-
// Éxito: Abrimos el HTML que nos devolvió el servidor en una nueva pestaña.
|
|
186
|
-
const newTab = window.open();
|
|
187
|
-
newTab.document.write(htmlContent);
|
|
188
|
-
newTab.document.close();
|
|
189
|
-
})
|
|
190
|
-
.catch(error => {
|
|
191
|
-
Swal.fire({ icon: 'error', title: 'Error de Inicio de Sesión', text: error.message });
|
|
192
|
-
})
|
|
193
|
-
.finally(() => {
|
|
194
|
-
$button.prop('disabled', false);
|
|
195
|
-
$spinner.addClass('d-none');
|
|
196
|
-
});
|
|
197
|
-
|
|
198
|
-
});
|
|
199
|
-
});
|
|
200
|
-
</script>
|
|
201
|
-
{% endblock %}
|