Skip to content

Commit 27da64b

Browse files
lumburovskalinaJWittmeyeranmarhindi
authored
release-v-1-15-0 (#228)
* Users into organization count is not correct(deleted users are counted) * null for empty org id * Searches in kratos if cache doesnt hold values * Fixes progress 0 log * Adds alembic to migrate the db * Fixes faulty gates similarity search display * adds soo indicator to mapped request * remove print * cancel task doesn’t work * Adds return for config chagnes * Adds session handler for starlett middleware * Hotfix session connection loss * submodules ref --------- Co-authored-by: JWittmeyer <[email protected]> Co-authored-by: anmarhindi <[email protected]>
1 parent be59c33 commit 27da64b

File tree

16 files changed

+219
-49
lines changed

16 files changed

+219
-49
lines changed
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
"""ensured user cascade behaviour
2+
3+
Revision ID: 706d5611a73e
4+
Revises: 194838aa0431
5+
Create Date: 2024-06-12 09:29:07.617462
6+
7+
"""
8+
from alembic import op
9+
import sqlalchemy as sa
10+
11+
12+
# revision identifiers, used by Alembic.
13+
revision = '706d5611a73e'
14+
down_revision = '194838aa0431'
15+
branch_labels = None
16+
depends_on = None
17+
18+
19+
def upgrade():
20+
# ### commands auto generated by Alembic - please adjust! ###
21+
op.drop_constraint('admin_message_archived_by_fkey', 'admin_message', type_='foreignkey')
22+
op.drop_constraint('admin_message_created_by_fkey', 'admin_message', type_='foreignkey')
23+
op.create_foreign_key(None, 'admin_message', 'user', ['archived_by'], ['id'], ondelete='SET NULL')
24+
op.create_foreign_key(None, 'admin_message', 'user', ['created_by'], ['id'], ondelete='SET NULL')
25+
op.drop_constraint('agreement_user_id_fkey', 'agreement', type_='foreignkey')
26+
op.create_foreign_key(None, 'agreement', 'user', ['user_id'], ['id'], ondelete='SET NULL')
27+
op.drop_constraint('comment_data_created_by_fkey', 'comment_data', type_='foreignkey')
28+
op.create_foreign_key(None, 'comment_data', 'user', ['created_by'], ['id'], ondelete='SET NULL')
29+
op.drop_constraint('data_slice_created_by_fkey', 'data_slice', type_='foreignkey')
30+
op.create_foreign_key(None, 'data_slice', 'user', ['created_by'], ['id'], ondelete='SET NULL')
31+
op.drop_constraint('embedding_created_by_fkey', 'embedding', type_='foreignkey')
32+
op.create_foreign_key(None, 'embedding', 'user', ['created_by'], ['id'], ondelete='SET NULL')
33+
op.drop_constraint('information_source_created_by_fkey', 'information_source', type_='foreignkey')
34+
op.create_foreign_key(None, 'information_source', 'user', ['created_by'], ['id'], ondelete='SET NULL')
35+
op.drop_constraint('labeling_access_link_created_by_fkey', 'labeling_access_link', type_='foreignkey')
36+
op.create_foreign_key(None, 'labeling_access_link', 'user', ['created_by'], ['id'], ondelete='SET NULL')
37+
op.drop_constraint('labeling_task_label_created_by_fkey', 'labeling_task_label', type_='foreignkey')
38+
op.create_foreign_key(None, 'labeling_task_label', 'user', ['created_by'], ['id'], ondelete='SET NULL')
39+
op.drop_constraint('project_created_by_fkey', 'project', type_='foreignkey')
40+
op.create_foreign_key(None, 'project', 'user', ['created_by'], ['id'], ondelete='SET NULL')
41+
op.drop_constraint('record_label_association_created_by_fkey', 'record_label_association', type_='foreignkey')
42+
op.create_foreign_key(None, 'record_label_association', 'user', ['created_by'], ['id'], ondelete='SET NULL')
43+
op.create_index(op.f('ix_task_queue_created_by'), 'task_queue', ['created_by'], unique=False)
44+
op.drop_constraint('task_queue_created_by_fkey', 'task_queue', type_='foreignkey')
45+
op.create_foreign_key(None, 'task_queue', 'user', ['created_by'], ['id'], ondelete='SET NULL')
46+
op.drop_constraint('upload_task_user_id_fkey', 'upload_task', type_='foreignkey')
47+
op.create_foreign_key(None, 'upload_task', 'user', ['user_id'], ['id'], ondelete='SET NULL')
48+
op.create_index(op.f('ix_cognition_macro_execution_organization_id'), 'macro_execution', ['organization_id'], unique=False, schema='cognition')
49+
op.create_index(op.f('ix_cognition_macro_execution_link_organization_id'), 'macro_execution_link', ['organization_id'], unique=False, schema='cognition')
50+
# ### end Alembic commands ###
51+
52+
53+
def downgrade():
54+
# ### commands auto generated by Alembic - please adjust! ###
55+
op.drop_index(op.f('ix_cognition_macro_execution_link_organization_id'), table_name='macro_execution_link', schema='cognition')
56+
op.drop_index(op.f('ix_cognition_macro_execution_organization_id'), table_name='macro_execution', schema='cognition')
57+
op.drop_constraint(None, 'upload_task', type_='foreignkey')
58+
op.create_foreign_key('upload_task_user_id_fkey', 'upload_task', 'user', ['user_id'], ['id'], ondelete='CASCADE')
59+
op.drop_constraint(None, 'task_queue', type_='foreignkey')
60+
op.create_foreign_key('task_queue_created_by_fkey', 'task_queue', 'user', ['created_by'], ['id'])
61+
op.drop_index(op.f('ix_task_queue_created_by'), table_name='task_queue')
62+
op.drop_constraint(None, 'record_label_association', type_='foreignkey')
63+
op.create_foreign_key('record_label_association_created_by_fkey', 'record_label_association', 'user', ['created_by'], ['id'], ondelete='CASCADE')
64+
op.drop_constraint(None, 'project', type_='foreignkey')
65+
op.create_foreign_key('project_created_by_fkey', 'project', 'user', ['created_by'], ['id'], ondelete='CASCADE')
66+
op.drop_constraint(None, 'labeling_task_label', type_='foreignkey')
67+
op.create_foreign_key('labeling_task_label_created_by_fkey', 'labeling_task_label', 'user', ['created_by'], ['id'], ondelete='CASCADE')
68+
op.drop_constraint(None, 'labeling_access_link', type_='foreignkey')
69+
op.create_foreign_key('labeling_access_link_created_by_fkey', 'labeling_access_link', 'user', ['created_by'], ['id'], ondelete='CASCADE')
70+
op.drop_constraint(None, 'information_source', type_='foreignkey')
71+
op.create_foreign_key('information_source_created_by_fkey', 'information_source', 'user', ['created_by'], ['id'], ondelete='CASCADE')
72+
op.drop_constraint(None, 'embedding', type_='foreignkey')
73+
op.create_foreign_key('embedding_created_by_fkey', 'embedding', 'user', ['created_by'], ['id'], ondelete='CASCADE')
74+
op.drop_constraint(None, 'data_slice', type_='foreignkey')
75+
op.create_foreign_key('data_slice_created_by_fkey', 'data_slice', 'user', ['created_by'], ['id'], ondelete='CASCADE')
76+
op.drop_constraint(None, 'comment_data', type_='foreignkey')
77+
op.create_foreign_key('comment_data_created_by_fkey', 'comment_data', 'user', ['created_by'], ['id'])
78+
op.drop_constraint(None, 'agreement', type_='foreignkey')
79+
op.create_foreign_key('agreement_user_id_fkey', 'agreement', 'user', ['user_id'], ['id'], ondelete='CASCADE')
80+
op.drop_constraint(None, 'admin_message', type_='foreignkey')
81+
op.drop_constraint(None, 'admin_message', type_='foreignkey')
82+
op.create_foreign_key('admin_message_created_by_fkey', 'admin_message', 'user', ['created_by'], ['id'])
83+
op.create_foreign_key('admin_message_archived_by_fkey', 'admin_message', 'user', ['archived_by'], ['id'])
84+
# ### end Alembic commands ###

api/transfer.py

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
import traceback
33
import time
44
from typing import Optional, Dict
5-
from time import sleep
65
from starlette.endpoints import HTTPEndpoint
76
from starlette.responses import PlainTextResponse, JSONResponse
87
from controller.embedding.manager import recreate_embeddings
@@ -299,22 +298,25 @@ def put(self, request) -> PlainTextResponse:
299298
cognition_prj.organization_id, cognition_prj.created_by, True
300299
).id
301300
)
301+
cached = {str(e.id): str(e.created_by) for e in execution_entries}
302302

