diff --git a/.ameba.yml b/.ameba.yml new file mode 100644 index 00000000..da071e97 --- /dev/null +++ b/.ameba.yml @@ -0,0 +1,2 @@ +Lint/NotNil: + Enabled: false diff --git a/OPENAPI_DOC.yml b/OPENAPI_DOC.yml index b7f07473..a3c78330 100644 --- a/OPENAPI_DOC.yml +++ b/OPENAPI_DOC.yml @@ -6240,6 +6240,14 @@ paths: schema: type: string nullable: true + - name: public + in: query + description: return systems which are public + example: "true" + required: false + schema: + type: boolean + nullable: true - name: q in: query description: returns results based on a [simple query string](https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-simple-query-string-query.html) @@ -13991,70 +13999,34 @@ paths: application/json: schema: $ref: '#/components/schemas/PlaceOS__Api__Application__ContentError' - /api/engine/v2/zones: - get: - summary: list the configured zones + /api/engine/v2/webrtc/guest_entry/{system_id}: + post: + summary: this route provides guest access to an anonymous chat room + description: 'this route provides guest access to an anonymous chat room + + the guest participant details will be forwarded to any listening systems + + additional fields provided as part of the guest post will also be forwarded' tags: - - Zones - operationId: PlaceOS::Api::Zones#index + - WebRTC + operationId: PlaceOS::Api::WebRTC#guest_entry + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/PlaceOS__Api__GuestParticipant' + required: true parameters: - - name: parent_id - in: query - description: only return zones who have this zone as a parent - example: zone-1234 - required: false - schema: - type: string - nullable: true - - name: tags - in: query - description: return zones with particular tags - example: building,level - required: false - schema: - type: array - items: - type: string - nullable: true - - name: q - in: query - description: returns results based on a [simple query string](https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-simple-query-string-query.html) - required: false - schema: - type: string - - name: limit - in: query - description: the maximum number of results to return - example: "10000" - required: false - schema: - type: integer - format: UInt32 - - name: offset - in: query - description: deprecated, the starting offset of the result set. Used to implement - pagination - required: false - schema: - type: integer - format: UInt32 - - name: ref - in: query - description: a token for accessing the next page of results, provided in the - `Link` header - required: false + - name: system_id + in: path + description: either a system id or a unique permalink + example: sys-12345 + required: true schema: type: string - nullable: true responses: 200: description: OK - content: - application/json: - schema: - type: array - items: - $ref: '#/components/schemas/PlaceOS__Model__Zone' 409: description: Conflict content: @@ -14105,25 +14077,19 @@ paths: application/json: schema: $ref: '#/components/schemas/PlaceOS__Api__Application__ContentError' + /api/engine/v2/webrtc/guest/exit: post: - summary: add a new zone + summary: Guest users should call this route when ending a call gracefully + description: 'Guest users should call this route when ending a call gracefully + + it will remove the authentication token and close any open websockets' tags: - - Zones - operationId: PlaceOS::Api::Zones#create - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/PlaceOS__Model__Zone' - required: true + - WebRTC + operationId: PlaceOS::Api::WebRTC#guest_exit parameters: [] responses: - 201: - description: Created - content: - application/json: - schema: - $ref: '#/components/schemas/PlaceOS__Model__Zone' + 200: + description: OK 409: description: Conflict content: @@ -14174,32 +14140,37 @@ paths: application/json: schema: $ref: '#/components/schemas/PlaceOS__Api__Application__ContentError' - /api/engine/v2/zones/{id}: - get: - summary: return the details of the zone + /api/engine/v2/webrtc/kick/{user_id}/{session_id}: + post: + summary: Call ended for the user + description: 'Call ended for the user + + similar to guest exit without the token expiration + + other members of the call will stop communicating with them' tags: - - Zones - operationId: PlaceOS::Api::Zones#show + - WebRTC + operationId: PlaceOS::Api::WebRTC#kick_user + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/PlaceOS__Api__KickReason' + required: true parameters: - - name: id + - name: user_id in: path required: true schema: type: string - - name: complete - in: query - description: also return any triggers associated with the zone - example: "true" - required: false + - name: session_id + in: path + required: true schema: - type: boolean + type: string responses: 200: description: OK - content: - application/json: - schema: - $ref: '#/components/schemas/PlaceOS__Model__Zone' 409: description: Conflict content: @@ -14250,19 +14221,14 @@ paths: application/json: schema: $ref: '#/components/schemas/PlaceOS__Api__Application__ContentError' - put: - summary: update the details of a zone + /api/engine/v2/webrtc/members/{session_id}: + get: + summary: Obtain a list of the connected users in chat session provided tags: - - Zones - operationId: PlaceOS::Api::Zones#update - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/PlaceOS__Model__Zone' - required: true + - WebRTC + operationId: PlaceOS::Api::WebRTC#members parameters: - - name: id + - name: session_id in: path required: true schema: @@ -14273,7 +14239,9 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/PlaceOS__Model__Zone' + type: array + items: + $ref: '#/components/schemas/String' 409: description: Conflict content: @@ -14324,20 +14292,42 @@ paths: application/json: schema: $ref: '#/components/schemas/PlaceOS__Api__Application__ContentError' - delete: - summary: remove a zone and any children zones + /api/engine/v2/webrtc/transfer/{user_id}/{session_id}: + post: + summary: for authorised users to move people from one chat to another + description: 'for authorised users to move people from one chat to another + + the body can be used to pass any custom connection details' tags: - - Zones - operationId: PlaceOS::Api::Zones#destroy + - WebRTC + operationId: PlaceOS::Api::WebRTC#transfer_guest + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/_JSON__Any___Nil_' + required: true parameters: - - name: id + - name: user_id in: path required: true schema: type: string + - name: session_id + in: path + required: false + schema: + type: string + nullable: true responses: - 202: - description: Accepted + 200: + description: OK + 428: + description: Precondition Required + content: + application/json: + schema: + $ref: '#/components/schemas/Bool' 409: description: Conflict content: @@ -14388,20 +14378,20 @@ paths: application/json: schema: $ref: '#/components/schemas/PlaceOS__Api__Application__ContentError' - patch: - summary: update the details of a zone + /api/engine/v2/webrtc/room/{system_id}: + get: + summary: this route provides the details of a public chat room + description: 'this route provides the details of a public chat room + + it takes either the system `id` or `code` for a more friendly lookup' tags: - - Zones - operationId: PlaceOS::Api::Zones#update{2} - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/PlaceOS__Model__Zone' - required: true + - WebRTC + operationId: PlaceOS::Api::WebRTC#public_room parameters: - - name: id + - name: system_id in: path + description: either a system id or a unique permalink + example: sys-12345 required: true schema: type: string @@ -14411,7 +14401,7 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/PlaceOS__Model__Zone' + $ref: '#/components/schemas/PlaceOS__Api__WebRTC__RoomDetails' 409: description: Conflict content: @@ -14462,22 +14452,39 @@ paths: application/json: schema: $ref: '#/components/schemas/PlaceOS__Api__Application__ContentError' - /api/engine/v2/zones/{id}/metadata: + /api/engine/v2/webrtc/rooms: get: - summary: return metadata associcated with the selected zone + summary: this route provides a list of public chat rooms for the current domain tags: - - Zones - operationId: PlaceOS::Api::Zones#metadata + - WebRTC + operationId: PlaceOS::Api::WebRTC#index parameters: - - name: id - in: path - required: true + - name: q + in: query + description: returns results based on a [simple query string](https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-simple-query-string-query.html) + required: false schema: type: string - - name: name + - name: limit in: query - description: only return the metadata key we are interested in - example: workplace-config + description: the maximum number of results to return + example: "10000" + required: false + schema: + type: integer + format: UInt32 + - name: offset + in: query + description: deprecated, the starting offset of the result set. Used to implement + pagination + required: false + schema: + type: integer + format: UInt32 + - name: ref + in: query + description: a token for accessing the next page of results, provided in the + `Link` header required: false schema: type: string @@ -14488,7 +14495,9 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/Hash_String__PlaceOS__Model__Metadata__Interface_' + type: array + items: + $ref: '#/components/schemas/PlaceOS__Api__WebRTC__RoomDetails' 409: description: Conflict content: @@ -14539,27 +14548,16 @@ paths: application/json: schema: $ref: '#/components/schemas/PlaceOS__Api__Application__ContentError' - /api/engine/v2/zones/{id}/triggers: + /api/engine/v2/webrtc/signaller: get: - summary: Return triggers attached to current zone + summary: WebRTC signaller websocket endpoint, managing call participants tags: - - Zones - operationId: PlaceOS::Api::Zones#trigger_instances - parameters: - - name: id - in: path - required: true - schema: - type: string + - WebRTC + operationId: PlaceOS::Api::WebRTC#signaller + parameters: [] responses: - 200: - description: OK - content: - application/json: - schema: - type: array - items: - $ref: '#/components/schemas/PlaceOS__Model__Trigger' + 101: + description: Switching Protocols 409: description: Conflict content: @@ -14610,46 +14608,215 @@ paths: application/json: schema: $ref: '#/components/schemas/PlaceOS__Api__Application__ContentError' - /api/engine/v2/zones/{id}/exec/{module_slug}/{method}: - post: - summary: Execute a method on a module across all systems in a Zone + /api/engine/v2/zones: + get: + summary: list the configured zones tags: - Zones - operationId: PlaceOS::Api::Zones#zone_execute - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/Array_JSON__Any_' - required: true + operationId: PlaceOS::Api::Zones#index parameters: - - name: id - in: path - required: true + - name: parent_id + in: query + description: only return zones who have this zone as a parent + example: zone-1234 + required: false schema: type: string - - name: module_slug - in: path - description: the combined module class and index, index is optional and defaults - to 1 - example: Display_2 - required: true + nullable: true + - name: tags + in: query + description: return zones with particular tags + example: building,level + required: false + schema: + type: array + items: + type: string + nullable: true + - name: q + in: query + description: returns results based on a [simple query string](https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-simple-query-string-query.html) + required: false schema: type: string - - name: method + - name: limit + in: query + description: the maximum number of results to return + example: "10000" + required: false + schema: + type: integer + format: UInt32 + - name: offset + in: query + description: deprecated, the starting offset of the result set. Used to implement + pagination + required: false + schema: + type: integer + format: UInt32 + - name: ref + in: query + description: a token for accessing the next page of results, provided in the + `Link` header + required: false + schema: + type: string + nullable: true + responses: + 200: + description: OK + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/PlaceOS__Model__Zone' + 409: + description: Conflict + content: + application/json: + schema: + $ref: '#/components/schemas/PlaceOS__Api__Application__CommonError' + 401: + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/PlaceOS__Api__Application__CommonError' + 403: + description: Forbidden + 404: + description: Not Found + content: + application/json: + schema: + $ref: '#/components/schemas/PlaceOS__Api__Application__CommonError' + 408: + description: Request Timeout + content: + application/json: + schema: + $ref: '#/components/schemas/PlaceOS__Api__Application__CommonError' + 400: + description: Bad Request + content: + application/json: + schema: + $ref: '#/components/schemas/PlaceOS__Api__Application__ParameterError' + 422: + description: Unprocessable Entity + content: + application/json: + schema: + $ref: '#/components/schemas/PlaceOS__Api__Application__ParameterError' + 406: + description: Not Acceptable + content: + application/json: + schema: + $ref: '#/components/schemas/PlaceOS__Api__Application__ContentError' + 415: + description: Unsupported Media Type + content: + application/json: + schema: + $ref: '#/components/schemas/PlaceOS__Api__Application__ContentError' + post: + summary: add a new zone + tags: + - Zones + operationId: PlaceOS::Api::Zones#create + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/PlaceOS__Model__Zone' + required: true + parameters: [] + responses: + 201: + description: Created + content: + application/json: + schema: + $ref: '#/components/schemas/PlaceOS__Model__Zone' + 409: + description: Conflict + content: + application/json: + schema: + $ref: '#/components/schemas/PlaceOS__Api__Application__CommonError' + 401: + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/PlaceOS__Api__Application__CommonError' + 403: + description: Forbidden + 404: + description: Not Found + content: + application/json: + schema: + $ref: '#/components/schemas/PlaceOS__Api__Application__CommonError' + 408: + description: Request Timeout + content: + application/json: + schema: + $ref: '#/components/schemas/PlaceOS__Api__Application__CommonError' + 400: + description: Bad Request + content: + application/json: + schema: + $ref: '#/components/schemas/PlaceOS__Api__Application__ParameterError' + 422: + description: Unprocessable Entity + content: + application/json: + schema: + $ref: '#/components/schemas/PlaceOS__Api__Application__ParameterError' + 406: + description: Not Acceptable + content: + application/json: + schema: + $ref: '#/components/schemas/PlaceOS__Api__Application__ContentError' + 415: + description: Unsupported Media Type + content: + application/json: + schema: + $ref: '#/components/schemas/PlaceOS__Api__Application__ContentError' + /api/engine/v2/zones/{id}: + get: + summary: return the details of the zone + tags: + - Zones + operationId: PlaceOS::Api::Zones#show + parameters: + - name: id in: path - description: the method to execute on the module - example: power required: true schema: type: string + - name: complete + in: query + description: also return any triggers associated with the zone + example: "true" + required: false + schema: + type: boolean responses: 200: description: OK content: application/json: schema: - $ref: '#/components/schemas/PlaceOS__Api__Zones__ZoneExecResponse' + $ref: '#/components/schemas/PlaceOS__Model__Zone' 409: description: Conflict content: @@ -14700,621 +14867,662 @@ paths: application/json: schema: $ref: '#/components/schemas/PlaceOS__Api__Application__ContentError' -components: - schemas: - PlaceOS__Model__ApiKey__PublicResponse: - type: object - properties: - created_at: - type: string - format: date-time - updated_at: - type: string - format: date-time - name: - type: string - description: - type: string - scopes: - type: array - items: - type: object - user_id: - type: string - nullable: true - authority_id: + put: + summary: update the details of a zone + tags: + - Zones + operationId: PlaceOS::Api::Zones#update + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/PlaceOS__Model__Zone' + required: true + parameters: + - name: id + in: path + required: true + schema: type: string - nullable: true - user: - type: object - properties: - id: - type: string - nullable: true - created_at: - type: string - format: date-time - nullable: true - updated_at: - type: string - format: date-time - nullable: true - name: - type: string - nullable: true - nickname: - type: string - nullable: true - email: - type: string - format: email - nullable: true - phone: - type: string - nullable: true - country: - type: string - nullable: true - image: - type: string - nullable: true - ui_theme: - type: string - nullable: true - misc: - type: string - nullable: true - login_name: - type: string - nullable: true - staff_id: - type: string - nullable: true - first_name: - type: string - nullable: true - last_name: - type: string - nullable: true - building: - type: string - nullable: true - department: - type: string - nullable: true - preferred_language: - type: string - nullable: true - password_digest: - type: string - nullable: true - email_digest: - type: string - nullable: true - card_number: - type: string - nullable: true - deleted: - type: boolean - nullable: true - groups: - type: array - items: - type: string - nullable: true - access_token: - type: string - nullable: true - refresh_token: - type: string - nullable: true - expires_at: - type: integer - format: Int64 - nullable: true - expires: - type: boolean - nullable: true - password: - type: string - nullable: true - sys_admin: - type: boolean - nullable: true - support: - type: boolean - nullable: true - authority_id: - type: string - nullable: true - admin_destroy_lock: - type: object - properties: - id: - type: string - nullable: true - key: - type: string - nullable: true - instance_token: - type: string - nullable: true - expires_at: - type: string - format: date-time - nullable: true - nullable: true - nullable: true - authority: - type: object - properties: - id: - type: string - nullable: true - created_at: - type: string - format: date-time - nullable: true - updated_at: - type: string - format: date-time - nullable: true - name: - type: string - nullable: true - description: - type: string - nullable: true - domain: - type: string - nullable: true - login_url: - type: string - nullable: true - logout_url: - type: string - nullable: true - internals: - type: object - additionalProperties: - type: object - nullable: true - config: - type: object - additionalProperties: - type: object - nullable: true - nullable: true - x_api_key: - type: string - nullable: true - permissions: - type: string - enum: - - user - - support - - admin - - admin_support - nullable: true - id: - type: string - nullable: true - required: - - created_at - - updated_at - - name - - description - - scopes - PlaceOS__Model__ApiKey: - type: object - properties: - id: - type: string - nullable: true - created_at: - type: string - format: date-time - nullable: true - updated_at: - type: string - format: date-time - nullable: true - name: - type: string - nullable: true - description: - type: string - nullable: true - scopes: - type: array - items: - type: object - nullable: true - permissions: - type: string - enum: - - user - - support - - admin - - admin_support - nullable: true - secret: + responses: + 200: + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/PlaceOS__Model__Zone' + 409: + description: Conflict + content: + application/json: + schema: + $ref: '#/components/schemas/PlaceOS__Api__Application__CommonError' + 401: + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/PlaceOS__Api__Application__CommonError' + 403: + description: Forbidden + 404: + description: Not Found + content: + application/json: + schema: + $ref: '#/components/schemas/PlaceOS__Api__Application__CommonError' + 408: + description: Request Timeout + content: + application/json: + schema: + $ref: '#/components/schemas/PlaceOS__Api__Application__CommonError' + 400: + description: Bad Request + content: + application/json: + schema: + $ref: '#/components/schemas/PlaceOS__Api__Application__ParameterError' + 422: + description: Unprocessable Entity + content: + application/json: + schema: + $ref: '#/components/schemas/PlaceOS__Api__Application__ParameterError' + 406: + description: Not Acceptable + content: + application/json: + schema: + $ref: '#/components/schemas/PlaceOS__Api__Application__ContentError' + 415: + description: Unsupported Media Type + content: + application/json: + schema: + $ref: '#/components/schemas/PlaceOS__Api__Application__ContentError' + delete: + summary: remove a zone and any children zones + tags: + - Zones + operationId: PlaceOS::Api::Zones#destroy + parameters: + - name: id + in: path + required: true + schema: type: string - nullable: true - user_id: - type: string - nullable: true - authority_id: - type: string - nullable: true - PlaceOS__Model__UserJWT: - type: object - properties: - iss: - type: string - iat: - type: string - format: date-time - exp: - type: string - format: date-time - aud: - type: string - sub: - type: string - scope: - type: array - items: - type: object - u: - type: object - properties: - n: - type: string - e: - type: string - p: - enum: - - 0 - - 1 - - 2 - - 3 - r: - type: array - items: - type: string - required: - - n - - e - - p - - r - required: - - iss - - iat - - exp - - aud - - sub - - scope - - u - PlaceOS__Model__AssetInstance: - type: object - properties: - id: - type: string - nullable: true - created_at: - type: string - format: date-time - nullable: true - updated_at: - type: string - format: date-time - nullable: true - name: - type: string - nullable: true - tracking: - type: string - enum: - - in_storage - - on_the_way - - in_room - - returned - nullable: true - approval: - type: boolean - nullable: true - asset_id: - type: string - nullable: true - requester_id: - type: string - nullable: true - zone_id: - type: string - nullable: true - usage_start: - type: string - format: date-time - nullable: true - usage_end: - type: string - format: date-time - nullable: true - PlaceOS__Model__Asset: - type: object - properties: - id: - type: string - nullable: true - created_at: + responses: + 202: + description: Accepted + 409: + description: Conflict + content: + application/json: + schema: + $ref: '#/components/schemas/PlaceOS__Api__Application__CommonError' + 401: + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/PlaceOS__Api__Application__CommonError' + 403: + description: Forbidden + 404: + description: Not Found + content: + application/json: + schema: + $ref: '#/components/schemas/PlaceOS__Api__Application__CommonError' + 408: + description: Request Timeout + content: + application/json: + schema: + $ref: '#/components/schemas/PlaceOS__Api__Application__CommonError' + 400: + description: Bad Request + content: + application/json: + schema: + $ref: '#/components/schemas/PlaceOS__Api__Application__ParameterError' + 422: + description: Unprocessable Entity + content: + application/json: + schema: + $ref: '#/components/schemas/PlaceOS__Api__Application__ParameterError' + 406: + description: Not Acceptable + content: + application/json: + schema: + $ref: '#/components/schemas/PlaceOS__Api__Application__ContentError' + 415: + description: Unsupported Media Type + content: + application/json: + schema: + $ref: '#/components/schemas/PlaceOS__Api__Application__ContentError' + patch: + summary: update the details of a zone + tags: + - Zones + operationId: PlaceOS::Api::Zones#update{2} + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/PlaceOS__Model__Zone' + required: true + parameters: + - name: id + in: path + required: true + schema: type: string - format: date-time - nullable: true - updated_at: + responses: + 200: + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/PlaceOS__Model__Zone' + 409: + description: Conflict + content: + application/json: + schema: + $ref: '#/components/schemas/PlaceOS__Api__Application__CommonError' + 401: + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/PlaceOS__Api__Application__CommonError' + 403: + description: Forbidden + 404: + description: Not Found + content: + application/json: + schema: + $ref: '#/components/schemas/PlaceOS__Api__Application__CommonError' + 408: + description: Request Timeout + content: + application/json: + schema: + $ref: '#/components/schemas/PlaceOS__Api__Application__CommonError' + 400: + description: Bad Request + content: + application/json: + schema: + $ref: '#/components/schemas/PlaceOS__Api__Application__ParameterError' + 422: + description: Unprocessable Entity + content: + application/json: + schema: + $ref: '#/components/schemas/PlaceOS__Api__Application__ParameterError' + 406: + description: Not Acceptable + content: + application/json: + schema: + $ref: '#/components/schemas/PlaceOS__Api__Application__ContentError' + 415: + description: Unsupported Media Type + content: + application/json: + schema: + $ref: '#/components/schemas/PlaceOS__Api__Application__ContentError' + /api/engine/v2/zones/{id}/metadata: + get: + summary: return metadata associcated with the selected zone + tags: + - Zones + operationId: PlaceOS::Api::Zones#metadata + parameters: + - name: id + in: path + required: true + schema: type: string - format: date-time - nullable: true - name: + - name: name + in: query + description: only return the metadata key we are interested in + example: workplace-config + required: false + schema: type: string nullable: true - category: + responses: + 200: + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/Hash_String__PlaceOS__Model__Metadata__Interface_' + 409: + description: Conflict + content: + application/json: + schema: + $ref: '#/components/schemas/PlaceOS__Api__Application__CommonError' + 401: + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/PlaceOS__Api__Application__CommonError' + 403: + description: Forbidden + 404: + description: Not Found + content: + application/json: + schema: + $ref: '#/components/schemas/PlaceOS__Api__Application__CommonError' + 408: + description: Request Timeout + content: + application/json: + schema: + $ref: '#/components/schemas/PlaceOS__Api__Application__CommonError' + 400: + description: Bad Request + content: + application/json: + schema: + $ref: '#/components/schemas/PlaceOS__Api__Application__ParameterError' + 422: + description: Unprocessable Entity + content: + application/json: + schema: + $ref: '#/components/schemas/PlaceOS__Api__Application__ParameterError' + 406: + description: Not Acceptable + content: + application/json: + schema: + $ref: '#/components/schemas/PlaceOS__Api__Application__ContentError' + 415: + description: Unsupported Media Type + content: + application/json: + schema: + $ref: '#/components/schemas/PlaceOS__Api__Application__ContentError' + /api/engine/v2/zones/{id}/triggers: + get: + summary: Return triggers attached to current zone + tags: + - Zones + operationId: PlaceOS::Api::Zones#trigger_instances + parameters: + - name: id + in: path + required: true + schema: type: string - nullable: true - description: + responses: + 200: + description: OK + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/PlaceOS__Model__Trigger' + 409: + description: Conflict + content: + application/json: + schema: + $ref: '#/components/schemas/PlaceOS__Api__Application__CommonError' + 401: + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/PlaceOS__Api__Application__CommonError' + 403: + description: Forbidden + 404: + description: Not Found + content: + application/json: + schema: + $ref: '#/components/schemas/PlaceOS__Api__Application__CommonError' + 408: + description: Request Timeout + content: + application/json: + schema: + $ref: '#/components/schemas/PlaceOS__Api__Application__CommonError' + 400: + description: Bad Request + content: + application/json: + schema: + $ref: '#/components/schemas/PlaceOS__Api__Application__ParameterError' + 422: + description: Unprocessable Entity + content: + application/json: + schema: + $ref: '#/components/schemas/PlaceOS__Api__Application__ParameterError' + 406: + description: Not Acceptable + content: + application/json: + schema: + $ref: '#/components/schemas/PlaceOS__Api__Application__ContentError' + 415: + description: Unsupported Media Type + content: + application/json: + schema: + $ref: '#/components/schemas/PlaceOS__Api__Application__ContentError' + /api/engine/v2/zones/{id}/exec/{module_slug}/{method}: + post: + summary: Execute a method on a module across all systems in a Zone + tags: + - Zones + operationId: PlaceOS::Api::Zones#zone_execute + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/Array_JSON__Any_' + required: true + parameters: + - name: id + in: path + required: true + schema: type: string - nullable: true - purchase_date: + - name: module_slug + in: path + description: the combined module class and index, index is optional and defaults + to 1 + example: Display_2 + required: true + schema: + type: string + - name: method + in: path + description: the method to execute on the module + example: power + required: true + schema: + type: string + responses: + 200: + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/PlaceOS__Api__Zones__ZoneExecResponse' + 409: + description: Conflict + content: + application/json: + schema: + $ref: '#/components/schemas/PlaceOS__Api__Application__CommonError' + 401: + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/PlaceOS__Api__Application__CommonError' + 403: + description: Forbidden + 404: + description: Not Found + content: + application/json: + schema: + $ref: '#/components/schemas/PlaceOS__Api__Application__CommonError' + 408: + description: Request Timeout + content: + application/json: + schema: + $ref: '#/components/schemas/PlaceOS__Api__Application__CommonError' + 400: + description: Bad Request + content: + application/json: + schema: + $ref: '#/components/schemas/PlaceOS__Api__Application__ParameterError' + 422: + description: Unprocessable Entity + content: + application/json: + schema: + $ref: '#/components/schemas/PlaceOS__Api__Application__ParameterError' + 406: + description: Not Acceptable + content: + application/json: + schema: + $ref: '#/components/schemas/PlaceOS__Api__Application__ContentError' + 415: + description: Unsupported Media Type + content: + application/json: + schema: + $ref: '#/components/schemas/PlaceOS__Api__Application__ContentError' +components: + schemas: + PlaceOS__Model__ApiKey__PublicResponse: + type: object + properties: + created_at: type: string format: date-time - nullable: true - good_until_date: + updated_at: type: string format: date-time - nullable: true - identifier: + name: type: string - nullable: true - brand: + description: type: string - nullable: true - purchase_price: - type: integer - format: Int32 - nullable: true - images: + scopes: type: array items: - type: string - nullable: true - invoice: + type: object + user_id: type: string nullable: true - quantity: - type: integer - format: Int32 - nullable: true - in_use: - type: integer - format: Int32 + authority_id: + type: string nullable: true - other_data: + user: type: object - nullable: true - parent_id: - type: string - nullable: true - asset_instances: - type: array - items: - type: object - properties: - id: - type: string - nullable: true - created_at: - type: string - format: date-time - nullable: true - updated_at: - type: string - format: date-time - nullable: true - name: - type: string - nullable: true - tracking: - type: string - enum: - - in_storage - - on_the_way - - in_room - - returned - nullable: true - approval: - type: boolean - nullable: true - asset_id: - type: string - nullable: true - requester_id: - type: string - nullable: true - zone_id: - type: string - nullable: true - usage_start: - type: string - format: date-time - nullable: true - usage_end: + properties: + id: + type: string + nullable: true + created_at: + type: string + format: date-time + nullable: true + updated_at: + type: string + format: date-time + nullable: true + name: + type: string + nullable: true + nickname: + type: string + nullable: true + email: + type: string + format: email + nullable: true + phone: + type: string + nullable: true + country: + type: string + nullable: true + image: + type: string + nullable: true + ui_theme: + type: string + nullable: true + misc: + type: string + nullable: true + login_name: + type: string + nullable: true + staff_id: + type: string + nullable: true + first_name: + type: string + nullable: true + last_name: + type: string + nullable: true + building: + type: string + nullable: true + department: + type: string + nullable: true + preferred_language: + type: string + nullable: true + password_digest: + type: string + nullable: true + email_digest: + type: string + nullable: true + card_number: + type: string + nullable: true + deleted: + type: boolean + nullable: true + groups: + type: array + items: type: string - format: date-time - nullable: true - nullable: true - _Hash_String__Array_PlaceOS__Model__AssetInstance____JSON__Any____PlaceOS__Model__Asset_: - anyOf: - - type: object - additionalProperties: - anyOf: - - type: array - items: + nullable: true + access_token: + type: string + nullable: true + refresh_token: + type: string + nullable: true + expires_at: + type: integer + format: Int64 + nullable: true + expires: + type: boolean + nullable: true + password: + type: string + nullable: true + sys_admin: + type: boolean + nullable: true + support: + type: boolean + nullable: true + authority_id: + type: string + nullable: true + admin_destroy_lock: type: object properties: id: type: string nullable: true - created_at: - type: string - format: date-time - nullable: true - updated_at: - type: string - format: date-time - nullable: true - name: - type: string - nullable: true - tracking: - type: string - enum: - - in_storage - - on_the_way - - in_room - - returned - nullable: true - approval: - type: boolean - nullable: true - asset_id: - type: string - nullable: true - requester_id: - type: string - nullable: true - zone_id: + key: type: string nullable: true - usage_start: + instance_token: type: string - format: date-time nullable: true - usage_end: + expires_at: type: string format: date-time nullable: true - - type: object - - type: object - properties: - id: - type: string - nullable: true - created_at: - type: string - format: date-time - nullable: true - updated_at: - type: string - format: date-time - nullable: true - name: - type: string - nullable: true - category: - type: string - nullable: true - description: - type: string - nullable: true - purchase_date: - type: string - format: date-time - nullable: true - good_until_date: - type: string - format: date-time - nullable: true - identifier: - type: string - nullable: true - brand: - type: string - nullable: true - purchase_price: - type: integer - format: Int32 - nullable: true - images: - type: array - items: + nullable: true + nullable: true + authority: + type: object + properties: + id: type: string - nullable: true - invoice: - type: string - nullable: true - quantity: - type: integer - format: Int32 - nullable: true - in_use: - type: integer - format: Int32 - nullable: true - other_data: - type: object - nullable: true - parent_id: - type: string - nullable: true - asset_instances: - type: array - items: + nullable: true + created_at: + type: string + format: date-time + nullable: true + updated_at: + type: string + format: date-time + nullable: true + name: + type: string + nullable: true + description: + type: string + nullable: true + domain: + type: string + nullable: true + login_url: + type: string + nullable: true + logout_url: + type: string + nullable: true + internals: type: object - properties: - id: - type: string - nullable: true - created_at: - type: string - format: date-time - nullable: true - updated_at: - type: string - format: date-time - nullable: true - name: - type: string - nullable: true - tracking: - type: string - enum: - - in_storage - - on_the_way - - in_room - - returned - nullable: true - approval: - type: boolean - nullable: true - asset_id: - type: string - nullable: true - requester_id: - type: string - nullable: true - zone_id: - type: string - nullable: true - usage_start: - type: string - format: date-time - nullable: true - usage_end: - type: string - format: date-time - nullable: true - nullable: true - PlaceOS__Model__LdapAuthentication: + additionalProperties: + type: object + nullable: true + config: + type: object + additionalProperties: + type: object + nullable: true + nullable: true + x_api_key: + type: string + nullable: true + permissions: + type: string + enum: + - user + - support + - admin + - admin_support + nullable: true + id: + type: string + nullable: true + required: + - created_at + - updated_at + - name + - description + - scopes + PlaceOS__Model__ApiKey: type: object properties: id: @@ -15331,113 +15539,126 @@ components: name: type: string nullable: true - port: - type: integer - format: Int32 - nullable: true - auth_method: - type: string - nullable: true - uid: - type: string - nullable: true - host: + description: type: string nullable: true - base: - type: string + scopes: + type: array + items: + type: object nullable: true - bind_dn: + permissions: type: string + enum: + - user + - support + - admin + - admin_support nullable: true - password: + secret: type: string nullable: true - filter: + user_id: type: string nullable: true authority_id: type: string nullable: true - PlaceOS__Model__SamlAuthentication: + PlaceOS__Model__UserJWT: type: object properties: - id: + iss: type: string - nullable: true - created_at: + iat: type: string format: date-time - nullable: true - updated_at: + exp: type: string format: date-time - nullable: true - name: + aud: type: string - nullable: true - issuer: + sub: type: string - nullable: true - idp_sso_target_url_runtime_params: + scope: + type: array + items: + type: object + u: type: object - additionalProperties: - type: string - nullable: true - name_identifier_format: + properties: + n: + type: string + e: + type: string + p: + enum: + - 0 + - 1 + - 2 + - 3 + r: + type: array + items: + type: string + required: + - n + - e + - p + - r + required: + - iss + - iat + - exp + - aud + - sub + - scope + - u + PlaceOS__Model__AssetInstance: + type: object + properties: + id: type: string nullable: true - uid_attribute: + created_at: type: string + format: date-time nullable: true - assertion_consumer_service_url: + updated_at: type: string + format: date-time nullable: true - idp_sso_target_url: + name: type: string nullable: true - idp_cert: + tracking: type: string + enum: + - in_storage + - on_the_way + - in_room + - returned nullable: true - idp_cert_fingerprint: - type: string + approval: + type: boolean nullable: true - attribute_service_name: + asset_id: type: string nullable: true - attribute_statements: - type: object - additionalProperties: - type: array - items: - type: string - nullable: true - request_attributes: - type: array - items: - type: object - properties: - name: - type: string - name_format: - type: string - friendly_name: - type: string - required: - - name - - name_format - - friendly_name + requester_id: + type: string nullable: true - idp_slo_target_url: + zone_id: type: string nullable: true - slo_default_relay_state: + usage_start: type: string + format: date-time nullable: true - authority_id: + usage_end: type: string + format: date-time nullable: true - PlaceOS__Model__OAuthAuthentication: + PlaceOS__Model__Asset: type: object properties: id: @@ -15454,364 +15675,263 @@ components: name: type: string nullable: true - client_id: + category: type: string nullable: true - client_secret: - type: string - nullable: true - info_mappings: - type: object - additionalProperties: - type: string - nullable: true - authorize_params: - type: object - additionalProperties: - type: string - nullable: true - ensure_matching: - type: object - additionalProperties: - type: array - items: - type: string - nullable: true - site: - type: string - nullable: true - authorize_url: - type: string - nullable: true - token_method: - type: string - nullable: true - auth_scheme: - type: string - nullable: true - token_url: - type: string - nullable: true - scope: - type: string - nullable: true - raw_info_url: - type: string - nullable: true - authority_id: - type: string - nullable: true - PlaceOS__Model__Broker: - type: object - properties: - id: + description: type: string nullable: true - created_at: + purchase_date: type: string format: date-time nullable: true - updated_at: + good_until_date: type: string format: date-time nullable: true - auth_type: - type: string - enum: - - certificate - - no_auth - - user_password - nullable: true - name: - type: string - nullable: true - description: + identifier: type: string nullable: true - host: + brand: type: string nullable: true - port: + purchase_price: type: integer format: Int32 nullable: true - tls: - type: boolean + images: + type: array + items: + type: string nullable: true - username: + invoice: type: string nullable: true - password: - type: string + quantity: + type: integer + format: Int32 nullable: true - certificate: - type: string + in_use: + type: integer + format: Int32 nullable: true - secret: + other_data: + type: object + nullable: true + parent_id: type: string nullable: true - filters: + asset_instances: type: array items: - type: string + type: object + properties: + id: + type: string + nullable: true + created_at: + type: string + format: date-time + nullable: true + updated_at: + type: string + format: date-time + nullable: true + name: + type: string + nullable: true + tracking: + type: string + enum: + - in_storage + - on_the_way + - in_room + - returned + nullable: true + approval: + type: boolean + nullable: true + asset_id: + type: string + nullable: true + requester_id: + type: string + nullable: true + zone_id: + type: string + nullable: true + usage_start: + type: string + format: date-time + nullable: true + usage_end: + type: string + format: date-time + nullable: true nullable: true - PlaceOS__Api__Cluster__NodeStatus: - type: object - properties: - id: - type: string - uri: - type: object - load: - type: object - properties: - local: + _Hash_String__Array_PlaceOS__Model__AssetInstance____JSON__Any____PlaceOS__Model__Asset_: + anyOf: + - type: object + additionalProperties: + anyOf: + - type: array + items: type: object properties: - hostname: + id: type: string - cpu_count: - type: integer - format: Int32 - core_cpu: - type: number - format: Float64 - total_cpu: - type: number - format: Float64 - memory_total: - type: integer - format: Int64 - memory_usage: - type: integer - format: Int64 - core_memory: - type: integer - format: Int64 - required: - - hostname - - cpu_count - - core_cpu - - total_cpu - - memory_total - - memory_usage - - core_memory - edge: - type: object - additionalProperties: - type: object - properties: - hostname: - type: string - cpu_count: - type: integer - format: Int32 - core_cpu: - type: number - format: Float64 - total_cpu: - type: number - format: Float64 - memory_total: - type: integer - format: Int64 - memory_usage: - type: integer - format: Int64 - core_memory: - type: integer - format: Int64 - required: - - hostname - - cpu_count - - core_cpu - - total_cpu - - memory_total - - memory_usage - - core_memory - required: - - local - - edge - nullable: true - status: - type: object - properties: - available_repositories: - type: array - items: - type: string - unavailable_repositories: - type: array - items: - type: object - properties: - name: - type: string - reason: - type: string - required: - - name - - reason - compiled_drivers: - type: array - items: - type: string - unavailable_drivers: - type: array - items: - type: object - properties: - name: - type: string - reason: - type: string - required: - - name - - reason - run_count: - type: object - properties: - local: - type: object - properties: - modules: - type: integer - format: Int32 - drivers: - type: integer - format: Int32 - required: - - modules - - drivers - edge: - type: object - additionalProperties: - type: object - properties: - modules: - type: integer - format: Int32 - drivers: - type: integer - format: Int32 - required: - - modules - - drivers - required: - - local - - edge - required: - - available_repositories - - unavailable_repositories - - compiled_drivers - - unavailable_drivers - - run_count - nullable: true - required: - - id - - uri - PlaceOS__Api__Cluster__DriverStatus: - type: object - properties: - driver: - type: string - local: - type: object - properties: - modules: - type: array - items: - type: string - status: + nullable: true + created_at: + type: string + format: date-time + nullable: true + updated_at: + type: string + format: date-time + nullable: true + name: + type: string + nullable: true + tracking: + type: string + enum: + - in_storage + - on_the_way + - in_room + - returned + nullable: true + approval: + type: boolean + nullable: true + asset_id: + type: string + nullable: true + requester_id: + type: string + nullable: true + zone_id: + type: string + nullable: true + usage_start: + type: string + format: date-time + nullable: true + usage_end: + type: string + format: date-time + nullable: true + - type: object + - type: object + properties: + id: + type: string + nullable: true + created_at: + type: string + format: date-time + nullable: true + updated_at: + type: string + format: date-time + nullable: true + name: + type: string + nullable: true + category: + type: string + nullable: true + description: + type: string + nullable: true + purchase_date: + type: string + format: date-time + nullable: true + good_until_date: + type: string + format: date-time + nullable: true + identifier: + type: string + nullable: true + brand: + type: string + nullable: true + purchase_price: + type: integer + format: Int32 + nullable: true + images: + type: array + items: + type: string + nullable: true + invoice: + type: string + nullable: true + quantity: + type: integer + format: Int32 + nullable: true + in_use: + type: integer + format: Int32 + nullable: true + other_data: + type: object + nullable: true + parent_id: + type: string + nullable: true + asset_instances: + type: array + items: type: object properties: - running: + id: + type: string + nullable: true + created_at: + type: string + format: date-time + nullable: true + updated_at: + type: string + format: date-time + nullable: true + name: + type: string + nullable: true + tracking: + type: string + enum: + - in_storage + - on_the_way + - in_room + - returned + nullable: true + approval: type: boolean - module_instances: - type: integer - format: Int32 - last_exit_code: - type: integer - format: Int32 - launch_count: - type: integer - format: Int32 - launch_time: - type: integer - format: Int64 - percentage_cpu: - type: number - format: Float64 nullable: true - memory_total: - type: integer - format: Int64 + asset_id: + type: string nullable: true - memory_usage: - type: integer - format: Int64 + requester_id: + type: string nullable: true - required: - - running - - module_instances - - last_exit_code - - launch_count - - launch_time - nullable: true - required: - - modules - edge: - type: object - additionalProperties: - type: object - properties: - modules: - type: array - items: + zone_id: type: string - status: - type: object - properties: - running: - type: boolean - module_instances: - type: integer - format: Int32 - last_exit_code: - type: integer - format: Int32 - launch_count: - type: integer - format: Int32 - launch_time: - type: integer - format: Int64 - percentage_cpu: - type: number - format: Float64 - nullable: true - memory_total: - type: integer - format: Int64 - nullable: true - memory_usage: - type: integer - format: Int64 - nullable: true - required: - - running - - module_instances - - last_exit_code - - launch_count - - launch_time - nullable: true - required: - - modules - required: - - driver - - local - - edge - PlaceOS__Model__Authority: + nullable: true + usage_start: + type: string + format: date-time + nullable: true + usage_end: + type: string + format: date-time + nullable: true + nullable: true + PlaceOS__Model__LdapAuthentication: type: object properties: id: @@ -15828,29 +15948,35 @@ components: name: type: string nullable: true - description: + port: + type: integer + format: Int32 + nullable: true + auth_method: type: string nullable: true - domain: + uid: type: string nullable: true - login_url: + host: type: string nullable: true - logout_url: + base: type: string nullable: true - internals: - type: object - additionalProperties: - type: object + bind_dn: + type: string nullable: true - config: - type: object - additionalProperties: - type: object + password: + type: string nullable: true - PlaceOS__Model__Driver: + filter: + type: string + nullable: true + authority_id: + type: string + nullable: true + PlaceOS__Model__SamlAuthentication: type: object properties: id: @@ -15867,59 +15993,68 @@ components: name: type: string nullable: true - description: + issuer: type: string nullable: true - json_schema: + idp_sso_target_url_runtime_params: type: object + additionalProperties: + type: string nullable: true - default_uri: + name_identifier_format: type: string nullable: true - default_port: - type: integer - format: Int32 - nullable: true - role: + uid_attribute: type: string - enum: - - ssh - - device - - service - - websocket - - logic nullable: true - file_name: + assertion_consumer_service_url: type: string nullable: true - commit: + idp_sso_target_url: type: string nullable: true - compilation_output: + idp_cert: type: string nullable: true - module_name: + idp_cert_fingerprint: type: string nullable: true - ignore_connected: - type: boolean - nullable: true - repository_id: + attribute_service_name: type: string nullable: true - compilation_status: + attribute_statements: type: object additionalProperties: - type: boolean + type: array + items: + type: string nullable: true - NamedTuple_compilation_output__String_: - type: object - properties: - compilation_output: + request_attributes: + type: array + items: + type: object + properties: + name: + type: string + name_format: + type: string + friendly_name: + type: string + required: + - name + - name_format + - friendly_name + nullable: true + idp_slo_target_url: type: string - required: - - compilation_output - PlaceOS__Model__Settings: + nullable: true + slo_default_relay_state: + type: string + nullable: true + authority_id: + type: string + nullable: true + PlaceOS__Model__OAuthAuthentication: type: object properties: id: @@ -15933,40 +16068,57 @@ components: type: string format: date-time nullable: true - modified_by_id: + name: type: string nullable: true - settings_id: + client_id: type: string nullable: true - encryption_level: + client_secret: type: string - enum: - - none - - support - - admin - - never_display nullable: true - settings_string: - type: string + info_mappings: + type: object + additionalProperties: + type: string nullable: true - keys: - type: array - items: + authorize_params: + type: object + additionalProperties: type: string nullable: true - parent_type: + ensure_matching: + type: object + additionalProperties: + type: array + items: + type: string + nullable: true + site: type: string - enum: - - control_system - - driver - - module - - zone nullable: true - parent_id: + authorize_url: type: string nullable: true - PlaceOS__Model__Module: + token_method: + type: string + nullable: true + auth_scheme: + type: string + nullable: true + token_url: + type: string + nullable: true + scope: + type: string + nullable: true + raw_info_url: + type: string + nullable: true + authority_id: + type: string + nullable: true + PlaceOS__Model__Broker: type: object properties: id: @@ -15980,425 +16132,342 @@ components: type: string format: date-time nullable: true - ip: - type: string - nullable: true - port: - type: integer - format: Int32 - nullable: true - tls: - type: boolean - nullable: true - udp: - type: boolean - nullable: true - makebreak: - type: boolean - nullable: true - uri: + auth_type: type: string + enum: + - certificate + - no_auth + - user_password nullable: true name: type: string nullable: true - custom_name: + description: type: string nullable: true - role: + host: type: string - enum: - - ssh - - device - - service - - websocket - - logic nullable: true - connected: - type: boolean + port: + type: integer + format: Int32 nullable: true - running: + tls: type: boolean nullable: true - notes: + username: type: string nullable: true - ignore_connected: - type: boolean - nullable: true - ignore_startstop: - type: boolean - nullable: true - control_system_id: + password: type: string nullable: true - driver_id: + certificate: type: string nullable: true - edge_id: + secret: type: string nullable: true - driver: + filters: + type: array + items: + type: string + nullable: true + PlaceOS__Api__Cluster__NodeStatus: + type: object + properties: + id: + type: string + uri: + type: object + load: type: object properties: - name: - type: string - description: - type: string - nullable: true - module_name: - type: string - nullable: true + local: + type: object + properties: + hostname: + type: string + cpu_count: + type: integer + format: Int32 + core_cpu: + type: number + format: Float64 + total_cpu: + type: number + format: Float64 + memory_total: + type: integer + format: Int64 + memory_usage: + type: integer + format: Int64 + core_memory: + type: integer + format: Int64 + required: + - hostname + - cpu_count + - core_cpu + - total_cpu + - memory_total + - memory_usage + - core_memory + edge: + type: object + additionalProperties: + type: object + properties: + hostname: + type: string + cpu_count: + type: integer + format: Int32 + core_cpu: + type: number + format: Float64 + total_cpu: + type: number + format: Float64 + memory_total: + type: integer + format: Int64 + memory_usage: + type: integer + format: Int64 + core_memory: + type: integer + format: Int64 + required: + - hostname + - cpu_count + - core_cpu + - total_cpu + - memory_total + - memory_usage + - core_memory required: - - name - nullable: true - compiled: - type: boolean + - local + - edge nullable: true - control_system: + status: type: object properties: - name: - type: string - zone_data: + available_repositories: + type: array + items: + type: string + unavailable_repositories: type: array items: type: object properties: - id: - type: string - nullable: true - created_at: - type: string - format: date-time - nullable: true - updated_at: - type: string - format: date-time - nullable: true name: type: string - nullable: true - description: - type: string - nullable: true - tags: - type: array - items: - type: string - nullable: true - location: - type: string - nullable: true - display_name: + reason: type: string - nullable: true - code: + required: + - name + - reason + compiled_drivers: + type: array + items: + type: string + unavailable_drivers: + type: array + items: + type: object + properties: + name: type: string - nullable: true - type: + reason: type: string - nullable: true - count: + required: + - name + - reason + run_count: + type: object + properties: + local: + type: object + properties: + modules: + type: integer + format: Int32 + drivers: + type: integer + format: Int32 + required: + - modules + - drivers + edge: + type: object + additionalProperties: + type: object + properties: + modules: + type: integer + format: Int32 + drivers: + type: integer + format: Int32 + required: + - modules + - drivers + required: + - local + - edge + required: + - available_repositories + - unavailable_repositories + - compiled_drivers + - unavailable_drivers + - run_count + nullable: true + required: + - id + - uri + PlaceOS__Api__Cluster__DriverStatus: + type: object + properties: + driver: + type: string + local: + type: object + properties: + modules: + type: array + items: + type: string + status: + type: object + properties: + running: + type: boolean + module_instances: + type: integer + format: Int32 + last_exit_code: + type: integer + format: Int32 + launch_count: + type: integer + format: Int32 + launch_time: + type: integer + format: Int64 + percentage_cpu: + type: number + format: Float64 + nullable: true + memory_total: + type: integer + format: Int64 + nullable: true + memory_usage: + type: integer + format: Int64 + nullable: true + required: + - running + - module_instances + - last_exit_code + - launch_count + - launch_time + nullable: true + required: + - modules + edge: + type: object + additionalProperties: + type: object + properties: + modules: + type: array + items: + type: string + status: + type: object + properties: + running: + type: boolean + module_instances: type: integer format: Int32 - nullable: true - capacity: + last_exit_code: + type: integer + format: Int32 + launch_count: type: integer format: Int32 + launch_time: + type: integer + format: Int64 + percentage_cpu: + type: number + format: Float64 nullable: true - map_id: - type: string - nullable: true - timezone: - type: object - nullable: true - triggers: - type: array - items: - type: string - nullable: true - images: - type: array - items: - type: string - nullable: true - parent_id: - type: string - nullable: true - remove_triggers: - type: array - items: - type: string + memory_total: + type: integer + format: Int64 nullable: true - add_triggers: - type: array - items: - type: string + memory_usage: + type: integer + format: Int64 nullable: true - trigger_data: - type: array - items: - type: object - properties: - id: - type: string - nullable: true - created_at: - type: string - format: date-time - nullable: true - updated_at: - type: string - format: date-time - nullable: true - name: - type: string - nullable: true - description: - type: string - nullable: true - actions: - type: object - properties: - functions: - type: array - items: - type: object - properties: - mod: - type: string - nullable: true - method: - type: string - nullable: true - args: - type: object - additionalProperties: - type: object - nullable: true - nullable: true - mailers: - type: array - items: - type: object - properties: - emails: - type: array - items: - type: string - nullable: true - content: - type: string - nullable: true - nullable: true - nullable: true - conditions: - type: object - properties: - comparisons: - type: array - items: - type: object - properties: - left: - anyOf: - - type: boolean - - type: number - format: Float64 - - type: integer - format: Int64 - - type: object - properties: - mod: - type: string - status: - type: string - keys: - type: array - items: - type: string - required: - - mod - - status - - keys - - type: string - nullable: true - operator: - type: string - enum: - - and - - equal - - exclusive_or - - greater_than - - greater_than_or_equal - - less_than - - less_than_or_equal - - not_equal - - or - nullable: true - right: - anyOf: - - type: boolean - - type: number - format: Float64 - - type: integer - format: Int64 - - type: object - properties: - mod: - type: string - status: - type: string - keys: - type: array - items: - type: string - required: - - mod - - status - - keys - - type: string - nullable: true - nullable: true - time_dependents: - type: array - items: - type: object - properties: - type: - type: string - enum: - - at - - cron - nullable: true - time: - type: string - format: date-time - nullable: true - cron: - type: string - nullable: true - timezone: - type: string - nullable: true - nullable: true - nullable: true - debounce_period: - type: integer - format: Int32 - nullable: true - important: - type: boolean - nullable: true - enable_webhook: - type: boolean - nullable: true - supported_methods: - type: array - items: - type: string - nullable: true - control_system_id: - type: string - nullable: true - trigger_instances: - type: array - items: - type: object - properties: - id: - type: string - nullable: true - created_at: - type: string - format: date-time - nullable: true - updated_at: - type: string - format: date-time - nullable: true - enabled: - type: boolean - nullable: true - triggered: - type: boolean - nullable: true - important: - type: boolean - nullable: true - exec_enabled: - type: boolean - nullable: true - webhook_secret: - type: string - nullable: true - trigger_count: - type: integer - format: Int32 - nullable: true - control_system_id: - type: string - nullable: true - trigger_id: - type: string - nullable: true - zone_id: - type: string - nullable: true - name: - type: string - nullable: true - control_system: - type: object - properties: - name: - type: string - id: - type: string - required: - - name - - id - nullable: true - nullable: true - nullable: true - update_systems: - type: boolean required: - - update_systems - required: - - name - - zone_data - nullable: true - Array_JSON__Any_: - type: array - items: - type: object - Hash_String__String_: - type: object - additionalProperties: - type: string - String: - type: string - PlaceOS__Api__Modules__PingResult: + - running + - module_instances + - last_exit_code + - launch_count + - launch_time + nullable: true + required: + - modules + required: + - driver + - local + - edge + PlaceOS__Model__Authority: type: object properties: - host: + id: type: string - pingable: - type: boolean nullable: true - warning: + created_at: type: string + format: date-time nullable: true - exception: + updated_at: type: string + format: date-time nullable: true - required: - - host - Bool: - type: boolean - PlaceOS__Model__ControlSystem: + name: + type: string + nullable: true + description: + type: string + nullable: true + domain: + type: string + nullable: true + login_url: + type: string + nullable: true + logout_url: + type: string + nullable: true + internals: + type: object + additionalProperties: + type: object + nullable: true + config: + type: object + additionalProperties: + type: object + nullable: true + PlaceOS__Model__Driver: type: object properties: id: @@ -16418,381 +16487,625 @@ components: description: type: string nullable: true - features: - type: array - items: - type: string + json_schema: + type: object nullable: true - email: + default_uri: type: string - format: email nullable: true - bookable: + default_port: + type: integer + format: Int32 + nullable: true + role: + type: string + enum: + - ssh + - device + - service + - websocket + - logic + nullable: true + file_name: + type: string + nullable: true + commit: + type: string + nullable: true + compilation_output: + type: string + nullable: true + module_name: + type: string + nullable: true + ignore_connected: type: boolean nullable: true - display_name: + repository_id: type: string nullable: true - code: + compilation_status: + type: object + additionalProperties: + type: boolean + nullable: true + NamedTuple_compilation_output__String_: + type: object + properties: + compilation_output: + type: string + required: + - compilation_output + PlaceOS__Model__Settings: + type: object + properties: + id: type: string nullable: true - type: + created_at: type: string + format: date-time nullable: true - capacity: - type: integer - format: Int32 + updated_at: + type: string + format: date-time nullable: true - map_id: + modified_by_id: type: string nullable: true - images: + settings_id: + type: string + nullable: true + encryption_level: + type: string + enum: + - none + - support + - admin + - never_display + nullable: true + settings_string: + type: string + nullable: true + keys: type: array items: type: string nullable: true - timezone: - type: object + parent_type: + type: string + enum: + - control_system + - driver + - module + - zone nullable: true - support_url: + parent_id: type: string nullable: true - version: - type: integer - format: Int32 + PlaceOS__Model__Module: + type: object + properties: + id: + type: string nullable: true - installed_ui_devices: + created_at: + type: string + format: date-time + nullable: true + updated_at: + type: string + format: date-time + nullable: true + ip: + type: string + nullable: true + port: type: integer format: Int32 nullable: true - zones: - type: array - items: - type: string + tls: + type: boolean nullable: true - modules: - type: array - items: - type: string + udp: + type: boolean nullable: true - remove_zones: - type: array - items: - type: string + makebreak: + type: boolean nullable: true - add_zones: - type: array - items: - type: string + uri: + type: string nullable: true - zone_data: - type: array - items: - type: object - properties: - id: - type: string - nullable: true - created_at: - type: string - format: date-time - nullable: true - updated_at: - type: string - format: date-time - nullable: true - name: - type: string - nullable: true - description: - type: string - nullable: true - tags: - type: array - items: - type: string - nullable: true - location: - type: string - nullable: true - display_name: - type: string - nullable: true - code: - type: string - nullable: true - type: - type: string - nullable: true - count: - type: integer - format: Int32 - nullable: true - capacity: - type: integer - format: Int32 - nullable: true - map_id: - type: string - nullable: true - timezone: + name: + type: string + nullable: true + custom_name: + type: string + nullable: true + role: + type: string + enum: + - ssh + - device + - service + - websocket + - logic + nullable: true + connected: + type: boolean + nullable: true + running: + type: boolean + nullable: true + notes: + type: string + nullable: true + ignore_connected: + type: boolean + nullable: true + ignore_startstop: + type: boolean + nullable: true + control_system_id: + type: string + nullable: true + driver_id: + type: string + nullable: true + edge_id: + type: string + nullable: true + driver: + type: object + properties: + name: + type: string + description: + type: string + nullable: true + module_name: + type: string + nullable: true + required: + - name + nullable: true + compiled: + type: boolean + nullable: true + control_system: + type: object + properties: + name: + type: string + zone_data: + type: array + items: type: object - nullable: true - triggers: - type: array - items: - type: string - nullable: true - images: - type: array - items: - type: string - nullable: true - parent_id: - type: string - nullable: true - remove_triggers: - type: array - items: - type: string - nullable: true - add_triggers: - type: array - items: - type: string - nullable: true - trigger_data: - type: array - items: - type: object - properties: - id: + properties: + id: + type: string + nullable: true + created_at: + type: string + format: date-time + nullable: true + updated_at: + type: string + format: date-time + nullable: true + name: + type: string + nullable: true + description: + type: string + nullable: true + tags: + type: array + items: type: string - nullable: true - created_at: + nullable: true + location: + type: string + nullable: true + display_name: + type: string + nullable: true + code: + type: string + nullable: true + type: + type: string + nullable: true + count: + type: integer + format: Int32 + nullable: true + capacity: + type: integer + format: Int32 + nullable: true + map_id: + type: string + nullable: true + timezone: + type: object + nullable: true + triggers: + type: array + items: type: string - format: date-time - nullable: true - updated_at: + nullable: true + images: + type: array + items: type: string - format: date-time - nullable: true - name: + nullable: true + parent_id: + type: string + nullable: true + remove_triggers: + type: array + items: type: string - nullable: true - description: + nullable: true + add_triggers: + type: array + items: type: string - nullable: true - actions: + nullable: true + trigger_data: + type: array + items: type: object properties: - functions: - type: array - items: - type: object - properties: - mod: - type: string - nullable: true - method: - type: string - nullable: true - args: - type: object - additionalProperties: - type: object - nullable: true + id: + type: string nullable: true - mailers: - type: array - items: - type: object - properties: - emails: - type: array - items: - type: string - nullable: true - content: - type: string - nullable: true + created_at: + type: string + format: date-time nullable: true - nullable: true - conditions: - type: object - properties: - comparisons: - type: array - items: - type: object - properties: - left: - anyOf: - - type: boolean - - type: number - format: Float64 - - type: integer - format: Int64 - - type: object - properties: - mod: - type: string - status: - type: string - keys: - type: array - items: - type: string - required: - - mod - - status - - keys - - type: string - nullable: true - operator: - type: string - enum: - - and - - equal - - exclusive_or - - greater_than - - greater_than_or_equal - - less_than - - less_than_or_equal - - not_equal - - or - nullable: true - right: - anyOf: - - type: boolean - - type: number - format: Float64 - - type: integer - format: Int64 - - type: object - properties: - mod: - type: string - status: + updated_at: + type: string + format: date-time + nullable: true + name: + type: string + nullable: true + description: + type: string + nullable: true + actions: + type: object + properties: + functions: + type: array + items: + type: object + properties: + mod: + type: string + nullable: true + method: + type: string + nullable: true + args: + type: object + additionalProperties: + type: object + nullable: true + nullable: true + mailers: + type: array + items: + type: object + properties: + emails: + type: array + items: type: string - keys: - type: array - items: - type: string - required: - - mod - - status - - keys - - type: string - nullable: true + nullable: true + content: + type: string + nullable: true + nullable: true nullable: true - time_dependents: + conditions: + type: object + properties: + comparisons: + type: array + items: + type: object + properties: + left: + anyOf: + - type: boolean + - type: number + format: Float64 + - type: integer + format: Int64 + - type: object + properties: + mod: + type: string + status: + type: string + keys: + type: array + items: + type: string + required: + - mod + - status + - keys + - type: string + nullable: true + operator: + type: string + enum: + - and + - equal + - exclusive_or + - greater_than + - greater_than_or_equal + - less_than + - less_than_or_equal + - not_equal + - or + nullable: true + right: + anyOf: + - type: boolean + - type: number + format: Float64 + - type: integer + format: Int64 + - type: object + properties: + mod: + type: string + status: + type: string + keys: + type: array + items: + type: string + required: + - mod + - status + - keys + - type: string + nullable: true + nullable: true + time_dependents: + type: array + items: + type: object + properties: + type: + type: string + enum: + - at + - cron + nullable: true + time: + type: string + format: date-time + nullable: true + cron: + type: string + nullable: true + timezone: + type: string + nullable: true + nullable: true + nullable: true + debounce_period: + type: integer + format: Int32 + nullable: true + important: + type: boolean + nullable: true + enable_webhook: + type: boolean + nullable: true + supported_methods: + type: array + items: + type: string + nullable: true + control_system_id: + type: string + nullable: true + trigger_instances: type: array items: type: object properties: - type: + id: type: string - enum: - - at - - cron nullable: true - time: + created_at: type: string format: date-time nullable: true - cron: + updated_at: type: string + format: date-time nullable: true - timezone: + enabled: + type: boolean + nullable: true + triggered: + type: boolean + nullable: true + important: + type: boolean + nullable: true + exec_enabled: + type: boolean + nullable: true + webhook_secret: + type: string + nullable: true + trigger_count: + type: integer + format: Int32 + nullable: true + control_system_id: + type: string + nullable: true + trigger_id: + type: string + nullable: true + zone_id: + type: string + nullable: true + name: type: string nullable: true + control_system: + type: object + properties: + name: + type: string + id: + type: string + required: + - name + - id + nullable: true nullable: true - nullable: true - debounce_period: - type: integer - format: Int32 - nullable: true - important: - type: boolean - nullable: true - enable_webhook: - type: boolean - nullable: true - supported_methods: - type: array - items: - type: string - nullable: true - control_system_id: - type: string - nullable: true - trigger_instances: - type: array - items: - type: object - properties: - id: - type: string - nullable: true - created_at: - type: string - format: date-time - nullable: true - updated_at: - type: string - format: date-time - nullable: true - enabled: - type: boolean - nullable: true - triggered: - type: boolean - nullable: true - important: - type: boolean - nullable: true - exec_enabled: - type: boolean - nullable: true - webhook_secret: - type: string - nullable: true - trigger_count: - type: integer - format: Int32 - nullable: true - control_system_id: - type: string - nullable: true - trigger_id: - type: string - nullable: true - zone_id: - type: string - nullable: true - name: - type: string - nullable: true - control_system: - type: object - properties: - name: - type: string - id: - type: string - required: - - name - - id - nullable: true - nullable: true - nullable: true - update_systems: - type: boolean - required: - - update_systems + nullable: true + update_systems: + type: boolean + required: + - update_systems + required: + - name + - zone_data nullable: true - module_data: + Array_JSON__Any_: + type: array + items: + type: object + Hash_String__String_: + type: object + additionalProperties: + type: string + String: + type: string + PlaceOS__Api__Modules__PingResult: + type: object + properties: + host: + type: string + pingable: + type: boolean + nullable: true + warning: + type: string + nullable: true + exception: + type: string + nullable: true + required: + - host + Bool: + type: boolean + PlaceOS__Model__ControlSystem: + type: object + properties: + id: + type: string + nullable: true + created_at: + type: string + format: date-time + nullable: true + updated_at: + type: string + format: date-time + nullable: true + name: + type: string + nullable: true + description: + type: string + nullable: true + features: + type: array + items: + type: string + nullable: true + email: + type: string + format: email + nullable: true + bookable: + type: boolean + nullable: true + public: + type: boolean + nullable: true + display_name: + type: string + nullable: true + code: + type: string + nullable: true + type: + type: string + nullable: true + capacity: + type: integer + format: Int32 + nullable: true + map_id: + type: string + nullable: true + images: + type: array + items: + type: string + nullable: true + timezone: + type: object + nullable: true + support_url: + type: string + nullable: true + version: + type: integer + format: Int32 + nullable: true + installed_ui_devices: + type: integer + format: Int32 + nullable: true + zones: + type: array + items: + type: string + nullable: true + modules: + type: array + items: + type: string + nullable: true + remove_zones: + type: array + items: + type: string + nullable: true + add_zones: + type: array + items: + type: string + nullable: true + zone_data: type: array items: type: object @@ -16808,476 +17121,298 @@ components: type: string format: date-time nullable: true - ip: + name: type: string nullable: true - port: - type: integer - format: Int32 - nullable: true - tls: - type: boolean - nullable: true - udp: - type: boolean + description: + type: string nullable: true - makebreak: - type: boolean + tags: + type: array + items: + type: string nullable: true - uri: + location: type: string nullable: true - name: + display_name: type: string nullable: true - custom_name: + code: type: string nullable: true - role: + type: type: string - enum: - - ssh - - device - - service - - websocket - - logic nullable: true - connected: - type: boolean + count: + type: integer + format: Int32 nullable: true - running: - type: boolean + capacity: + type: integer + format: Int32 nullable: true - notes: + map_id: type: string nullable: true - ignore_connected: - type: boolean + timezone: + type: object nullable: true - ignore_startstop: - type: boolean + triggers: + type: array + items: + type: string nullable: true - control_system_id: - type: string + images: + type: array + items: + type: string nullable: true - driver_id: + parent_id: type: string nullable: true - edge_id: - type: string + remove_triggers: + type: array + items: + type: string nullable: true - driver: - type: object - properties: - name: - type: string - description: - type: string - nullable: true - module_name: - type: string - nullable: true - required: - - name - nullable: true - compiled: - type: boolean + add_triggers: + type: array + items: + type: string nullable: true - control_system: - type: object - properties: - name: - type: string - zone_data: - type: array - items: + trigger_data: + type: array + items: + type: object + properties: + id: + type: string + nullable: true + created_at: + type: string + format: date-time + nullable: true + updated_at: + type: string + format: date-time + nullable: true + name: + type: string + nullable: true + description: + type: string + nullable: true + actions: type: object properties: - id: - type: string - nullable: true - created_at: - type: string - format: date-time - nullable: true - updated_at: - type: string - format: date-time - nullable: true - name: - type: string - nullable: true - description: - type: string - nullable: true - tags: - type: array - items: - type: string - nullable: true - location: - type: string - nullable: true - display_name: - type: string - nullable: true - code: - type: string - nullable: true - type: - type: string - nullable: true - count: - type: integer - format: Int32 - nullable: true - capacity: - type: integer - format: Int32 - nullable: true - map_id: - type: string - nullable: true - timezone: - type: object - nullable: true - triggers: - type: array - items: - type: string - nullable: true - images: + functions: type: array items: - type: string - nullable: true - parent_id: - type: string + type: object + properties: + mod: + type: string + nullable: true + method: + type: string + nullable: true + args: + type: object + additionalProperties: + type: object + nullable: true nullable: true - remove_triggers: + mailers: type: array items: - type: string + type: object + properties: + emails: + type: array + items: + type: string + nullable: true + content: + type: string + nullable: true nullable: true - add_triggers: + nullable: true + conditions: + type: object + properties: + comparisons: type: array items: - type: string + type: object + properties: + left: + anyOf: + - type: boolean + - type: number + format: Float64 + - type: integer + format: Int64 + - type: object + properties: + mod: + type: string + status: + type: string + keys: + type: array + items: + type: string + required: + - mod + - status + - keys + - type: string + nullable: true + operator: + type: string + enum: + - and + - equal + - exclusive_or + - greater_than + - greater_than_or_equal + - less_than + - less_than_or_equal + - not_equal + - or + nullable: true + right: + anyOf: + - type: boolean + - type: number + format: Float64 + - type: integer + format: Int64 + - type: object + properties: + mod: + type: string + status: + type: string + keys: + type: array + items: + type: string + required: + - mod + - status + - keys + - type: string + nullable: true nullable: true - trigger_data: + time_dependents: type: array items: type: object properties: - id: - type: string - nullable: true - created_at: + type: type: string - format: date-time + enum: + - at + - cron nullable: true - updated_at: + time: type: string format: date-time nullable: true - name: + cron: type: string nullable: true - description: + timezone: type: string nullable: true - actions: - type: object - properties: - functions: - type: array - items: - type: object - properties: - mod: - type: string - nullable: true - method: - type: string - nullable: true - args: - type: object - additionalProperties: - type: object - nullable: true - nullable: true - mailers: - type: array - items: - type: object - properties: - emails: - type: array - items: - type: string - nullable: true - content: - type: string - nullable: true - nullable: true - nullable: true - conditions: - type: object - properties: - comparisons: - type: array - items: - type: object - properties: - left: - anyOf: - - type: boolean - - type: number - format: Float64 - - type: integer - format: Int64 - - type: object - properties: - mod: - type: string - status: - type: string - keys: - type: array - items: - type: string - required: - - mod - - status - - keys - - type: string - nullable: true - operator: - type: string - enum: - - and - - equal - - exclusive_or - - greater_than - - greater_than_or_equal - - less_than - - less_than_or_equal - - not_equal - - or - nullable: true - right: - anyOf: - - type: boolean - - type: number - format: Float64 - - type: integer - format: Int64 - - type: object - properties: - mod: - type: string - status: - type: string - keys: - type: array - items: - type: string - required: - - mod - - status - - keys - - type: string - nullable: true - nullable: true - time_dependents: - type: array - items: - type: object - properties: - type: - type: string - enum: - - at - - cron - nullable: true - time: - type: string - format: date-time - nullable: true - cron: - type: string - nullable: true - timezone: - type: string - nullable: true - nullable: true - nullable: true - debounce_period: - type: integer - format: Int32 - nullable: true - important: - type: boolean - nullable: true - enable_webhook: - type: boolean - nullable: true - supported_methods: - type: array - items: - type: string - nullable: true - control_system_id: - type: string - nullable: true - trigger_instances: - type: array - items: - type: object - properties: - id: - type: string - nullable: true - created_at: - type: string - format: date-time - nullable: true - updated_at: - type: string - format: date-time - nullable: true - enabled: - type: boolean - nullable: true - triggered: - type: boolean - nullable: true - important: - type: boolean - nullable: true - exec_enabled: - type: boolean - nullable: true - webhook_secret: - type: string - nullable: true - trigger_count: - type: integer - format: Int32 - nullable: true - control_system_id: - type: string - nullable: true - trigger_id: - type: string - nullable: true - zone_id: - type: string - nullable: true - name: - type: string - nullable: true - control_system: - type: object - properties: - name: - type: string - id: - type: string - required: - - name - - id - nullable: true - nullable: true nullable: true - update_systems: - type: boolean - required: - - update_systems - required: - - name - - zone_data + nullable: true + debounce_period: + type: integer + format: Int32 + nullable: true + important: + type: boolean + nullable: true + enable_webhook: + type: boolean + nullable: true + supported_methods: + type: array + items: + type: string + nullable: true + control_system_id: + type: string + nullable: true + trigger_instances: + type: array + items: + type: object + properties: + id: + type: string + nullable: true + created_at: + type: string + format: date-time + nullable: true + updated_at: + type: string + format: date-time + nullable: true + enabled: + type: boolean + nullable: true + triggered: + type: boolean + nullable: true + important: + type: boolean + nullable: true + exec_enabled: + type: boolean + nullable: true + webhook_secret: + type: string + nullable: true + trigger_count: + type: integer + format: Int32 + nullable: true + control_system_id: + type: string + nullable: true + trigger_id: + type: string + nullable: true + zone_id: + type: string + nullable: true + name: + type: string + nullable: true + control_system: + type: object + properties: + name: + type: string + id: + type: string + required: + - name + - id + nullable: true + nullable: true nullable: true + update_systems: + type: boolean + required: + - update_systems nullable: true - update_triggers: - type: boolean - required: - - update_triggers - PlaceOS__Model__Zone: - type: object - properties: - id: - type: string - nullable: true - created_at: - type: string - format: date-time - nullable: true - updated_at: - type: string - format: date-time - nullable: true - name: - type: string - nullable: true - description: - type: string - nullable: true - tags: - type: array - items: - type: string - nullable: true - location: - type: string - nullable: true - display_name: - type: string - nullable: true - code: - type: string - nullable: true - type: - type: string - nullable: true - count: - type: integer - format: Int32 - nullable: true - capacity: - type: integer - format: Int32 - nullable: true - map_id: - type: string - nullable: true - timezone: - type: object - nullable: true - triggers: - type: array - items: - type: string - nullable: true - images: - type: array - items: - type: string - nullable: true - parent_id: - type: string - nullable: true - remove_triggers: - type: array - items: - type: string - nullable: true - add_triggers: - type: array - items: - type: string - nullable: true - trigger_data: + module_data: type: array items: type: object @@ -17293,776 +17428,402 @@ components: type: string format: date-time nullable: true + ip: + type: string + nullable: true + port: + type: integer + format: Int32 + nullable: true + tls: + type: boolean + nullable: true + udp: + type: boolean + nullable: true + makebreak: + type: boolean + nullable: true + uri: + type: string + nullable: true name: type: string nullable: true - description: + custom_name: type: string nullable: true - actions: + role: + type: string + enum: + - ssh + - device + - service + - websocket + - logic + nullable: true + connected: + type: boolean + nullable: true + running: + type: boolean + nullable: true + notes: + type: string + nullable: true + ignore_connected: + type: boolean + nullable: true + ignore_startstop: + type: boolean + nullable: true + control_system_id: + type: string + nullable: true + driver_id: + type: string + nullable: true + edge_id: + type: string + nullable: true + driver: type: object properties: - functions: + name: + type: string + description: + type: string + nullable: true + module_name: + type: string + nullable: true + required: + - name + nullable: true + compiled: + type: boolean + nullable: true + control_system: + type: object + properties: + name: + type: string + zone_data: type: array items: type: object properties: - mod: + id: type: string nullable: true - method: + created_at: type: string + format: date-time nullable: true - args: - type: object - additionalProperties: - type: object + updated_at: + type: string + format: date-time nullable: true - nullable: true - mailers: - type: array - items: - type: object - properties: - emails: + name: + type: string + nullable: true + description: + type: string + nullable: true + tags: type: array items: type: string nullable: true - content: + location: type: string nullable: true - nullable: true - nullable: true - conditions: - type: object - properties: - comparisons: - type: array - items: - type: object - properties: - left: - anyOf: - - type: boolean - - type: number - format: Float64 - - type: integer - format: Int64 - - type: object - properties: - mod: - type: string - status: - type: string - keys: - type: array - items: - type: string - required: - - mod - - status - - keys - - type: string + display_name: + type: string nullable: true - operator: + code: type: string - enum: - - and - - equal - - exclusive_or - - greater_than - - greater_than_or_equal - - less_than - - less_than_or_equal - - not_equal - - or nullable: true - right: - anyOf: - - type: boolean - - type: number - format: Float64 - - type: integer - format: Int64 - - type: object - properties: - mod: - type: string - status: - type: string - keys: - type: array - items: - type: string - required: - - mod - - status - - keys - - type: string + type: + type: string nullable: true - nullable: true - time_dependents: - type: array - items: - type: object - properties: - type: - type: string - enum: - - at - - cron + count: + type: integer + format: Int32 nullable: true - time: - type: string - format: date-time + capacity: + type: integer + format: Int32 nullable: true - cron: + map_id: type: string nullable: true timezone: - type: string + type: object nullable: true - nullable: true - nullable: true - debounce_period: - type: integer - format: Int32 - nullable: true - important: - type: boolean - nullable: true - enable_webhook: - type: boolean - nullable: true - supported_methods: - type: array - items: - type: string - nullable: true - control_system_id: - type: string - nullable: true - trigger_instances: - type: array - items: - type: object - properties: - id: - type: string - nullable: true - created_at: - type: string - format: date-time - nullable: true - updated_at: - type: string - format: date-time - nullable: true - enabled: - type: boolean - nullable: true - triggered: - type: boolean - nullable: true - important: - type: boolean - nullable: true - exec_enabled: - type: boolean - nullable: true - webhook_secret: - type: string - nullable: true - trigger_count: - type: integer - format: Int32 - nullable: true - control_system_id: - type: string - nullable: true - trigger_id: - type: string - nullable: true - zone_id: - type: string - nullable: true - name: - type: string - nullable: true - control_system: - type: object - properties: - name: - type: string - id: + triggers: + type: array + items: + type: string + nullable: true + images: + type: array + items: + type: string + nullable: true + parent_id: type: string - required: - - name - - id - nullable: true - nullable: true - nullable: true - update_systems: - type: boolean - required: - - update_systems - Hash_String__PlaceOS__Model__Metadata__Interface_: - type: object - additionalProperties: - type: object - properties: - name: - type: string - description: - type: string - details: - type: object - parent_id: - type: string - nullable: true - schema_id: - type: string - nullable: true - editors: - type: array - items: - type: string - modified_by_id: - type: string - nullable: true - updated_at: - type: string - format: date-time - created_at: - type: string - format: date-time - required: - - name - - description - - details - - editors - - updated_at - - created_at - Hash_String__Int32_: - type: object - additionalProperties: - type: integer - format: Int32 - JSON__Any: - type: object - Hash_String__PlaceOS__Api__Systems__FunctionDetails_: - type: object - additionalProperties: - type: object - properties: - arity: - type: integer - format: Int32 - params: - type: object - additionalProperties: - type: object - order: - type: array - items: - type: string - required: - - arity - - params - - order - NamedTuple_token__String_: - type: object - properties: - token: - type: string - required: - - token - PlaceOS__Model__Edge: - type: object - properties: - id: - type: string - nullable: true - created_at: - type: string - format: date-time - nullable: true - updated_at: - type: string - format: date-time - nullable: true - name: - type: string - nullable: true - description: - type: string - nullable: true - api_key_id: - type: string - nullable: true - user_id: - type: string - nullable: true - PlaceOS__Model__Edge__CreateBody: - type: object - properties: - name: - type: string - user_id: - type: string - nullable: true - description: - type: string - required: - - name - - description - PlaceOS__Model__Edge__KeyResponse: - type: object - properties: - created_at: - type: string - format: date-time - updated_at: - type: string - format: date-time - name: - type: string - description: - type: string - user_id: - type: string - x_api_key: - type: string - required: - - created_at - - updated_at - - name - - description - - user_id - - x_api_key - PlaceOS__Api__Metadata__Children: - type: object - properties: - zone: - type: object - properties: - id: - type: string - nullable: true - created_at: - type: string - format: date-time - nullable: true - updated_at: - type: string - format: date-time - nullable: true - name: - type: string - nullable: true - description: - type: string - nullable: true - tags: - type: array - items: - type: string - nullable: true - location: - type: string - nullable: true - display_name: - type: string - nullable: true - code: - type: string - nullable: true - type: - type: string - nullable: true - count: - type: integer - format: Int32 - nullable: true - capacity: - type: integer - format: Int32 - nullable: true - map_id: - type: string - nullable: true - timezone: - type: object - nullable: true - triggers: - type: array - items: - type: string - nullable: true - images: - type: array - items: - type: string - nullable: true - parent_id: - type: string - nullable: true - remove_triggers: - type: array - items: - type: string - nullable: true - add_triggers: - type: array - items: - type: string - nullable: true - trigger_data: - type: array - items: - type: object - properties: - id: - type: string - nullable: true - created_at: - type: string - format: date-time - nullable: true - updated_at: - type: string - format: date-time - nullable: true - name: - type: string - nullable: true - description: - type: string - nullable: true - actions: - type: object - properties: - functions: - type: array - items: - type: object - properties: - mod: - type: string - nullable: true - method: - type: string - nullable: true - args: - type: object - additionalProperties: - type: object - nullable: true - nullable: true - mailers: - type: array - items: - type: object - properties: - emails: - type: array - items: + nullable: true + remove_triggers: + type: array + items: + type: string + nullable: true + add_triggers: + type: array + items: + type: string + nullable: true + trigger_data: + type: array + items: + type: object + properties: + id: type: string - nullable: true - content: - type: string - nullable: true - nullable: true - nullable: true - conditions: - type: object - properties: - comparisons: - type: array - items: - type: object - properties: - left: - anyOf: - - type: boolean - - type: number - format: Float64 - - type: integer - format: Int64 - - type: object + nullable: true + created_at: + type: string + format: date-time + nullable: true + updated_at: + type: string + format: date-time + nullable: true + name: + type: string + nullable: true + description: + type: string + nullable: true + actions: + type: object properties: - mod: - type: string - status: - type: string - keys: + functions: type: array items: - type: string - required: - - mod - - status - - keys - - type: string - nullable: true - operator: - type: string - enum: - - and - - equal - - exclusive_or - - greater_than - - greater_than_or_equal - - less_than - - less_than_or_equal - - not_equal - - or - nullable: true - right: - anyOf: - - type: boolean - - type: number - format: Float64 - - type: integer - format: Int64 - - type: object + type: object + properties: + mod: + type: string + nullable: true + method: + type: string + nullable: true + args: + type: object + additionalProperties: + type: object + nullable: true + nullable: true + mailers: + type: array + items: + type: object + properties: + emails: + type: array + items: + type: string + nullable: true + content: + type: string + nullable: true + nullable: true + nullable: true + conditions: + type: object properties: - mod: - type: string - status: - type: string - keys: + comparisons: type: array items: - type: string - required: - - mod - - status - - keys - - type: string - nullable: true - nullable: true - time_dependents: - type: array - items: - type: object - properties: - type: - type: string - enum: - - at - - cron - nullable: true - time: - type: string - format: date-time - nullable: true - cron: - type: string - nullable: true - timezone: - type: string - nullable: true - nullable: true - nullable: true - debounce_period: - type: integer - format: Int32 - nullable: true - important: - type: boolean - nullable: true - enable_webhook: - type: boolean - nullable: true - supported_methods: - type: array - items: - type: string - nullable: true - control_system_id: - type: string - nullable: true - trigger_instances: - type: array - items: - type: object - properties: - id: - type: string - nullable: true - created_at: - type: string - format: date-time - nullable: true - updated_at: - type: string - format: date-time - nullable: true - enabled: - type: boolean - nullable: true - triggered: - type: boolean - nullable: true - important: - type: boolean + type: object + properties: + left: + anyOf: + - type: boolean + - type: number + format: Float64 + - type: integer + format: Int64 + - type: object + properties: + mod: + type: string + status: + type: string + keys: + type: array + items: + type: string + required: + - mod + - status + - keys + - type: string + nullable: true + operator: + type: string + enum: + - and + - equal + - exclusive_or + - greater_than + - greater_than_or_equal + - less_than + - less_than_or_equal + - not_equal + - or + nullable: true + right: + anyOf: + - type: boolean + - type: number + format: Float64 + - type: integer + format: Int64 + - type: object + properties: + mod: + type: string + status: + type: string + keys: + type: array + items: + type: string + required: + - mod + - status + - keys + - type: string + nullable: true + nullable: true + time_dependents: + type: array + items: + type: object + properties: + type: + type: string + enum: + - at + - cron + nullable: true + time: + type: string + format: date-time + nullable: true + cron: + type: string + nullable: true + timezone: + type: string + nullable: true + nullable: true + nullable: true + debounce_period: + type: integer + format: Int32 + nullable: true + important: + type: boolean + nullable: true + enable_webhook: + type: boolean + nullable: true + supported_methods: + type: array + items: + type: string + nullable: true + control_system_id: + type: string + nullable: true + trigger_instances: + type: array + items: + type: object + properties: + id: + type: string + nullable: true + created_at: + type: string + format: date-time + nullable: true + updated_at: + type: string + format: date-time + nullable: true + enabled: + type: boolean + nullable: true + triggered: + type: boolean + nullable: true + important: + type: boolean + nullable: true + exec_enabled: + type: boolean + nullable: true + webhook_secret: + type: string + nullable: true + trigger_count: + type: integer + format: Int32 + nullable: true + control_system_id: + type: string + nullable: true + trigger_id: + type: string + nullable: true + zone_id: + type: string + nullable: true + name: + type: string + nullable: true + control_system: + type: object + properties: + name: + type: string + id: + type: string + required: + - name + - id + nullable: true + nullable: true nullable: true - exec_enabled: + update_systems: type: boolean - nullable: true - webhook_secret: - type: string - nullable: true - trigger_count: - type: integer - format: Int32 - nullable: true - control_system_id: - type: string - nullable: true - trigger_id: - type: string - nullable: true - zone_id: - type: string - nullable: true - name: - type: string - nullable: true - control_system: - type: object - properties: - name: - type: string - id: - type: string - required: - - name - - id - nullable: true - nullable: true - nullable: true - update_systems: - type: boolean - required: - - update_systems - metadata: - type: object - additionalProperties: - type: object - properties: - name: - type: string - description: - type: string - details: - type: object - parent_id: - type: string - nullable: true - schema_id: - type: string - nullable: true - editors: - type: array - items: - type: string - modified_by_id: - type: string + required: + - update_systems + required: + - name + - zone_data nullable: true - updated_at: - type: string - format: date-time - created_at: - type: string - format: date-time - required: - - name - - description - - details - - editors - - updated_at - - created_at - required: - - zone - - metadata - PlaceOS__Model__Metadata__Interface: - type: object - properties: - name: - type: string - description: - type: string - details: - type: object - parent_id: - type: string - nullable: true - schema_id: - type: string - nullable: true - editors: - type: array - items: - type: string - modified_by_id: - type: string nullable: true - updated_at: - type: string - format: date-time - created_at: - type: string - format: date-time + update_triggers: + type: boolean required: - - name - - description - - details - - editors - - updated_at - - created_at - Hash_String__Array_PlaceOS__Model__Metadata__Interface__: - type: object - additionalProperties: - type: array - items: - type: object - properties: - name: - type: string - description: - type: string - details: - type: object - parent_id: - type: string - nullable: true - schema_id: - type: string - nullable: true - editors: - type: array - items: - type: string - modified_by_id: - type: string - nullable: true - updated_at: - type: string - format: date-time - created_at: - type: string - format: date-time - required: - - name - - description - - details - - editors - - updated_at - - created_at - PlaceOS__Model__DoorkeeperApplication: + - update_triggers + PlaceOS__Model__Zone: type: object properties: id: @@ -18079,954 +17840,2702 @@ components: name: type: string nullable: true - secret: - type: string - nullable: true - scopes: - type: string - nullable: true - owner_id: - type: string - nullable: true - redirect_uri: - type: string - nullable: true - skip_authorization: - type: boolean - nullable: true - confidential: - type: boolean - nullable: true - revoked_at: - type: string - format: date-time - nullable: true - uid: - type: string - nullable: true - PlaceOS__Model__Repository: - type: object - properties: - id: - type: string - nullable: true - created_at: + description: type: string - format: date-time nullable: true - updated_at: - type: string - format: date-time + tags: + type: array + items: + type: string nullable: true - name: + location: type: string nullable: true - description: + display_name: type: string nullable: true - folder_name: + code: type: string nullable: true - uri: + type: type: string nullable: true - commit_hash: - type: string + count: + type: integer + format: Int32 nullable: true - branch: - type: string + capacity: + type: integer + format: Int32 nullable: true - deployed_commit_hash: + map_id: type: string nullable: true - release: - type: boolean + timezone: + type: object nullable: true - username: - type: string + triggers: + type: array + items: + type: string nullable: true - password: - type: string + images: + type: array + items: + type: string nullable: true - repo_type: + parent_id: type: string - enum: - - driver - - interface nullable: true - NamedTuple_commit_hash__String_: - type: object - properties: - commit_hash: - type: string - required: - - commit_hash - GitRepository__Commit: - type: object - properties: - hash: - type: string - subject: - type: string - author: - type: string + remove_triggers: + type: array + items: + type: string nullable: true - date: - type: string + add_triggers: + type: array + items: + type: string nullable: true - commit: - type: string - required: - - hash - - subject - - commit - PlaceOS__Api__Root__PlatformInfo: - type: object - properties: - version: - type: string - changelog: - type: string - required: - - version - - changelog - PlaceOS__Model__Version: - type: object - properties: - service: - type: string - commit: - type: string - version: - type: string - build_time: - type: string - platform_version: - type: string - required: - - service - - commit - - version - - build_time - - platform_version - PlaceOS__Model__JsonSchema: - type: object - properties: - id: - type: string - nullable: true - created_at: - type: string - format: date-time - nullable: true - updated_at: - type: string - format: date-time - nullable: true - name: - type: string - nullable: true - description: - type: string - nullable: true - schema: - type: object - nullable: true - PlaceOS__Model__TriggerInstance: - type: object - properties: - id: - type: string - nullable: true - created_at: - type: string - format: date-time - nullable: true - updated_at: - type: string - format: date-time - nullable: true - enabled: - type: boolean - nullable: true - triggered: - type: boolean - nullable: true - important: - type: boolean - nullable: true - exec_enabled: - type: boolean - nullable: true - webhook_secret: - type: string - nullable: true - trigger_count: - type: integer - format: Int32 - nullable: true - control_system_id: - type: string - nullable: true - trigger_id: - type: string - nullable: true - zone_id: - type: string - nullable: true - name: - type: string - nullable: true - control_system: - type: object - properties: - name: - type: string - id: - type: string - required: - - name - - id - nullable: true - PlaceOS__Api__SystemTriggers__UpdateParams: - type: object - properties: - enabled: - type: boolean - nullable: true - important: - type: boolean - nullable: true - exec_enabled: - type: boolean - nullable: true - PlaceOS__Model__Trigger: - type: object - properties: - id: - type: string - nullable: true - created_at: - type: string - format: date-time - nullable: true - updated_at: - type: string - format: date-time - nullable: true - name: - type: string - nullable: true - description: - type: string - nullable: true - actions: - type: object - properties: - functions: - type: array - items: - type: object - properties: - mod: - type: string - nullable: true - method: - type: string - nullable: true - args: - type: object - additionalProperties: - type: object - nullable: true - nullable: true - mailers: - type: array - items: + trigger_data: + type: array + items: + type: object + properties: + id: + type: string + nullable: true + created_at: + type: string + format: date-time + nullable: true + updated_at: + type: string + format: date-time + nullable: true + name: + type: string + nullable: true + description: + type: string + nullable: true + actions: type: object properties: - emails: + functions: type: array items: - type: string - nullable: true - content: - type: string - nullable: true - nullable: true - nullable: true - conditions: - type: object - properties: - comparisons: - type: array - items: - type: object - properties: - left: - anyOf: - - type: boolean - - type: number - format: Float64 - - type: integer - format: Int64 - - type: object + type: object properties: mod: type: string - status: + nullable: true + method: type: string - keys: - type: array - items: - type: string - required: - - mod - - status - - keys - - type: string - nullable: true - operator: - type: string - enum: - - and - - equal - - exclusive_or - - greater_than - - greater_than_or_equal - - less_than - - less_than_or_equal - - not_equal - - or + nullable: true + args: + type: object + additionalProperties: + type: object + nullable: true nullable: true - right: - anyOf: - - type: boolean - - type: number - format: Float64 - - type: integer - format: Int64 - - type: object + mailers: + type: array + items: + type: object properties: - mod: - type: string - status: - type: string - keys: + emails: type: array items: type: string - required: - - mod - - status - - keys - - type: string + nullable: true + content: + type: string + nullable: true nullable: true - nullable: true - time_dependents: - type: array - items: + nullable: true + conditions: type: object properties: - type: - type: string - enum: - - at - - cron - nullable: true - time: - type: string - format: date-time - nullable: true - cron: - type: string + comparisons: + type: array + items: + type: object + properties: + left: + anyOf: + - type: boolean + - type: number + format: Float64 + - type: integer + format: Int64 + - type: object + properties: + mod: + type: string + status: + type: string + keys: + type: array + items: + type: string + required: + - mod + - status + - keys + - type: string + nullable: true + operator: + type: string + enum: + - and + - equal + - exclusive_or + - greater_than + - greater_than_or_equal + - less_than + - less_than_or_equal + - not_equal + - or + nullable: true + right: + anyOf: + - type: boolean + - type: number + format: Float64 + - type: integer + format: Int64 + - type: object + properties: + mod: + type: string + status: + type: string + keys: + type: array + items: + type: string + required: + - mod + - status + - keys + - type: string + nullable: true nullable: true - timezone: - type: string + time_dependents: + type: array + items: + type: object + properties: + type: + type: string + enum: + - at + - cron + nullable: true + time: + type: string + format: date-time + nullable: true + cron: + type: string + nullable: true + timezone: + type: string + nullable: true nullable: true - nullable: true - nullable: true - debounce_period: - type: integer - format: Int32 - nullable: true - important: - type: boolean - nullable: true - enable_webhook: - type: boolean - nullable: true - supported_methods: - type: array - items: - type: string - nullable: true - control_system_id: - type: string - nullable: true - trigger_instances: - type: array - items: - type: object - properties: - id: - type: string - nullable: true - created_at: - type: string - format: date-time - nullable: true - updated_at: - type: string - format: date-time nullable: true - enabled: - type: boolean - nullable: true - triggered: - type: boolean + debounce_period: + type: integer + format: Int32 nullable: true important: type: boolean nullable: true - exec_enabled: + enable_webhook: type: boolean nullable: true - webhook_secret: - type: string - nullable: true - trigger_count: - type: integer - format: Int32 + supported_methods: + type: array + items: + type: string nullable: true control_system_id: type: string nullable: true - trigger_id: - type: string - nullable: true - zone_id: - type: string - nullable: true - name: - type: string - nullable: true - control_system: - type: object - properties: - name: - type: string - id: - type: string - required: - - name - - id + trigger_instances: + type: array + items: + type: object + properties: + id: + type: string + nullable: true + created_at: + type: string + format: date-time + nullable: true + updated_at: + type: string + format: date-time + nullable: true + enabled: + type: boolean + nullable: true + triggered: + type: boolean + nullable: true + important: + type: boolean + nullable: true + exec_enabled: + type: boolean + nullable: true + webhook_secret: + type: string + nullable: true + trigger_count: + type: integer + format: Int32 + nullable: true + control_system_id: + type: string + nullable: true + trigger_id: + type: string + nullable: true + zone_id: + type: string + nullable: true + name: + type: string + nullable: true + control_system: + type: object + properties: + name: + type: string + id: + type: string + required: + - name + - id + nullable: true nullable: true nullable: true - PlaceOS__Model__User__AdminResponse: + update_systems: + type: boolean + required: + - update_systems + Hash_String__PlaceOS__Model__Metadata__Interface_: type: object - properties: - created_at: - type: string - format: date-time - name: - type: string - nickname: - type: string - email: - type: string - format: email - phone: - type: string - country: - type: string - image: - type: string - ui_theme: - type: string - misc: - type: string - login_name: + additionalProperties: + type: object + properties: + name: + type: string + description: + type: string + details: + type: object + parent_id: + type: string + nullable: true + schema_id: + type: string + nullable: true + editors: + type: array + items: + type: string + modified_by_id: + type: string + nullable: true + updated_at: + type: string + format: date-time + created_at: + type: string + format: date-time + required: + - name + - description + - details + - editors + - updated_at + - created_at + Hash_String__Int32_: + type: object + additionalProperties: + type: integer + format: Int32 + JSON__Any: + type: object + Hash_String__PlaceOS__Api__Systems__FunctionDetails_: + type: object + additionalProperties: + type: object + properties: + arity: + type: integer + format: Int32 + params: + type: object + additionalProperties: + type: object + order: + type: array + items: + type: string + required: + - arity + - params + - order + NamedTuple_token__String_: + type: object + properties: + token: type: string - nullable: true - staff_id: + required: + - token + PlaceOS__Model__Edge: + type: object + properties: + id: type: string nullable: true - first_name: + created_at: type: string + format: date-time nullable: true - last_name: + updated_at: type: string + format: date-time nullable: true - building: + name: type: string nullable: true - department: + description: type: string nullable: true - preferred_language: + api_key_id: type: string nullable: true - email_digest: + user_id: type: string nullable: true - card_number: + PlaceOS__Model__Edge__CreateBody: + type: object + properties: + name: type: string - nullable: true - deleted: - type: boolean - groups: - type: array - items: - type: string - sys_admin: - type: boolean - support: - type: boolean - authority_id: + user_id: type: string nullable: true - id: + description: type: string - nullable: true required: - - created_at - name - - nickname - - email - - phone - - country - - image - - ui_theme - - misc - - deleted - - groups - - sys_admin - - support - PlaceOS__Api__Users__AccessToken: + - description + PlaceOS__Model__Edge__KeyResponse: type: object properties: - token: + created_at: + type: string + format: date-time + updated_at: + type: string + format: date-time + name: + type: string + description: + type: string + user_id: + type: string + x_api_key: type: string - expires: - type: integer - format: Int64 - nullable: true required: - - token - ? _PlaceOS__Model__User__AdminMetadataResponse___PlaceOS__Model__User__AdminResponse___PlaceOS__Model__User__PublicMetadataResponse___PlaceOS__Model__User__PublicResponse_ - : anyOf: - - type: object - properties: - created_at: - type: string - format: date-time - name: - type: string - nickname: - type: string - email: - type: string - format: email - phone: - type: string - country: - type: string - image: - type: string - ui_theme: - type: string - misc: - type: string - login_name: - type: string - nullable: true - staff_id: - type: string - nullable: true - first_name: - type: string - nullable: true - last_name: - type: string - nullable: true - building: - type: string - nullable: true - department: - type: string - nullable: true - preferred_language: - type: string - nullable: true - email_digest: - type: string - nullable: true - card_number: - type: string - nullable: true - deleted: - type: boolean - groups: - type: array - items: + - created_at + - updated_at + - name + - description + - user_id + - x_api_key + PlaceOS__Api__Metadata__Children: + type: object + properties: + zone: + type: object + properties: + id: type: string - sys_admin: - type: boolean - support: - type: boolean - authority_id: - type: string - nullable: true - id: - type: string - nullable: true - required: - - created_at - - name - - nickname - - email - - phone - - country - - image - - ui_theme - - misc - - deleted - - groups - - sys_admin - - support - - type: object - properties: - created_at: - type: string - format: date-time - name: - type: string - nickname: - type: string - email: - type: string - format: email - phone: - type: string - country: - type: string - image: - type: string - ui_theme: - type: string - misc: - type: string - login_name: - type: string - nullable: true - staff_id: - type: string - nullable: true - first_name: - type: string - nullable: true - last_name: - type: string - nullable: true - building: - type: string - nullable: true - department: - type: string - nullable: true - preferred_language: - type: string - nullable: true - email_digest: - type: string - nullable: true - card_number: - type: string - nullable: true - deleted: - type: boolean - groups: - type: array - items: + nullable: true + created_at: type: string - sys_admin: - type: boolean - support: - type: boolean - authority_id: - type: string - nullable: true - id: - type: string - nullable: true - required: - - created_at - - name - - nickname - - email - - phone - - country - - image - - ui_theme - - misc - - deleted - - groups - - sys_admin - - support - - type: object - properties: - created_at: - type: string - format: date-time - name: - type: string - nickname: - type: string - email: - type: string - format: email - phone: - type: string - country: - type: string - image: - type: string - staff_id: - type: string - nullable: true - first_name: - type: string - nullable: true - last_name: - type: string - nullable: true - building: - type: string - nullable: true - department: - type: string - nullable: true - preferred_language: - type: string - nullable: true - email_digest: - type: string - nullable: true - deleted: - type: boolean - groups: - type: array - items: + format: date-time + nullable: true + updated_at: type: string - authority_id: - type: string - nullable: true - id: - type: string - nullable: true - required: - - created_at - - name - - nickname - - email - - phone - - country - - image - - deleted - - groups - - type: object - properties: - created_at: - type: string - format: date-time - name: - type: string - nickname: - type: string - email: - type: string - format: email - phone: - type: string - country: - type: string - image: - type: string - staff_id: - type: string - nullable: true - first_name: - type: string - nullable: true - last_name: - type: string - nullable: true - building: - type: string - nullable: true - department: - type: string - nullable: true - preferred_language: - type: string - nullable: true - email_digest: - type: string - nullable: true - deleted: - type: boolean - groups: - type: array - items: + format: date-time + nullable: true + name: type: string - authority_id: - type: string - nullable: true - id: - type: string - nullable: true - required: - - created_at - - name - - nickname - - email - - phone - - country - - image - - deleted - - groups - PlaceOS__Model__User: - type: object - properties: - id: - type: string - nullable: true - created_at: - type: string - format: date-time - nullable: true - updated_at: - type: string - format: date-time - nullable: true - name: - type: string - nullable: true - nickname: - type: string - nullable: true - email: - type: string - format: email - nullable: true - phone: - type: string - nullable: true - country: - type: string - nullable: true - image: - type: string - nullable: true - ui_theme: - type: string - nullable: true - misc: - type: string - nullable: true - login_name: - type: string - nullable: true - staff_id: - type: string - nullable: true - first_name: - type: string - nullable: true - last_name: - type: string - nullable: true - building: - type: string - nullable: true - department: - type: string - nullable: true - preferred_language: - type: string - nullable: true - password_digest: - type: string - nullable: true - email_digest: - type: string - nullable: true - card_number: - type: string - nullable: true - deleted: - type: boolean - nullable: true - groups: - type: array - items: - type: string - nullable: true - access_token: - type: string - nullable: true - refresh_token: - type: string - nullable: true - expires_at: - type: integer - format: Int64 - nullable: true - expires: - type: boolean - nullable: true - password: - type: string - nullable: true - sys_admin: - type: boolean - nullable: true - support: - type: boolean - nullable: true - authority_id: - type: string - nullable: true - admin_destroy_lock: - type: object - properties: - id: + nullable: true + description: type: string nullable: true - key: + tags: + type: array + items: + type: string + nullable: true + location: type: string nullable: true - instance_token: + display_name: + type: string + nullable: true + code: + type: string + nullable: true + type: + type: string + nullable: true + count: + type: integer + format: Int32 + nullable: true + capacity: + type: integer + format: Int32 + nullable: true + map_id: + type: string + nullable: true + timezone: + type: object + nullable: true + triggers: + type: array + items: + type: string + nullable: true + images: + type: array + items: + type: string + nullable: true + parent_id: type: string nullable: true - expires_at: - type: string - format: date-time + remove_triggers: + type: array + items: + type: string + nullable: true + add_triggers: + type: array + items: + type: string + nullable: true + trigger_data: + type: array + items: + type: object + properties: + id: + type: string + nullable: true + created_at: + type: string + format: date-time + nullable: true + updated_at: + type: string + format: date-time + nullable: true + name: + type: string + nullable: true + description: + type: string + nullable: true + actions: + type: object + properties: + functions: + type: array + items: + type: object + properties: + mod: + type: string + nullable: true + method: + type: string + nullable: true + args: + type: object + additionalProperties: + type: object + nullable: true + nullable: true + mailers: + type: array + items: + type: object + properties: + emails: + type: array + items: + type: string + nullable: true + content: + type: string + nullable: true + nullable: true + nullable: true + conditions: + type: object + properties: + comparisons: + type: array + items: + type: object + properties: + left: + anyOf: + - type: boolean + - type: number + format: Float64 + - type: integer + format: Int64 + - type: object + properties: + mod: + type: string + status: + type: string + keys: + type: array + items: + type: string + required: + - mod + - status + - keys + - type: string + nullable: true + operator: + type: string + enum: + - and + - equal + - exclusive_or + - greater_than + - greater_than_or_equal + - less_than + - less_than_or_equal + - not_equal + - or + nullable: true + right: + anyOf: + - type: boolean + - type: number + format: Float64 + - type: integer + format: Int64 + - type: object + properties: + mod: + type: string + status: + type: string + keys: + type: array + items: + type: string + required: + - mod + - status + - keys + - type: string + nullable: true + nullable: true + time_dependents: + type: array + items: + type: object + properties: + type: + type: string + enum: + - at + - cron + nullable: true + time: + type: string + format: date-time + nullable: true + cron: + type: string + nullable: true + timezone: + type: string + nullable: true + nullable: true + nullable: true + debounce_period: + type: integer + format: Int32 + nullable: true + important: + type: boolean + nullable: true + enable_webhook: + type: boolean + nullable: true + supported_methods: + type: array + items: + type: string + nullable: true + control_system_id: + type: string + nullable: true + trigger_instances: + type: array + items: + type: object + properties: + id: + type: string + nullable: true + created_at: + type: string + format: date-time + nullable: true + updated_at: + type: string + format: date-time + nullable: true + enabled: + type: boolean + nullable: true + triggered: + type: boolean + nullable: true + important: + type: boolean + nullable: true + exec_enabled: + type: boolean + nullable: true + webhook_secret: + type: string + nullable: true + trigger_count: + type: integer + format: Int32 + nullable: true + control_system_id: + type: string + nullable: true + trigger_id: + type: string + nullable: true + zone_id: + type: string + nullable: true + name: + type: string + nullable: true + control_system: + type: object + properties: + name: + type: string + id: + type: string + required: + - name + - id + nullable: true + nullable: true + nullable: true + update_systems: + type: boolean + required: + - update_systems + metadata: + type: object + additionalProperties: + type: object + properties: + name: + type: string + description: + type: string + details: + type: object + parent_id: + type: string + nullable: true + schema_id: + type: string + nullable: true + editors: + type: array + items: + type: string + modified_by_id: + type: string + nullable: true + updated_at: + type: string + format: date-time + created_at: + type: string + format: date-time + required: + - name + - description + - details + - editors + - updated_at + - created_at + required: + - zone + - metadata + PlaceOS__Model__Metadata__Interface: + type: object + properties: + name: + type: string + description: + type: string + details: + type: object + parent_id: + type: string + nullable: true + schema_id: + type: string + nullable: true + editors: + type: array + items: + type: string + modified_by_id: + type: string + nullable: true + updated_at: + type: string + format: date-time + created_at: + type: string + format: date-time + required: + - name + - description + - details + - editors + - updated_at + - created_at + Hash_String__Array_PlaceOS__Model__Metadata__Interface__: + type: object + additionalProperties: + type: array + items: + type: object + properties: + name: + type: string + description: + type: string + details: + type: object + parent_id: + type: string + nullable: true + schema_id: + type: string + nullable: true + editors: + type: array + items: + type: string + modified_by_id: + type: string + nullable: true + updated_at: + type: string + format: date-time + created_at: + type: string + format: date-time + required: + - name + - description + - details + - editors + - updated_at + - created_at + PlaceOS__Model__DoorkeeperApplication: + type: object + properties: + id: + type: string + nullable: true + created_at: + type: string + format: date-time + nullable: true + updated_at: + type: string + format: date-time + nullable: true + name: + type: string + nullable: true + secret: + type: string + nullable: true + scopes: + type: string + nullable: true + owner_id: + type: string + nullable: true + redirect_uri: + type: string + nullable: true + skip_authorization: + type: boolean + nullable: true + confidential: + type: boolean + nullable: true + revoked_at: + type: string + format: date-time + nullable: true + uid: + type: string + nullable: true + PlaceOS__Model__Repository: + type: object + properties: + id: + type: string + nullable: true + created_at: + type: string + format: date-time + nullable: true + updated_at: + type: string + format: date-time + nullable: true + name: + type: string + nullable: true + description: + type: string + nullable: true + folder_name: + type: string + nullable: true + uri: + type: string + nullable: true + commit_hash: + type: string + nullable: true + branch: + type: string + nullable: true + deployed_commit_hash: + type: string + nullable: true + release: + type: boolean + nullable: true + username: + type: string + nullable: true + password: + type: string + nullable: true + repo_type: + type: string + enum: + - driver + - interface + nullable: true + NamedTuple_commit_hash__String_: + type: object + properties: + commit_hash: + type: string + required: + - commit_hash + GitRepository__Commit: + type: object + properties: + hash: + type: string + subject: + type: string + author: + type: string + nullable: true + date: + type: string + nullable: true + commit: + type: string + required: + - hash + - subject + - commit + PlaceOS__Api__Root__PlatformInfo: + type: object + properties: + version: + type: string + changelog: + type: string + required: + - version + - changelog + PlaceOS__Model__Version: + type: object + properties: + service: + type: string + commit: + type: string + version: + type: string + build_time: + type: string + platform_version: + type: string + required: + - service + - commit + - version + - build_time + - platform_version + PlaceOS__Model__JsonSchema: + type: object + properties: + id: + type: string + nullable: true + created_at: + type: string + format: date-time + nullable: true + updated_at: + type: string + format: date-time + nullable: true + name: + type: string + nullable: true + description: + type: string + nullable: true + schema: + type: object + nullable: true + PlaceOS__Model__TriggerInstance: + type: object + properties: + id: + type: string + nullable: true + created_at: + type: string + format: date-time + nullable: true + updated_at: + type: string + format: date-time + nullable: true + enabled: + type: boolean + nullable: true + triggered: + type: boolean + nullable: true + important: + type: boolean + nullable: true + exec_enabled: + type: boolean + nullable: true + webhook_secret: + type: string + nullable: true + trigger_count: + type: integer + format: Int32 + nullable: true + control_system_id: + type: string + nullable: true + trigger_id: + type: string + nullable: true + zone_id: + type: string + nullable: true + name: + type: string + nullable: true + control_system: + type: object + properties: + name: + type: string + id: + type: string + required: + - name + - id + nullable: true + PlaceOS__Api__SystemTriggers__UpdateParams: + type: object + properties: + enabled: + type: boolean + nullable: true + important: + type: boolean + nullable: true + exec_enabled: + type: boolean + nullable: true + PlaceOS__Model__Trigger: + type: object + properties: + id: + type: string + nullable: true + created_at: + type: string + format: date-time + nullable: true + updated_at: + type: string + format: date-time + nullable: true + name: + type: string + nullable: true + description: + type: string + nullable: true + actions: + type: object + properties: + functions: + type: array + items: + type: object + properties: + mod: + type: string + nullable: true + method: + type: string + nullable: true + args: + type: object + additionalProperties: + type: object + nullable: true + nullable: true + mailers: + type: array + items: + type: object + properties: + emails: + type: array + items: + type: string + nullable: true + content: + type: string + nullable: true + nullable: true + nullable: true + conditions: + type: object + properties: + comparisons: + type: array + items: + type: object + properties: + left: + anyOf: + - type: boolean + - type: number + format: Float64 + - type: integer + format: Int64 + - type: object + properties: + mod: + type: string + status: + type: string + keys: + type: array + items: + type: string + required: + - mod + - status + - keys + - type: string + nullable: true + operator: + type: string + enum: + - and + - equal + - exclusive_or + - greater_than + - greater_than_or_equal + - less_than + - less_than_or_equal + - not_equal + - or + nullable: true + right: + anyOf: + - type: boolean + - type: number + format: Float64 + - type: integer + format: Int64 + - type: object + properties: + mod: + type: string + status: + type: string + keys: + type: array + items: + type: string + required: + - mod + - status + - keys + - type: string + nullable: true + nullable: true + time_dependents: + type: array + items: + type: object + properties: + type: + type: string + enum: + - at + - cron + nullable: true + time: + type: string + format: date-time + nullable: true + cron: + type: string + nullable: true + timezone: + type: string + nullable: true + nullable: true + nullable: true + debounce_period: + type: integer + format: Int32 + nullable: true + important: + type: boolean + nullable: true + enable_webhook: + type: boolean + nullable: true + supported_methods: + type: array + items: + type: string + nullable: true + control_system_id: + type: string + nullable: true + trigger_instances: + type: array + items: + type: object + properties: + id: + type: string + nullable: true + created_at: + type: string + format: date-time + nullable: true + updated_at: + type: string + format: date-time + nullable: true + enabled: + type: boolean + nullable: true + triggered: + type: boolean + nullable: true + important: + type: boolean + nullable: true + exec_enabled: + type: boolean + nullable: true + webhook_secret: + type: string + nullable: true + trigger_count: + type: integer + format: Int32 + nullable: true + control_system_id: + type: string + nullable: true + trigger_id: + type: string + nullable: true + zone_id: + type: string + nullable: true + name: + type: string + nullable: true + control_system: + type: object + properties: + name: + type: string + id: + type: string + required: + - name + - id + nullable: true + nullable: true + PlaceOS__Model__User__AdminResponse: + type: object + properties: + created_at: + type: string + format: date-time + name: + type: string + nickname: + type: string + email: + type: string + format: email + phone: + type: string + country: + type: string + image: + type: string + ui_theme: + type: string + misc: + type: string + login_name: + type: string + nullable: true + staff_id: + type: string + nullable: true + first_name: + type: string + nullable: true + last_name: + type: string + nullable: true + building: + type: string + nullable: true + department: + type: string + nullable: true + preferred_language: + type: string + nullable: true + email_digest: + type: string + nullable: true + card_number: + type: string + nullable: true + deleted: + type: boolean + groups: + type: array + items: + type: string + sys_admin: + type: boolean + support: + type: boolean + authority_id: + type: string + nullable: true + id: + type: string + nullable: true + required: + - created_at + - name + - nickname + - email + - phone + - country + - image + - ui_theme + - misc + - deleted + - groups + - sys_admin + - support + PlaceOS__Api__Users__AccessToken: + type: object + properties: + token: + type: string + expires: + type: integer + format: Int64 + nullable: true + required: + - token + ? _PlaceOS__Model__User__AdminMetadataResponse___PlaceOS__Model__User__AdminResponse___PlaceOS__Model__User__PublicMetadataResponse___PlaceOS__Model__User__PublicResponse_ + : anyOf: + - type: object + properties: + created_at: + type: string + format: date-time + name: + type: string + nickname: + type: string + email: + type: string + format: email + phone: + type: string + country: + type: string + image: + type: string + ui_theme: + type: string + misc: + type: string + login_name: + type: string + nullable: true + staff_id: + type: string + nullable: true + first_name: + type: string + nullable: true + last_name: + type: string + nullable: true + building: + type: string + nullable: true + department: + type: string + nullable: true + preferred_language: + type: string + nullable: true + email_digest: + type: string + nullable: true + card_number: + type: string + nullable: true + deleted: + type: boolean + groups: + type: array + items: + type: string + sys_admin: + type: boolean + support: + type: boolean + authority_id: + type: string + nullable: true + id: + type: string + nullable: true + required: + - created_at + - name + - nickname + - email + - phone + - country + - image + - ui_theme + - misc + - deleted + - groups + - sys_admin + - support + - type: object + properties: + created_at: + type: string + format: date-time + name: + type: string + nickname: + type: string + email: + type: string + format: email + phone: + type: string + country: + type: string + image: + type: string + ui_theme: + type: string + misc: + type: string + login_name: + type: string + nullable: true + staff_id: + type: string + nullable: true + first_name: + type: string + nullable: true + last_name: + type: string + nullable: true + building: + type: string + nullable: true + department: + type: string + nullable: true + preferred_language: + type: string + nullable: true + email_digest: + type: string + nullable: true + card_number: + type: string + nullable: true + deleted: + type: boolean + groups: + type: array + items: + type: string + sys_admin: + type: boolean + support: + type: boolean + authority_id: + type: string + nullable: true + id: + type: string + nullable: true + required: + - created_at + - name + - nickname + - email + - phone + - country + - image + - ui_theme + - misc + - deleted + - groups + - sys_admin + - support + - type: object + properties: + created_at: + type: string + format: date-time + name: + type: string + nickname: + type: string + email: + type: string + format: email + phone: + type: string + country: + type: string + image: + type: string + staff_id: + type: string + nullable: true + first_name: + type: string + nullable: true + last_name: + type: string + nullable: true + building: + type: string + nullable: true + department: + type: string + nullable: true + preferred_language: + type: string + nullable: true + email_digest: + type: string + nullable: true + deleted: + type: boolean + groups: + type: array + items: + type: string + authority_id: + type: string + nullable: true + id: + type: string + nullable: true + required: + - created_at + - name + - nickname + - email + - phone + - country + - image + - deleted + - groups + - type: object + properties: + created_at: + type: string + format: date-time + name: + type: string + nickname: + type: string + email: + type: string + format: email + phone: + type: string + country: + type: string + image: + type: string + staff_id: + type: string + nullable: true + first_name: + type: string + nullable: true + last_name: + type: string + nullable: true + building: + type: string + nullable: true + department: + type: string + nullable: true + preferred_language: + type: string + nullable: true + email_digest: + type: string + nullable: true + deleted: + type: boolean + groups: + type: array + items: + type: string + authority_id: + type: string + nullable: true + id: + type: string + nullable: true + required: + - created_at + - name + - nickname + - email + - phone + - country + - image + - deleted + - groups + PlaceOS__Model__User: + type: object + properties: + id: + type: string + nullable: true + created_at: + type: string + format: date-time + nullable: true + updated_at: + type: string + format: date-time + nullable: true + name: + type: string + nullable: true + nickname: + type: string + nullable: true + email: + type: string + format: email + nullable: true + phone: + type: string + nullable: true + country: + type: string + nullable: true + image: + type: string + nullable: true + ui_theme: + type: string + nullable: true + misc: + type: string + nullable: true + login_name: + type: string + nullable: true + staff_id: + type: string + nullable: true + first_name: + type: string + nullable: true + last_name: + type: string + nullable: true + building: + type: string + nullable: true + department: + type: string + nullable: true + preferred_language: + type: string + nullable: true + password_digest: + type: string + nullable: true + email_digest: + type: string + nullable: true + card_number: + type: string + nullable: true + deleted: + type: boolean + nullable: true + groups: + type: array + items: + type: string + nullable: true + access_token: + type: string + nullable: true + refresh_token: + type: string + nullable: true + expires_at: + type: integer + format: Int64 + nullable: true + expires: + type: boolean + nullable: true + password: + type: string + nullable: true + sys_admin: + type: boolean + nullable: true + support: + type: boolean + nullable: true + authority_id: + type: string + nullable: true + admin_destroy_lock: + type: object + properties: + id: + type: string + nullable: true + key: + type: string + nullable: true + instance_token: + type: string + nullable: true + expires_at: + type: string + format: date-time + nullable: true + nullable: true + PlaceOS__Model__User__GroupResponse: + type: object + properties: + groups: + type: array + items: + type: string + id: + type: string + nullable: true + required: + - groups + PlaceOS__Api__GuestParticipant: + type: object + properties: + captcha: + type: string + name: + type: string + email: + type: string + nullable: true + phone: + type: string + nullable: true + type: + type: string + nullable: true + chat_to_user_id: + type: string + nullable: true + user_id: + type: string + session_id: + type: string + required: + - captcha + - name + - user_id + - session_id + PlaceOS__Api__KickReason: + type: object + properties: + reason: + type: string + required: + - reason + _JSON__Any___Nil_: + type: object + nullable: true + PlaceOS__Api__WebRTC__RoomDetails: + type: object + properties: + system: + type: object + properties: + id: + type: string + nullable: true + created_at: + type: string + format: date-time + nullable: true + updated_at: + type: string + format: date-time + nullable: true + name: + type: string + nullable: true + description: + type: string + nullable: true + features: + type: array + items: + type: string + nullable: true + email: + type: string + format: email + nullable: true + bookable: + type: boolean + nullable: true + public: + type: boolean + nullable: true + display_name: + type: string + nullable: true + code: + type: string + nullable: true + type: + type: string + nullable: true + capacity: + type: integer + format: Int32 + nullable: true + map_id: + type: string + nullable: true + images: + type: array + items: + type: string + nullable: true + timezone: + type: object + nullable: true + support_url: + type: string + nullable: true + version: + type: integer + format: Int32 + nullable: true + installed_ui_devices: + type: integer + format: Int32 + nullable: true + zones: + type: array + items: + type: string + nullable: true + modules: + type: array + items: + type: string + nullable: true + remove_zones: + type: array + items: + type: string + nullable: true + add_zones: + type: array + items: + type: string + nullable: true + zone_data: + type: array + items: + type: object + properties: + id: + type: string + nullable: true + created_at: + type: string + format: date-time + nullable: true + updated_at: + type: string + format: date-time + nullable: true + name: + type: string + nullable: true + description: + type: string + nullable: true + tags: + type: array + items: + type: string + nullable: true + location: + type: string + nullable: true + display_name: + type: string + nullable: true + code: + type: string + nullable: true + type: + type: string + nullable: true + count: + type: integer + format: Int32 + nullable: true + capacity: + type: integer + format: Int32 + nullable: true + map_id: + type: string + nullable: true + timezone: + type: object + nullable: true + triggers: + type: array + items: + type: string + nullable: true + images: + type: array + items: + type: string + nullable: true + parent_id: + type: string + nullable: true + remove_triggers: + type: array + items: + type: string + nullable: true + add_triggers: + type: array + items: + type: string + nullable: true + trigger_data: + type: array + items: + type: object + properties: + id: + type: string + nullable: true + created_at: + type: string + format: date-time + nullable: true + updated_at: + type: string + format: date-time + nullable: true + name: + type: string + nullable: true + description: + type: string + nullable: true + actions: + type: object + properties: + functions: + type: array + items: + type: object + properties: + mod: + type: string + nullable: true + method: + type: string + nullable: true + args: + type: object + additionalProperties: + type: object + nullable: true + nullable: true + mailers: + type: array + items: + type: object + properties: + emails: + type: array + items: + type: string + nullable: true + content: + type: string + nullable: true + nullable: true + nullable: true + conditions: + type: object + properties: + comparisons: + type: array + items: + type: object + properties: + left: + anyOf: + - type: boolean + - type: number + format: Float64 + - type: integer + format: Int64 + - type: object + properties: + mod: + type: string + status: + type: string + keys: + type: array + items: + type: string + required: + - mod + - status + - keys + - type: string + nullable: true + operator: + type: string + enum: + - and + - equal + - exclusive_or + - greater_than + - greater_than_or_equal + - less_than + - less_than_or_equal + - not_equal + - or + nullable: true + right: + anyOf: + - type: boolean + - type: number + format: Float64 + - type: integer + format: Int64 + - type: object + properties: + mod: + type: string + status: + type: string + keys: + type: array + items: + type: string + required: + - mod + - status + - keys + - type: string + nullable: true + nullable: true + time_dependents: + type: array + items: + type: object + properties: + type: + type: string + enum: + - at + - cron + nullable: true + time: + type: string + format: date-time + nullable: true + cron: + type: string + nullable: true + timezone: + type: string + nullable: true + nullable: true + nullable: true + debounce_period: + type: integer + format: Int32 + nullable: true + important: + type: boolean + nullable: true + enable_webhook: + type: boolean + nullable: true + supported_methods: + type: array + items: + type: string + nullable: true + control_system_id: + type: string + nullable: true + trigger_instances: + type: array + items: + type: object + properties: + id: + type: string + nullable: true + created_at: + type: string + format: date-time + nullable: true + updated_at: + type: string + format: date-time + nullable: true + enabled: + type: boolean + nullable: true + triggered: + type: boolean + nullable: true + important: + type: boolean + nullable: true + exec_enabled: + type: boolean + nullable: true + webhook_secret: + type: string + nullable: true + trigger_count: + type: integer + format: Int32 + nullable: true + control_system_id: + type: string + nullable: true + trigger_id: + type: string + nullable: true + zone_id: + type: string + nullable: true + name: + type: string + nullable: true + control_system: + type: object + properties: + name: + type: string + id: + type: string + required: + - name + - id + nullable: true + nullable: true + nullable: true + update_systems: + type: boolean + required: + - update_systems + nullable: true + module_data: + type: array + items: + type: object + properties: + id: + type: string + nullable: true + created_at: + type: string + format: date-time + nullable: true + updated_at: + type: string + format: date-time + nullable: true + ip: + type: string + nullable: true + port: + type: integer + format: Int32 + nullable: true + tls: + type: boolean + nullable: true + udp: + type: boolean + nullable: true + makebreak: + type: boolean + nullable: true + uri: + type: string + nullable: true + name: + type: string + nullable: true + custom_name: + type: string + nullable: true + role: + type: string + enum: + - ssh + - device + - service + - websocket + - logic + nullable: true + connected: + type: boolean + nullable: true + running: + type: boolean + nullable: true + notes: + type: string + nullable: true + ignore_connected: + type: boolean + nullable: true + ignore_startstop: + type: boolean + nullable: true + control_system_id: + type: string + nullable: true + driver_id: + type: string + nullable: true + edge_id: + type: string + nullable: true + driver: + type: object + properties: + name: + type: string + description: + type: string + nullable: true + module_name: + type: string + nullable: true + required: + - name + nullable: true + compiled: + type: boolean + nullable: true + control_system: + type: object + properties: + name: + type: string + zone_data: + type: array + items: + type: object + properties: + id: + type: string + nullable: true + created_at: + type: string + format: date-time + nullable: true + updated_at: + type: string + format: date-time + nullable: true + name: + type: string + nullable: true + description: + type: string + nullable: true + tags: + type: array + items: + type: string + nullable: true + location: + type: string + nullable: true + display_name: + type: string + nullable: true + code: + type: string + nullable: true + type: + type: string + nullable: true + count: + type: integer + format: Int32 + nullable: true + capacity: + type: integer + format: Int32 + nullable: true + map_id: + type: string + nullable: true + timezone: + type: object + nullable: true + triggers: + type: array + items: + type: string + nullable: true + images: + type: array + items: + type: string + nullable: true + parent_id: + type: string + nullable: true + remove_triggers: + type: array + items: + type: string + nullable: true + add_triggers: + type: array + items: + type: string + nullable: true + trigger_data: + type: array + items: + type: object + properties: + id: + type: string + nullable: true + created_at: + type: string + format: date-time + nullable: true + updated_at: + type: string + format: date-time + nullable: true + name: + type: string + nullable: true + description: + type: string + nullable: true + actions: + type: object + properties: + functions: + type: array + items: + type: object + properties: + mod: + type: string + nullable: true + method: + type: string + nullable: true + args: + type: object + additionalProperties: + type: object + nullable: true + nullable: true + mailers: + type: array + items: + type: object + properties: + emails: + type: array + items: + type: string + nullable: true + content: + type: string + nullable: true + nullable: true + nullable: true + conditions: + type: object + properties: + comparisons: + type: array + items: + type: object + properties: + left: + anyOf: + - type: boolean + - type: number + format: Float64 + - type: integer + format: Int64 + - type: object + properties: + mod: + type: string + status: + type: string + keys: + type: array + items: + type: string + required: + - mod + - status + - keys + - type: string + nullable: true + operator: + type: string + enum: + - and + - equal + - exclusive_or + - greater_than + - greater_than_or_equal + - less_than + - less_than_or_equal + - not_equal + - or + nullable: true + right: + anyOf: + - type: boolean + - type: number + format: Float64 + - type: integer + format: Int64 + - type: object + properties: + mod: + type: string + status: + type: string + keys: + type: array + items: + type: string + required: + - mod + - status + - keys + - type: string + nullable: true + nullable: true + time_dependents: + type: array + items: + type: object + properties: + type: + type: string + enum: + - at + - cron + nullable: true + time: + type: string + format: date-time + nullable: true + cron: + type: string + nullable: true + timezone: + type: string + nullable: true + nullable: true + nullable: true + debounce_period: + type: integer + format: Int32 + nullable: true + important: + type: boolean + nullable: true + enable_webhook: + type: boolean + nullable: true + supported_methods: + type: array + items: + type: string + nullable: true + control_system_id: + type: string + nullable: true + trigger_instances: + type: array + items: + type: object + properties: + id: + type: string + nullable: true + created_at: + type: string + format: date-time + nullable: true + updated_at: + type: string + format: date-time + nullable: true + enabled: + type: boolean + nullable: true + triggered: + type: boolean + nullable: true + important: + type: boolean + nullable: true + exec_enabled: + type: boolean + nullable: true + webhook_secret: + type: string + nullable: true + trigger_count: + type: integer + format: Int32 + nullable: true + control_system_id: + type: string + nullable: true + trigger_id: + type: string + nullable: true + zone_id: + type: string + nullable: true + name: + type: string + nullable: true + control_system: + type: object + properties: + name: + type: string + id: + type: string + required: + - name + - id + nullable: true + nullable: true + nullable: true + update_systems: + type: boolean + required: + - update_systems + required: + - name + - zone_data + nullable: true nullable: true - nullable: true - PlaceOS__Model__User__GroupResponse: - type: object - properties: - groups: - type: array - items: - type: string - id: - type: string - nullable: true + update_triggers: + type: boolean + required: + - update_triggers + metadata: + type: object + additionalProperties: + type: object + properties: + name: + type: string + description: + type: string + details: + type: object + parent_id: + type: string + nullable: true + schema_id: + type: string + nullable: true + editors: + type: array + items: + type: string + modified_by_id: + type: string + nullable: true + updated_at: + type: string + format: date-time + created_at: + type: string + format: date-time + required: + - name + - description + - details + - editors + - updated_at + - created_at required: - - groups + - system + - metadata PlaceOS__Api__Zones__ZoneExecResponse: type: object properties: diff --git a/shard.lock b/shard.lock index 42bb035b..9aaa1572 100644 --- a/shard.lock +++ b/shard.lock @@ -7,7 +7,7 @@ shards: action-controller: git: https://github.com/spider-gazelle/action-controller.git - version: 5.5.4 + version: 5.6.2 active-model: git: https://github.com/spider-gazelle/active-model.git @@ -15,7 +15,7 @@ shards: ameba: git: https://github.com/crystal-ameba/ameba.git - version: 1.4.0 + version: 1.4.2 any_hash: git: https://github.com/sija/any_hash.cr.git @@ -171,7 +171,7 @@ shards: openssl_ext: git: https://github.com/spider-gazelle/openssl_ext.git - version: 2.2.1 + version: 2.3.0 opentelemetry-api: git: https://github.com/wyhaines/opentelemetry-api.cr.git @@ -203,7 +203,7 @@ shards: placeos-core: git: https://github.com/placeos/core.git - version: 4.9.0+git.commit.e5450a48ed8b4ebaf7b1d78774261025ea1f654d + version: 4.9.2+git.commit.fd790705c4faca54a68da64268ac271b579b0c49 placeos-core-client: # Overridden git: https://github.com/placeos/core-client.git @@ -211,7 +211,7 @@ shards: placeos-driver: git: https://github.com/placeos/driver.git - version: 6.7.2 + version: 6.7.4 placeos-frontend-loader: git: https://github.com/placeos/frontend-loader.git @@ -223,7 +223,7 @@ shards: placeos-models: git: https://github.com/placeos/models.git - version: 8.13.2 + version: 8.13.3 placeos-resource: git: https://github.com/place-labs/resource.git @@ -231,7 +231,7 @@ shards: pool: git: https://github.com/ysbaddaden/pool.git - version: 0.2.4 + version: 0.3.0 promise: git: https://github.com/spider-gazelle/promise.git @@ -243,11 +243,11 @@ shards: raven: git: https://github.com/sija/raven.cr.git - version: 1.9.2+git.commit.de91bb38858124270ea06be61641153b8947e18f + version: 1.9.3+git.commit.f328bfdafe335f31e476c275fd434ac16049adea redis: git: https://github.com/stefanwille/crystal-redis.git - version: 2.8.3 + version: 2.9.0 redis-cluster: git: https://github.com/caspiano/redis-cluster.cr.git diff --git a/spec/controllers/modules_spec.cr b/spec/controllers/modules_spec.cr index 137a2997..4b30cca1 100644 --- a/spec/controllers/modules_spec.cr +++ b/spec/controllers/modules_spec.cr @@ -85,8 +85,9 @@ module PlaceOS::Api sys.save! # Call the index method of the controller + params = HTTP::Params{"control_system_id" => sys.id.as(String)} response = client.get( - "#{Modules.base_route}?#{HTTP::Params{"control_system_id" => sys.id.as(String)}}", + "#{Modules.base_route}?#{params}", headers: Spec::Authentication.headers, ) diff --git a/spec/controllers/repositories_spec.cr b/spec/controllers/repositories_spec.cr index c8fb6320..93506e48 100644 --- a/spec/controllers/repositories_spec.cr +++ b/spec/controllers/repositories_spec.cr @@ -32,7 +32,7 @@ module PlaceOS::Api end describe "mutating URIs" do - it "does not update Driver repositories with modified URIs" do + it "does update Driver repositories with modified URIs" do repository = Model::Generator.repository(type: Model::Repository::Type::Driver).save! id = repository.id.as(String) @@ -43,7 +43,7 @@ module PlaceOS::Api headers: Spec::Authentication.headers, ) - result.status_code.should eq 422 + result.status_code.should eq 200 end it "does update Interface repositories with modified URIs" do diff --git a/spec/webrtc/clustered_sessions_spec.cr b/spec/webrtc/clustered_sessions_spec.cr new file mode 100644 index 00000000..99b58636 --- /dev/null +++ b/spec/webrtc/clustered_sessions_spec.cr @@ -0,0 +1,36 @@ +require "../helper" + +module PlaceOS::Api + describe ClusteredSessions do + sessions = ClusteredSessions.new + session_id = UUID.random.to_s + user_id = UUID.random.to_s + + before_each do + sessions = ClusteredSessions.new + session_id = UUID.random.to_s + user_id = UUID.random.to_s + end + + it "adds a user to a session" do + sessions.local_sessions.should eq [] of String + sessions.add_user(session_id, user_id) + sessions.local_sessions.should eq [session_id] + sessions.user_list(session_id).should eq [user_id] + + sessions.lookup_session(user_id).should eq session_id + end + + it "removes a user from a session" do + sessions.add_user(session_id, user_id) + sessions.user_list(session_id).should eq [user_id] + sessions.remove_user(session_id, user_id) + sessions.user_list(session_id).should eq [] of String + sessions.local_sessions.should eq [] of String + end + + it "list users even if the session doesn't exist" do + sessions.user_list(session_id).should eq [] of String + end + end +end diff --git a/spec/webrtc/signaller_spec.cr b/spec/webrtc/signaller_spec.cr new file mode 100644 index 00000000..2194f1a8 --- /dev/null +++ b/spec/webrtc/signaller_spec.cr @@ -0,0 +1,74 @@ +require "../helper" + +module PlaceOS::Api + describe WebRTC do + it "opens a websocket session" do + updates = [] of SessionSignal + + on_message = ->(message : String) { + updates << SessionSignal.from_json message + } + + session_id = UUID.random.to_s + user_id = UUID.random.to_s + transfer = {login: "user", pass: "pass"}.to_json + + signaller(on_message) do |ws| + ws.closed?.should be_false + ws.send(SessionSignal.new( + id: "SIGNAL::#{Time.utc.to_unix_ms}+#{Random::Secure.hex(6)}", + type: :join, + session_id: session_id, + user_id: user_id, + to_user: "server", + value: nil + ).to_json) + sleep 0.5 + updates.size.should eq 2 + + sessions = CallDetails::SESSIONS + sessions.user_list(session_id).should eq [user_id] + sessions.lookup_session(user_id).should eq session_id + + # test transfer signal + # WebRTC::MANAGER.transfer(user_id, session_id, transfer) + client.post( + path: "/api/engine/v2/webrtc/transfer/#{user_id}/#{session_id}", + body: transfer, + headers: Spec::Authentication.headers, + ) + sleep 0.5 + updates.size.should eq 3 + updates[-1].value.should eq transfer + + # test kick user + # MANAGER.kick_user(auth_id, user_id, session_id, details) + client.post( + path: "/api/engine/v2/webrtc/kick/#{user_id}/#{session_id}", + body: {reason: "bad user"}.to_json, + headers: Spec::Authentication.headers, + ) + sleep 0.5 + updates.size.should eq 4 + ws.closed?.should be_true + end + end + end +end + +def signaller(on_message : Proc(String, _) = ->(_msg : String) {}, &) + host = "localhost" + bearer = PlaceOS::Api::Spec::Authentication.headers["Authorization"].split(' ').last + path = File.join(PlaceOS::Api::WebRTC.base_route, "signaller?bearer_token=#{bearer}") + + # Create a websocket connection, then run the session + socket = client.establish_ws(path, headers: HTTP::Headers{"Host" => host}) + + socket.on_message &on_message + + spawn(same_thread: true) { socket.run } + + yield socket + + socket.close +end diff --git a/spec/websocket/session_spec.cr b/spec/websocket/session_spec.cr index 91fc982e..a4ee42c1 100644 --- a/spec/websocket/session_spec.cr +++ b/spec/websocket/session_spec.cr @@ -180,7 +180,7 @@ end # Binds to the system websocket endpoint # -def bind(base, auth, on_message : Proc(String, _) = ->(_msg : String) {}) +def bind(base, auth, on_message : Proc(String, _) = ->(_msg : String) {}, &) host = "localhost" bearer = auth["Authorization"].split(' ').last path = File.join(base, "control?bearer_token=#{bearer}") @@ -200,7 +200,7 @@ end # Binds to the websocket API # Yields API websocket, and a control system + module # Cleans up the websocket and models -def test_websocket_api(base, headers) +def test_websocket_api(base, headers, &) # Create a System control_system = PlaceOS::Model::Generator.control_system.save! @@ -228,7 +228,7 @@ def test_websocket_api(base, headers) {updates, control_system, mod} end -def test_websocket_exec(base, headers) +def test_websocket_exec(base, headers, &) control_system = PlaceOS::Model::Generator.control_system.save! mod = PlaceOS::Model::Generator.module(control_system: control_system).save! diff --git a/src/constants.cr b/src/constants.cr index 59b55d44..42e5fac7 100644 --- a/src/constants.cr +++ b/src/constants.cr @@ -22,6 +22,9 @@ module PlaceOS::Api INFLUX_HOST = ENV["INFLUX_HOST"]? INFLUX_ORG = ENV["INFLUX_ORG"]? || "placeos" + # https://developer.mozilla.org/en-US/docs/Web/API/RTCIceServer + WEBRTC_DEFAULT_ICE_CONFIG = ENV["WEBRTC_DEFAULT_ICE_CONFIG"]? || {urls: "stun:stun.l.google.com:19302"}.to_json + # server defaults in `./app.cr` TRIGGERS_URI = URI.parse(ENV["TRIGGERS_URI"]? || "http://triggers:3000") diff --git a/src/placeos-rest-api/controllers/application.cr b/src/placeos-rest-api/controllers/application.cr index 436bcd84..d0223671 100644 --- a/src/placeos-rest-api/controllers/application.cr +++ b/src/placeos-rest-api/controllers/application.cr @@ -102,12 +102,12 @@ module PlaceOS::Api # Callbacks ########################################################################### - # All routes are authenticated, except root + # All routes are authenticated # NOTE:: we don't need these to use strong params - before_action :authorize!, except: [:root, :mqtt_user, :mqtt_access] + before_action :authorize! # Simplifies determining user's requests in server-side logs - before_action :set_user_id, except: [:root, :mqtt_user, :mqtt_access] + before_action :set_user_id def set_user_id Log.context.set(user_id: user_token.id) diff --git a/src/placeos-rest-api/controllers/drivers.cr b/src/placeos-rest-api/controllers/drivers.cr index 01e4f757..2d9b7f5d 100644 --- a/src/placeos-rest-api/controllers/drivers.cr +++ b/src/placeos-rest-api/controllers/drivers.cr @@ -97,7 +97,7 @@ module PlaceOS::Api if current_driver.commit.starts_with?("RECOMPILE") nil else - if (recompiled = Drivers.recompile(current_driver)) + if recompiled = Drivers.recompile(current_driver) if recompiled.destroyed? raise Error::NotFound.new("driver was deleted") else @@ -114,8 +114,7 @@ module PlaceOS::Api driver.update_fields(commit: "RECOMPILE-#{driver.commit}") # Wait until the commit hash is not head with a timeout of 90 seconds - # ameba:disable Style/RedundantReturn - return Utils::Changefeeds.await_model_change(driver, timeout: 90.seconds) do |update| + Utils::Changefeeds.await_model_change(driver, timeout: 90.seconds) do |update| update.destroyed? || !update.recompile_commit? end end diff --git a/src/placeos-rest-api/controllers/edges.cr b/src/placeos-rest-api/controllers/edges.cr index aca75e98..b2cd2786 100644 --- a/src/placeos-rest-api/controllers/edges.cr +++ b/src/placeos-rest-api/controllers/edges.cr @@ -58,7 +58,7 @@ module PlaceOS::Api # admins can obtain the token edge nodes will use to connect to the cluster @[AC::Route::GET("/:id/token")] def token : NamedTuple(token: String) - raise Error::Forbidden.new("not an admin") unless is_admin? + raise Error::Forbidden.new("not an admin") unless user_admin? {token: current_edge.x_api_key} end diff --git a/src/placeos-rest-api/controllers/metadata.cr b/src/placeos-rest-api/controllers/metadata.cr index 4b9eb726..267da6c6 100644 --- a/src/placeos-rest-api/controllers/metadata.cr +++ b/src/placeos-rest-api/controllers/metadata.cr @@ -23,7 +23,7 @@ module PlaceOS::Api parent_id : String ) # NOTE: Will the user token ever be assigned a zone id? - raise Error::Forbidden.new unless is_support? || parent_id == user_token.id + raise Error::Forbidden.new unless user_support? || parent_id == user_token.id end ############################################################################################### diff --git a/src/placeos-rest-api/controllers/mqtt.cr b/src/placeos-rest-api/controllers/mqtt.cr index e962457e..33fa9057 100644 --- a/src/placeos-rest-api/controllers/mqtt.cr +++ b/src/placeos-rest-api/controllers/mqtt.cr @@ -4,6 +4,10 @@ module PlaceOS::Api class MQTT < Application base "/api/engine/v2/mqtt/" + # skip authentication for the healthcheck + skip_action :authorize!, only: [:mqtt_user, :mqtt_access] + skip_action :set_user_id, only: [:mqtt_user, :mqtt_access] + # For MQTT JWT access: https://github.com/iegomez/mosquitto-go-auth#remote-mode # jwt_response_mode: status, jwt_params_mode: form @[AC::Route::POST("/user")] @@ -38,7 +42,7 @@ module PlaceOS::Api # - x-api-key # - JWTs protected def mqtt_parse_jwt(validate : Bool = true) - unless (auth = request.headers["Authorization"]?) + unless auth = request.headers["Authorization"]? raise Error::Unauthorized.new("missing mqtt token") end @@ -46,7 +50,7 @@ module PlaceOS::Api when 1 # work with x-api-key @user_token = Model::ApiKey.find_key!(auth.lchop("Bearer ").rstrip).build_jwt when 2 # work with jwt-token - unless (token = acquire_token) + unless token = acquire_token raise Error::Unauthorized.new("missing mqtt token") end diff --git a/src/placeos-rest-api/controllers/repositories.cr b/src/placeos-rest-api/controllers/repositories.cr index a6d33505..2f51c3d3 100644 --- a/src/placeos-rest-api/controllers/repositories.cr +++ b/src/placeos-rest-api/controllers/repositories.cr @@ -58,11 +58,6 @@ module PlaceOS::Api current = current_repo current.assign_attributes(repo) - # Must destroy and re-add to change driver repository URIs - if current.uri_changed? && current.repo_type.driver? - raise Error::ModelValidation.new({Error::Field.new(:uri, "`uri` of Driver repositories cannot change")}) - end - raise Error::ModelValidation.new(current.errors) unless current.save current end diff --git a/src/placeos-rest-api/controllers/root.cr b/src/placeos-rest-api/controllers/root.cr index 6fc81ccd..481a84fc 100644 --- a/src/placeos-rest-api/controllers/root.cr +++ b/src/placeos-rest-api/controllers/root.cr @@ -28,6 +28,10 @@ module PlaceOS::Api # Healthcheck ############################################################################################### + # skip authentication for the healthcheck + skip_action :authorize!, only: :root + skip_action :set_user_id, only: :root + # returns 200 OK when the service is healthy (can connect to the databases etc) @[AC::Route::GET("/")] def root : Nil @@ -48,7 +52,7 @@ module PlaceOS::Api ).then(&.all?).get end - private def self.check_resource?(resource) + private def self.check_resource?(resource, &) Log.trace { "healthchecking #{resource}" } !!yield rescue e diff --git a/src/placeos-rest-api/controllers/system-triggers.cr b/src/placeos-rest-api/controllers/system-triggers.cr index ae5537dc..d37a23c3 100644 --- a/src/placeos-rest-api/controllers/system-triggers.cr +++ b/src/placeos-rest-api/controllers/system-triggers.cr @@ -162,7 +162,7 @@ module PlaceOS::Api trigger_instance.control_system_details = ControlSystemDetails.new(cs.name.as(String), cs.id.as(String)) end trigger_instance.name = trigger_instance.trigger.try &.name - trigger_instance.hide_secret unless is_admin? + trigger_instance.hide_secret unless user_admin? trigger_instance end end diff --git a/src/placeos-rest-api/controllers/systems.cr b/src/placeos-rest-api/controllers/systems.cr index dcf0f2f0..bab43ddd 100644 --- a/src/placeos-rest-api/controllers/systems.cr +++ b/src/placeos-rest-api/controllers/systems.cr @@ -93,7 +93,9 @@ module PlaceOS::Api @[AC::Param::Info(description: "return systems which are using the trigger id provided", example: "trig-1234")] trigger_id : String? = nil, @[AC::Param::Info(description: "return systems which are in the zone provided", example: "zone-1234")] - zone_id : String? = nil + zone_id : String? = nil, + @[AC::Param::Info(description: "return systems which are public", example: "true")] + public : Bool? = nil ) : Array(Model::ControlSystem) elastic = Model::ControlSystem.elastic query = Model::ControlSystem.elastic.query(search_params) @@ -150,6 +152,13 @@ module PlaceOS::Api }) end + # filter by public + if public + query.should({ + "public" => [true], + }) + end + query.search_field "name" query.sort(NAME_SORT_ASC) paginate_results(elastic, query) diff --git a/src/placeos-rest-api/controllers/users.cr b/src/placeos-rest-api/controllers/users.cr index 75ed5e6d..0840f3d3 100644 --- a/src/placeos-rest-api/controllers/users.cr +++ b/src/placeos-rest-api/controllers/users.cr @@ -61,7 +61,7 @@ module PlaceOS::Api @[AC::Route::Filter(:before_action, only: [:update])] protected def check_authorization # Does the current user have permission to perform the current action - raise Error::Forbidden.new unless user.id == current_user.id || is_admin? + raise Error::Forbidden.new unless user.id == current_user.id || user_admin? end ############################################################################################### @@ -172,14 +172,14 @@ module PlaceOS::Api query.must_not({"deleted" => [true]}) unless include_deleted - if !is_admin? + if !user_admin? # regular users can only see their own domain query.filter({"authority_id" => [current_user.authority_id.as(String)]}) elsif authority = authority_id query.filter({"authority_id" => [authority]}) end - if is_admin? + if user_admin? if include_metadata paginate_results(elastic, query).map &.to_admin_metadata_struct.as(UserDetails) else @@ -201,7 +201,7 @@ module PlaceOS::Api include_metadata : Bool = false ) : UserDetails # We only want to provide limited "public" information - if is_admin? + if user_admin? include_metadata ? user.to_admin_metadata_struct : user.to_admin_struct else include_metadata ? user.to_public_metadata_struct : user.to_public_struct @@ -230,7 +230,7 @@ module PlaceOS::Api # (the users themselves should not have access to these) body = new_user.to_json the_user = user - if is_admin? + if user_admin? the_user.assign_admin_attributes_from_json(body) end the_user.assign_attributes_from_json(body) diff --git a/src/placeos-rest-api/controllers/webrtc.cr b/src/placeos-rest-api/controllers/webrtc.cr new file mode 100644 index 00000000..611037ae --- /dev/null +++ b/src/placeos-rest-api/controllers/webrtc.cr @@ -0,0 +1,283 @@ +require "base64" +require "./application" +require "./webrtc/*" + +module PlaceOS::Api + class WebRTC < Application + base "/api/engine/v2/webrtc/" + + # skip authentication for guest_entry and room details + skip_action :authorize!, only: [:guest_entry, :public_room] + skip_action :set_user_id, only: [:guest_entry, :public_room] + + # allow guest access to the signalling route + before_action :can_read_guest, only: [:signaller, :guest_exit, :index] + + ############################################################################################### + + @[AC::Route::Filter(:before_action, only: [:guest_entry, :public_room])] + def find_current_control_system( + @[AC::Param::Info(description: "either a system id or a unique permalink", example: "sys-12345")] + system_id : String + ) + system = if system_id.starts_with? "sys-" + Model::ControlSystem.find!(system_id, runopts: {"read_mode" => "majority"}) + else + res = Model::ControlSystem.where(code: system_id).first? + raise Error::NotFound.new("could not find room #{system_id}") unless res + res + end + + # ensure the system is public + raise Error::NotFound.new("could not find room #{system_id}") unless system.public + + Log.context.set(control_system_id: system.id.not_nil!) + @current_control_system = system + end + + getter! current_control_system : Model::ControlSystem + + # Response helpers + ############################################################################################### + + struct CaptchaResponse + include JSON::Serializable + + property? success : Bool + end + + class PlaceOS::Api::Error + class RecaptchaFailed < Error + end + + class GuestAccessDisabled < Error + end + end + + ############################################################################################### + + # 401 if recaptcha fails + @[AC::Route::Exception(Error::RecaptchaFailed, status_code: HTTP::Status::UNAUTHORIZED)] + def recaptcha_failed(error) : CommonError + Log.debug { error.message } + CommonError.new(error, false) + end + + JWT_SECRET = ENV["JWT_SECRET"]?.try { |k| Base64.decode_string(k) } + + # this route provides guest access to an anonymous chat room + # the guest participant details will be forwarded to any listening systems + # additional fields provided as part of the guest post will also be forwarded + @[AC::Route::POST("/guest_entry/:system_id", body: guest)] + def guest_entry( + guest : GuestParticipant, + @[AC::Param::Info(description: "either a system id or a unique permalink", example: "sys-12345")] + system_id : String + ) : Nil + jwt_secret = JWT_SECRET + raise Error::GuestAccessDisabled.new("guest access not enabled") unless jwt_secret + + # captcha, name, phone, type, chat_to_user_id, room_id, guest_chat_id (user_id), session_id + authority = current_authority.not_nil! + if recaptcha_secret = authority.internals["recaptcha_secret"]?.try(&.as_s) + HTTP::Client.new("www.google.com", tls: true) do |client| + client.connect_timeout = 2 + + begin + captresp = client.post("/recaptcha/api/siteverify?secret=#{recaptcha_secret}&response=#{guest.captcha}") + if captresp.success? + result = CaptchaResponse.from_json(captresp.body) + raise Error::RecaptchaFailed.new("recaptcha rejected") unless result.success? + else + raise Error::RecaptchaFailed.new("error verifying recaptcha response") + end + rescue error + # We don't want chat to be out of action if google is down, so we'll continue + Log.error(exception: error) { "recaptcha failed" } + end + end + else + raise Error::RecaptchaFailed.new("recaptcha not configured") unless authority.internals["recaptcha_skip"]? == true + end + + expires = 12.hours.from_now + payload = { + iss: "POS", + iat: 1.minute.ago.to_unix, + exp: expires.to_unix, + jti: UUID.random.to_s, + aud: authority.domain, + scope: ["guest"], + sub: "guest-#{UUID.random}", + u: { + n: guest.name, + e: guest.email || "#{guest.phone}@phone" || "#{guest.name}@unknown", + p: 0, + r: [guest.user_id, system_id], + }, + } + + jwt = JWT.encode(payload, jwt_secret, JWT::Algorithm::RS256) + response.cookies << HTTP::Cookie.new( + name: "bearer_token", + value: jwt, + path: "/api/engine/v2/webrtc", + expires: expires, + secure: true, + http_only: true, + samesite: :strict + ) + + # check if there is alternative room handling the chat members + system = current_control_system + chat_system = system.id + system.zones.each do |zone_id| + meta = Model::Metadata.build_metadata(zone_id, "bindings") + if payload = meta["bindings"]?.try(&.details) + if chat_room = payload["chat_room"]?.try(&.as_s?) + chat_system = chat_room + break + end + end + end + + # signals routed to the system id that represents the application managing the chat + ::PlaceOS::Driver::RedisStorage.with_redis &.publish("placeos/#{authority.id}/chat/#{chat_system}/guest/entry", { + system.id.not_nil! => guest, + }.to_json) + end + + # Guest users should call this route when ending a call gracefully + # it will remove the authentication token and close any open websockets + @[AC::Route::POST("/guest/exit")] + def guest_exit : Nil + response.cookies << HTTP::Cookie.new( + name: "bearer_token", + value: "", + path: "/api/engine/v2/webrtc", + expires: Time.utc, + secure: true, + http_only: true, + samesite: :strict + ) + + token = user_token + if token.scope.first == "guest" && token.id.starts_with?("guest-") + user_id = token.user.roles.first + authority = current_authority.not_nil! + auth_id = authority.id.as(String) + self.class.end_call(user_id, auth_id) + end + end + + def self.end_call(user_id, auth_id) + spawn do + # give the browser a moment to update its cookie + # we don't want them reconnecting + sleep 1 + Log.info { "signalling end call for #{user_id} on #{auth_id}" } + MANAGER.end_call(user_id, auth_id) + end + end + + # Call ended for the user + # similar to guest exit without the token expiration + # other members of the call will stop communicating with them + @[AC::Route::POST("/kick/:user_id/:session_id", body: details)] + def kick_user(user_id : String, session_id : String, details : KickReason) : Nil + authority = current_authority.not_nil! + auth_id = authority.id.as(String) + MANAGER.kick_user(auth_id, user_id, session_id, details) + end + + # Obtain a list of the connected users in chat session provided + @[AC::Route::GET("/members/:session_id")] + def members(session_id : String) : Array(String) + MANAGER.member_list(session_id) + end + + # for authorised users to move people from one chat to another + # the body can be used to pass any custom connection details + @[AC::Route::POST("/transfer/:user_id/?:session_id", body: body, status: { + Nil => HTTP::Status::OK, + Bool => HTTP::Status::PRECONDITION_REQUIRED, + })] + def transfer_guest( + user_id : String, + session_id : String? = nil, + body : JSON::Any? = nil + ) : Nil | Bool + result = MANAGER.transfer(user_id, session_id, body.try &.to_json) + case result + in .signal_sent? + nil + in .no_session? + true + in .no_connection? + false + end + end + + struct RoomDetails + include JSON::Serializable + + getter system : Model::ControlSystem + getter metadata : Hash(String, PlaceOS::Model::Metadata::Interface) + + def initialize(@system, @metadata) + end + end + + # this route provides the details of a public chat room + # it takes either the system `id` or `code` for a more friendly lookup + @[AC::Route::GET("/room/:system_id")] + def public_room( + @[AC::Param::Info(description: "either a system id or a unique permalink", example: "sys-12345")] + system_id : String + ) : RoomDetails + system = current_control_system + meta = Model::Metadata.build_metadata(system.id.not_nil!, nil) + RoomDetails.new(system, meta) + end + + # this route provides a list of public chat rooms for the current domain + @[AC::Route::GET("/rooms")] + def index : Array(RoomDetails) + elastic = Model::ControlSystem.elastic + query = Model::ControlSystem.elastic.query(search_params) + query.must({ + "public" => [true], + }) + + if zone_id = current_authority.not_nil!.internals["webrtc_zone"]?.try(&.as_s?) + query.must({ + "zones" => [zone_id], + }) + end + + query.search_field "name" + query.sort(NAME_SORT_ASC) + paginate_results(elastic, query).map do |system| + meta = Model::Metadata.build_metadata(system.id.not_nil!, nil) + RoomDetails.new(system, meta) + end + end + + ICE_CONFIG = {} of String => String + MANAGER = ChatManager.new(ICE_CONFIG) + + # WebRTC signaller websocket endpoint, managing call participants + @[AC::Route::WebSocket("/signaller")] + def signaller(websocket) : Nil + Log.trace { {request_id: request_id, frame: "OPEN"} } + + authority = current_authority.not_nil! + auth_id = authority.id.as(String) + + # https://developer.mozilla.org/en-US/docs/Web/API/RTCIceServer + ICE_CONFIG[auth_id] = authority.internals["webrtc_ice"]?.try(&.to_json) || WEBRTC_DEFAULT_ICE_CONFIG + + MANAGER.handle_session(websocket, request_id, user_token.id, auth_id) + end + end +end diff --git a/src/placeos-rest-api/controllers/webrtc/call_details.cr b/src/placeos-rest-api/controllers/webrtc/call_details.cr new file mode 100644 index 00000000..964c749a --- /dev/null +++ b/src/placeos-rest-api/controllers/webrtc/call_details.cr @@ -0,0 +1,34 @@ +require "./clustered_sessions" + +module PlaceOS::Api + class CallDetails + getter id : String + getter peers : Hash(String, HTTP::WebSocket) + + getter created_at : Time + property updated_at : Time + + SESSIONS = ClusteredSessions.new + + def add(user_id : String, websocket : HTTP::WebSocket) + SESSIONS.add_user(id, user_id) + peers[user_id] = websocket + @updated_at = Time.utc + end + + def remove(user_id : String) + SESSIONS.remove_user(id, user_id) + peers.delete user_id + @updated_at = Time.utc + end + + def all_peers + SESSIONS.user_list(id) + end + + def initialize(@id : String) + @peers = {} of String => HTTP::WebSocket + @updated_at = @created_at = Time.utc + end + end +end diff --git a/src/placeos-rest-api/controllers/webrtc/chat_manager.cr b/src/placeos-rest-api/controllers/webrtc/chat_manager.cr new file mode 100644 index 00000000..9aaaa37f --- /dev/null +++ b/src/placeos-rest-api/controllers/webrtc/chat_manager.cr @@ -0,0 +1,322 @@ +require "http" +require "./kick_reason" + +module PlaceOS::Api + # use a manager so the we can free the request context objects + class ChatManager + Log = ::Log.for(self) + + def initialize(@ice_config) + # grab the existing `PlaceOS::Driver::Subscriptions` instance + subscriber = PlaceOS::Api::WebSocket::Session.subscriptions.@subscriber + subscriber.channel("internal/chat/forward_signal") do |_, payload| + signal = SessionSignal.from_json(payload) + perform_forwarded_signal(signal) + end + subscriber.channel("internal/chat/kick_user") do |_, payload| + user_id, reason = Tuple(String, String).from_json(payload) + perform_kick_user(user_id, reason) + end + subscriber.channel("internal/chat/transfer_user") do |_, payload| + user_id, session_id, connection_details = Tuple(String, String?, String?).from_json(payload) + perform_transfer(user_id, session_id, connection_details) + end + + spawn { ping_sockets } + end + + # ================================= + # Websocket Ping / ensure connected + # ================================= + + protected def ping_sockets + loop do + sleep 30 + + # ping the sockets to ensure connectivity + begin + connections = sockets.dup + id = "SIGNAL::#{Time.utc.to_unix_ms}+#{Random::Secure.hex(6)}" + connections.each do |websocket, session| + perform_ping(id, websocket, session) rescue Exception + end + rescue + end + end + end + + protected def perform_ping(id, websocket, session) + send_signal(websocket, SessionSignal.new( + id: id, + type: :ping, + session_id: session.session_id, + user_id: "SERVER::DATA", + to_user: session.user_id, + value: "{}" + )) + rescue + end + + # ================================= + # Various helpers + # ================================= + + protected def redis_publish(path : String, payload) + ::PlaceOS::Driver::RedisStorage.with_redis &.publish(path, payload.to_json) + end + + def create_new_call(signal) : CallDetails + calls[signal.session_id] = CallDetails.new(signal.session_id) + end + + def send_signal(websocket, signal) + Log.trace { "Sending signal #{signal.type} to #{signal.session_id}" } + websocket.send(signal.to_json) + rescue + # we'll ignore websocket send failures, the user will be cleaned up + end + + def member_list(session_id : String) : Array(String) + CallDetails::SESSIONS.user_list(session_id) + end + + # ================================= + # Connection management + # ================================= + + # authority_id => config string + private getter ice_config : Hash(String, String) + private getter calls = {} of String => CallDetails + private getter sockets = {} of HTTP::WebSocket => SessionSignal + private getter user_lookup = {} of String => HTTP::WebSocket + + def handle_session(websocket, request_id, user_id, auth_id) + websocket.on_message do |message| + Log.context.set(request_id: request_id, user_id: user_id) + Log.trace { {frame: "TEXT", text: message} } + + signal = SessionSignal.from_json(message) + signal.place_user_id = user_id + signal.place_auth_id = auth_id + + case signal.type + when .join? + on_join_signal(websocket, signal, auth_id) + when .offer?, .answer?, .candidate?, .leave? + forward_signal(websocket, signal) + else + Log.warn { "user #{user_id} sent unsupported signal #{signal.type}" } + end + + if call = calls[signal.session_id]? + call.updated_at = Time.utc + end + end + + websocket.on_close do |_| + Log.trace { {request_id: request_id, frame: "CLOSE"} } + + if connect_details = sockets.delete websocket + user_lookup.delete connect_details.user_id + remove_from_call(connect_details) + + # signals routed to the system id that represents the application managing the chat + redis_publish("placeos/#{auth_id}/chat/user/left", { + connect_details.session_id => connect_details.user_id, + }) + end + end + end + + def remove_from_call(connect_details : SessionSignal) + session_id = connect_details.session_id + + if call = calls[session_id]? + # inform the call peers that the user is gone + call.remove connect_details.user_id + # cleanup empty sessions + calls.delete(session_id) if call.peers.empty? + end + + # forward the leave signal to all the members of the call + connect_details.type = :leave + CallDetails::SESSIONS.user_list(session_id).each do |user_id| + connect_details.to_user = user_id + redis_publish("placeos/internal/chat/forward_signal", connect_details) + end + end + + def on_join_signal(websocket, signal, auth_id) : Nil + call = calls[signal.session_id]? || create_new_call(signal) + + # check the current user can join the call (prevent spoofing) + # TODO:: look into this now the service is clustered + if existing_peer_ws = call.peers[signal.user_id]? + if existing_user = sockets[existing_peer_ws]? + if existing_user.place_user_id != signal.place_user_id + Log.warn { "possible hacking attempt by #{signal.place_user_id}, attempting to spoof #{existing_user.place_user_id}" } + websocket.close + return + end + end + end + + # check if the user is already in another call and remove them + if existing_user = sockets[websocket]? + remove_from_call existing_user + end + + # add the user to the new call + user_lookup[signal.user_id] = websocket + call.add(signal.user_id, websocket) + sockets[websocket] = signal + + # Return RTC configuration details + send_signal(websocket, SessionSignal.new( + id: "SIGNAL::#{Time.utc.to_unix_ms}+#{Random::Secure.hex(6)}", + type: :join, + session_id: signal.session_id, + user_id: "SERVER::DATA", + to_user: signal.user_id, + value: ice_config[auth_id] + )) + + # Send participant list + send_signal(websocket, SessionSignal.new( + id: "SIGNAL::#{Time.utc.to_unix_ms}+#{Random::Secure.hex(6)}", + type: :participant_list, + session_id: signal.session_id, + user_id: "SERVER::DATA", + to_user: signal.user_id, + value: call.peers.keys.to_json + )) + + # signals routed to the system id that represents the application managing the chat + redis_publish("placeos/#{signal.place_auth_id}/chat/user/joined", { + signal.session_id => signal.user_id, + }) + end + + # ================================ + # Forward signal + # ================================ + + def forward_signal(websocket, signal) : Nil + if call = calls[signal.session_id]? + # check the current user is in the call + if existing_peer_ws = call.peers[signal.user_id]? + if existing_user = sockets[existing_peer_ws]? + if existing_user.place_user_id != signal.place_user_id + Log.warn { "possible hacking attempt by #{signal.place_user_id}, attempting to spoof #{existing_user.place_user_id}" } + websocket.close + return + end + end + else + Log.warn { "possible hacking attempt by #{signal.place_user_id}, attempting to signal a call they are not in" } + websocket.close + return + end + + redis_publish("placeos/internal/chat/forward_signal", signal) + end + end + + # all security checks have occured at this point, forward the message + # if the user is connected to this server + protected def perform_forwarded_signal(signal) + if call = calls[signal.session_id]? + if to_user = call.peers[signal.to_user]? + send_signal(to_user, signal) + end + end + end + + # ================================ + # Kick User / User exited + # ================================ + + # the user has exited chat + def end_call(user_id : String, auth_id : String) + # find the users websocket + redis_publish("placeos/internal/chat/kick_user", {user_id, "call ended"}) + + # signal the user exited + redis_publish("placeos/#{auth_id}/chat/user/exited", { + user_id: user_id, + }) + end + + def kick_user(auth_id : String, user_id : String, session_id : String, details : KickReason) + # find the users websocket + redis_publish("placeos/internal/chat/kick_user", {user_id, details.reason}) + + # TODO:: need the auth id here! + redis_publish("placeos/#{auth_id}/chat/user/exited", { + user_id: user_id, + }) + end + + def perform_kick_user(user_id, reason) + # find the users websocket + websocket = user_lookup[user_id]? + return unless websocket + + connect_details = sockets[websocket]? + return unless connect_details + + # send the kicked user a leave signal + send_signal(websocket, SessionSignal.new( + id: "SIGNAL::#{Time.utc.to_unix_ms}+#{Random::Secure.hex(6)}", + type: :leave, + session_id: connect_details.session_id, + user_id: user_id, + to_user: user_id, + value: KickReason.new(reason).to_json + )) + + websocket.close + end + + # ================================ + # Transfer user + # ================================ + + enum TransferResult + NoConnection + NoSession # not currently used + SignalSent + end + + # transfer a user to a new chat room + def transfer(user_id : String, session_id : String? = nil, payload : String? = nil) : TransferResult + current_session_id = CallDetails::SESSIONS.lookup_session(user_id) + return TransferResult::NoConnection unless current_session_id + + redis_publish("placeos/internal/chat/transfer_user", {user_id, session_id, payload}) + TransferResult::SignalSent + end + + def perform_transfer(user_id : String, session_id : String? = nil, payload : String? = nil) + # find the users websocket + websocket = user_lookup[user_id]? + return unless websocket + + connect_details = sockets[websocket]? + return unless connect_details + + # remove the user from the current call + remove_from_call(connect_details) if session_id && session_id != connect_details.session_id + + # send the user a Transfer signal + send_signal(websocket, SessionSignal.new( + id: "SIGNAL::#{Time.utc.to_unix_ms}+#{Random::Secure.hex(6)}", + type: :transfer, + session_id: session_id || connect_details.session_id, + user_id: "SERVER::DATA", + to_user: user_id, + value: payload + )) + end + end +end diff --git a/src/placeos-rest-api/controllers/webrtc/clustered_sessions.cr b/src/placeos-rest-api/controllers/webrtc/clustered_sessions.cr new file mode 100644 index 00000000..514a056d --- /dev/null +++ b/src/placeos-rest-api/controllers/webrtc/clustered_sessions.cr @@ -0,0 +1,88 @@ +require "set" +require "digest" +require "placeos-driver/proxy/remote_driver" + +# stores the session participant IDs in a set in redis +class PlaceOS::Api::ClusteredSessions + def initializer + sleep_time = 60 + rand(50) + spawn { touch_sessions(sleep_time) } + end + + # we track local sessions and keep those keys alive in redis + TTL_SECONDS = 6.minutes.total_seconds.to_i + @session_mutex = Mutex.new + @sessions = Hash(String, Set(String)).new { |hash, key| hash[key] = Set(String).new } + + protected def with_redis(&) + ::PlaceOS::Driver::RedisStorage.with_redis do |redis| + yield redis + end + end + + def local_sessions + @session_mutex.synchronize { @sessions.keys } + end + + def set_key(session_id : String) : String + "placeos:chat:session:#{Digest::SHA1.hexdigest(session_id)}" + end + + def user_key(user_id : String) : String + "placeos:chat:user:#{Digest::SHA1.hexdigest(user_id)}" + end + + def user_list(session_id : String) : Array(String) + result = with_redis &.smembers(set_key(session_id)) + result.compact_map &.as?(String) + end + + def add_user(session_id : String, user_id : String) : Nil + redis_key = set_key(session_id) + @session_mutex.synchronize { @sessions[session_id] << user_id } + with_redis do |redis| + redis.pipelined(redis_key, reconnect: true) do |pipeline| + pipeline.sadd(redis_key, user_id) + pipeline.expire(redis_key, TTL_SECONDS) + end + redis.set(user_key(user_id), session_id, ex: 24.hours.total_seconds.to_i) + end + end + + def lookup_session(user_id : String) + with_redis do |redis| + redis.get(user_key(user_id)) + end + end + + def remove_user(session_id : String, user_id : String) : Nil + @session_mutex.synchronize do + set = @sessions[session_id] + set.delete(user_id) + @sessions.delete(session_id) if set.empty? + end + + # if the set above is empty then this node will let the session expire + redis_key = set_key(session_id) + with_redis do |redis| + redis.pipelined(redis_key, reconnect: true) do |pipeline| + pipeline.srem(redis_key, user_id) + pipeline.expire(redis_key, TTL_SECONDS) + end + # NOTE:: don't remove the user lookup to avoid race conditions + end + end + + def touch_sessions(sleep_time : Int32) + loop do + sleep sleep_time + begin + sessions = @session_mutex.synchronize { @sessions.dup } + sessions.each_key do |session_id| + with_redis(&.expire(set_key(session_id), TTL_SECONDS)) rescue Exception + end + rescue + end + end + end +end diff --git a/src/placeos-rest-api/controllers/webrtc/guest_participant.cr b/src/placeos-rest-api/controllers/webrtc/guest_participant.cr new file mode 100644 index 00000000..f58e9ad9 --- /dev/null +++ b/src/placeos-rest-api/controllers/webrtc/guest_participant.cr @@ -0,0 +1,26 @@ +require "json" + +module PlaceOS::Api + class GuestParticipant + include JSON::Serializable + include JSON::Serializable::Unmapped + + property captcha : String + property name : String + property email : String? + property phone : String? + + # the type of guest (additional information) + property type : String? + + # the placeos user id we would like to notify if we have the user details + property chat_to_user_id : String? + + # the users chat id. This purely generated on the frontend + # not a placeos user_id, we use it to track browser instances + property user_id : String + + # the chat session id the user is planning to use, the initial chat room + property session_id : String + end +end diff --git a/src/placeos-rest-api/controllers/webrtc/kick_reason.cr b/src/placeos-rest-api/controllers/webrtc/kick_reason.cr new file mode 100644 index 00000000..c882bbc4 --- /dev/null +++ b/src/placeos-rest-api/controllers/webrtc/kick_reason.cr @@ -0,0 +1,12 @@ +require "json" + +module PlaceOS::Api + struct KickReason + include JSON::Serializable + + getter reason : String + + def initialize(@reason) + end + end +end diff --git a/src/placeos-rest-api/controllers/webrtc/session_signal.cr b/src/placeos-rest-api/controllers/webrtc/session_signal.cr new file mode 100644 index 00000000..0f3d5a1e --- /dev/null +++ b/src/placeos-rest-api/controllers/webrtc/session_signal.cr @@ -0,0 +1,51 @@ +require "json" + +module PlaceOS::Api + enum SignalType + Join + ParticipantList + Candidate + Offer + Answer + Ping + Leave + + # this is sent to the client when someone is to be moved into a new space + # the session id may or may not change - if session_id is different + # then the user will be cleaned up as if disconnect was called, allowing them + # to call join again, similar semantics to leave + Transfer + end + + struct SessionSignal + include JSON::Serializable + + # message id, generated by the sender + getter id : String + + # the unique id of the chat to join + property session_id : String + + # the type of message + property type : SignalType + + # the chat user identifier, globally unique + getter user_id : String + + @[JSON::Field(ignore: true)] + property place_user_id : String? = nil + + @[JSON::Field(ignore: true)] + property place_auth_id : String? = nil + + # the id of the user we want to communicate with + property to_user : String? + + # the payload, if any + @[JSON::Field(converter: String::RawConverter)] + property value : String? + + def initialize(@id, @session_id, @type, @user_id, @to_user, @value) + end + end +end diff --git a/src/placeos-rest-api/controllers/zones.cr b/src/placeos-rest-api/controllers/zones.cr index d1cfdfab..391f6579 100644 --- a/src/placeos-rest-api/controllers/zones.cr +++ b/src/placeos-rest-api/controllers/zones.cr @@ -64,7 +64,7 @@ module PlaceOS::Api "tags" => filter_tags, }) else - raise Error::Forbidden.new unless is_support? || is_admin? + raise Error::Forbidden.new unless user_support? query.search_field "name" end diff --git a/src/placeos-rest-api/utilities/current-user.cr b/src/placeos-rest-api/utilities/current-user.cr index e0684e6e..b2c859be 100644 --- a/src/placeos-rest-api/utilities/current-user.cr +++ b/src/placeos-rest-api/utilities/current-user.cr @@ -18,7 +18,7 @@ module PlaceOS::Api end # check for X-API-Key use - if (token = request.headers["X-API-Key"]? || params["api-key"]? || cookies["api-key"]?.try(&.value)) + if token = request.headers["X-API-Key"]? || params["api-key"]? || cookies["api-key"]?.try(&.value) begin api_key = Model::ApiKey.find_key!(token) @user_token = user_token = api_key.build_jwt @@ -43,7 +43,7 @@ module PlaceOS::Api raise Error::Unauthorized.new "bearer malformed" end - unless (authority = current_authority) + unless authority = current_authority Log.warn { {message: "authority not found", action: "authorize!", host: request.hostname} } raise Error::Unauthorized.new "authority not found" end @@ -81,19 +81,19 @@ module PlaceOS::Api # Read admin status from supplied request JWT def check_admin - raise Error::Forbidden.new unless is_admin? + raise Error::Forbidden.new unless user_admin? end # Read support status from supplied request JWT def check_support - raise Error::Forbidden.new unless is_support? + raise Error::Forbidden.new unless user_support? end - def is_admin? + def user_admin? user_token.is_admin? end - def is_support? + def user_support? token = user_token token.is_support? || token.is_admin? end @@ -102,12 +102,12 @@ module PlaceOS::Api # - Authorization header # - "bearer_token" param protected def acquire_token : String? - if (token = request.headers["Authorization"]?) + if token = request.headers["Authorization"]? token = token.lchop("Bearer ").lchop("Token ").rstrip token unless token.empty? - elsif (token = params["bearer_token"]?) + elsif token = params["bearer_token"]? token.strip - elsif (token = cookies["bearer_token"]?.try(&.value)) + elsif token = cookies["bearer_token"]?.try(&.value) token.strip end end diff --git a/src/placeos-rest-api/websocket/manager.cr b/src/placeos-rest-api/websocket/manager.cr index 60e38a82..d86df927 100644 --- a/src/placeos-rest-api/websocket/manager.cr +++ b/src/placeos-rest-api/websocket/manager.cr @@ -20,6 +20,9 @@ module PlaceOS::Api::WebSocket spawn(name: "cleanup_sessions", same_thread: true) do cleanup_sessions end + spawn(name: "ping_sockets", same_thread: true) do + ping_sockets + end end # Creates the session and handles the cleanup @@ -50,5 +53,18 @@ module PlaceOS::Api::WebSocket session_lock.synchronize { @sessions = sessions.dup } end end + + protected def ping_sockets + loop do + sleep 80 + begin + connections = session_lock.synchronize { sessions.dup } + connections.each do |session| + session.ping rescue Exception + end + rescue + end + end + end end end diff --git a/src/placeos-rest-api/websocket/session.cr b/src/placeos-rest-api/websocket/session.cr index 33b94d42..a9feb98b 100644 --- a/src/placeos-rest-api/websocket/session.cr +++ b/src/placeos-rest-api/websocket/session.cr @@ -283,7 +283,7 @@ module PlaceOS::Api::WebSocket return cached if cached # Look up value, refresh cache if value found - if (module_id = module_id?(system_id, module_name, index)) + if module_id = module_id?(system_id, module_name, index) Driver::Proxy::System.driver_metadata?(module_id).tap do |meta| cache_lock.synchronize { metadata_cache[key] = meta } if meta end @@ -404,6 +404,11 @@ module PlaceOS::Api::WebSocket respond(response) end + # ensure the client is still there, we send pong as the existing clients ignore this + def ping + write("pong") + end + # Shutdown handler # def cleanup