diff --git a/OPENAPI_DOC.yml b/OPENAPI_DOC.yml index 036f98cd..36728d9e 100644 --- a/OPENAPI_DOC.yml +++ b/OPENAPI_DOC.yml @@ -6691,6 +6691,130 @@ paths: application/json: schema: $ref: '#/components/schemas/HealthCheck__BuildInfo' + /api/staff/v1/place: + get: + summary: Retrieves a list of rooms from the tenant place object + description: 'Retrieves a list of rooms from the tenant place object + + This function supports advanced filtering using Azure AD filter syntax. + + For more information on Azure AD filter syntax, visit: + + https://learn.microsoft.com/en-us/graph/filter-query-parameter?tabs=http' + tags: + - Place + operationId: Place_index + parameters: + - name: match + in: query + description: An optional query parameter to return a subset of properties + for a resource. With match, you can specify a subset or a superset of the + default properties. + example: id,displayName + required: false + schema: + type: string + nullable: true + - name: filter + in: query + description: An optional advanced search filter using Azure AD filter syntax + to query parameter to retrieve a subset of a collection.. + example: startsWith(givenName,'ben') or startsWith(surname,'ben') + required: false + schema: + type: string + nullable: true + - name: top + in: query + description: 'Optional: Use the top query parameter to specify the number + of items to be included in the result. Default value is 100' + example: "100" + required: false + schema: + type: integer + format: Int32 + nullable: true + - name: skip + in: query + description: 'Optional: Use skip query parameter to set the number of items + to skip at the start of a collection.' + example: 21 to retrieve search results from 21st record + required: false + schema: + type: integer + format: Int32 + nullable: true + responses: + 200: + description: OK + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/Office365__Room' + 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' /api/staff/v1/people: get: summary: Retrieves a list of users from the organization directory @@ -11824,6 +11948,108 @@ components: required: - commit - build_time + Office365__Room: + type: object + properties: + address: + type: object + properties: + city: + type: string + nullable: true + state: + type: string + nullable: true + street: + type: string + nullable: true + countryOrRegion: + type: string + nullable: true + postalCode: + type: string + nullable: true + nullable: true + displayName: + type: string + geoCoordinates: + type: object + properties: + altitudeAccuracy: + type: number + format: Float64 + nullable: true + accuracy: + type: number + format: Float64 + nullable: true + altitude: + type: number + format: Float64 + nullable: true + latitude: + type: number + format: Float64 + nullable: true + longitude: + type: number + format: Float64 + nullable: true + nullable: true + id: + type: string + phone: + type: string + nullable: true + audioDeviceName: + type: string + nullable: true + bookingType: + type: string + enum: + - reserved + - standard + nullable: true + building: + type: string + nullable: true + capacity: + type: integer + format: Int32 + nullable: true + displayDeviceName: + type: string + nullable: true + emailAddress: + type: string + nullable: true + floorLabel: + type: string + nullable: true + floorNumber: + type: integer + format: Int32 + nullable: true + isWheelChairAccessible: + type: boolean + nullable: true + label: + type: string + nullable: true + nickname: + type: string + nullable: true + tags: + type: array + items: + type: string + nullable: true + videoDeviceName: + type: string + nullable: true + required: + - displayName + - id PlaceCalendar__User: type: object properties: diff --git a/shard.lock b/shard.lock index ac6b8887..c7439362 100644 --- a/shard.lock +++ b/shard.lock @@ -115,7 +115,7 @@ shards: office365: git: https://github.com/placeos/office365.git - version: 1.25.3 + version: 1.25.4 openssl_ext: git: https://github.com/spider-gazelle/openssl_ext.git @@ -159,7 +159,7 @@ shards: placeos: git: https://github.com/placeos/crystal-client.git - version: 2.11.0 + version: 2.11.6 placeos-log-backend: git: https://github.com/place-labs/log-backend.git diff --git a/spec/controllers/place_spec.cr b/spec/controllers/place_spec.cr new file mode 100644 index 00000000..23709b62 --- /dev/null +++ b/spec/controllers/place_spec.cr @@ -0,0 +1,20 @@ +require "../spec_helper" + +describe Place do + client = AC::SpecHelper.client + headers = Mock::Headers.office365_guest + + describe "#index" do + it "should return a list of rooms" do + WebMock.stub(:post, "https://login.microsoftonline.com/bb89674a-238b-4b7d-91ec-6bebad83553a/oauth2/v2.0/token") + .to_return(body: File.read("./spec/fixtures/tokens/o365_token.json")) + WebMock.stub(:get, "https://graph.microsoft.com/v1.0/places/microsoft.graph.room") + .to_return(body: File.read("./spec/fixtures/place/index.json")) + + rooms = Array(Office365::Room).from_json(client.get(PLACE_BASE, headers: headers).body) + rooms.size.should eq(2) + end + end +end + +PLACE_BASE = Place.base_route diff --git a/spec/fixtures/place/index.json b/spec/fixtures/place/index.json new file mode 100644 index 00000000..90a57ba5 --- /dev/null +++ b/spec/fixtures/place/index.json @@ -0,0 +1,68 @@ +{ + "@odata.context": "https://graph.microsoft.com/v1.0/$metadata#places/microsoft.graph.room", + "value": [ + { + "id": "3162F1E1-C4C0-604B-51D8-91DA78989EB1", + "emailAddress": "cf100@contoso.com", + "displayName": "Conf Room 100", + "address": { + "street": "4567 Main Street", + "city": "Buffalo", + "state": "NY", + "postalCode": "98052", + "countryOrRegion": "USA" + }, + "geoCoordinates": { + "latitude": 47.640568390488626, + "longitude": -122.1293731033803 + }, + "phone": "000-000-0000", + "nickname": "Conf Room", + "label": "100", + "capacity": 50, + "building": "1", + "floorNumber": 1, + "isManaged": true, + "isWheelChairAccessible": false, + "bookingType": "standard", + "tags": [ + "bean bags" + ], + "audioDeviceName": null, + "videoDeviceName": null, + "displayDevice": "surface hub" + }, + { + "id": "3162F1E1-C4C0-604B-51D8-91DA78970B97", + "emailAddress": "cf200@contoso.com", + "displayName": "Conf Room 200", + "address": { + "street": "4567 Main Street", + "city": "Buffalo", + "state": "NY", + "postalCode": "98052", + "countryOrRegion": "USA" + }, + "geoCoordinates": { + "latitude": 47.640568390488625, + "longitude": -122.1293731033802 + }, + "phone": "000-000-0000", + "nickname": "Conf Room", + "label": "200", + "capacity": 40, + "building": "2", + "floorNumber": 2, + "isManaged": true, + "isWheelChairAccessible": false, + "bookingType": "standard", + "tags": [ + "benches", + "nice view" + ], + "audioDeviceName": null, + "videoDeviceName": null, + "displayDevice": "surface hub" + } + ] +} \ No newline at end of file diff --git a/src/controllers/events.cr b/src/controllers/events.cr index aab173bf..900b6b3e 100644 --- a/src/controllers/events.cr +++ b/src/controllers/events.cr @@ -47,7 +47,7 @@ class Events < Application private def confirm_access_for_add_attendee( event : PlaceCalendar::Event, metadata : EventMetadata, - system : PlaceOS::Client::API::Models::System? = nil, + system : PlaceOS::Client::API::Models::System? = nil ) return if metadata.permission.public? return if is_support? diff --git a/src/controllers/place.cr b/src/controllers/place.cr new file mode 100644 index 00000000..4ec1e40a --- /dev/null +++ b/src/controllers/place.cr @@ -0,0 +1,26 @@ +class Place < Application + base "/api/staff/v1/place" + + # Retrieves a list of rooms from the tenant place object + # This function supports advanced filtering using Azure AD filter syntax. + # For more information on Azure AD filter syntax, visit: + # https://learn.microsoft.com/en-us/graph/filter-query-parameter?tabs=http + @[AC::Route::GET("/")] + def index( + @[AC::Param::Info(name: "match", description: "An optional query parameter to return a subset of properties for a resource. With match, you can specify a subset or a superset of the default properties.", example: "id,displayName")] + match : String? = nil, + @[AC::Param::Info(name: "filter", description: "An optional advanced search filter using Azure AD filter syntax to query parameter to retrieve a subset of a collection..", example: "startsWith(givenName,'ben') or startsWith(surname,'ben')")] + filter : String? = nil, + @[AC::Param::Info(description: "Optional: Use the top query parameter to specify the number of items to be included in the result. Default value is 100", example: "100")] + top : Int32? = nil, + @[AC::Param::Info(description: "Optional: Use skip query parameter to set the number of items to skip at the start of a collection.", example: "21 to retrieve search results from 21st record")] + skip : Int32? = nil + ) : Array(Office365::Room) + case client.client_id + when :office365 + client.calendar.as(PlaceCalendar::Office365).client.list_rooms(match: match, filter: filter, top: top, skip: skip).as(Office365::Rooms).value + else + raise Error::NotImplemented.new("place query is not available for #{client.client_id}") + end + end +end