From f82bc4d2e42247176c6899784b09b49410aac2d7 Mon Sep 17 00:00:00 2001 From: Wouter Bouvy Date: Mon, 27 Jul 2020 17:16:26 +0200 Subject: [PATCH] 0.53 --- CHANGELOG.md | 34 +++++++ base.proto | 48 ++++++++++ dashboard.proto | 5 + event.proto | 1 + modem.proto | 92 ++++++++++++++++++- ...age_body_parser_automatic_assignment.proto | 2 + modem_transfer.proto | 9 ++ organization.proto | 29 +++++- 8 files changed, 214 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c7e911c..5fd53ef 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,39 @@ # Changelog Hiber API +### 0.53 (2020-07-27) + +#### Changes + +##### DashboardService + +- Performance fixes for message counts. + +##### EventService + +- Added `OrganizationCreatedEvent.avatar` with the avatar for the created organization. +- Limited `ModemMessageDroppedEvent` to messages using Hiberband. + +##### OrganizationService + +- Added `Organization.avatar` and `CreateOrganizationRequest.avatar`. +- Added `GetOrganizationAvatar` request to fetch avatars for organizations. + +##### ModemService + +- Added `ListModemsRequest.include_missing_group_parents` which when set adds missing group parents + to the `ListModemsRequest.Response.group_parents`. +- Added `Grouped` and `ListModemsGrouped` to list modems in a grouped structure. + Currently, the only grouped structure is the gateway and its connected devices. +- Performance fixes for + - message counts; + - listing messages when filtering on source. + +##### ModemTransferService + +- Added `TransferModemsRequest.Response.mark_received_automatically_failed` to indicate whether the + transfer was successfully marked received when requested, so we don't have to rollback the transfer. + If this field is false, the transfer needs to be marked as received manually in the receiver organization. + ### 0.52.3 (2020-07-13) This release contains a collection of performance fixes. diff --git a/base.proto b/base.proto index b44e08e..0028a5a 100644 --- a/base.proto +++ b/base.proto @@ -342,3 +342,51 @@ enum Health { WARNING = 1; ERROR = 2; } + +/* A NamedFile contains bytes with its mime-type and name. + * It can represent any file of any type. + * Note that depending on where in the API this is used, + * the server might put restrictions on file size, media-type or name length. + */ +message NamedFile { + /* The binary payload that represents the file */ + BytesOrHex data = 1; + /* The media-type of the file, as defined by RFC 6838 or its extensions */ + string media_type = 2; + /* A semantic name for this file. + * The name should be interpreted as-is. + * No hierarchical information is stored in the name, + * nor should you look at the "extension" to know its media-type. + * It might not even have a file extension. + * + * Also note that this file may contain characters that cannot be a valid file name on certain systems. + * + * Specific API calls may limit the validness of this field. + * For example setting a maximum length or disallowing certain characters. + */ + string name = 3; +} + +/* An avatar is represented either by a (publicly) fetchable URL that serves an image, + * xor a binary payload that knows its name and mime-type. + */ +message Avatar { + oneof url_or_image { + /* A URL that contains the location of avatar. + * It must be obtainable without credentials, though this is not validated by the API. + * Because the content behind URL's can change or become unavailable over time, + * the client should make sure it properly caches the data fetched from the URL. + * ("Properly" means [among other things] respecting the response headers for this resource) + */ + string url = 1; + /* The data of the avatar as a Named File + * When showing this image in a browser, one can make use of a `data` URI. + * The client must convert the bytes to base64 and can then construct a data URI like this + * + * data:;base64, + * + * Other type clients should be able to sort-of-directly set the data bytes as the source for an image. + */ + NamedFile image = 2; + } +} diff --git a/dashboard.proto b/dashboard.proto index 2949be4..65bee64 100644 --- a/dashboard.proto +++ b/dashboard.proto @@ -40,14 +40,19 @@ message DashboardRequest { /* Pick the organization to use (/impersonate). If unset, your default organization is used. */ string organization = 1; + /* Selection for ground stations and map blocks. */ hiber.map.MapSelection selection = 2 [deprecated=true]; + /* Selection for modem messages. */ hiber.modem.ModemMessageSelection message_count_selection = 3; + /* Selection for bundled events, only used when any value is set. */ hiber.event.EventSelection event_selection = 4; + /* Numeric timezone offset for message count, day grouping. Optional. */ int32 time_zone_offset = 5; + /* Timezone string for message count, day grouping. Optional. */ string time_zone = 6; } diff --git a/event.proto b/event.proto index 92b020a..9c94c92 100644 --- a/event.proto +++ b/event.proto @@ -630,6 +630,7 @@ message Event { organization.Organization created = 2; string title = 9; string description = 10; + Avatar avatar = 12; Timestamp time = 11; } diff --git a/modem.proto b/modem.proto index 510b983..4ca8d9b 100644 --- a/modem.proto +++ b/modem.proto @@ -19,6 +19,7 @@ option go_package = "hiber"; service ModemService { rpc Get (GetModemRequest) returns (Modem); rpc List (ListModemsRequest) returns (ListModemsRequest.Response); + rpc Grouped (ListModemsGrouped.Request) returns (ListModemsGrouped.Response); rpc Messages (ListModemMessagesRequest) returns (ListModemMessagesRequest.Response); rpc MessageCount (MessageCountRequest) returns (MessageCountRequest.Response); @@ -397,7 +398,14 @@ message ListModemsRequest { ListModemsRequest request = 2; Pagination.Result pagination = 3; repeated Sort sorted_by = 4; + + /* This will be populated with missing group parents (i.e. gateways) for the the modems on this page. + * Any group parent that is on the current page is not included in this list to avoid duplicate data. + * Only set when include_missing_group_parents is true in the request. + */ + repeated Modem group_parents = 5; } + /* Sorting options for the results. */ enum Sort { LAST_MESSAGE_RECEIVED = 0; @@ -410,25 +418,103 @@ message ListModemsRequest { STATUS_ASC = 4; STATUS_DESC = 5; - /* Sort ASCIIbetically on the name of the modem. De default name of the modem is its HEX number */ + /* Sort alphabetically on the name of the modem. De default name of the modem is its HEX number */ MODEM_NAME_ASC = 6; MODEM_NAME_DESC = 7; - /* Sort ASCIIbetically on the name of the organization that owns the modem */ + /* Sort alphabetically on the name of the organization that owns the modem */ ORGANIZATION_ASC = 8; ORGANIZATION_DESC = 9; } /* Pick the organization to use (/impersonate). If unset, your default organization is used. */ string organization = 1; + + /* Select which modems to return. */ ModemSelection selection = 2; + + /* Paginate through results. */ Pagination pagination = 3; + + /* Sort the modem with the given sort options. */ repeated Sort sort_by = 4 [packed = false]; - reserved 5; + + /* Whether to include inbound modems in the results. + * Inbound modems are modems that are in a transfer that has been sent *to* your organization, but that has not + * been marked as received yet. + */ bool include_inbound_modems = 6; + + /* Whether to include outbound modems in the results. + * Inbound modems are modems that are in a transfer that has been sent *from* your organization, but that has not + * been marked as received yet. + */ bool include_outbound_modems = 7; + + /* Include modems from the selected child organizations. */ Filter.ChildOrganizations child_organizations = 8; + + /* Filter modems by location. */ LocationSelection location_selection = 9; + + /* Set this to true to populate the group_parents field in the response. + * This will be populated with missing group parents (i.e. gateways) for the the modems on this page. + * Any group parent that is on the current page is not included in this list to avoid duplicate data. + */ + bool include_missing_group_parents = 10; + + reserved 5; +} + +/* Lists all modems the given criteria, grouped by gateway. + * Pagination is applied to modems in a group, not to the groups themselves. + */ +message ListModemsGrouped { + message Request { + /* The modems you want to display in the groups. + * This is a ListModemsRequest that is used to fetch the modems for each group, with the added limitation + * that the modems must be in the group. + * + * The usage of ListModemsRequest and ListModemsRequest.Response in the Response.Group was intentionally + * chosen to simplify pagination withing a group, since the response contains the request + * (which will be updated with the group it is in) and pagination to select the next page using the + * list method. + */ + ListModemsRequest group_content = 1; + + /* Select the parents for the groups to display. + * + * Anything selected here that cannot have any connected modems (i.e. a direct modem) wil be omitted + * unless allow_any_group_parent is set to true. + * Only gateways will have connected devices, so unless allow_any_group_parent is true, + * type is replaced with GATEWAY. This may change in the future if more grouping options are introduced. + */ + ListModemsRequest groups = 2; + + /* Set to true to allow group request to return modems that can never be the parent of a group. + * - If this flag is false, the modems for the groups are automatically filtered on being a parent of a group. + * Note that the group may still be empty, i.e. when a gateway has no connected devices. + * - If this flag is true, the group parents can include modems which cannot be a parent and for which + * the group can only be empty. + */ + bool allow_any_group_parent = 3; + } + + message Response { + /* The groups, based on a parent (typically a gateway unless allow_any_group_parent was set). + * This is a ListModemsRequest.Response, with the selection updated with its parent and includes + * the group parent in the group_parents field. + * + * The usage of ListModemsRequest and ListModemsRequest.Response in the Response.Group was intentionally + * chosen to simplify pagination withing a group, since the response contains the request + * (which will be updated with the group it is in) and pagination to select the next page using the + * list method. + */ + repeated ListModemsRequest.Response groups = 1; + Request request = 2; + Pagination.Result pagination = 3; + repeated ListModemsRequest.Sort sorted_by = 4; + } } message ListModemMessagesRequest { diff --git a/modem_message_body_parser_automatic_assignment.proto b/modem_message_body_parser_automatic_assignment.proto index 5ae931c..01145ba 100644 --- a/modem_message_body_parser_automatic_assignment.proto +++ b/modem_message_body_parser_automatic_assignment.proto @@ -11,6 +11,7 @@ option java_package = "global.hiber.api.grpc.modem.message.bodyparser"; option java_outer_classname = "ModemMessageBodyParserAutomaticAssignmentApi"; option go_package = "hiber"; +// protolint:disable MAX_LINE_LENGTH service ModemMessageBodyParserAutomaticAssignmentService { rpc List (ListBodyParserAutomaticAssignmentRules.Request) returns (ListBodyParserAutomaticAssignmentRules.Response); rpc Create (CreateBodyParserAutomaticAssignmentRule.Request) returns (CreateBodyParserAutomaticAssignmentRule.Response); @@ -23,6 +24,7 @@ service ModemMessageBodyParserAutomaticAssignmentService { rpc Delete (DeleteBodyParserAutomaticAssignmentRule.Request) returns (DeleteBodyParserAutomaticAssignmentRule.Response); } +// protolint:enable MAX_LINE_LENGTH /* A rule to assign a ModemMessageBodyParser to any number of modems automatically, based on varying criteria. * diff --git a/modem_transfer.proto b/modem_transfer.proto index 6d369f8..445c936 100644 --- a/modem_transfer.proto +++ b/modem_transfer.proto @@ -173,6 +173,15 @@ message TransferModemsRequest { message Response { TransferModemsRequest request = 1; ModemTransfer transfer = 2; + + /* When marking a transfer to be received automatically, + * the calling entity must be able to impersonate the receiving entity. + * If this (or any other part of the marking the transfer as received) fails, + * this boolean will be set to true. + * It is the clients responsibility to check this boolean and inform the client. + * Note that the transfer itself is created and can still be accepted manually. + */ + bool mark_received_automatically_failed = 3; } /* Pick the organization to use (/impersonate). If unset, your default organization is used. */ diff --git a/organization.proto b/organization.proto index 51b8093..73a27ad 100644 --- a/organization.proto +++ b/organization.proto @@ -21,6 +21,7 @@ service OrganizationService { rpc Tree (OrganizationTreeRequest) returns (OrganizationTreeRequest.Response); rpc ListChildOrganizations (ListChildOrganizationsRequest) returns (ListChildOrganizationsRequest.Response); rpc ValidateCreationToken (ValidateOrganizationCreationTokenRequest) returns (ValidateOrganizationCreationTokenRequest.Response); + rpc GetAvatar (GetOrganizationAvatar.Request) returns (GetOrganizationAvatar.Response); } /* Organization data. An Organization can have many linked users, but the organization is the owner @@ -41,13 +42,18 @@ message Organization { string phone = 3; } + /* The slug for this organization, used to identify organizations */ string organization = 1; + /* The name of the organization to display to the end-user */ string display_name = 2; - string vat_number = 3; + Address address = 4; + Contact contact = 7; + + string vat_number = 3; string billing_name = 5; Address billing_address = 6; - Contact contact = 7; + Timestamp contract_signature_date = 8; Timestamp created_at = 9; Timestamp updated_at = 10; @@ -81,6 +87,7 @@ message UpdateOrganizationRequest { string billing_name = 5; Organization.Address billing_address = 6; Organization.Contact contact = 7; + Avatar avatar = 8; } /* Get your current organization's organization tree. @@ -124,12 +131,17 @@ message CreateOrganizationRequest { */ string parent_organization = 1; - /* The name for the new organization. Lowercase, letters, numbers, dashes and underscores only. Required. */ + /* The name for the new organization. Lowercase, letters, numbers, dashes and underscores only. Required. + * Used as an identifier for the organization. + */ string new_organization = 2; /* The name to display for your organization (i.e. capitalized, with spaces, etc.). Default to the name above. */ string display_name = 3; + /* The avatar image representing this organisation. Usually the logo. */ + Avatar avatar = 11; + /* Whether this organization is created for a business. */ bool is_business = 4; @@ -189,3 +201,14 @@ message ValidateOrganizationCreationTokenRequest { /* A token that allows you to create an organization without having an organization. */ string organization_creation_token = 1; } + +message GetOrganizationAvatar { + message Request { + /* The slug for this organization, used to identify organizations */ + repeated string organizations = 1; + } + message Response { + /* Avatars, indexed by organization slug */ + map avatars = 1; + } +}