3939from models_library .projects_nodes import Node , NodeState , PartialNode
4040from models_library .projects_nodes_io import NodeID , NodeIDStr , PortLink
4141from models_library .projects_state import (
42- ProjectLocked ,
4342 ProjectRunningState ,
43+ ProjectShareState ,
4444 ProjectState ,
4545 ProjectStatus ,
4646 RunningState ,
8484 is_project_locked ,
8585 with_project_locked ,
8686)
87- from servicelib .utils import fire_and_forget_task , logged_gather
87+ from servicelib .utils import fire_and_forget_task , limited_gather , logged_gather
8888from simcore_postgres_database .models .users import UserRole
8989from simcore_postgres_database .utils_projects_nodes import (
9090 ProjectNodeCreate ,
@@ -1500,31 +1500,44 @@ async def try_close_project_for_user(
15001500 )
15011501
15021502
1503- async def _get_project_lock_state (
1503+ async def _get_project_share_state (
15041504 user_id : int ,
15051505 project_uuid : str ,
15061506 app : web .Application ,
1507- ) -> ProjectLocked :
1507+ ) -> ProjectShareState :
15081508 """returns the lock state of a project
15091509 1. If a project is locked for any reason, first return the project as locked and STATUS defined by lock
1510- 2. If a client_session_id is passed, then first check to see if the project is currently opened by this very user/tab combination, if yes returns the project as Locked and OPENED.
15111510 3. If any other user than user_id is using the project (even disconnected before the TTL is finished) then the project is Locked and OPENED.
15121511 4. If the same user is using the project with a valid socket id (meaning a tab is currently active) then the project is Locked and OPENED.
15131512 5. If the same user is using the project with NO socket id (meaning there is no current tab active) then the project is Unlocked and OPENED. which means the user can open it again.
15141513 """
1515- log .debug (
1516- "getting project [%s] lock state for user [%s]..." ,
1517- f"{ project_uuid = } " ,
1518- f"{ user_id = } " ,
1519- )
15201514 prj_locked_state = await get_project_locked_state (
15211515 get_redis_lock_manager_client_sdk (app ), project_uuid
15221516 )
15231517 if prj_locked_state :
15241518 log .debug (
1525- "project [%s] is locked: %s" , f"{ project_uuid = } " , f"{ prj_locked_state = } "
1519+ "project [%s] is currently locked: %s" ,
1520+ f"{ project_uuid = } " ,
1521+ f"{ prj_locked_state = } " ,
1522+ )
1523+ return ProjectShareState (
1524+ status = prj_locked_state .status ,
1525+ locked = prj_locked_state .status
1526+ in [
1527+ ProjectStatus .CLONING ,
1528+ ProjectStatus .EXPORTING ,
1529+ ProjectStatus .MAINTAINING ,
1530+ ],
1531+ current_user_groupids = (
1532+ [
1533+ await users_service .get_user_primary_group_id (
1534+ app , prj_locked_state .owner .user_id
1535+ )
1536+ ]
1537+ if prj_locked_state .owner
1538+ else []
1539+ ),
15261540 )
1527- return prj_locked_state
15281541
15291542 # let's now check if anyone has the project in use somehow
15301543 with managed_resource (user_id , None , app ) as rt :
@@ -1533,48 +1546,29 @@ async def _get_project_lock_state(
15331546 )
15341547 set_user_ids = {user_session .user_id for user_session in user_sessions_with_project }
15351548
1536- assert ( # nosec
1537- len (set_user_ids ) <= 1
1538- ) # nosec # NOTE: A project can only be opened by one user in one tab at the moment
1539-
15401549 if not set_user_ids :
15411550 # no one has the project, so it is unlocked and closed.
15421551 log .debug ("project [%s] is not in use" , f"{ project_uuid = } " )
1543- return ProjectLocked (value = False , status = ProjectStatus .CLOSED )
1552+ return ProjectShareState (
1553+ status = ProjectStatus .CLOSED , locked = False , current_user_groupids = []
1554+ )
15441555
15451556 log .debug (
15461557 "project [%s] might be used by the following users: [%s]" ,
15471558 f"{ project_uuid = } " ,
15481559 f"{ set_user_ids = } " ,
15491560 )
1550- usernames = [
1551- await users_service .get_user_fullname (app , user_id = uid ) for uid in set_user_ids
1552- ]
1553- # let's check if the project is opened by the same user, maybe already opened or closed in a orphaned session
1554- if set_user_ids .issubset ({user_id }) and not await _user_has_another_active_session (
1555- user_sessions_with_project , app
1556- ):
1557- # in this case the project is re-openable by the same user until it gets closed
1558- log .debug (
1559- "project [%s] is in use by the same user [%s] that is currently disconnected, so it is unlocked for this specific user and opened" ,
1560- f"{ project_uuid = } " ,
1561- f"{ set_user_ids = } " ,
1562- )
1563- return ProjectLocked (
1564- value = False ,
1565- owner = Owner (user_id = next (iter (set_user_ids )), ** usernames [0 ]),
1566- status = ProjectStatus .OPENED ,
1567- )
1568- # the project is opened in another tab or browser, or by another user, both case resolves to the project being locked, and opened
1569- log .debug (
1570- "project [%s] is in use by another user [%s], so it is locked" ,
1571- f"{ project_uuid = } " ,
1572- f"{ set_user_ids = } " ,
1573- )
1574- return ProjectLocked (
1575- value = True ,
1576- owner = Owner (user_id = next (iter (set_user_ids )), ** usernames [0 ]),
1561+
1562+ return ProjectShareState (
15771563 status = ProjectStatus .OPENED ,
1564+ locked = False ,
1565+ current_user_groupids = await limited_gather (
1566+ * [
1567+ users_service .get_user_primary_group_id (app , user_id = uid )
1568+ for uid in set_user_ids
1569+ ],
1570+ limit = 10 ,
1571+ ),
15781572 )
15791573
15801574
@@ -1584,7 +1578,7 @@ async def get_project_states_for_user(
15841578 # for templates: the project is never locked and never opened. also the running state is always unknown
15851579 running_state = RunningState .UNKNOWN
15861580 lock_state , computation_task = await logged_gather (
1587- _get_project_lock_state (user_id , project_uuid , app ),
1581+ _get_project_share_state (user_id , project_uuid , app ),
15881582 director_v2_service .get_computation_task (app , user_id , UUID (project_uuid )),
15891583 )
15901584 if computation_task :
@@ -1609,7 +1603,7 @@ async def add_project_states_for_user(
16091603 f"{ project ['uuid' ]= } " ,
16101604 )
16111605 # for templates: the project is never locked and never opened. also the running state is always unknown
1612- lock_state = await _get_project_lock_state (user_id , project ["uuid" ], app )
1606+ lock_state = await _get_project_share_state (user_id , project ["uuid" ], app )
16131607 running_state = RunningState .UNKNOWN
16141608
16151609 if not is_template and (
0 commit comments