Skip to content

Commit

Permalink
#11 Add filters on list endpoints
Browse files Browse the repository at this point in the history
  • Loading branch information
Valbou committed Oct 13, 2023
1 parent a0e0e15 commit ab5136d
Show file tree
Hide file tree
Showing 15 changed files with 96 additions and 20 deletions.
2 changes: 1 addition & 1 deletion ROADMAP.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ As vTaskr is an non profit project without fulltime dev, no release date can be
- [x] User can manage rights (create, read, update, delete and achieve)
- [x] User can't access to tasks not owned by at least one of his groups
- [x] User can delete his account efficiently (cannot delete a user if user has admin role on 2 groups or more !)
- [ ] Add filters on list endpoints (filter groups according to role or filter rights according to a group etc...)
- [x] Add filters on list endpoints (filter groups according to role or filter rights according to a group etc...)

## Go to v1.2.0
- [ ] Add Keycloak integration
Expand Down
4 changes: 3 additions & 1 deletion vtaskr/tasks/hmi/flask/api/v1/tags.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,9 +69,11 @@
def tags():
"""URL to current tenant tags - Token required"""
if request.method == "GET":
qsf = QueryStringFilter(query_string=request.query_string.decode(), dto=TaskDTO)

with current_app.sql.get_session() as session:
tag_service = TagService(session)
tags = tag_service.get_tags(g.user.id)
tags = tag_service.get_tags(g.user.id, qsf.get_filters())
if tags:
tags_dto = list_models_to_list_dto(TagMapperDTO, tags)
return ResponseAPI.get_response(list_dto_to_dict(tags_dto), 200)
Expand Down
7 changes: 5 additions & 2 deletions vtaskr/tasks/services/tags_service.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from sqlalchemy.orm import Session

from vtaskr.libs.flask.querystring import Filter
from vtaskr.libs.iam.config import PermissionControl
from vtaskr.libs.iam.constants import Permissions, Resources
from vtaskr.tasks.models import Tag
Expand All @@ -12,14 +13,16 @@ def __init__(self, session: Session) -> None:
self.tag_db = TagDB()
self.control = PermissionControl(self.session)

def get_tags(self, user_id: str) -> list[dict]:
def get_tags(
self, user_id: str, qs_filters: list[Filter] | None = None
) -> list[dict]:
"""Get a list of authorized tags"""

tenant_ids = self.control.all_tenants_with_access(
permission=Permissions.READ, user_id=user_id, resource=Resources.TAG
)

return self.tag_db.tags(self.session, tenant_ids)
return self.tag_db.tags(self.session, tenant_ids, qs_filters)

def get_tag(self, user_id: str, tag_id: str) -> Tag | None:
"""Get a tag if read permission was given"""
Expand Down
7 changes: 6 additions & 1 deletion vtaskr/users/hmi/flask/api/v1/group.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

from flask import current_app, g, request

from vtaskr.libs.flask.querystring import QueryStringFilter
from vtaskr.libs.flask.utils import ResponseAPI
from vtaskr.libs.hmi import dto_to_dict, list_dto_to_dict, list_models_to_list_dto
from vtaskr.libs.redis import rate_limited
Expand Down Expand Up @@ -68,8 +69,12 @@ def groups():

if request.method == "GET":
with current_app.sql.get_session() as session:
qsf = QueryStringFilter(
query_string=request.query_string.decode(), dto=GroupDTO
)

group_service = GroupService(session)
groups = group_service.get_all_groups(g.user.id)
groups = group_service.get_all_groups(g.user.id, qsf.get_filters())

groups_dto = list_models_to_list_dto(GroupMapperDTO, groups)
return ResponseAPI.get_response(list_dto_to_dict(groups_dto), 200)
Expand Down
7 changes: 6 additions & 1 deletion vtaskr/users/hmi/flask/api/v1/right.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

from flask import current_app, g, request

from vtaskr.libs.flask.querystring import QueryStringFilter
from vtaskr.libs.flask.utils import ResponseAPI
from vtaskr.libs.hmi import dto_to_dict, list_dto_to_dict, list_models_to_list_dto
from vtaskr.libs.redis import rate_limited
Expand Down Expand Up @@ -69,7 +70,11 @@ def rights():
right_service = RightService(session)

if request.method == "GET":
rights = right_service.get_all_rights(g.user.id)
qsf = QueryStringFilter(
query_string=request.query_string.decode(), dto=RightDTO
)

rights = right_service.get_all_rights(g.user.id, qsf.get_filters())
rights_dto = list_models_to_list_dto(RightMapperDTO, rights)
return ResponseAPI.get_response(list_dto_to_dict(rights_dto), 200)

Expand Down
7 changes: 6 additions & 1 deletion vtaskr/users/hmi/flask/api/v1/role.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

from flask import current_app, g, request