303303
def queue_tasks():
304304
token = general.get_ctx_token()
305-
for entry in execution_entries:
306-
task_queue_manager.add_task(
307-
refinery_prj_id,
308-
TaskType.RUN_COGNITION_MACRO,
309-
entry.created_by,
310-
{
311-
"macro_id": macro_id,
312-
"execution_id": str(entry.id),
313-
"execution_group_id": group_id,
314-
},
315-
)
316-
general.commit()
317-
general.remove_and_refresh_session(token, False)
305+
try:
306+
for exec_id in cached:
307+
task_queue_manager.add_task(
308+
refinery_prj_id,
309+
TaskType.RUN_COGNITION_MACRO,
310+
cached[exec_id],
311+
{
312+
"macro_id": macro_id,
313+
"execution_id": exec_id,
314+
"execution_group_id": group_id,
315+
},
316+
)
317+
general.commit()
318+
finally:
319+
general.remove_and_refresh_session(token, False)
318320

319321
daemon.run(queue_tasks)
320322

app.py

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
from fastapi import FastAPI
44
from api.healthcheck import Healthcheck
5+
from starlette.middleware import Middleware
56
from api.misc import IsDemoRest, IsManagedRest
67
from api.project import ProjectDetails, ProjectCreationFromWorkflow
78
from api.transfer import (
@@ -36,6 +37,7 @@
3637
from fast_api.routes.weak_supervision import router as weak_supervision_router
3738
from fast_api.routes.labeling_tasks import router as labeling_tasks_router
3839
from middleware.database_session import handle_db_session
40+
from middleware.starlette_tmp_middleware import DatabaseSessionHandler
3941
from starlette.applications import Starlette
4042
from starlette.routing import Route, Mount
4143

@@ -151,11 +153,8 @@
151153

152154
fastapi_app.middleware("http")(handle_db_session)
153155

154-
155-
app = Starlette(routes=routes)
156-
157-
# middleware = [Middleware(DatabaseSessionHandler)]
158-
# app = Starlette(routes=routes, middleware=middleware)
156+
middleware = [Middleware(DatabaseSessionHandler)]
157+
app = Starlette(routes=routes, middleware=middleware)
159158

160159
init_task_queues()
161160
check_in_deletion_projects()

controller/auth/kratos.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import requests
44
import logging
55
from datetime import datetime, timedelta
6+
from urllib.parse import quote
67

78
logging.basicConfig(level=logging.INFO)
89
logger: logging.Logger = logging.getLogger(__name__)
@@ -122,6 +123,19 @@ def get_userid_from_mail(user_mail: str) -> str:
122123
continue
123124
if values[key]["simple"]["mail"] == user_mail:
124125
return key
126+
# not in cached values, try search kratos
127+
return __search_kratos_for_user_mail(user_mail)
128+
129+
130+
def __search_kratos_for_user_mail(user_mail: str) -> str:
131+
request = requests.get(
132+
f"{KRATOS_ADMIN_URL}/identities?preview_credentials_identifier_similar={quote(user_mail)}"
133+
)
134+
if request.ok:
135+
identities = request.json()
136+
for i in identities:
137+
if i["traits"]["email"].lower() == user_mail.lower():
138+
return i["id"]
125139
return None
126140

127141

controller/auth/manager.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
from controller.misc import manager as misc_manager
1818
import sqlalchemy
1919

20-
DEV_USER_ID = "59e8dfca-ce56-44df-a8c7-5f05c61da499"
20+
DEV_USER_ID = "741df1c2-a531-43b6-b259-df23bc78e9a2"
2121

2222

2323
def get_organization_id_by_info(info) -> Organization:

controller/organization/manager.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,11 @@ def get_all_users(
7272
all_users, column_whitelist=USER_INFO_WHITELIST
7373
)
7474
all_users_expanded = kratos.expand_user_mail_name(all_users_dict)
75+
all_users_expanded = [
76+
user
77+
for user in all_users_expanded
78+
if user["firstName"] is not None and user["lastName"] is not None
79+
]
7580
return all_users_expanded
7681

7782

controller/payload/manager.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
from typing import Any, Dict, List, Optional
22
from controller.payload import payload_scheduler
33
from fast_api.types import (
4-
LabelingFunctionSampleRecordWrapper,
54
LabelingFunctionSampleRecords,
65
)
76
from submodules.model import InformationSourcePayload, enums
@@ -74,7 +73,7 @@ def get_labeling_function_on_10_records(
7473
}
7574
for record_item in sample_records
7675
],
77-
"containerLogs": container_logs,
76+
"containerLogs": [log for log in container_logs if "progress: " not in log],
7877
"codeHasErrors": code_has_errors,
7978
}
8079

