diff --git a/OPENAPI_DOC.yml b/OPENAPI_DOC.yml index 4903186..7d90f0a 100644 --- a/OPENAPI_DOC.yml +++ b/OPENAPI_DOC.yml @@ -211,6 +211,12 @@ paths: schema: type: string nullable: true + - name: link_ext + in: query + required: false + schema: + type: string + nullable: true responses: 200: description: OK @@ -570,7 +576,7 @@ paths: - name: limit in: query description: the maximum number of results to return - example: "10000" + example: "100000" required: false schema: type: integer @@ -4551,6 +4557,117 @@ paths: schema: $ref: '#/components/schemas/Application__CommonError' /api/staff/v1/events/{id}/metadata/{system_id}: + get: + summary: '# returns the event metadata requested.' + description: '# returns the event metadata requested. + + + by default it assumes the event exists on the resource calendar. + + you can provide a calendar param to override this default' + tags: + - Events + operationId: Events_get_metadata + parameters: + - name: id + in: path + description: the event id + example: AAMkAGVmMDEzMTM4LTZmYWUtNDdkNC1hMDZe + required: true + schema: + type: string + - name: system_id + in: path + description: the event space associated with this event + example: sys-1234 + required: true + schema: + type: string + - name: calendar + in: query + description: the calendar associated with this event id + example: user@org.com + required: false + schema: + type: string + nullable: true + - name: ical_uid + in: query + description: an alternative lookup for finding event-metadata + example: 5FC53010-1267-4F8E-BC28-1D7AE55A7C99 + required: false + schema: + type: string + nullable: true + responses: + 200: + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/JSON__Any' + 429: + description: Too Many Requests + content: + application/json: + schema: + $ref: '#/components/schemas/Application__CommonError' + 400: + description: Bad Request + content: + application/json: + schema: + $ref: '#/components/schemas/Application__CommonError' + 401: + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/Application__CommonError' + 403: + description: Forbidden + 404: + description: Not Found + content: + application/json: + schema: + $ref: '#/components/schemas/Application__CommonError' + 511: + description: Network Authentication Required + content: + application/json: + schema: + $ref: '#/components/schemas/Application__CommonError' + 406: + description: Not Acceptable + content: + application/json: + schema: + $ref: '#/components/schemas/Application__ContentError' + 415: + description: Unsupported Media Type + content: + application/json: + schema: + $ref: '#/components/schemas/Application__ContentError' + 422: + description: Unprocessable Entity + content: + application/json: + schema: + $ref: '#/components/schemas/Application__ValidationError' + 500: + description: Internal Server Error + content: + application/json: + schema: + $ref: '#/components/schemas/Application__CommonError' + 405: + description: Method Not Allowed + content: + application/json: + schema: + $ref: '#/components/schemas/Application__CommonError' put: summary: Replaces the metadata on a booking without touching the calendar event description: 'Replaces the metadata on a booking without touching the calendar diff --git a/spec/controllers/bookings_spec.cr b/spec/controllers/bookings_spec.cr index 508c921..85e8fe3 100644 --- a/spec/controllers/bookings_spec.cr +++ b/spec/controllers/bookings_spec.cr @@ -570,7 +570,7 @@ describe Bookings do asset_ids.should contain("desk-2") end - it "should return a list of asset ids (excluding checked out and deleted)", focus: true do + it "should return a list of asset ids (excluding checked out and deleted)" do tenant_id = get_tenant.id.not_nil! starting = Time.utc.to_unix diff --git a/src/controllers/events.cr b/src/controllers/events.cr index 2f52f9f..349a824 100644 --- a/src/controllers/events.cr +++ b/src/controllers/events.cr @@ -2,7 +2,7 @@ class Events < Application base "/api/staff/v1/events" # Skip scope check for relevant routes - skip_action :check_jwt_scope, only: [:show, :patch_metadata, :guest_checkin, :add_attendee] + skip_action :check_jwt_scope, only: [:show, :get_metadata, :patch_metadata, :guest_checkin, :add_attendee] # Skip actions that requres login # If a user is logged in then they will be run as part of @@ -921,6 +921,56 @@ class Events < Application end end + # # returns the event metadata requested. + # + # by default it assumes the event exists on the resource calendar. + # you can provide a calendar param to override this default + @[AC::Route::GET("/:id/metadata/:system_id")] + def get_metadata( + @[AC::Param::Info(name: "id", description: "the event id", example: "AAMkAGVmMDEzMTM4LTZmYWUtNDdkNC1hMDZe")] + original_id : String, + @[AC::Param::Info(description: "the event space associated with this event", example: "sys-1234")] + system_id : String, + @[AC::Param::Info(name: "calendar", description: "the calendar associated with this event id", example: "user@org.com")] + user_cal : String? = nil, + @[AC::Param::Info(description: "an alternative lookup for finding event-metadata", example: "5FC53010-1267-4F8E-BC28-1D7AE55A7C99")] + ical_uid : String? = nil, + ) : JSON::Any + event_id = original_id + placeos_client = get_placeos_client + + # Guest access + if user_token.guest_scope? + guest_event_id, guest_system_id = user.roles + system_id ||= guest_system_id + raise Error::Forbidden.new("guest #{user_token.id} attempting to view a system they are not associated with") unless system_id == guest_system_id + end + + system = placeos_client.systems.fetch(system_id) + cal_id = system.email.presence.try &.downcase + raise AC::Route::Param::ValueError.new("system '#{system.name}' (#{system_id}) does not have a resource email address specified", "system_id") unless cal_id + + user_email = user_token.guest_scope? ? cal_id : user.email.downcase + cal_id = user_cal || cal_id + + # attempt to find the metadata + query = EventMetadata.by_tenant(tenant.id).where(system_id: system_id) + if ical_uid.presence + query = query.where("ical_uid in (?,?) OR event_id = ?", ical_uid, event_id, event_id) + else + query = query.where(event_id: event_id) + end + raise Error::NotFound.new("metadata not found for event #{event_id}") unless meta = query.to_a.first? + + # Guest access + if user_token.guest_scope? + raise Error::Forbidden.new("guest #{user_token.id} attempting to view an event they are not associated with") unless guest_event_id.in?({meta.event_id, meta.recurring_master_id, meta.resource_master_id, meta.ical_uid}) + end + + raise Error::InconsistentState.new("ext_data must be present on metadata") unless meta_ext_data = meta.ext_data + meta_ext_data + end + # Patches the metadata on a booking without touching the calendar event # only updates the keys provided in the request #