from vtaskr.libs.flask.querystring import QueryStringFilter
from vtaskr.libs.flask.utils import ResponseAPI
from vtaskr.libs.hmi import dto_to_dict, list_dto_to_dict, list_models_to_list_dto
from vtaskr.libs.redis import rate_limited
Expand Down Expand Up @@ -68,8 +69,12 @@ def roles():

if request.method == "GET":
with current_app.sql.get_session() as session:
qsf = QueryStringFilter(
query_string=request.query_string.decode(), dto=RoleDTO
)

role_service = RoleService(session)
roles = role_service.get_all_roles(g.user.id)
roles = role_service.get_all_roles(g.user.id, qsf.get_filters())

roles_dto = list_models_to_list_dto(RoleMapperDTO, roles)
return ResponseAPI.get_response(list_dto_to_dict(roles_dto), 200)
Expand Down
7 changes: 6 additions & 1 deletion vtaskr/users/hmi/flask/api/v1/roletype.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

from flask import current_app, g, request

from vtaskr.libs.flask.querystring import QueryStringFilter
from vtaskr.libs.flask.utils import ResponseAPI
from vtaskr.libs.hmi import dto_to_dict, list_dto_to_dict, list_models_to_list_dto
from vtaskr.libs.redis import rate_limited
Expand Down Expand Up @@ -73,7 +74,11 @@ def roletypes():
roletype_service = RoleTypeService(session)

if request.method == "GET":
roletypes = roletype_service.get_all_roletypes(g.user.id)
qsf = QueryStringFilter(
query_string=request.query_string.decode(), dto=RoleTypeDTO
)

roletypes = roletype_service.get_all_roletypes(g.user.id, qsf.get_filters())
roletypes_dto = list_models_to_list_dto(RoleTypeMapperDTO, roletypes)
return ResponseAPI.get_response(list_dto_to_dict(roletypes_dto), 200)

Expand Down
12 changes: 11 additions & 1 deletion vtaskr/users/persistence/sqlalchemy/adapters/groups.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from sqlalchemy.orm import Session

