Skip to content

Commit 039488b

Browse files
feat: enhance audit logging for team management actions (#233)
* feat: enhance audit logging for team management actions - Updated AuditLogModel to include additional action types: "team_created", "member_joined_team", "member_added_to_team", "member_removed_from_team", and "team_updated". - Implemented audit logging in TeamService for team creation, member joining, member addition, member removal, and team updates to improve tracking of team activities. - Modified RemoveTeamMemberView to pass the user performing the removal for better audit trail. These changes improve accountability and traceability of team management actions. * refactor: clean up unused import in team_service.py - Removed the unused datetime and timezone import from team_service.py to streamline the code and improve maintainability. This change contributes to a cleaner and more organized codebase. * refactor: clean up whitespace in team_service.py - Removed unnecessary blank lines in the team_service.py file to improve code readability and maintainability. This change contributes to a cleaner and more organized codebase. * feat: enhance audit logging by adding member ID details - Updated the audit logging in TeamService to include the added member's ID in the details of the "member_added_to_team" action. This change improves the traceability of team member additions, enhancing accountability in team management activities. * fix: add missing comma in audit logging details - Added a missing comma in the details dictionary of the "member_added_to_team" action in TeamService. This minor fix ensures proper syntax and prevents potential issues in the logging functionality. --------- Co-authored-by: Amit Prakash <[email protected]>
1 parent 6007932 commit 039488b

File tree

3 files changed

+54
-3
lines changed

3 files changed

+54
-3
lines changed

todo/models/audit_log.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ class AuditLogModel(Document):
1313
previous_executor_id: PyObjectId | None = None
1414
new_executor_id: PyObjectId | None = None
1515
spoc_id: PyObjectId | None = None
16-
action: str # e.g., "assigned_to_team", "unassigned_from_team", "status_changed", "reassign_executor"
16+
action: str # e.g., "assigned_to_team", "unassigned_from_team", "status_changed", "reassign_executor", "team_created", "member_joined_team", "member_added_to_team", "member_removed_from_team", "team_updated"
1717
timestamp: datetime = Field(default_factory=lambda: datetime.now(timezone.utc))
1818
# For status changes
1919
status_from: str | None = None

todo/services/team_service.py

Lines changed: 51 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
from todo.constants.messages import AppMessages
99
from todo.utils.invite_code_utils import generate_invite_code
1010
from typing import List
11+
from todo.models.audit_log import AuditLogModel
12+
from todo.repositories.audit_log_repository import AuditLogRepository
1113

1214
DEFAULT_ROLE_ID = "1"
1315

@@ -90,6 +92,15 @@ def create_team(cls, dto: CreateTeamDTO, created_by_user_id: str) -> CreateTeamR
9092
if user_teams:
9193
UserTeamDetailsRepository.create_many(user_teams)
9294

95+
# Audit log for team creation
96+
AuditLogRepository.create(
97+
AuditLogModel(
98+
team_id=created_team.id,
99+
action="team_created",
100+
performed_by=PyObjectId(created_by_user_id),
101+
)
102+
)
103+
93104
# Convert to DTO
94105
team_dto = TeamDTO(
95106
id=str(created_team.id),
@@ -226,6 +237,15 @@ def join_team_by_invite_code(cls, invite_code: str, user_id: str) -> TeamDTO:
226237
)
227238
UserTeamDetailsRepository.create(user_team)
228239

240+
# Audit log for team join
241+
AuditLogRepository.create(
242+
AuditLogModel(
243+
team_id=team.id,
244+
action="member_joined_team",
245+
performed_by=PyObjectId(user_id),
246+
)
247+
)
248+
229249
# 4. Return team details
230250
return TeamDTO(
231251
id=str(team.id),
@@ -283,6 +303,15 @@ def update_team(cls, team_id: str, dto: UpdateTeamDTO, updated_by_user_id: str)
283303
if not success:
284304
raise ValueError(f"Failed to update team members for team with id {team_id}")
285305

306+
# Audit log for team update
307+
AuditLogRepository.create(
308+
AuditLogModel(
309+
team_id=PyObjectId(team_id),
310+
action="team_updated",
311+
performed_by=PyObjectId(updated_by_user_id),
312+
)
313+
)
314+
286315
# Convert to DTO
287316
return TeamDTO(
288317
id=str(updated_team.id),
@@ -364,6 +393,17 @@ def add_team_members(cls, team_id: str, member_ids: List[str], added_by_user_id:
364393
if new_user_teams:
365394
UserTeamDetailsRepository.create_many(new_user_teams)
366395

396+
# Audit log for team member addition
397+
for member_id in member_ids:
398+
AuditLogRepository.create(
399+
AuditLogModel(
400+
team_id=team.id,
401+
action="member_added_to_team",
402+
performed_by=PyObjectId(added_by_user_id),
403+
details={"added_member_id": member_id},
404+
)
405+
)
406+
367407
# Return updated team details
368408
return TeamDTO(
369409
id=str(team.id),
@@ -384,10 +424,20 @@ class TeamOrUserNotFound(Exception):
384424
pass
385425

386426
@classmethod
387-
def remove_member_from_team(cls, user_id: str, team_id: str):
427+
def remove_member_from_team(cls, user_id: str, team_id: str, removed_by_user_id: str = None):
388428
from todo.repositories.user_team_details_repository import UserTeamDetailsRepository
389429

390430
success = UserTeamDetailsRepository.remove_member_from_team(user_id=user_id, team_id=team_id)
391431
if not success:
392432
raise cls.TeamOrUserNotFound()
433+
434+
# Audit log for team member removal
435+
AuditLogRepository.create(
436+
AuditLogModel(
437+
team_id=PyObjectId(team_id),
438+
action="member_removed_from_team",
439+
performed_by=PyObjectId(removed_by_user_id) if removed_by_user_id else PyObjectId(user_id),
440+
)
441+
)
442+
393443
return True

todo/views/team.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -473,7 +473,8 @@ def delete(self, request, team_id, user_id):
473473
from todo.services.team_service import TeamService
474474

475475
try:
476-
TeamService.remove_member_from_team(user_id=user_id, team_id=team_id)
476+
# Pass the user performing the removal (request.user_id) and the user being removed (user_id)
477+
TeamService.remove_member_from_team(user_id=user_id, team_id=team_id, removed_by_user_id=request.user_id)
477478
return Response(status=status.HTTP_204_NO_CONTENT)
478479
except TeamService.TeamOrUserNotFound:
479480
return Response({"detail": "Team or user not found."}, status=status.HTTP_404_NOT_FOUND)

0 commit comments

Comments
 (0)