controller/user/manager.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,13 @@ def get_mapped_sorted_paginated_users(
127127
get_user["role"] = active_user_by_id["role"]
128128
get_user["organization"] = active_user_by_id["organizationName"]
129129

130+
public_meta = get_user["metadata_public"]
131+
get_user["sso_provider"] = (
132+
public_meta.get("registration_scope", {}).get("provider_id", None)
133+
if public_meta
134+
else None
135+
)
136+
130137
final_users.append(get_user)
131138
save_len_final_users += 1
132139

fast_api/models.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -419,3 +419,9 @@ class MappedSortedPaginatedUsers(BaseModel):
419419

420420
class DeleteUserBody(BaseModel):
421421
user_id: StrictStr
422+
423+
424+
class CancelTaskBody(BaseModel):
425+
project_id: StrictStr
426+
task_id: StrictStr
427+
task_type: StrictStr

fast_api/routes/client_response.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import json
22
from typing import Any, Optional
3-
from fastapi.responses import JSONResponse, Response
3+
from fastapi.responses import JSONResponse, PlainTextResponse, Response
44
from fastapi import status
55
from sqlalchemy.engine.row import Row
66
from submodules.model.models import Base
@@ -50,6 +50,12 @@ def wrap_content_for_frontend(content: Any):
5050
)
5151

