Skip to content

Commit f7c00b0

Browse files
committed
fixes repeated matches
1 parent c34781c commit f7c00b0

File tree

3 files changed

+110
-11
lines changed

3 files changed

+110
-11
lines changed

packages/postgres-database/src/simcore_postgres_database/utils_tags.py

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

88
from .utils_repos import pass_or_acquire_connection, transaction_context
99
from .utils_tags_sql import (
10-
count_users_with_access_rights_stmt,
10+
count_users_with_given_access_rights_stmt,
1111
create_tag_stmt,
1212
delete_tag_stmt,
1313
get_tag_stmt,
@@ -67,7 +67,7 @@ async def access_count(
6767
Returns >0 if it does and represents the number of groups granting this access to the user
6868
"""
6969
async with pass_or_acquire_connection(self.engine, connection) as conn:
70-
count_stmt = count_users_with_access_rights_stmt(
70+
count_stmt = count_users_with_given_access_rights_stmt(
7171
user_id=user_id, tag_id=tag_id, read=read, write=write, delete=delete
7272
)
7373
permissions_count: int | None = await conn.scalar(count_stmt)
@@ -89,6 +89,7 @@ async def create(
8989
write: bool = True,
9090
delete: bool = True,
9191
) -> TagDict:
92+
"""Creates tag and defaults to full access rights to `user_id`"""
9293
values = {
9394
"name": name,
9495
"color": color,
@@ -220,3 +221,38 @@ async def delete(
220221
if not deleted:
221222
msg = f"Could not delete {tag_id=}. Not found or insuficient access."
222223
raise TagOperationNotAllowedError(msg)
224+
225+
#
226+
# ACCESS RIGHTS
227+
#
228+
229+
async def create_access_rights(
230+
self,
231+
connection: AsyncConnection | None = None,
232+
*,
233+
user_id: int,
234+
tag_id: int,
235+
group_id: int,
236+
read: bool,
237+
write: bool,
238+
delete: bool,
239+
):
240+
...
241+
242+
async def update_access_rights(
243+
self,
244+
connection: AsyncConnection | None = None,
245+
*,
246+
user_id: int,
247+
tag_id: int,
248+
group_id: int,
249+
read: bool,
250+
write: bool,
251+
delete: bool,
252+
):
253+
...
254+
255+
async def delete_access_rights(
256+
self, connection: AsyncConnection | None = None, *, user_id: int, tag_id: int
257+
):
258+
...

packages/postgres-database/src/simcore_postgres_database/utils_tags_sql.py

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,6 @@
2323
]
2424

2525

26-
_COLUMNS = _TAG_COLUMNS + _ACCESS_RIGHTS_COLUMNS
27-
28-
2926
def _join_user_groups_tag(*, access_condition, tag_id: int, user_id: int):
3027
return user_to_groups.join(
3128
tags_access_rights,
@@ -57,24 +54,31 @@ def get_tag_stmt(
5754
user_id: int,
5855
tag_id: int,
5956
):
60-
return sa.select(*_COLUMNS).select_from(
57+
return sa.select(*_TAG_COLUMNS, *_ACCESS_RIGHTS_COLUMNS).select_from(
6158
_join_user_to_given_tag(
6259
access_condition=tags_access_rights.c.read.is_(True),
63-
tag_id=tag_id,
60+
tag_id=tag_id, # makes it unique result or None
6461
user_id=user_id,
6562
)
6663
)
6764

6865

6966
def list_tags_stmt(*, user_id: int):
7067
return (
71-
sa.select(*_COLUMNS)
68+
sa.select(
69+
*_TAG_COLUMNS,
70+
# MOST permisive aggregation of access-rights
71+
sa.func.bool_or(tags_access_rights.c.read).label("read"),
72+
sa.func.bool_or(tags_access_rights.c.write).label("write"),
73+
sa.func.bool_or(tags_access_rights.c.delete).label("delete")
74+
)
7275
.select_from(
7376
_join_user_to_tags(
7477
access_condition=tags_access_rights.c.read.is_(True),
7578
user_id=user_id,
7679
)
7780
)
81+
.group_by(tags.c.id) # makes it tag.id uniqueness
7882
.order_by(tags.c.id)
7983
)
8084

@@ -83,7 +87,7 @@ def create_tag_stmt(**values):
8387
return tags.insert().values(**values).returning(*_TAG_COLUMNS)
8488

8589

86-
def count_users_with_access_rights_stmt(
90+
def count_users_with_given_access_rights_stmt(
8791
*,
8892
user_id: int,
8993
tag_id: int,
@@ -92,7 +96,7 @@ def count_users_with_access_rights_stmt(
9296
delete: bool | None
9397
):
9498
"""
95-
How many users are given these access permissions
99+
How many users are given EXACTLY these access permissions
96100
"""
97101
access = []
98102
if read is not None:
@@ -146,7 +150,7 @@ def update_tag_stmt(*, user_id: int, tag_id: int, **updates):
146150
& (user_to_groups.c.uid == user_id)
147151
)
148152
.values(**updates)
149-
.returning(*_COLUMNS)
153+
.returning(*_TAG_COLUMNS, *_ACCESS_RIGHTS_COLUMNS)
150154
)
151155

152156

@@ -166,6 +170,11 @@ def delete_tag_stmt(*, user_id: int, tag_id: int):
166170
)
167171

168172

173+
#
174+
# PROJECT TAGS
175+
#
176+
177+
169178
def get_tags_for_project_stmt(*, project_index: int):
170179
return sa.select(projects_tags.c.tag_id).where(
171180
projects_tags.c.project_id == project_index
@@ -183,6 +192,11 @@ def add_tag_to_project_stmt(*, project_index: int, tag_id: int):
183192
)
184193

185194

195+
#
196+
# SERVICE TAGS
197+
#
198+
199+
186200
def get_tags_for_services_stmt(*, key: str, version: str):
187201
return sa.select(services_tags.c.tag_id).where(
188202
(services_tags.c.service_key == key)

packages/postgres-database/tests/test_utils_tags.py

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
get_tag_stmt,
2828
get_tags_for_project_stmt,
2929
get_tags_for_services_stmt,
30+
list_tags_stmt,
3031
set_tag_access_rights_stmt,
3132
update_tag_stmt,
3233
)
@@ -436,6 +437,49 @@ async def test_tags_repo_list_and_get(
436437
)
437438

438439

440+
async def test_tags_repo_uniquely_list_shared_tags(
441+
asyncpg_engine: AsyncEngine,
442+
connection: SAConnection,
443+
user: RowProxy,
444+
group: RowProxy,
445+
):
446+
conn = connection
447+
tags_repo = TagsRepo(asyncpg_engine)
448+
449+
# (setup): create a tag and share with group
450+
expected_tag_id = await create_tag(
451+
conn,
452+
name="T1",
453+
description=f"tag for {user.id}",
454+
color="blue",
455+
group_id=user.primary_gid,
456+
read=True,
457+
write=False, # <-- cannot write
458+
delete=True,
459+
)
460+
await create_tag_access(
461+
conn,
462+
tag_id=expected_tag_id,
463+
group_id=group.gid,
464+
read=True,
465+
write=True, # < -- group can write
466+
delete=False,
467+
)
468+
469+
# (check) can read
470+
got = await tags_repo.get(user_id=user.id, tag_id=expected_tag_id)
471+
assert got
472+
assert got["write"] is False
473+
474+
user_tags = await tags_repo.list_all(user_id=user.id)
475+
assert len(user_tags) == 1
476+
# checks that the agregattion is the MOST permisive
477+
assert user_tags[0]["id"] == expected_tag_id
478+
assert user_tags[0]["read"] is True
479+
assert user_tags[0]["write"] is True
480+
assert user_tags[0]["delete"] is True
481+
482+
439483
async def test_tags_repo_update(
440484
asyncpg_engine: AsyncEngine,
441485
connection: SAConnection,
@@ -619,6 +663,11 @@ def _check(func_smt, **kwargs):
619663
service_key = "simcore/services/comp/isolve"
620664
service_version = "2.0.85"
621665

666+
_check(
667+
list_tags_stmt,
668+
user_id=user_id,
669+
)
670+
622671
_check(
623672
get_tag_stmt,
624673
user_id=user_id,

0 commit comments

Comments
 (0)