diff --git a/autotests/clients/rest/projects/client.py b/autotests/clients/rest/projects/client.py index 84dc6d11..6a7e54db 100644 --- a/autotests/clients/rest/projects/client.py +++ b/autotests/clients/rest/projects/client.py @@ -141,7 +141,7 @@ async def get_positions( specialization_ids: list[uuid.UUID] | Type[Empty] = Empty, skill_ids: list[uuid.UUID] | Type[Empty] = Empty, joined_user_id: uuid.UUID | Type[Empty] = Empty, - project_query_text: str | Type[Empty] = Empty, + query: str | Type[Empty] = Empty, project_startline_ge: datetime | Type[Empty] = Empty, project_startline_le: datetime | Type[Empty] = Empty, project_deadline_ge: datetime | Type[Empty] = Empty, @@ -156,7 +156,7 @@ async def get_positions( "specialization_ids": specialization_ids, "skill_ids": skill_ids, "joined_user_id": joined_user_id, - "project_query_text": project_query_text, + "query": query, "project_startline_ge": project_startline_ge, "project_startline_le": project_startline_le, "project_deadline_ge": project_deadline_ge, diff --git a/autotests/rest/projects/test_positions.py b/autotests/rest/projects/test_positions.py index 028c6c02..c2da7c8e 100644 --- a/autotests/rest/projects/test_positions.py +++ b/autotests/rest/projects/test_positions.py @@ -20,7 +20,7 @@ pytest.lazy_fixture("random_projects_rest_client"), )) @pytest.mark.parametrize( - ("project_id", "specialization_ids", "skill_ids", "joined_user_id", "project_query_text", + ("project_id", "specialization_ids", "skill_ids", "joined_user_id", "query", "project_startline_ge", "project_startline_le", "project_deadline_ge", "project_deadline_le", "project_statuses", "page", "per_page"), ( @@ -48,7 +48,7 @@ async def test_get_positions( specialization_ids: list[uuid.UUID] | Type[Empty], skill_ids: list[uuid.UUID] | Type[Empty], joined_user_id: uuid.UUID | Type[Empty], - project_query_text: str | Type[Empty], + query: str | Type[Empty], project_startline_ge: datetime | Type[Empty], project_startline_le: datetime | Type[Empty], project_deadline_ge: datetime | Type[Empty], @@ -62,7 +62,7 @@ async def test_get_positions( specialization_ids=specialization_ids, skill_ids=skill_ids, joined_user_id=joined_user_id, - project_query_text=project_query_text, + query=query, project_startline_ge=project_startline_ge, project_startline_le=project_startline_le, project_deadline_ge=project_deadline_ge, diff --git a/sapphire/projects/api/rest/positions/handlers.py b/sapphire/projects/api/rest/positions/handlers.py index 81034412..4822fc3e 100644 --- a/sapphire/projects/api/rest/positions/handlers.py +++ b/sapphire/projects/api/rest/positions/handlers.py @@ -30,7 +30,7 @@ async def get_positions( "specialization_ids": filters.specialization_ids, "skill_ids": filters.skill_ids, "joined_user_id": filters.joined_user_id, - "project_query_text": filters.project_query_text, + "query": filters.query, "project_startline_ge": filters.project_startline_ge, "project_startline_le": filters.project_startline_le, "project_deadline_ge": filters.project_deadline_ge, diff --git a/sapphire/projects/api/rest/positions/schemas.py b/sapphire/projects/api/rest/positions/schemas.py index 0c630eea..e4968069 100644 --- a/sapphire/projects/api/rest/positions/schemas.py +++ b/sapphire/projects/api/rest/positions/schemas.py @@ -16,7 +16,7 @@ class PositionListFiltersRequest(BaseModel): specialization_ids: list[uuid.UUID] | Type[Empty] = Field(fastapi.Query(Empty)) skill_ids: list[uuid.UUID] | Type[Empty] = Field(fastapi.Query(Empty)) joined_user_id: uuid.UUID | Type[Empty] = Empty - project_query_text: str | Type[Empty] = Empty + query: str | Type[Empty] = Empty project_startline_ge: AwareDatetime | Type[Empty] = Empty project_startline_le: AwareDatetime | Type[Empty] = Empty project_deadline_ge: AwareDatetime | Type[Empty] = Empty diff --git a/sapphire/projects/api/rest/projects/handlers.py b/sapphire/projects/api/rest/projects/handlers.py index eca04e79..8f5369d3 100644 --- a/sapphire/projects/api/rest/projects/handlers.py +++ b/sapphire/projects/api/rest/projects/handlers.py @@ -56,7 +56,7 @@ async def get_projects( async with database_service.transaction() as session: params = { "session": session, - "query_text": filters.query_text, + "query": filters.query, "owner_id": filters.owner_id, "user_id": filters.user_id, "startline_le": filters.startline_le, diff --git a/sapphire/projects/api/rest/projects/schemas.py b/sapphire/projects/api/rest/projects/schemas.py index 02823396..f5cad328 100644 --- a/sapphire/projects/api/rest/projects/schemas.py +++ b/sapphire/projects/api/rest/projects/schemas.py @@ -48,7 +48,7 @@ class ProjectListResponse(PaginatedResponse): class ProjectListFiltersRequest(BaseModel): - query_text: str | Type[Empty] = Empty + query: str | Type[Empty] = Empty owner_id: uuid.UUID | Type[Empty] = Empty user_id: uuid.UUID | Type[Empty] = Empty startline_ge: AwareDatetime | Type[Empty] = Empty diff --git a/sapphire/projects/database/service.py b/sapphire/projects/database/service.py index d38694ac..e07c0103 100644 --- a/sapphire/projects/database/service.py +++ b/sapphire/projects/database/service.py @@ -16,6 +16,8 @@ Project, ProjectHistory, ProjectStatusEnum, + Skill, + Specialization, Review, User, ) @@ -137,7 +139,7 @@ async def _get_positions_filters( specialization_ids: list[uuid.UUID] | Type[Empty] = Empty, skill_ids: list[uuid.UUID] | Type[Empty] = Empty, joined_user_id: uuid.UUID | Type[Empty] = Empty, - project_query_text: str | Type[Empty] = Empty, + query: str | Type[Empty] = Empty, project_startline_ge: datetime | Type[Empty] = Empty, project_startline_le: datetime | Type[Empty] = Empty, project_deadline_ge: datetime | Type[Empty] = Empty, @@ -167,10 +169,21 @@ async def _get_positions_filters( )) )) - if project_query_text is not Empty: - project_filters.append(or_( - Project.name.icontains(project_query_text), - Project.description.icontains(project_query_text), + if query is not Empty: + filters.append(or_( + Position.project_id.in_(select(Project.id).where(or_( + Project.name.icontains(query), + Project.description.icontains(query), + ))), + Position.specialization_id.in_(select(Specialization.id).where(or_( + Specialization.name.icontains(query), + Specialization.name_en.icontains(query), + ))), + Position.id.in_(select(PositionSkill.position_id).where( + PositionSkill.skill_id.in_(select(Skill.id).where( + Skill.name.icontains(query), + )), + )), )) if project_startline_ge is not Empty: project_filters.append(Project.startline >= project_startline_ge) @@ -210,7 +223,7 @@ async def get_positions_count( specialization_ids: list[uuid.UUID] | Type[Empty] = Empty, skill_ids: list[uuid.UUID] | Type[Empty] = Empty, joined_user_id: uuid.UUID | Type[Empty] = Empty, - project_query_text: str | Type[Empty] = Empty, + query: str | Type[Empty] = Empty, project_startline_ge: datetime | Type[Empty] = Empty, project_startline_le: datetime | Type[Empty] = Empty, project_deadline_ge: datetime | Type[Empty] = Empty, @@ -222,7 +235,7 @@ async def get_positions_count( specialization_ids=specialization_ids, skill_ids=skill_ids, joined_user_id=joined_user_id, - project_query_text=project_query_text, + query=query, project_startline_ge=project_startline_ge, project_startline_le=project_startline_le, project_deadline_ge=project_deadline_ge, @@ -241,7 +254,7 @@ async def get_positions( specialization_ids: list[uuid.UUID] | Type[Empty] = Empty, skill_ids: list[uuid.UUID] | Type[Empty] = Empty, joined_user_id: uuid.UUID | Type[Empty] = Empty, - project_query_text: str | Type[Empty] = Empty, + query: str | Type[Empty] = Empty, project_startline_ge: datetime | Type[Empty] = Empty, project_startline_le: datetime | Type[Empty] = Empty, project_deadline_ge: datetime | Type[Empty] = Empty, @@ -255,7 +268,7 @@ async def get_positions( specialization_ids=specialization_ids, skill_ids=skill_ids, joined_user_id=joined_user_id, - project_query_text=project_query_text, + query=query, project_startline_ge=project_startline_ge, project_startline_le=project_startline_le, project_deadline_ge=project_deadline_ge, @@ -486,7 +499,7 @@ async def update_participant_status( async def _get_projects_filters( self, - query_text: str | Type[Empty] = Empty, + query: str | Type[Empty] = Empty, owner_id: uuid.UUID | Type[Empty] = Empty, user_id: uuid.UUID | Type[Empty] = Empty, startline_le: datetime | Type[Empty] = Empty, @@ -502,11 +515,11 @@ async def _get_projects_filters( position_filters = [] participant_filters = [] - if query_text is not Empty: + if query is not Empty: filters.append( or_( - Project.name.icontains(query_text), - Project.description.icontains(query_text), + Project.name.icontains(query), + Project.description.icontains(query), ) ) if owner_id is not Empty: @@ -568,7 +581,7 @@ async def _get_projects_filters( async def get_projects_count( self, session: AsyncSession, - query_text: str | Type[Empty] = Empty, + query: str | Type[Empty] = Empty, owner_id: uuid.UUID | Type[Empty] = Empty, user_id: uuid.UUID | Type[Empty] = Empty, startline_le: datetime | Type[Empty] = Empty, @@ -580,9 +593,9 @@ async def get_projects_count( position_specialization_ids: list[uuid.UUID] | Type[Empty] = Empty, participant_user_ids: list[uuid.UUID] | Type[Empty] = Empty, ) -> int: - query = select(func.count(Project.id)) # pylint: disable=not-callable + statement = select(func.count(Project.id)) # pylint: disable=not-callable filters = await self._get_projects_filters( - query_text=query_text, + query=query, owner_id=owner_id, user_id=user_id, startline_le=startline_le, @@ -596,13 +609,13 @@ async def get_projects_count( ) query = query.where(*filters) - result = await session.scalar(query) + result = await session.scalar(statement) return result async def get_projects( self, session: AsyncSession, - query_text: str | Type[Empty] = Empty, + query: str | Type[Empty] = Empty, owner_id: uuid.UUID | Type[Empty] = Empty, user_id: uuid.UUID | Type[Empty] = Empty, startline_le: datetime | Type[Empty] = Empty, @@ -616,9 +629,9 @@ async def get_projects( page: int = 1, per_page: int = 10, ) -> list[Project]: - query = select(Project).order_by(Project.created_at.desc()) + statement = select(Project).order_by(Project.created_at.desc()) filters = await self._get_projects_filters( - query_text=query_text, + query=query, owner_id=owner_id, user_id=user_id, startline_le=startline_le, @@ -635,7 +648,7 @@ async def get_projects( offset = (page - 1) * per_page query = query.limit(per_page).offset(offset) - result = await session.execute(query) + result = await session.execute(statement) return list(result.unique().scalars().all()) diff --git a/sapphire/users/cache/service.py b/sapphire/users/cache/service.py index 127a9815..5ad8d2c3 100644 --- a/sapphire/users/cache/service.py +++ b/sapphire/users/cache/service.py @@ -1,4 +1,4 @@ -import uuid +import secrets from sapphire.common.cache.service import BaseCacheService @@ -7,7 +7,7 @@ class Service(BaseCacheService): async def set_state(self) -> str: - state = str(uuid.uuid4()) + state = secrets.token_hex(32) key = f"users:auth:oauth2:habr:state:{state}" await self.redis.set(key, state, ex=120) return state diff --git a/tests/projects/database/test_projects_database_service.py b/tests/projects/database/test_projects_database_service.py index 754c139c..70b40db2 100644 --- a/tests/projects/database/test_projects_database_service.py +++ b/tests/projects/database/test_projects_database_service.py @@ -114,7 +114,7 @@ async def test_get_projects_with_all_query_params(service: Service): startline_le = datetime.now(tz=timezone.utc) + timedelta(days=30) deadline_ge = datetime.now(tz=timezone.utc) - timedelta(days=30) deadline_le = datetime.now(tz=timezone.utc) + timedelta(days=30) - query_text = "query_text" + query = "query" position_skill_ids = [uuid.uuid4(), uuid.uuid4()] position_specialization_ids = [uuid.uuid4(), uuid.uuid4()] expected_projects = [Project(id=project_id, name="test", owner_id=owner_id)] @@ -124,7 +124,7 @@ async def test_get_projects_with_all_query_params(service: Service): projects = await service.get_projects( session=session, - query_text=query_text, + query=query, owner_id=owner_id, deadline_ge=deadline_ge, deadline_le=deadline_le,