Skip to content

Commit

Permalink
Merge pull request #6667 from hotosm/fastapi-refactor
Browse files Browse the repository at this point in the history
* Organisation statistics.   * Email on team actions. * Campaign create and json responses handled. * Project info language update for different locales fixed
  • Loading branch information
prabinoid authored Dec 26, 2024
2 parents 942a81e + 17b14bf commit e2a11d9
Show file tree
Hide file tree
Showing 7 changed files with 63 additions and 26 deletions.
31 changes: 23 additions & 8 deletions backend/api/campaigns/resources.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from databases import Database
from fastapi import APIRouter, Depends, Request
from fastapi.responses import JSONResponse

from backend.db import get_db
from backend.models.dtos.campaign_dto import (
Expand Down Expand Up @@ -138,13 +139,20 @@ async def update_campaign(
raise ValueError("User not a Org Manager")
except ValueError as e:
error_msg = f"CampaignsRestAPI PATCH: {str(e)}"
return {"Error": error_msg, "SubCode": "UserNotPermitted"}, 403
return JSONResponse(
content={"Error": error_msg, "SubCode": "UserNotPermitted"}, status_code=403
)
try:
campaign = await CampaignService.update_campaign(campaign_dto, campaign_id, db)
return {"Success": "Campaign {} updated".format(campaign.id)}, 200
return JSONResponse(
content={"Success": "Campaign {} updated".format(campaign.id)},
status_code=200,
)
except ValueError:
error_msg = "Campaign PATCH - name already exists"
return {"Error": error_msg, "SubCode": "NameExists"}
return JSONResponse(
content={"Error": error_msg, "SubCode": "NameExists"}, status_code=400
)


@router.delete("/{campaign_id}/")
Expand Down Expand Up @@ -200,11 +208,13 @@ async def delete_campaign(
raise ValueError("User not a Org Manager")
except ValueError as e:
error_msg = f"CampaignsRestAPI DELETE: {str(e)}"
return {"Error": error_msg, "SubCode": "UserNotPermitted"}, 403
return JSONResponse(
content={"Error": error_msg, "SubCode": "UserNotPermitted"}, status_code=403
)

campaign = await CampaignService.get_campaign(campaign_id, db)
await CampaignService.delete_campaign(campaign.id, db)
return {"Success": "Campaign deleted"}, 200
return JSONResponse(content={"Success": "Campaign deleted"}, status_code=200)


@router.get("/", response_model=CampaignListDTO)
Expand Down Expand Up @@ -298,10 +308,15 @@ async def create_campaign(
raise ValueError("User not a Org Manager")
except ValueError as e:
error_msg = f"CampaignsAllAPI POST: {str(e)}"
return {"Error": error_msg, "SubCode": "UserNotPermitted"}, 403
return JSONResponse(
content={"Error": error_msg, "SubCode": "UserNotPermitted"}, status_code=403
)

try:
campaign_id = await CampaignService.create_campaign(campaign_dto, db)
return {"campaignId": campaign_id}, 201
return JSONResponse(content={"campaignId": campaign_id}, status_code=201)
except ValueError as e:
return {"Error": str(e).split("-")[1], "SubCode": str(e).split("-")[0]}, 409
return JSONResponse(
content={"Error": str(e).split("-")[1], "SubCode": str(e).split("-")[0]},
status_code=409,
)
1 change: 0 additions & 1 deletion backend/models/postgis/project.py
Original file line number Diff line number Diff line change
Expand Up @@ -685,7 +685,6 @@ async def update(self, project_dto: ProjectDTO, db: Database):
new_info = await ProjectInfo.create_from_dto(
dto, self.id, db
) # Can't find info so must be new locale
self.project_info.append(new_info)
else:
await ProjectInfo.update_from_dto(ProjectInfo(**project_info), dto, db)

Expand Down
5 changes: 4 additions & 1 deletion backend/models/postgis/project_info.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,10 @@ async def update_from_dto(self, dto: ProjectInfoDTO, db: Database):
columns.pop("locale", None)
query = (
update(ProjectInfo.__table__)
.where(ProjectInfo.project_id == self.project_id)
.where(
ProjectInfo.project_id == self.project_id,
ProjectInfo.locale == self.locale,
)
.values(**columns)
)
result = await db.execute(query)
Expand Down
16 changes: 8 additions & 8 deletions backend/services/messaging/message_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -235,7 +235,6 @@ async def _push_messages(messages: list, db: Database):
if (i + 1) % 10 == 0:
time.sleep(0.5)

# TODO Explore better approach.
if messages_objs:
insert_values = [
{
Expand Down Expand Up @@ -461,14 +460,13 @@ async def send_request_to_join_team(
message.message_type = MessageType.REQUEST_TEAM_NOTIFICATION.value
message.from_user_id = from_user
message.to_user_id = to_user
message.date = timestamp()
message.read = False
user_link = MessageService.get_user_link(from_username)
team_link = MessageService.get_team_link(team_name, team_id, True)
message.subject = f"{user_link} requested to join {team_link}"
message.message = f"{user_link} has requested to join the {team_link} team.\
Access the team management page to accept or reject that request."
await Message.save(message, db)
user = await UserService.get_user_by_id(to_user, db)
await MessageService._push_messages([dict(message=message, user=user)], db)

@staticmethod
async def accept_reject_request_to_join_team(
Expand All @@ -492,7 +490,8 @@ async def accept_reject_request_to_join_team(
message.message = (
f"{user_link} has {response}ed your request to join the {team_link} team."
)
await Message.save(message, db)
user = await UserService.get_user_by_id(to_user, db)
await MessageService._push_messages([dict(message=message, user=user)], db)

@staticmethod
async def accept_reject_invitation_request_for_team(
Expand Down Expand Up @@ -522,7 +521,8 @@ async def accept_reject_invitation_request_for_team(
sending_member,
MessageService.get_team_link(team_name, team_id, True),
)
await Message.save(message, db)
user = await UserService.get_user_by_id(to_user, db)
await MessageService._push_messages([dict(message=message, user=user)], db)

@staticmethod
async def send_team_join_notification(
Expand All @@ -545,8 +545,8 @@ async def send_team_join_notification(
Access the {team_link}'s page to view more info about this team."
message.date = timestamp()
message.read = False

await Message.save(message, db)
user = await UserService.get_user_by_id(to_user, db)
await MessageService._push_messages([dict(message=message, user=user)], db)

@staticmethod
async def send_message_after_chat(
Expand Down
2 changes: 1 addition & 1 deletion backend/services/stats_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -748,7 +748,7 @@ async def get_task_stats(

if org_id:
filters.append("AND organisation_id = :org_id")
values["org_id"] = org_id
values["org_id"] = int(org_id)

if org_name:
filters.append("""
Expand Down
3 changes: 1 addition & 2 deletions backend/services/team_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from loguru import logger
from markdown import markdown

from backend.db import db_connection
from backend.exceptions import NotFound
from backend.models.dtos.message_dto import MessageDTO
from backend.models.dtos.stats_dto import Pagination
Expand All @@ -28,7 +29,6 @@
from backend.services.messaging.message_service import MessageService
from backend.services.organisation_service import OrganisationService
from backend.services.users.user_service import UserService
from backend.db import db_connection


class TeamServiceError(Exception):
Expand Down Expand Up @@ -812,7 +812,6 @@ async def send_message_to_all_team_members(
team_member.user_id, conn
)
messages.append(dict(message=message, user=user))
# Push messages
await MessageService._push_messages(messages, conn)
logger.info("Messages sent successfully.")
except Exception as e:
Expand Down
31 changes: 26 additions & 5 deletions scripts/locust/locustfile.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,15 @@
import os
from locust import HttpUser, TaskSet, task, between

# Define tokens for Flask and FastAPI
FASTAPI_TOKEN = "TVRBeU5UQTBOVFkuWjJVOWNnLmtBNUZUcDZaMkpYVGJ2QnhFN29mb3lqZXZlSQ=="
FLASK_TOKEN = "TVRBeU5UQTBOVFkuWjJVeDV3LmtDTHhCbFdQR2ROZTEzYzJORWRVblp4akFCMA=="

LOCUST_HOST = os.getenv("LOCUST_HOST", "https://tm.naxa.com.np")


AUTH_TOKEN = FASTAPI_TOKEN if "tm-fastapi.naxa.com.np" in LOCUST_HOST else FLASK_TOKEN

class ProjectAndComments(TaskSet):
@task
def get_project(self):
Expand All @@ -12,8 +21,18 @@ def get_comments(self):

class ProjectList(TaskSet):
@task
def get_project(self):
self.client.get("/api/v2/projects/")
def project_list(self):
self.client.get("/api/v2/projects/?action=any&omitMapResults=true", headers={"Authorization": f"Token {AUTH_TOKEN}"})

class TaskStatistics(TaskSet):
@task
def get_contributions(self):
self.client.get("/api/v2/tasks/statistics/?startDate=2024-01-01", headers={"Authorization": f"Token {AUTH_TOKEN}"})

class TaskPage(TaskSet):
@task
def get_tasks(self):
self.client.get("/api/v2/projects/114/tasks/", headers={"Authorization": f"Token {AUTH_TOKEN}"})

class GetSimilarProjects(TaskSet):
@task
Expand Down Expand Up @@ -43,6 +62,9 @@ def get_action_any(self):
# Mapping task names to classes
task_mapping = {
"project_and_comments": ProjectAndComments,
"project_list": ProjectList,
"task_statistics": TaskStatistics,
"task_page": TaskPage,
"similar_projects": GetSimilarProjects,
"contributions": GetContributions,
"contributions_by_day": GetContributionsByDay,
Expand All @@ -57,9 +79,8 @@ class ApiBenchmarkUser(HttpUser):
# Dynamically select tasks based on environment variable or CLI parameter
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
task_name = os.getenv("TASK_SET", "get_contributions").lower()
print(task_name, "The task name....")
self.tasks = [task_mapping.get(task_name, GetContributions)]
task_name = os.getenv("TASK_SET", "project_list").lower()
self.tasks = [task_mapping.get(task_name, TaskPage)]


'''
Expand Down

0 comments on commit e2a11d9

Please sign in to comment.