Skip to content

Commit

Permalink
Merge pull request #6634 from hotosm/fastapi-refactor
Browse files Browse the repository at this point in the history
fix: Project search and deletion.
  • Loading branch information
prabinoid authored Nov 15, 2024
2 parents 56a3e96 + 907a616 commit 58b8bf4
Show file tree
Hide file tree
Showing 7 changed files with 52 additions and 53 deletions.
13 changes: 8 additions & 5 deletions backend/api/projects/actions.py
Original file line number Diff line number Diff line change
Expand Up @@ -160,15 +160,18 @@ async def post(
}, 400

if not ProjectAdminService.is_user_action_permitted_on_project(user.id, project_id):
return {
"Error": "User is not a manager of the project",
"SubCode": "UserPermissionError",
}, 403
return JSONResponse(
content={
"Error": "User is not a manager of the project",
"SubCode": "UserPermissionError",
},
status_code=403,
)
threading.Thread(
target=MessageService.send_message_to_all_contributors,
args=(project_id, message_dto),
).start()
return {"Success": "Messages started"}, 200
return JSONResponse(content={"Success": "Messages started"}, status_code=200)


@router.post("/{project_id}/actions/feature/")
Expand Down
25 changes: 21 additions & 4 deletions backend/api/teams/actions.py
Original file line number Diff line number Diff line change
Expand Up @@ -314,14 +314,26 @@ async def post(
)


import asyncio


# Function to run async code in a thread
def run_asyncio_in_thread(func, *args, **kwargs):
# Create a new event loop for the thread
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)
# Create a new database connection (to be used in this thread)
db = get_db()
loop.run_until_complete(func(*args, db=db, **kwargs))


@router.post("/{team_id}/actions/message-members/")
async def post(
request: Request,
background_tasks: BackgroundTasks,
user: AuthUserDTO = Depends(login_required),
db: Database = Depends(get_db),
team_id: int = None,
message_dto: MessageDTO = Body(...),
):
"""
Message all team members
Expand Down Expand Up @@ -368,9 +380,11 @@ async def post(
description: Internal Server Error
"""
try:
request_json = await request.json()
request_json["from_user_id"] = user.id
message_dto = MessageDTO(**request_json)
# Validate if team is present
team = await TeamService.get_team_by_id(team_id, db)

is_manager = await TeamService.is_user_team_manager(team_id, user.id, db)
if not is_manager:
raise ValueError
Expand All @@ -397,10 +411,13 @@ async def post(
)

try:
# Start a new thread for sending messages
# Use threading to run the async function in a separate thread
# threading.Thread(
# target=TeamService.send_message_to_all_team_members,
# args=(team_id, team.name, message_dto, db),
# target=run_asyncio_in_thread,
# args=(TeamService.send_message_to_all_team_members, team_id, team.name, message_dto, user.id)
# ).start()

background_tasks.add_task(
TeamService.send_message_to_all_team_members,
team_id,
Expand Down
19 changes: 2 additions & 17 deletions backend/models/dtos/message_dto.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,8 @@ class ChatMessageDTO(BaseModel):
timestamp: datetime
username: str

# class Config:
# populate_by_name = True
class Config:
populate_by_name = True

# json_encoders = {
# datetime: lambda v: v.isoformat() + "Z" if v else None
Expand All @@ -76,21 +76,6 @@ class Config:

json_encoders = {datetime: lambda v: v.isoformat() + "Z" if v else None}

# def dict(self, *args, **kwargs):
# """
# Override the dict method to exclude `user_id` and `project_id`
# from the dictionary representation.
# """
# exclude_fields = {"user_id", "project_id"}
# # Generate the dict as usual, excluding the fields
# return super().dict(*args, **kwargs, exclude=exclude_fields)

# def dict(self, **kwargs):
# data = super().dict(**kwargs)
# if self.timestamp:
# data["timestamp"] = self.timestamp.isoformat() + "Z"
# return data


class ProjectChatDTO(BaseModel):
"""DTO describing all chat messages on one project"""
Expand Down
2 changes: 2 additions & 0 deletions backend/models/postgis/project.py
Original file line number Diff line number Diff line change
Expand Up @@ -825,6 +825,8 @@ async def delete(self, db: Database):
"tasks",
"project_info",
"project_chat",
"project_partnerships_history",
"project_partnerships",
]

# Start a transaction to ensure atomic deletion
Expand Down
16 changes: 0 additions & 16 deletions backend/models/postgis/team.py
Original file line number Diff line number Diff line change
Expand Up @@ -121,22 +121,6 @@ class Team(Base):
# organisation = relationship(Organisation, backref="teams", lazy="joined")
organisation = relationship(Organisation, backref="teams")

# async def create(self, db: Database):
# """Creates and saves the current model to the DB"""
# print(self.members)

# team = await db.execute(
# insert(Team.__table__).values(
# organisation_id=self.organisation_id,
# name=self.name,
# logo=self.logo,
# description=self.description,
# join_method=self.join_method,
# visibility=self.visibility,
# )
# )
# return team if team else None

async def create(self, db: Database):
"""Creates and saves the current model to the DB, including members if they exist."""

Expand Down
14 changes: 10 additions & 4 deletions backend/services/project_search_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -265,15 +265,21 @@ async def _filter_projects(search_dto: ProjectSearchDTO, user, db: Database):
search_text = "".join(
char for char in search_dto.text_search if char not in "@|&!><\\():"
)
or_search = " | ".join([x for x in search_text.split(" ") if x])
tsquery_search = " & ".join([x for x in search_text.split(" ") if x])
ilike_search = f"%{search_text}%"

subquery_filters.append(
"text_searchable @@ to_tsquery('english', :text_search) OR name ILIKE :text_search"
"""
text_searchable @@ to_tsquery('english', :tsquery_search)
OR name ILIKE :text_search
"""
)
params["text_search"] = or_search
params["tsquery_search"] = tsquery_search
params["text_search"] = ilike_search

filters.append(
"""
p.id IN (
p.id = ANY(
SELECT project_id
FROM project_info
WHERE {}
Expand Down
16 changes: 9 additions & 7 deletions backend/services/team_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -631,11 +631,15 @@ async def _get_team_members(team_id: int, db: Database):

@staticmethod
async def _get_active_team_members(team_id: int, db: Database):
query = """
SELECT * FROM team_members
WHERE team_id = :team_id AND active = TRUE
"""
return await db.fetch_all(query, values={"team_id": team_id})
try:
query = """
SELECT * FROM team_members
WHERE team_id = :team_id AND active = TRUE
"""
return await db.fetch_all(query, values={"team_id": team_id})
except Exception as e:
print(f"Error executing query: {str(e)}")
raise

@staticmethod
async def activate_team_member(team_id: int, user_id: int, db: Database):
Expand Down Expand Up @@ -791,15 +795,13 @@ async def send_message_to_all_team_members(
team_members = await TeamService._get_active_team_members(team_id, db)
user = await UserService.get_user_by_id(user_id, db)
sender = user.username

message_dto.message = (
"A message from {}, manager of {} team:<br/><br/>{}".format(
MessageService.get_user_profile_link(sender),
MessageService.get_team_link(team_name, team_id, False),
markdown(message_dto.message, output_format="html"),
)
)

messages = []
for team_member in team_members:
if team_member.user_id != user_id:
Expand Down

0 comments on commit 58b8bf4

Please sign in to comment.