-
Notifications
You must be signed in to change notification settings - Fork 49
feat(dashboard): create an event from the dashboard #354
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
6130431
3fae9d2
896f1e2
452cec7
babb953
800fa55
f8b03af
3e42153
44241f4
e5f0db3
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,10 +1,15 @@ | ||
| import frappe | ||
|
|
||
| from buzz.api.events import services | ||
| from buzz.api.events.schemas import MyEventsResponse | ||
| from buzz.api.events.schemas import CreatedEvent, MyEventsResponse, NewEvent | ||
|
|
||
|
|
||
| @frappe.whitelist() | ||
| def get_my_events() -> MyEventsResponse: | ||
| """Events hosted by the session user's teams, plus events they hold a ticket to.""" | ||
| return services.my_events() | ||
|
|
||
|
|
||
| @frappe.whitelist(methods=["POST"]) | ||
| def create_event(event: NewEvent) -> CreatedEvent: | ||
| return services.create_event(event) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,13 @@ | ||
| from frappe import _lt | ||
|
|
||
| from buzz.api.exceptions import BuzzAPIError, NotPermitted | ||
|
|
||
|
|
||
| class CannotCreateEvents(NotPermitted): | ||
| title = _lt("Not Permitted") | ||
| message = _lt("You cannot create events for this team.") | ||
|
|
||
|
|
||
| class ZoomNotAvailable(BuzzAPIError): | ||
| title = _lt("Zoom Not Available") | ||
| message = _lt("Zoom is not set up on this site, so a Zoom meeting cannot be created.") |
| Original file line number | Diff line number | Diff line change | ||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -99,8 +99,24 @@ def validate(self): | |||||||||||||||
| self.validate_tax_settings() | ||||||||||||||||
| self.validate_guest_verification_config() | ||||||||||||||||
| self.validate_custom_forms() | ||||||||||||||||
| self.validate_venue_team() | ||||||||||||||||
| self.set_time_zone_label() | ||||||||||||||||
|
|
||||||||||||||||
| def validate_venue_team(self): | ||||||||||||||||
| """A venue may only be linked by the team that owns it. | ||||||||||||||||
|
|
||||||||||||||||
| Nothing downstream re-checks this: the booking confirmation and the calendar | ||||||||||||||||
| invite both read the linked venue's address without a permission check, so a | ||||||||||||||||
| cross-team link publishes the other team's address. | ||||||||||||||||
| """ | ||||||||||||||||
| if not self.venue: | ||||||||||||||||
| return | ||||||||||||||||
|
|
||||||||||||||||
| venue_team = frappe.db.get_value("Event Venue", self.venue, "team") | ||||||||||||||||
| # An unstamped venue predates the team backfill; role permissions still gate it. | ||||||||||||||||
| if venue_team and venue_team != self.team: | ||||||||||||||||
| frappe.throw(_("Venue {0} belongs to another team.").format(self.venue)) | ||||||||||||||||
|
Comment on lines
+115
to
+118
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
When a manager supplies the name of a legacy venue whose How this was verified: The create API copies the supplied venue after authorizing only the event team, while downstream booking and calendar paths dereference the accepted venue without another ownership check.
Suggested change
Knowledge Base Used: Prompt To Fix With AIThis is a comment left during a code review.
Path: buzz/events/doctype/buzz_event/buzz_event.py
Line: 115-118
Comment:
**Unstamped venues bypass ownership**
When a manager supplies the name of a legacy venue whose `team` is null or empty, this truthiness check accepts the venue and links it to the manager's event, causing its address to be exposed through booking details, booking confirmation, and calendar invitations.
**How this was verified:** The create API copies the supplied venue after authorizing only the event team, while downstream booking and calendar paths dereference the accepted venue without another ownership check.
```suggestion
venue_team = frappe.db.get_value("Event Venue", self.venue, "team")
if venue_team != self.team:
frappe.throw(_("Venue {0} belongs to another team.").format(self.venue))
```
**Knowledge Base Used:**
- [Event configuration and scheduling](https://app.greptile.com/bwh-tech/-/custom-context/knowledge-base/bwhtech/buzz/-/docs/event-configuration.md)
- [Frappe application integration](https://app.greptile.com/bwh-tech/-/custom-context/knowledge-base/bwhtech/buzz/-/docs/frappe-application-integration.md)
---
For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Valid catch — an unstamped venue is linkable by any team, which is the same leak narrowed to legacy rows. The justification in my comment was a bad analogy: Not taking the suggestion in this PR, though. Dropping the truthiness check turns a data problem into a save failure — any site still holding such a row would find those events unsaveable, including edits that never touch the venue. The backfill should land first, then the guard tightens. Tracked in #375, which also notes that
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That’s a reasonable trade-off for this PR. The current check still protects already-stamped venues, while tightening it before the backfill is verified would make legacy records unsaveable—even on unrelated edits. #375 is the right follow-up: confirm |
||||||||||||||||
|
|
||||||||||||||||
| def set_time_zone_label(self): | ||||||||||||||||
| # validate runs before the mandatory check, so dates may still be empty here | ||||||||||||||||
| if not (self.time_zone and self.start_date and self.start_time): | ||||||||||||||||
|
|
||||||||||||||||
Uh oh!
There was an error while loading. Please reload this page.