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.

Files changed (159) hide show
  1. iatoolkit/__init__.py +8 -34
  2. iatoolkit/base_company.py +14 -3
  3. iatoolkit/common/routes.py +83 -52
  4. iatoolkit/common/session_manager.py +0 -1
  5. iatoolkit/common/util.py +0 -27
  6. iatoolkit/iatoolkit.py +61 -46
  7. iatoolkit/infra/llm_client.py +7 -8
  8. iatoolkit/infra/openai_adapter.py +1 -1
  9. iatoolkit/infra/redis_session_manager.py +48 -2
  10. iatoolkit/repositories/database_manager.py +17 -2
  11. iatoolkit/repositories/models.py +31 -6
  12. iatoolkit/repositories/profile_repo.py +7 -2
  13. iatoolkit/services/auth_service.py +188 -0
  14. iatoolkit/services/branding_service.py +147 -0
  15. iatoolkit/services/dispatcher_service.py +10 -40
  16. iatoolkit/services/excel_service.py +15 -15
  17. iatoolkit/services/history_service.py +3 -12
  18. iatoolkit/services/jwt_service.py +15 -24
  19. iatoolkit/services/onboarding_service.py +43 -0
  20. iatoolkit/services/profile_service.py +97 -44
  21. iatoolkit/services/query_service.py +124 -81
  22. iatoolkit/services/tasks_service.py +1 -1
  23. iatoolkit/services/user_feedback_service.py +67 -31
  24. iatoolkit/services/user_session_context_service.py +112 -54
  25. iatoolkit/static/images/fernando.jpeg +0 -0
  26. iatoolkit/static/js/{chat_feedback.js → chat_feedback_button.js} +6 -11
  27. iatoolkit/static/js/chat_history_button.js +126 -0
  28. iatoolkit/static/js/chat_logout_button.js +36 -0
  29. iatoolkit/static/js/chat_main.js +130 -220
  30. iatoolkit/static/js/chat_onboarding_button.js +97 -0
  31. iatoolkit/static/js/chat_prompt_manager.js +94 -0
  32. iatoolkit/static/js/chat_reload_button.js +52 -0
  33. iatoolkit/static/styles/chat_iatoolkit.css +329 -507
  34. iatoolkit/static/styles/chat_modal.css +95 -56
  35. iatoolkit/static/styles/landing_page.css +182 -0
  36. iatoolkit/static/styles/onboarding.css +169 -0
  37. iatoolkit/system_prompts/query_main.prompt +3 -12
  38. iatoolkit/templates/_company_header.html +20 -0
  39. iatoolkit/templates/_login_widget.html +40 -0
  40. iatoolkit/templates/base.html +8 -3
  41. iatoolkit/templates/change_password.html +54 -37
  42. iatoolkit/templates/chat.html +149 -66
  43. iatoolkit/templates/chat_modals.html +47 -18
  44. iatoolkit/templates/error.html +41 -8
  45. iatoolkit/templates/forgot_password.html +37 -24
  46. iatoolkit/templates/index.html +140 -0
  47. iatoolkit/templates/login_simulation.html +34 -0
  48. iatoolkit/templates/onboarding_shell.html +105 -0
  49. iatoolkit/templates/signup.html +64 -66
  50. iatoolkit/views/base_login_view.py +81 -0
  51. iatoolkit/views/change_password_view.py +23 -12
  52. iatoolkit/views/external_login_view.py +61 -28
  53. iatoolkit/views/{file_store_view.py → file_store_api_view.py} +9 -2
  54. iatoolkit/views/forgot_password_view.py +23 -13
  55. iatoolkit/views/history_api_view.py +52 -0
  56. iatoolkit/views/home_view.py +58 -25
  57. iatoolkit/views/index_view.py +14 -0
  58. iatoolkit/views/init_context_api_view.py +68 -0
  59. iatoolkit/views/llmquery_api_view.py +45 -0
  60. iatoolkit/views/login_simulation_view.py +81 -0
  61. iatoolkit/views/login_view.py +118 -34
  62. iatoolkit/views/logout_api_view.py +45 -0
  63. iatoolkit/views/{prompt_view.py → prompt_api_view.py} +7 -7
  64. iatoolkit/views/signup_view.py +38 -29
  65. iatoolkit/views/{tasks_view.py → tasks_api_view.py} +10 -36
  66. iatoolkit/views/tasks_review_api_view.py +55 -0
  67. iatoolkit/views/{user_feedback_view.py → user_feedback_api_view.py} +16 -31
  68. iatoolkit/views/verify_user_view.py +13 -8
  69. {iatoolkit-0.8.1.dist-info → iatoolkit-0.63.4.dist-info}/METADATA +2 -2
  70. iatoolkit-0.63.4.dist-info/RECORD +113 -0
  71. {iatoolkit-0.8.1.dist-info → iatoolkit-0.63.4.dist-info}/top_level.txt +0 -1
  72. iatoolkit/common/auth.py +0 -200
  73. iatoolkit/static/images/arrow_up.png +0 -0
  74. iatoolkit/static/images/diagrama_iatoolkit.jpg +0 -0
  75. iatoolkit/static/images/logo_clinica.png +0 -0
  76. iatoolkit/static/images/logo_iatoolkit.png +0 -0
  77. iatoolkit/static/images/logo_maxxa.png +0 -0
  78. iatoolkit/static/images/logo_notaria.png +0 -0
  79. iatoolkit/static/images/logo_tarjeta.png +0 -0
  80. iatoolkit/static/images/logo_umayor.png +0 -0
  81. iatoolkit/static/images/upload.png +0 -0
  82. iatoolkit/static/js/chat_history.js +0 -117
  83. iatoolkit/templates/home.html +0 -201
  84. iatoolkit/templates/login.html +0 -43
  85. iatoolkit/views/chat_token_request_view.py +0 -98
  86. iatoolkit/views/chat_view.py +0 -51
  87. iatoolkit/views/download_file_view.py +0 -58
  88. iatoolkit/views/external_chat_login_view.py +0 -88
  89. iatoolkit/views/history_view.py +0 -57
  90. iatoolkit/views/llmquery_view.py +0 -65
  91. iatoolkit/views/tasks_review_view.py +0 -83
  92. iatoolkit-0.8.1.dist-info/RECORD +0 -175
  93. tests/__init__.py +0 -5
  94. tests/common/__init__.py +0 -0
  95. tests/common/test_auth.py +0 -279
  96. tests/common/test_routes.py +0 -42
  97. tests/common/test_session_manager.py +0 -59
  98. tests/common/test_util.py +0 -444
  99. tests/companies/__init__.py +0 -5
  100. tests/conftest.py +0 -36
  101. tests/infra/__init__.py +0 -5
  102. tests/infra/connectors/__init__.py +0 -5
  103. tests/infra/connectors/test_google_drive_connector.py +0 -107
  104. tests/infra/connectors/test_local_file_connector.py +0 -85
  105. tests/infra/connectors/test_s3_connector.py +0 -95
  106. tests/infra/test_call_service.py +0 -92
  107. tests/infra/test_database_manager.py +0 -59
  108. tests/infra/test_gemini_adapter.py +0 -137
  109. tests/infra/test_google_chat_app.py +0 -68
  110. tests/infra/test_llm_client.py +0 -165
  111. tests/infra/test_llm_proxy.py +0 -122
  112. tests/infra/test_mail_app.py +0 -94
  113. tests/infra/test_openai_adapter.py +0 -105
  114. tests/infra/test_redis_session_manager_service.py +0 -117
  115. tests/repositories/__init__.py +0 -5
  116. tests/repositories/test_database_manager.py +0 -87
  117. tests/repositories/test_document_repo.py +0 -76
  118. tests/repositories/test_llm_query_repo.py +0 -340
  119. tests/repositories/test_models.py +0 -38
  120. tests/repositories/test_profile_repo.py +0 -142
  121. tests/repositories/test_tasks_repo.py +0 -76
  122. tests/repositories/test_vs_repo.py +0 -107
  123. tests/services/__init__.py +0 -5
  124. tests/services/test_dispatcher_service.py +0 -274
  125. tests/services/test_document_service.py +0 -181
  126. tests/services/test_excel_service.py +0 -208
  127. tests/services/test_file_processor_service.py +0 -121
  128. tests/services/test_history_service.py +0 -164
  129. tests/services/test_jwt_service.py +0 -255
  130. tests/services/test_load_documents_service.py +0 -112
  131. tests/services/test_mail_service.py +0 -70
  132. tests/services/test_profile_service.py +0 -379
  133. tests/services/test_prompt_manager_service.py +0 -190
  134. tests/services/test_query_service.py +0 -243
  135. tests/services/test_search_service.py +0 -39
  136. tests/services/test_sql_service.py +0 -160
  137. tests/services/test_tasks_service.py +0 -252
  138. tests/services/test_user_feedback_service.py +0 -389
  139. tests/services/test_user_session_context_service.py +0 -132
  140. tests/views/__init__.py +0 -5
  141. tests/views/test_change_password_view.py +0 -191
  142. tests/views/test_chat_token_request_view.py +0 -188
  143. tests/views/test_chat_view.py +0 -98
  144. tests/views/test_download_file_view.py +0 -149
  145. tests/views/test_external_chat_login_view.py +0 -120
  146. tests/views/test_external_login_view.py +0 -102
  147. tests/views/test_file_store_view.py +0 -128
  148. tests/views/test_forgot_password_view.py +0 -142
  149. tests/views/test_history_view.py +0 -336
  150. tests/views/test_home_view.py +0 -61
  151. tests/views/test_llm_query_view.py +0 -154
  152. tests/views/test_login_view.py +0 -114
  153. tests/views/test_prompt_view.py +0 -111
  154. tests/views/test_signup_view.py +0 -140
  155. tests/views/test_tasks_review_view.py +0 -104
  156. tests/views/test_tasks_view.py +0 -130
  157. tests/views/test_user_feedback_view.py +0 -214
  158. tests/views/test_verify_user_view.py +0 -110
  159. {iatoolkit-0.8.1.dist-info → iatoolkit-0.63.4.dist-info}/WHEEL +0 -0
