Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 14 additions & 3 deletions src/impl/Event/router_v1.py
Original file line number Diff line number Diff line change
Expand Up @@ -379,9 +379,20 @@ def resend_accept_mail(
return {"success": True}


@router.get("/{event_id}/send_slack_mail/")
def send_slack_mail(event_id: int, token: BaseToken = Depends(JWTBearer())):
event_service.send_slack_mail(event_id, token)
@router.post("/{event_id}/send_slack_mail/")
def send_slack_mail(event_id: int, slackUrl: str, token: BaseToken = Depends(JWTBearer())):
Copy link

Copilot AI Nov 17, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The slackUrl parameter should be part of a request body model rather than a query parameter. For POST endpoints, it's a best practice to use request body objects (Pydantic models) for data parameters. Consider creating a schema like SlackMailRequest with a slack_url field and use it as the body parameter.

Copilot uses AI. Check for mistakes.
event_service.send_slack_mail(event_id, slackUrl, token)
return {"success": True}

@router.post("/{event_id}/send_reminder_mails/")
def send_reminder_mails(
event_id: int,
token: BaseToken = Depends(JWTBearer()),
):
"""
Send reminder mails to all accepted hackers of an event
"""
event_service.send_reminder_mails(event_id, token)
return {"success": True}


Expand Down
71 changes: 68 additions & 3 deletions src/impl/Event/service.py
Original file line number Diff line number Diff line change
Expand Up @@ -972,7 +972,7 @@ def resend_mail(self, event_id: int, hacker_id: int, data: BaseToken):
db.session.commit()

@BaseService.needs_service(MailClient)
def send_slack_mail(self, event_id: int, data: BaseToken):
def send_slack_mail(self, event_id: int, slackUrl: str, data: BaseToken):
Copy link

Copilot AI Nov 17, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing input validation: The slackUrl parameter is not validated before use. Consider adding validation to ensure it's a valid URL format and not empty. This is especially important since this URL will be sent to users via email and could be a security concern if arbitrary strings are accepted.

Copilot uses AI. Check for mistakes.
if not data.check([UserType.LLEIDAHACKER]):
raise AuthenticationException("Not authorized")
event = self.get_by_id(event_id)
Expand All @@ -984,16 +984,81 @@ def send_slack_mail(self, event_id: int, data: BaseToken):
hackers = event.accepted_hackers

for hacker in hackers:
self.mail_client.create_mail(
mail = self.mail_client.create_mail(
MailCreate(
template_id=self.mail_client.get_internall_template_id(
InternalTemplate.EVENT_SLACK_INVITE
),
subject="HackEPS2024 slack invitation",
receiver_id=str(hacker.id),
receiver_mail=str(hacker.email),
fields="https://join.slack.com/t/hackeps2024/shared_invite/zt-2usc9qny9-z3NkybNlCXFAI9m0Cl~FsQ",
fields=slackUrl,
)
)
# send the created mail
self.mail_client.send_mail_by_id(mail.id)

db.session.commit()

@BaseService.needs_service(MailClient)
def send_reminder_mails(
self,
event_id: int,
data: BaseToken,
):
if not data.check([UserType.LLEIDAHACKER]):
raise AuthenticationException("Not authorized")
event = self.get_by_id(event_id)
if event.archived:
raise InvalidDataException(
"Unable to operate with an archived event, unarchive it first"
)

hackers = event.accepted_hackers

for hacker in hackers:
try:
reg = (
db.session.query(HackerRegistration)
.filter(
HackerRegistration.user_id == hacker.id,
HackerRegistration.event_id == event.id,
)
.first()
)
# send reminder only if registration exists and assistance not confirmed
if reg is None or reg.confirmed_assistance:
continue

# ensure there is a confirmation token for this registration
if not reg.confirm_assistance_token:
reg.confirm_assistance_token = AssistenceToken(hacker, event.id).to_token()

# compute days left until event (rounded down)
try:
delta = event.start_date - datetime.now()
days_left = max(0, int(delta.total_seconds() // 86400))
except Exception:
days_left = 0

fields = f"{hacker.name},{event.name},{days_left},{reg.confirm_assistance_token}"

mail = self.mail_client.create_mail(
MailCreate(
template_id=self.mail_client.get_internall_template_id(
InternalTemplate.EVENT_HACKER_REMINDER
),
subject=f"{event.name} - Recordatori de confirmació d'assistència",
receiver_id=str(hacker.id),
receiver_mail=str(hacker.email),
fields=fields,
)
)
# send the created mail
self.mail_client.send_mail_by_id(mail.id)
db.session.commit()
except Exception as e:
db.session.rollback()
# Optionally log the error here, e.g.:
# print(f"Failed to send reminder to hacker {hacker.id}: {e}")
continue
2 changes: 2 additions & 0 deletions src/impl/Mail/internall_templates.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,7 @@ class InternalTemplate(Enum):

EVENT_HACKER_REGISTERED = "event_hacker_registered"
EVENT_HACKER_ACCEPTED = "event_hacker_accepted"

EVENT_HACKER_REMINDER = "event_hacker_reminder"
# EVENT_HACKER_REJECTED = 'event_hacker_accepted'
# EVENT_HACKER_CONFIRMATION = 'event_hacker_confirmation'
Loading