5252

53+
GENERIC_FAILURE_RESPONSE = PlainTextResponse(
54+
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
55+
content="An error occurred",
56+
)
57+
58+
5359
def get_silent_success() -> JSONResponse:
5460
return SILENT_SUCCESS_RESPONSE
5561

fast_api/routes/misc.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
from fastapi import APIRouter, Body, Request
33
from exceptions.exceptions import ProjectAccessError
44
from fast_api.models import (
5+
CancelTaskBody,
56
ModelProviderDeleteModelBody,
67
ModelProviderDownloadModelBody,
78
)
@@ -108,9 +109,15 @@ def get_all_tasks(request: Request, only_running: bool):
108109

109110

110111
@router.post("/cancel-task")
111-
def cancel_task(request: Request, project_id: str, task_id: str, task_type: str):
112+
def cancel_task(
113+
request: Request,
114+
body: CancelTaskBody = Body(...),
115+
):
112116

113117
auth.check_admin_access(request.state.info)
118+
task_type = body.task_type
119+
project_id = body.project_id
120+
task_id = body.task_id
114121

115122
if task_type == enums.TaskType.ATTRIBUTE_CALCULATION.value:
116123
controller_manager.cancel_attribute_calculation(project_id, task_id)

fast_api/routes/organization.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,9 @@ def get_user_info_extended(request: Request):
7676
data = {
7777
"userInfo": {
7878
"id": str(user.id),
79-
"organizationId": str(user.organization_id),
79+
"organizationId": (
80+
str(user.organization_id) if user.organization_id else None
81+
),
8082
"firstName": name.get("first"),
8183
"lastName": name.get("last"),
8284
"mail": mail,
@@ -216,11 +218,13 @@ def update_config(request: Request, body: UpdateConfigBody = Body(...)):
216218
print(
217219
"config should only be changed for open source/local version to prevent limit issues"
218220
)
221+
return
219222
misc.update_config(body.dict_str)
220223
misc.refresh_config()
221224
orgs = organization.get_all()
222225
if not orgs or len(orgs) != 1:
223226
print("local version should only have one organization")
227+
return
224228

225229
for org in orgs:
226230
# send to all so all are notified about the change
@@ -275,6 +279,7 @@ def get_all_organizations(request: Request):
275279
}
276280
}
277281
for user in org.users
282+
if resolve_user_mail_by_id(user.id) is not None
278283
]
279284
},
280285
"maxRows": org.max_rows,

fast_api/routes/project.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -305,11 +305,18 @@ def labeling_tasks_by_project_id(project_id: str) -> str:
305305
"/{project_id}/labeling-tasks-by-project-id-with-embeddings",
306306
dependencies=[Depends(auth_manager.check_project_access_dep)],
307307
)
308-
def labeling_tasks_by_project_id_with_embeddings(project_id: str) -> str:
308+
def labeling_tasks_by_project_id_with_embeddings(
309+
project_id: str, only_on_attribute: bool = False
310+
) -> str:
309311
embeddings = get_all_embeddings_by_project_id(project_id)
310312

311313
embeddings_edges = []
312314
for embedding in embeddings:
315+
if (
316+
only_on_attribute
317+
and embedding.type != enums.EmbeddingType.ON_ATTRIBUTE.value
318+
):
319+
continue
313320
attribute = attr_manager.get_attribute(project_id, embedding.attribute_id)
314321
embeddings_edges.append(
315322
{

0 commit comments

Comments
 (0)