from vtaskr.libs.flask.querystring import Filter
from vtaskr.libs.iam.constants import Permissions, Resources
from vtaskr.libs.sqlalchemy.default_adapter import DefaultDB
from vtaskr.users.models import Group, Right, Role, RoleType
Expand Down Expand Up @@ -36,7 +37,16 @@ def accessibles_by_user_with_permission(

return [r[0] for r in session.execute(self.qs.statement)]

def get_all_user_groups(self, session: Session, user_id: str) -> list[Group] | None:
def get_all_user_groups(
self,
session: Session,
user_id: str,
filters: list[Filter] | None = None,
) -> list[Group] | None:
filters = filters or []
if filters:
self.qs.from_filters(filters)

self.qs.select().join(Group.roles).where(
Role.user_id == user_id,
)
Expand Down
10 changes: 9 additions & 1 deletion vtaskr/users/persistence/sqlalchemy/adapters/rights.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from sqlalchemy.orm import Session

from vtaskr.libs.flask.querystring import Filter
from vtaskr.libs.sqlalchemy.default_adapter import DefaultDB
from vtaskr.users.models import Right
from vtaskr.users.persistence.ports import AbstractRightPort
Expand All @@ -12,8 +13,15 @@ def __init__(self) -> None:
self.qs = RightQueryset()

def get_all_user_rights(
self, session: Session, user_id: str, group_ids: list[str]
self,
session: Session,
group_ids: list[str],
filters: list[Filter] | None = None,
) -> list[Right]:
filters = filters or []
if filters:
self.qs.from_filters(filters)

self.qs.select().both_user_have_and_user_can_use(group_ids=group_ids)

return session.scalars(self.qs.statement).all()
Expand Down
11 changes: 10 additions & 1 deletion vtaskr/users/persistence/sqlalchemy/adapters/role.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from sqlalchemy.orm import Session

from vtaskr.libs.flask.querystring import Filter
from vtaskr.libs.sqlalchemy.default_adapter import DefaultDB
from vtaskr.users.models import Role
from vtaskr.users.persistence.ports import AbstractRolePort
Expand Down Expand Up @@ -28,8 +29,16 @@ def get_a_user_role(
return session.scalars(self.qs.statement).one_or_none()

def get_all_user_roles(
self, session: Session, user_id: str, group_ids: list[str]
self,
session: Session,
user_id: str,
group_ids: list[str],
filters: list[Filter] | None = None,
) -> list[Role]:
filters = filters or []
if filters:
self.qs.from_filters(filters)

self.qs.select().both_is_mine_and_is_under_my_control(
user_id=user_id, group_ids=group_ids
)
Expand Down
10 changes: 9 additions & 1 deletion vtaskr/users/persistence/sqlalchemy/adapters/roletypes.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from sqlalchemy.orm import Session

from vtaskr.libs.flask.querystring import Filter
from vtaskr.libs.sqlalchemy.default_adapter import DefaultDB
from vtaskr.users.models import RoleType
from vtaskr.users.persistence.ports import AbstractRoleTypePort
Expand Down Expand Up @@ -35,8 +36,15 @@ def get_a_user_roletype(
return session.scalars(self.qs.statement).one_or_none()

def get_all_user_roletypes(
self, session: Session, group_ids: list[str]
self,
session: Session,
group_ids: list[str],
filters: list[Filter] | None = None,
) -> list[RoleType]:
filters = filters or []
if filters:
self.qs.from_filters(filters)

self.qs.select().user_can_use(group_ids=group_ids)

return session.scalars(self.qs.statement).all()
11 changes: 9 additions & 2 deletions vtaskr/users/services/group_service.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from sqlalchemy.orm import Session

from vtaskr.libs.flask.querystring import Filter
from vtaskr.libs.iam.constants import Permissions, Resources
from vtaskr.users.models import Group
from vtaskr.users.persistence import GroupDB
Expand Down Expand Up @@ -44,10 +45,16 @@ def create_private_group(self, user_id: str) -> Group:

return self.create_group(user_id=user_id, group_name="Private")

def get_all_groups(self, user_id: str) -> list[Group] | None:
def get_all_groups(
self,
user_id: str,
qs_filters: list[Filter] | None = None,
) -> list[Group] | None:
"""Return all user associated groups"""

return self.group_db.get_all_user_groups(self.session, user_id=user_id)
return self.group_db.get_all_user_groups(
self.session, user_id=user_id, filters=qs_filters
)

def get_group(self, user_id: str, group_id: str) -> Group | None:
"""Retrieve just a group if permission was given"""
Expand Down
7 changes: 5 additions & 2 deletions vtaskr/users/services/right_service.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from sqlalchemy.orm import Session

from vtaskr.libs.flask.querystring import Filter
from vtaskr.libs.iam.constants import Permissions, Resources
from vtaskr.users.models import Right, RoleType
from vtaskr.users.persistence import RightDB
Expand Down Expand Up @@ -106,14 +107,16 @@ def get_right(self, user_id, right_id) -> Right | None:
self.session, user_id, right_id, group_ids=group_ids
)

def get_all_rights(self, user_id: str) -> list[Right]:
def get_all_rights(
self, user_id: str, qs_filters: list[Filter] | None = None
) -> list[Right]:
"""Return a list of all user's available rights"""

group_ids = self.control.all_tenants_with_access(
Permissions.READ, user_id=user_id, resource=Resources.ROLETYPE
)
return self.right_db.get_all_user_rights(
self.session, user_id, group_ids=group_ids
self.session, group_ids=group_ids, filters=qs_filters
)

def update_right(self, user_id: str, right: Right, roletype: RoleType) -> bool:
Expand Down
7 changes: 5 additions & 2 deletions vtaskr/users/services/role_service.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from sqlalchemy.orm import Session

from vtaskr.libs.flask.querystring import Filter
from vtaskr.libs.iam.constants import Permissions, Resources
from vtaskr.users.models import Role
from vtaskr.users.persistence import RoleDB
Expand Down Expand Up @@ -60,14 +61,16 @@ def get_role(self, user_id, role_id) -> Role | None:
self.session, user_id, role_id, group_ids=group_ids
)

def get_all_roles(self, user_id: str) -> list[Role]:
def get_all_roles(
self, user_id: str, qs_filters: list[Filter] | None = None
) -> list[Role]:
"""Return a list of all user's roles"""

group_ids = self.control.all_tenants_with_access(
Permissions.CREATE, user_id=user_id, resource=Resources.ROLE
)
return self.role_db.get_all_user_roles(
self.session, user_id, group_ids=group_ids
self.session, user_id, group_ids=group_ids, filters=qs_filters
)

def update_role(self, user_id: str, role: Role) -> bool:
Expand Down
7 changes: 5 additions & 2 deletions vtaskr/users/services/roletype_service.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from sqlalchemy.orm import Session

from vtaskr.libs.flask.querystring import Filter
from vtaskr.libs.iam.constants import Permissions, Resources
from vtaskr.users.models import RoleType
from vtaskr.users.persistence import RoleTypeDB
Expand Down Expand Up @@ -63,15 +64,17 @@ def get_roletype(self, user_id: str, roletype_id: str) -> RoleType | None:
self.session, roletype_id, group_ids=group_ids
)

def get_all_roletypes(self, user_id: str) -> list[RoleType]:
def get_all_roletypes(
self, user_id: str, qs_filters: list[Filter] | None = None
) -> list[RoleType]:
"""Return a list of all user's available roletypes"""

group_ids = self.control.all_tenants_with_access(
Permissions.READ, user_id=user_id, resource=Resources.ROLETYPE
)

return self.roletype_db.get_all_user_roletypes(
self.session, group_ids=group_ids
self.session, group_ids=group_ids, filters=qs_filters
)

def update_roletype(self, user_id: str, roletype: RoleType) -> bool:
Expand Down

0 comments on commit ab5136d

Please sign in to comment.