Skip to content

Commit

Permalink
updated user preferences and tests
Browse files Browse the repository at this point in the history
  • Loading branch information
aurthurm committed Oct 27, 2024
1 parent c09321a commit 0fe5f6d
Show file tree
Hide file tree
Showing 20 changed files with 200 additions and 119 deletions.
3 changes: 3 additions & 0 deletions al_revision.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#!/bin/sh

alembic revision --autogenerate -m "$1"
2 changes: 1 addition & 1 deletion felicity/alembic.ini → alembic.ini
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

[alembic]
# path to migration scripts
script_location = migrations
script_location = felicity/migrations

# template used to generate migration files
# file_template = %%(rev)s_%%(slug)s
Expand Down
3 changes: 0 additions & 3 deletions felicity/al_revision.sh

This file was deleted.

70 changes: 35 additions & 35 deletions felicity/api/gql/user/mutations.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,16 +88,16 @@ def simple_task(message: str):
class UserMutations:
@strawberry.mutation(permission_classes=[IsAuthenticated])
async def create_user(
self,
info,
first_name: str,
last_name: str,
email: str,
user_name: str,
password: str,
passwordc: str,
group_uid: str | None = None,
open_reg: bool | None = False,
self,
info,
first_name: str,
last_name: str,
email: str,
user_name: str,
password: str,
passwordc: str,
group_uid: str | None = None,
open_reg: bool | None = False,
) -> UserResponse:
user_service = UserService()
group_service = GroupService()
Expand All @@ -124,6 +124,7 @@ async def create_user(
"user_name": user_name,
"password": password,
"is_superuser": False,
"login_retry": 0,
"created_by_uid": felicity_user.uid,
"updated_by_uid": felicity_user.uid,
}
Expand All @@ -135,29 +136,28 @@ async def create_user(
user = await user_service.save(user)

# initial user-preferences
pref_in = user_schemas.UserPreferenceCreate(expanded_menu=False, theme="LIGHT")
preference = await user_preference_service.create(pref_in)
user = await user_service.link_preference(
user.uid, preference_uid=preference.uid
)
pref = user_preference_service.get(user_uid=user.uid)
if not pref:
pref_in = user_schemas.UserPreferenceCreate(user_uid=user.uid, expanded_menu=False, theme="LIGHT")
await user_preference_service.create(pref_in)

if user_in.email:
logger.info("Handle email sending in a standalone service")
return StrawberryMapper[UserType]().map(**user.marshal_simple())

@strawberry.mutation(permission_classes=[IsAuthenticated])
async def update_user(
self,
info,
user_uid: str,
first_name: str | None,
last_name: str | None,
mobile_phone: str | None,
email: str | None,
group_uid: str | None,
is_active: bool | None,
password: str | None = None,
passwordc: str | None = None,
self,
info,
user_uid: str,
first_name: str | None,
last_name: str | None,
mobile_phone: str | None,
email: str | None,
group_uid: str | None,
is_active: bool | None,
password: str | None = None,
passwordc: str | None = None,
) -> UserResponse:
user_service = UserService()
group_service = GroupService()
Expand Down Expand Up @@ -202,7 +202,7 @@ async def update_user(

@strawberry.mutation
async def authenticate_user(
self, info, username: str, password: str
self, info, username: str, password: str
) -> AuthenticatedDataResponse:
user_service = UserService()

Expand Down Expand Up @@ -248,7 +248,7 @@ async def request_password_reset(self, info, email: str) -> MessageResponse:

@strawberry.mutation()
async def validate_password_reset_token(
self, info, token: str
self, info, token: str
) -> PasswordResetValidityResponse:
user_service = UserService()
email = verify_password_reset_token(token)
Expand All @@ -265,11 +265,11 @@ async def validate_password_reset_token(

@strawberry.mutation()
async def reset_password(
self,
info,
user_uid: str,
password: str,
passwordc: str,
self,
info,
user_uid: str,
password: str,
passwordc: str,
) -> MessageResponse:
user_service = UserService()

Expand Down Expand Up @@ -311,7 +311,7 @@ async def create_group(self, info, payload: GroupInputType) -> GroupResponse:

@strawberry.mutation(permission_classes=[IsAuthenticated])
async def update_group(
self, info, uid: str, payload: GroupInputType
self, info, uid: str, payload: GroupInputType
) -> GroupResponse:
group_service = GroupService()

Expand All @@ -336,7 +336,7 @@ async def update_group(

@strawberry.mutation(permission_classes=[IsAuthenticated])
async def update_group_permissions(
self, info, group_uid: str, permission_uid: str
self, info, group_uid: str, permission_uid: str
) -> UpdatedGroupPermsResponse:
group_service = GroupService()
permission_service = PermissionService()
Expand Down
34 changes: 17 additions & 17 deletions felicity/apps/abstract/repository.py
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,7 @@ async def table_insert(self, table: Any, mappings: list[dict]) -> None:
await session.flush()

async def query_table(
self, table: Table, columns: list[str] | None = None, **kwargs
self, table: Table, columns: list[str] | None = None, **kwargs
):
"""
Query a specific table with optional column selection and filters.
Expand Down Expand Up @@ -444,11 +444,11 @@ async def search(self, **kwargs) -> list[M]:
return list(combined)

async def filter(
self,
filters: dict | list[dict],
sort_attrs: list[str] | None = None,
limit: int | None = None,
either: bool = False,
self,
filters: dict | list[dict],
sort_attrs: list[str] | None = None,
limit: int | None = None,
either: bool = False,
) -> list[M]:
"""
Filter model instances based on the given conditions.
Expand All @@ -471,13 +471,13 @@ async def filter(
return found

async def paginate(
self,
page_size: int | None,
after_cursor: str | None,
before_cursor: str | None,
filters: dict | list[dict] | None,
sort_by: list[str] | None,
**kwargs,
self,
page_size: int | None,
after_cursor: str | None,
before_cursor: str | None,
filters: dict | list[dict] | None,
sort_by: list[str] | None,
**kwargs,
) -> PageCursor:
"""
Paginate model instances based on the given conditions.
Expand Down Expand Up @@ -575,10 +575,10 @@ def build_node(self, item: Any) -> EdgeNode:

@staticmethod
def build_page_info(
start_cursor: str | None = None,
end_cursor: str | None = None,
has_next_page: bool = False,
has_previous_page: bool = False,
start_cursor: str | None = None,
end_cursor: str | None = None,
has_next_page: bool = False,
has_previous_page: bool = False,
) -> PageInfo:
"""
Build a PageInfo object with the given parameters.
Expand Down
1 change: 0 additions & 1 deletion felicity/apps/client/schemas.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,6 @@ class ClientContactBaseInDB(ClientContactBase):
class ClientContactCreate(ClientContactBase):
client_uid: str
email: str
user_name: str


# Properties to receive via API on update
Expand Down
30 changes: 15 additions & 15 deletions felicity/apps/common/utils/serializer.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@


def _marshall_object(
obj,
path: list[str] | None = None,
memoize: dict | None = None,
exclude: list[str] | None = None,
depth: int = 2,
obj,
path: list[str] | None = None,
memoize: dict | None = None,
exclude: list[str] | None = None,
depth: int = 2,
) -> dict | str:
"""
Custom marshaller function to convert objects to dictionaries or strings with proper handling for
Expand Down Expand Up @@ -62,18 +62,18 @@ def _marshall_object(


def marshaller(
obj,
path: list[str] | None = None,
memoize: dict | None = None,
exclude: list[str] | None = None,
depth: int = 2,
obj,
path: list[str] | None = None,
memoize: dict | None = None,
exclude: list[str] | None = None,
depth: int = 2,
) -> dict:
if isinstance(obj, str):
raise TypeError("Unsupported object of type 'str'")
# if isinstance(obj, str):
# return obj

output = _marshall_object(obj, path, memoize, exclude, depth)

if isinstance(output, str):
raise TypeError("Unexpected return type 'str' while marshalling")
#
# if isinstance(output, str):
# raise TypeError("Unexpected return type 'str' while marshalling")

return output
14 changes: 7 additions & 7 deletions felicity/apps/reflex/services.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
from operator import gt, lt, eq, ge, le, ne
from typing import List, Optional

from cachetools import TTLCache, cached
from cachetools import TTLCache

from felicity.apps.abstract.service import BaseService
from felicity.apps.analysis.entities.analysis import Analysis, Sample
Expand Down Expand Up @@ -173,9 +173,9 @@ async def set_reflex_actions(cls, analysis_results: List[AnalysisResult]) -> Non
logger.info(f"Reflex actions set for {result}")

@staticmethod
@cached(cache=reflex_action_cache)
# @cached(cache=reflex_action_cache)
async def get_reflex_action(
analysis_uid: str, level: int
analysis_uid: str, level: int
) -> Optional[ReflexAction]:
"""
Get reflex action with caching to improve performance.
Expand Down Expand Up @@ -278,7 +278,7 @@ async def decide(self, brain: ReflexBrain) -> None:
await self.apply_actions(brain.actions, results_pool)

async def evaluate(
self, conditions: list[ReflexBrainCondition], results_pool: List[AnalysisResult]
self, conditions: list[ReflexBrainCondition], results_pool: List[AnalysisResult]
) -> bool:
"""
Evaluate conditions for decision-making.
Expand All @@ -298,7 +298,7 @@ async def evaluate(

@staticmethod
async def _eval_condition(
condition: ReflexBrainCondition, results_pool: List[AnalysisResult]
condition: ReflexBrainCondition, results_pool: List[AnalysisResult]
) -> bool:
"""
Evaluate a single condition against the results pool.
Expand Down Expand Up @@ -401,7 +401,7 @@ async def _eval_condition(
return all(evaluations)

async def apply_actions(
self, actions: list[ReflexBrainAction], results_pool: List[AnalysisResult]
self, actions: list[ReflexBrainAction], results_pool: List[AnalysisResult]
) -> None:
"""
Execute actions for a matching reflex brain.
Expand Down Expand Up @@ -436,7 +436,7 @@ async def apply_actions(
await self.analysis_result_service.hide_report(r.uid)

async def get_results_pool(
self, conditions: list[ReflexBrainCondition]
self, conditions: list[ReflexBrainCondition]
) -> List[AnalysisResult]:
"""
Get a pool of relevant analysis results for the given conditions.
Expand Down
25 changes: 18 additions & 7 deletions felicity/apps/user/entities.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,13 @@
from sqlalchemy.orm import Mapped, relationship

from felicity.apps.abstract.entity import BaseEntity

from .abstract import AbstractBaseUser

logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)


# TODO: Refactor User to LaboratoryContact, UserAuth to ContactAuth


"""
Many to Many Link between Group and User
"""
Expand All @@ -38,13 +35,19 @@
class User(AbstractBaseUser):
__tablename__ = "user"

# One-to-one relationship with UserPreference
preference: Mapped["UserPreference"] = relationship(
"UserPreference",
back_populates="user",
lazy="selectin",
uselist=False,
cascade="all, delete-orphan",
foreign_keys="[UserPreference.user_uid]"
)

groups = relationship(
"Group", secondary=user_groups, back_populates="members", lazy="selectin"
)
preference_uid = Column(String, ForeignKey("user_preference.uid"))
preference = relationship(
"UserPreference", foreign_keys=[preference_uid], lazy="selectin"
)


class Permission(BaseEntity):
Expand Down Expand Up @@ -85,6 +88,14 @@ class UserPreference(BaseEntity):

__tablename__ = "user_preference"

user_uid = Column(String, ForeignKey("user.uid", ondelete="CASCADE"), unique=True)
user: Mapped["User"] = relationship(
"User",
back_populates="preference",
foreign_keys=[user_uid],
single_parent=True
)

expanded_menu = Column(Boolean(), default=False)
departments = relationship(
"Department", secondary=department_preference, lazy="selectin"
Expand Down
2 changes: 2 additions & 0 deletions felicity/apps/user/schemas.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

from felicity.apps.common.schemas import BaseAuditModel, BaseModel


#
# Permission Schema
#
Expand Down Expand Up @@ -87,6 +88,7 @@ class GroupInDB(GroupInDBBase):
# User Preferences
#
class UserPreferenceBase(BaseAuditModel):
user_uid: str
expanded_menu: bool | None = False
theme: str | None = "light"

Expand Down
Loading

0 comments on commit 0fe5f6d

Please sign in to comment.