// Copyright © 2022 The Things Network Foundation, The Things Industries B.V. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. syntax = "proto3"; package ttn.lorawan.v3; import "google/api/annotations.proto"; import "google/protobuf/any.proto"; import "google/protobuf/empty.proto"; import "google/protobuf/timestamp.proto"; import "protoc-gen-openapiv2/options/annotations.proto"; import "thethings/flags/annotations.proto"; import "thethings/json/annotations.proto"; import "ttn/lorawan/v3/enums.proto"; import "ttn/lorawan/v3/identifiers.proto"; import "validate/validate.proto"; option go_package = "go.thethings.network/lorawan-stack/v3/pkg/ttnpb"; message Notification { // The immutable ID of the notification. Generated by the server. string id = 1; // The time when the notification was triggered. google.protobuf.Timestamp created_at = 2; // The entity this notification is about. EntityIdentifiers entity_ids = 3; // The type of this notification. // TODO: Replace with type NotificationType in v4 https://github.com/TheThingsNetwork/lorawan-stack/issues/7384. string notification_type = 4 [(validate.rules).string = { in: [ "unknown", "api_key_created", "api_key_changed", "client_requested", "collaborator_changed", "entity_state_changed", "invitation", "login_token", "password_changed", "temporary_password", "user_requested", "validate" ] }]; // The data related to the notification. google.protobuf.Any data = 5; // If the notification was triggered by a user action, this contains the identifiers of the user that triggered the notification. UserIdentifiers sender_ids = 6; // If the notification was triggered by an event pipeline, this contains the identifiers of that pipeline. // EventPipelineIdentifiers event_pipeline_ids = 7; reserved "event_pipeline_ids"; reserved 7; // Relation of the notification receiver to the entity. repeated NotificationReceiver receivers = 8; // Whether an email was sent for the notification. bool email = 9 [deprecated = true]; // The status of the notification. NotificationStatus status = 10; // The time when the notification status was updated. google.protobuf.Timestamp status_updated_at = 11; } enum NotificationType { option (thethings.json.enum) = {marshal_as_string: true}; UNKNOWN = 0; API_KEY_CREATED = 1; API_KEY_CHANGED = 2; CLIENT_REQUESTED = 3; COLLABORATOR_CHANGED = 4; ENTITY_STATE_CHANGED = 5; INVITATION = 6; LOGIN_TOKEN = 7; PASSWORD_CHANGED = 8; TEMPORARY_PASSWORD = 9; USER_REQUESTED = 10; VALIDATE = 11; } enum NotificationReceiver { option (thethings.json.enum) = { marshal_as_string: true, prefix: "NOTIFICATION_RECEIVER" }; NOTIFICATION_RECEIVER_UNKNOWN = 0; // Notification is received by collaborators of the entity. // If the collaborator is an organization, the notification is received by organization members. NOTIFICATION_RECEIVER_COLLABORATOR = 1; // Notification is received by administrative contact of the entity. // If this is an organization, the notification is received by organization members. NOTIFICATION_RECEIVER_ADMINISTRATIVE_CONTACT = 3; // Notification is received by technical contact of the entity. // If this is an organization, the notification is received by organization members. NOTIFICATION_RECEIVER_TECHNICAL_CONTACT = 4; } enum NotificationStatus { option (thethings.json.enum) = { marshal_as_string: true, prefix: "NOTIFICATION_STATUS" }; NOTIFICATION_STATUS_UNSEEN = 0; NOTIFICATION_STATUS_SEEN = 1; NOTIFICATION_STATUS_ARCHIVED = 2; } message CreateNotificationRequest { // The entity this notification is about. EntityIdentifiers entity_ids = 1 [(validate.rules).message.required = true]; // The type of this notification. string notification_type = 2 [(validate.rules).string = { in: [ "unknown", "api_key_created", "api_key_changed", "client_requested", "collaborator_changed", "entity_state_changed", "invitation", "login_token", "password_changed", "temporary_password", "user_requested", "validate" ] }]; // The data related to the notification. google.protobuf.Any data = 3; // If the notification was triggered by a user action, this contains the identifiers of the user that triggered the notification. UserIdentifiers sender_ids = 4; // Receivers of the notification. repeated NotificationReceiver receivers = 5 [(validate.rules).repeated = { min_items: 1, unique: true, items: { enum: {defined_only: true} } }]; // Whether an email should be sent for the notification. bool email = 6 [deprecated = true]; } message CreateNotificationResponse { string id = 1; } message ListNotificationsRequest { option (thethings.flags.message) = { select: false, set: true }; // The IDs of the receiving user. UserIdentifiers receiver_ids = 1 [(validate.rules).message.required = true]; // Select notifications with these statuses. // An empty list is interpreted as "all". repeated NotificationStatus status = 2 [(validate.rules).repeated = { unique: true, items: { enum: {defined_only: true} } }]; // Limit the number of results per page. uint32 limit = 3 [(validate.rules).uint32.lte = 1000]; // Page number for pagination. 0 is interpreted as 1. uint32 page = 4; } message ListNotificationsResponse { repeated Notification notifications = 1; } message UpdateNotificationStatusRequest { option (thethings.flags.message) = { select: false, set: true }; // The IDs of the receiving user. UserIdentifiers receiver_ids = 1 [(validate.rules).message.required = true]; // The IDs of the notifications to update the status of. repeated string ids = 2 [(validate.rules).repeated = { min_items: 1, max_items: 1000, unique: true, items: { string: {len: 36} } }]; // The status to set on the notifications. NotificationStatus status = 3 [(validate.rules).enum = {defined_only: true}]; } // The NotificationService is used to send notifications. service NotificationService { option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_tag) = {description: "Read and manage notifications."}; // Create a new notification. Can only be called by internal services using cluster auth. rpc Create(CreateNotificationRequest) returns (CreateNotificationResponse); // List the notifications for a user or an organization. // When called with user credentials and empty receiver_ids, this will list // notifications for the current user and its organizations. rpc List(ListNotificationsRequest) returns (ListNotificationsResponse) { option (google.api.http) = { additional_bindings {get: "/users/{receiver_ids.user_id}/notifications"} }; } // Batch-update multiple notifications to the same status. rpc UpdateStatus(UpdateNotificationStatusRequest) returns (google.protobuf.Empty) { option (google.api.http) = { patch: "/users/{receiver_ids.user_id}/notifications" body: "*" }; } } message EntityStateChangedNotification { State state = 1 [(validate.rules).enum.defined_only = true]; string state_description = 2 [(validate.rules).string.max_len = 128]; }