@@ -1,214 +0,0 @@
1
- # Copyright (c) 2024 Fernando Libedinsky
2
- # Product: IAToolkit
3
- #
4
- # IAToolkit is open source software.
5
-
6
- import pytest
7
- from unittest.mock import MagicMock, patch
8
- from flask import Flask
9
- from iatoolkit.views.user_feedback_view import UserFeedbackView
10
- from iatoolkit.services.user_feedback_service import UserFeedbackService
11
- from iatoolkit.common.auth import IAuthentication
12
-
13
-
14
- class TestUserFeedbackView:
15
- @staticmethod
16
- def create_app():
17
- app = Flask(__name__)
18
- app.testing = True
19
- return app
20
-
21
- @pytest.fixture(autouse=True)
22
- def setup(self):
23
- self.app = self.create_app()
24
- self.client = self.app.test_client()
25
- self.feedback_service = MagicMock(spec=UserFeedbackService)
26
- self.iauthentication = MagicMock(spec=IAuthentication)
27
-
28
- self.iauthentication.verify.return_value = {
29
- 'success': True,
30
- 'company_id': 101,
31
- 'external_user_id': 'test_user_id'
32
- }
33
-
34
- # register the view
35
- self.feedback_view = UserFeedbackView.as_view("feedback",
36
- user_feedback_service=self.feedback_service,
37
- iauthentication=self.iauthentication)
38
- self.app.add_url_rule('/<company_short_name>/feedback',
39
- view_func=self.feedback_view,
40
- methods=["POST"])
41
-
42
-
43
- def test_post_when_missing_data(self):
44
- response = self.client.post('/my_company/feedback',
45
- json={})
46
-
47
- assert response.status_code == 400
48
- self.feedback_service.new_feedback.assert_not_called()
49
-
50
- def test_post_when_auth_error(self):
51
- self.iauthentication.verify.return_value = {'error_message': 'error in authentication'}
52
- response = self.client.post('/my_company/feedback',
53
- json={'external_user_id': 'flibe'})
54
-
55
- assert response.status_code == 401
56
- assert response.json["error_message"] == 'error in authentication'
57
-
58
- def test_post_when_missing_message(self):
59
- response = self.client.post('/my_company/feedback',
60
- json={'external_user_id': 'flibe'})
61
-
62
- assert response.status_code == 400
63
- assert response.json["error_message"] == 'Falta el mensaje de feedback'
64
- self.feedback_service.new_feedback.assert_not_called()
65
-
66
- def test_post_when_missing_space(self):
67
- response = self.client.post('/my_company/feedback',
68
- json={'external_user_id': 'flibe', 'message': 'test message'})
69
-
70
- assert response.status_code == 400
71
- assert response.json["error_message"] == 'Falta el espacio de Google Chat'
72
- self.feedback_service.new_feedback.assert_not_called()
73
-
74
- def test_post_when_missing_type(self):
75
- response = self.client.post('/my_company/feedback',
76
- json={'external_user_id': 'flibe', 'message': 'test message', 'space': 'spaces/test'})
77
-
78
- assert response.status_code == 400
79
- assert response.json["error_message"] == 'Falta el tipo de feedback'
80
- self.feedback_service.new_feedback.assert_not_called()
81
-
82
- def test_post_when_missing_rating(self):
83
- response = self.client.post('/my_company/feedback',
84
- json={'external_user_id': 'flibe', 'message': 'test message', 'space': 'spaces/test', 'type': 'MESSAGE_TRIGGER'})
85
-
86
- assert response.status_code == 400
87
- assert response.json["error_message"] == 'Falta la calificación'
88
- self.feedback_service.new_feedback.assert_not_called()
89
-
90
- @patch("iatoolkit.views.user_feedback_view.render_template")
91
- def test_post_when_exception(self, mock_render_template):
92
- mock_render_template.return_value = "<html><body></body></html>"
93
- self.feedback_service.new_feedback.side_effect = Exception('error')
94
-
95
- response = self.client.post('/my_company/feedback',
96
- json={
97
- 'message': 'feedback message',
98
- 'external_user_id': 'flibe',
99
- 'space': 'spaces/test',
100
- 'type': 'MESSAGE_TRIGGER',
101
- 'rating': 4
102
- })
103
-
104
- assert response.status_code == 500
105
-
106
- def test_post_when_service_error(self):
107
- self.feedback_service.new_feedback.return_value = {'error': 'an error'}
108
-
109
- response = self.client.post('/my_company/feedback',
110
- json={
111
- 'message': 'feedback message',
112
- 'external_user_id': 'flibe',
113
- 'space': 'spaces/test',
114
- 'type': 'MESSAGE_TRIGGER',
115
- 'rating': 3
116
- })
117
-
118
- assert response.status_code == 402
119
- assert response.json == {'error_message': 'an error'}
120
-
121
- def test_post_when_ok(self):
122
- self.feedback_service.new_feedback.return_value = {'message': "Feedback guardado correctamente"}
123
-
124
- response = self.client.post('/my_company/feedback',
125
- json={
126
- 'message': 'feedback message',
127
- 'external_user_id': 'flibe',
128
- 'space': 'spaces/test',
129
- 'type': 'MESSAGE_TRIGGER',
130
- 'rating': 5
131
- })
132
-
133
- assert response.status_code == 200
134
- assert response.json == {'message': "Feedback guardado correctamente"}
135
-
136
- def test_post_with_all_required_fields(self):
137
- """Test that all required fields are passed to the service correctly"""
138
- self.feedback_service.new_feedback.return_value = {'message': "Feedback guardado correctamente"}
139
-
140
- test_data = {
141
- 'message': 'test feedback message',
142
- 'external_user_id': 'test_user_123',
143
- 'local_user_id': 456,
144
- 'space': 'spaces/custom-space',
145
- 'type': 'CUSTOM_TYPE',
146
- 'rating': 4
147
- }
148
-
149
- response = self.client.post('/my_company/feedback', json=test_data)
150
-
151
- assert response.status_code == 200
152
-
153
- # Verify service was called with all parameters
154
- self.feedback_service.new_feedback.assert_called_once_with(
155
- company_short_name='my_company',
156
- message='test feedback message',
157
- external_user_id='test_user_123',
158
- local_user_id=456,
159
- space='spaces/custom-space',
160
- type='CUSTOM_TYPE',
161
- rating=4
162
- )
163
-
164
- def test_post_with_optional_local_user_id(self):
165
- """Test that local_user_id is optional and defaults to 0"""
166
- self.feedback_service.new_feedback.return_value = {'message': "Feedback guardado correctamente"}
167
-
168
- test_data = {
169
- 'message': 'test feedback message',
170
- 'external_user_id': 'test_user_123',
171
- 'space': 'spaces/test',
172
- 'type': 'MESSAGE_TRIGGER',
173
- 'rating': 2
174
- }
175
-
176
- response = self.client.post('/my_company/feedback', json=test_data)
177
-
178
- assert response.status_code == 200
179
-
180
- # Verify service was called with default local_user_id
181
- call_args = self.feedback_service.new_feedback.call_args[1]
182
- assert call_args['local_user_id'] == 0
183
-
184
- def test_post_with_different_rating_values(self):
185
- """Test that different rating values are accepted"""
186
- self.feedback_service.new_feedback.return_value = {'message': "Feedback guardado correctamente"}
187
-
188
- # Test with rating 1
189
- response1 = self.client.post('/my_company/feedback',
190
- json={
191
- 'message': 'feedback message',
192
- 'external_user_id': 'flibe',
193
- 'space': 'spaces/test',
194
- 'type': 'MESSAGE_TRIGGER',
195
- 'rating': 1
196
- })
197
- assert response1.status_code == 200
198
-
199
- # Test with rating 5
200
- response2 = self.client.post('/my_company/feedback',
201
- json={
202
- 'message': 'feedback message',
203
- 'external_user_id': 'flibe',
204
- 'space': 'spaces/test',
205
- 'type': 'MESSAGE_TRIGGER',
206
- 'rating': 5
207
- })
208
- assert response2.status_code == 200
209
-
210
- # Verify both calls were made with correct ratings
211
- calls = self.feedback_service.new_feedback.call_args_list
212
- assert len(calls) == 2
213
- assert calls[0][1]['rating'] == 1
214
- assert calls[1][1]['rating'] == 5
@@ -1,110 +0,0 @@
1
- # Copyright (c) 2024 Fernando Libedinsky
2
- # Product: IAToolkit
3
- #
4
- # IAToolkit is open source software.
5
-
6
- import pytest
7
- from flask import Flask
8
- from unittest.mock import MagicMock, patch
9
- from iatoolkit.services.profile_service import ProfileService
10
- from iatoolkit.repositories.models import Company
11
- from iatoolkit.views.verify_user_view import VerifyAccountView
12
- import os
13
- from itsdangerous import SignatureExpired
14
-
15
-
16
- class TestVerifyAccountView:
17
- @classmethod
18
- def setup_class(cls):
19
- cls.patcher = patch.dict(os.environ, {"USER_VERIF_KEY": "mocked_secret_key"})
20
- cls.patcher.start()
21
-
22
- @staticmethod
23
- def create_app():
24
- """Configura la aplicación Flask para pruebas."""
25
- app = Flask(__name__)
26
- app.testing = True
27
- return app
28
-
29
- @pytest.fixture(autouse=True)
30
- def setup(self):
31
- """Configura el cliente y los mocks antes de cada test."""
32
- self.app = self.create_app()
33
- self.client = self.app.test_client()
34
- self.profile_service = MagicMock(spec=ProfileService)
35
- self.test_company = Company(
36
- id=1,
37
- name="Empresa de Prueba",
38
- short_name="test_company",
39
- logo_file="test_logo.png"
40
- )
41
- self.profile_service.get_company_by_short_name.return_value = self.test_company
42
-
43
- # Registrar la vista
44
- view = VerifyAccountView.as_view("verify_account", profile_service=self.profile_service)
45
- self.app.add_url_rule("/<company_short_name>/verify/<token>", view_func=view, methods=["GET"])
46
-
47
- @patch("iatoolkit.views.verify_user_view.render_template")
48
- def test_get_with_invalid_company(self, mock_render):
49
- self.profile_service.get_company_by_short_name.return_value = None
50
- response = self.client.get("/test_company/verify/<expired_token>")
51
- assert response.status_code == 404
52
-
53
-
54
- @patch("iatoolkit.views.verify_user_view.render_template")
55
- @patch("iatoolkit.views.verify_user_view.URLSafeTimedSerializer")
56
- def test_get_with_expired_token(self, mock_serializer_class, mock_render_template):
57
- # Configura que el serializer lance una excepción de expiración
58
- mock_serializer = mock_serializer_class.return_value
59
- mock_serializer.loads.side_effect = SignatureExpired('error')
60
-
61
- mock_render_template.return_value = "<html><body><h1>Signup Page</h1></body></html>"
62
- response = self.client.get("/test_company/verify/<expired_token>")
63
-
64
- assert response.status_code == 400
65
-
66
- @patch("iatoolkit.views.verify_user_view.render_template")
67
- @patch("iatoolkit.views.verify_user_view.URLSafeTimedSerializer")
68
- def test_verify_with_error(self, mock_serializer, mock_render_template):
69
- # Simula que el token es válido y contiene un email
70
- mock_serializer.return_value.loads.return_value = "nonexistent@email.com"
71
- mock_render_template.return_value = "<html><body><h1>Signup Page</h1></body></html>"
72
- self.profile_service.verify_account.return_value = {'error': 'invalid link'}
73
-
74
- response = self.client.get("/test_company/verify/<valid_token>")
75
- assert response.status_code == 400
76
-
77
- @patch("iatoolkit.views.verify_user_view.render_template")
78
- @patch("iatoolkit.views.verify_user_view.URLSafeTimedSerializer")
79
- def test_verify_ok(self, mock_serializer, mock_render_template):
80
- # Simula que el token es válido y contiene un email
81
- mock_serializer.return_value.loads.return_value = "nonexistent@email.com"
82
- mock_render_template.return_value = "<html><body><h1>Signup Page</h1></body></html>"
83
- self.profile_service.verify_account.return_value = {"message": "account verified"}
84
-
85
- response = self.client.get("/test_company/verify/<valid_token>")
86
-
87
- mock_render_template.assert_called_once_with(
88
- "login.html",
89
- company=self.test_company,
90
- company_short_name='test_company',
91
- alert_icon='success',
92
- alert_message="account verified"
93
- )
94
-
95
- assert response.status_code == 200
96
-
97
- @patch("iatoolkit.views.verify_user_view.render_template")
98
- @patch("iatoolkit.views.verify_user_view.URLSafeTimedSerializer")
99
- def test_post_unexpected_error(self, mock_serializer, mock_render_template):
100
- mock_serializer.return_value.loads.return_value = "nonexistent@email.com"
101
- self.profile_service.verify_account.side_effect = Exception('an error')
102
- response = self.client.get("/test_company/verify/<valid_token>")
103
-
104
- mock_render_template.assert_called_once_with(
105
- "error.html",
106
- company=self.test_company,
107
- company_short_name='test_company',
108
- message="Ha ocurrido un error inesperado."
109
- )
110
- assert response.status_code == 500