// Copyright 2025 Google LLC
//
// 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 google.cloud.chronicle.v1;

import "google/api/annotations.proto";
import "google/api/client.proto";
import "google/api/field_behavior.proto";
import "google/api/resource.proto";
import "google/protobuf/empty.proto";
import "google/protobuf/field_mask.proto";
import "google/protobuf/timestamp.proto";

option csharp_namespace = "Google.Cloud.Chronicle.V1";
option go_package = "cloud.google.com/go/chronicle/apiv1/chroniclepb;chroniclepb";
option java_multiple_files = true;
option java_outer_classname = "DataAccessProto";
option java_package = "com.google.cloud.chronicle.v1";
option php_namespace = "Google\\Cloud\\Chronicle\\V1";
option ruby_package = "Google::Cloud::Chronicle::V1";

// DataAccessControlService exposes resources and endpoints related to data
// access control.
service DataAccessControlService {
  option (google.api.default_host) = "chronicle.googleapis.com";
  option (google.api.oauth_scopes) =
      "https://www.googleapis.com/auth/cloud-platform";

  // Creates a data access label.
  // Data access labels are applied to incoming event data and selected in data
  // access scopes (another resource), and only users with scopes containing the
  // label can see data with that label. Currently, the data access label
  // resource only includes custom labels, which are labels that correspond
  // to UDM queries over event data.
  rpc CreateDataAccessLabel(CreateDataAccessLabelRequest)
      returns (DataAccessLabel) {
    option (google.api.http) = {
      post: "/v1/{parent=projects/*/locations/*/instances/*}/dataAccessLabels"
      body: "data_access_label"
    };
    option (google.api.method_signature) =
        "parent,data_access_label,data_access_label_id";
  }

  // Gets a data access label.
  rpc GetDataAccessLabel(GetDataAccessLabelRequest) returns (DataAccessLabel) {
    option (google.api.http) = {
      get: "/v1/{name=projects/*/locations/*/instances/*/dataAccessLabels/*}"
    };
    option (google.api.method_signature) = "name";
  }

  // Lists all data access labels for the customer.
  rpc ListDataAccessLabels(ListDataAccessLabelsRequest)
      returns (ListDataAccessLabelsResponse) {
    option (google.api.http) = {
      get: "/v1/{parent=projects/*/locations/*/instances/*}/dataAccessLabels"
    };
    option (google.api.method_signature) = "parent";
  }

  // Updates a data access label.
  rpc UpdateDataAccessLabel(UpdateDataAccessLabelRequest)
      returns (DataAccessLabel) {
    option (google.api.http) = {
      patch: "/v1/{data_access_label.name=projects/*/locations/*/instances/*/dataAccessLabels/*}"
      body: "data_access_label"
    };
    option (google.api.method_signature) = "data_access_label,update_mask";
  }

  // Deletes a data access label. When a label is deleted, new
  // data that enters in the system will not receive the label, but the label
  // will not be removed from old data that still refers to it.
  rpc DeleteDataAccessLabel(DeleteDataAccessLabelRequest)
      returns (google.protobuf.Empty) {
    option (google.api.http) = {
      delete: "/v1/{name=projects/*/locations/*/instances/*/dataAccessLabels/*}"
    };
    option (google.api.method_signature) = "name";
  }

  // Creates a data access scope.
  // Data access scope is a combination of allowed and denied labels attached
  // to a permission group. If a scope has allowed labels A and B and denied
  // labels C and D, then the group of people attached to the scope
  // will have permissions to see all events labeled with A or B (or both) and
  // not labeled with either C or D.
  rpc CreateDataAccessScope(CreateDataAccessScopeRequest)
      returns (DataAccessScope) {
    option (google.api.http) = {
      post: "/v1/{parent=projects/*/locations/*/instances/*}/dataAccessScopes"
      body: "data_access_scope"
    };
    option (google.api.method_signature) =
        "parent,data_access_scope,data_access_scope_id";
  }

  // Retrieves an existing data access scope.
  rpc GetDataAccessScope(GetDataAccessScopeRequest) returns (DataAccessScope) {
    option (google.api.http) = {
      get: "/v1/{name=projects/*/locations/*/instances/*/dataAccessScopes/*}"
    };
    option (google.api.method_signature) = "name";
  }

  // Lists all existing data access scopes for the customer.
  rpc ListDataAccessScopes(ListDataAccessScopesRequest)
      returns (ListDataAccessScopesResponse) {
    option (google.api.http) = {
      get: "/v1/{parent=projects/*/locations/*/instances/*}/dataAccessScopes"
    };
    option (google.api.method_signature) = "parent";
  }

  // Updates a data access scope.
  rpc UpdateDataAccessScope(UpdateDataAccessScopeRequest)
      returns (DataAccessScope) {
    option (google.api.http) = {
      patch: "/v1/{data_access_scope.name=projects/*/locations/*/instances/*/dataAccessScopes/*}"
      body: "data_access_scope"
    };
    option (google.api.method_signature) = "data_access_scope,update_mask";
  }

  // Deletes a data access scope.
  rpc DeleteDataAccessScope(DeleteDataAccessScopeRequest)
      returns (google.protobuf.Empty) {
    option (google.api.http) = {
      delete: "/v1/{name=projects/*/locations/*/instances/*/dataAccessScopes/*}"
    };
    option (google.api.method_signature) = "name";
  }
}

// Request message for CreateDataAccessLabel.
message CreateDataAccessLabelRequest {
  // Required. The parent resource where this Data Access Label will be created.
  // Format: `projects/{project}/locations/{location}/instances/{instance}`
  string parent = 1 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.resource_reference) = {
      child_type: "chronicle.googleapis.com/DataAccessLabel"
    }
  ];

  // Required. Data access label to create.
  DataAccessLabel data_access_label = 2
      [(google.api.field_behavior) = REQUIRED];

  // Required. The ID to use for the data access label, which will become the
  // label's display name and the final component of the label's resource name.
  // The maximum number of characters should be 63. Regex pattern is as per AIP:
  // https://google.aip.dev/122#resource-id-segments
  string data_access_label_id = 3 [(google.api.field_behavior) = REQUIRED];
}

// Request message to retrieve a data access label.
message GetDataAccessLabelRequest {
  // Required. The ID of the data access label to retrieve.
  // Format:
  // `projects/{project}/locations/{location}/instances/{instance}/dataAccessLabels/{data_access_label}`
  string name = 1 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.resource_reference) = {
      type: "chronicle.googleapis.com/DataAccessLabel"
    }
  ];
}

// Request message for ListDataAccessLabels.
message ListDataAccessLabelsRequest {
  // Required. The parent resource where this data access label will be created.
  // Format: `projects/{project}/locations/{location}/instances/{instance}`
  string parent = 1 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.resource_reference) = {
      child_type: "chronicle.googleapis.com/DataAccessLabel"
    }
  ];

  // The maximum number of data access labels to return. The service may return
  // fewer than this value. If unspecified, at most 100 data access labels will
  // be returned. The maximum value is 1000; values above 1000 will be coerced
  // to 1000.
  int32 page_size = 2;

  // A page token, received from a previous `ListDataAccessLabelsRequest` call.
  // Provide this to retrieve the subsequent page.
  string page_token = 3;

  // Optional. A filter which should follow the guidelines of AIP-160.
  // Supports filtering on all fieds of DataAccessLabel and all operations as
  // mentioned in https://google.aip.dev/160.
  // example filter: "create_time greater than \"2023-04-21T11:30:00-04:00\" OR
  // display_name:\"-21-1\"".
  string filter = 4 [(google.api.field_behavior) = OPTIONAL];
}

// Response message for ListDataAccessLabels.
message ListDataAccessLabelsResponse {
  // List of data access labels.
  repeated DataAccessLabel data_access_labels = 1;

  // A token, which can be sent as `page_token` to retrieve the next page.
  // If this field is omitted, there are no subsequent pages.
  string next_page_token = 2;
}

// Request message for UpdateDataAccessLabel method.
message UpdateDataAccessLabelRequest {
  // Required. The data access label to update.
  //
  // The label's `name` field is used to identify the label to update.
  // Format:
  // `projects/{project}/locations/{location}/instances/{instance}/dataAccessLabels/{data_access_label}`
  DataAccessLabel data_access_label = 1
      [(google.api.field_behavior) = REQUIRED];

  // The list of fields to update. If not included, all fields with a non-empty
  // value will be overwritten. Currently, only the description and definition
  // fields are supported for update; an update call that attempts to update any
  // other fields will return INVALID_ARGUMENT.
  google.protobuf.FieldMask update_mask = 2;
}

// Request message to delete a data access label.
message DeleteDataAccessLabelRequest {
  // Required. The ID of the data access label to delete.
  // Format:
  // `projects/{project}/locations/{location}/instances/{instance}/dataAccessLabels/{data_access_label}`
  string name = 1 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.resource_reference) = {
      type: "chronicle.googleapis.com/DataAccessLabel"
    }
  ];
}

// Request message for CreateDataAccessScope.
message CreateDataAccessScopeRequest {
  // Required. The parent resource where this Data Access Scope will be created.
  // Format: `projects/{project}/locations/{location}/instances/{instance}`
  string parent = 1 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.resource_reference) = {
      child_type: "chronicle.googleapis.com/DataAccessScope"
    }
  ];

  // Required. Data access scope to create.
  DataAccessScope data_access_scope = 2
      [(google.api.field_behavior) = REQUIRED];

  // Required. The user provided scope id which will become the last part of the
  // name of the scope resource. Needs to be compliant with
  // https://google.aip.dev/122
  string data_access_scope_id = 3 [(google.api.field_behavior) = REQUIRED];
}

// Request message to retrieve a data access scope.
message GetDataAccessScopeRequest {
  // Required. The ID of the data access scope to retrieve.
  // Format:
  // `projects/{project}/locations/{location}/instances/{instance}/dataAccessScopes/{data_access_scope}`
  string name = 1 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.resource_reference) = {
      type: "chronicle.googleapis.com/DataAccessScope"
    }
  ];
}

// Request message for ListDataAccessScopes.
message ListDataAccessScopesRequest {
  // Required. The parent resource where this data access scope will be created.
  // Format: `projects/{project}/locations/{location}/instances/{instance}`
  string parent = 1 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.resource_reference) = {
      child_type: "chronicle.googleapis.com/DataAccessScope"
    }
  ];

  // The maximum number of data access scopes to return. The service may return
  // fewer than this value. If unspecified, at most 100 data access scopes will
  // be returned. The maximum value is 1000; values above 1000 will be coerced
  // to 1000.
  int32 page_size = 2;

  // A page token, received from a previous `ListDataAccessScopesRequest` call.
  // Provide this to retrieve the subsequent page.
  string page_token = 3;

  // Optional. A filter which should follow the guidelines of AIP-160.
  // Supports filtering on all fieds of DataAccessScope and all operations as
  // mentioned in https://google.aip.dev/160.
  // example filter: "create_time greater than \"2023-04-21T11:30:00-04:00\" OR
  // display_name:\"-21-1\"".
  string filter = 4 [(google.api.field_behavior) = OPTIONAL];
}

// Response message for ListDataAccessScopes.
message ListDataAccessScopesResponse {
  // List of data access scopes.
  repeated DataAccessScope data_access_scopes = 1;

  // Whether or not global scope is granted to the user.
  optional bool global_data_access_scope_granted = 3;

  // A token, which can be sent as `page_token` to retrieve the next page.
  // If this field is omitted, there are no subsequent pages.
  string next_page_token = 2;
}

// Request message for UpdateDataAccessScope method.
message UpdateDataAccessScopeRequest {
  // Required. The data access scope to update.
  //
  // The scope's `name` field is used to identify the scope to update.
  // Format:
  // `projects/{project}/locations/{location}/instances/{instance}/dataAccessScopes/{data_access_scope}`
  DataAccessScope data_access_scope = 1
      [(google.api.field_behavior) = REQUIRED];

  // The list of fields to update. If not included, all fields with a non-empty
  // value will be overwritten. Currently, only the description, the allowed
  // and denied labels list fields are supported for update;
  // an update call that attempts to update any
  // other fields will return INVALID_ARGUMENT.
  google.protobuf.FieldMask update_mask = 2;
}

// Request message to delete a data access scope.
message DeleteDataAccessScopeRequest {
  // Required. The ID of the data access scope to delete.
  // Format:
  // `projects/{project}/locations/{location}/instances/{instance}/dataAccessScopes/{data_access_scope}`
  string name = 1 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.resource_reference) = {
      type: "chronicle.googleapis.com/DataAccessScope"
    }
  ];
}

// A DataAccessLabel is a label on events to define user access to data.
message DataAccessLabel {
  option (google.api.resource) = {
    type: "chronicle.googleapis.com/DataAccessLabel"
    pattern: "projects/{project}/locations/{location}/instances/{instance}/dataAccessLabels/{data_access_label}"
  };

  // Required.
  // The definition of the data access label that determines which
  // data gets tagged with this label.
  oneof definition {
    // A UDM query over event data.
    string udm_query = 3;
  }

  // The unique resource name of the data access label.
  string name = 1 [(google.api.resource_reference) = {
    type: "chronicle.googleapis.com/DataAccessLabel"
  }];

  // Output only. The short name displayed for the label as it appears on event
  // data.
  string display_name = 8 [(google.api.field_behavior) = OUTPUT_ONLY];

  // Output only. The time at which the data access label was created.
  google.protobuf.Timestamp create_time = 4
      [(google.api.field_behavior) = OUTPUT_ONLY];

  // Output only. The time at which the data access label was last updated.
  google.protobuf.Timestamp update_time = 5
      [(google.api.field_behavior) = OUTPUT_ONLY];

  // Output only. The user who created the data access label.
  string author = 6 [(google.api.field_behavior) = OUTPUT_ONLY];

  // Output only. The user who last updated the data access label.
  string last_editor = 7 [(google.api.field_behavior) = OUTPUT_ONLY];

  // Optional. A description of the data access label for a human reader.
  string description = 2 [(google.api.field_behavior) = OPTIONAL];
}

// A DataAccessScope is a boolean expression of data access labels used
// to restrict access to data for users.
message DataAccessScope {
  option (google.api.resource) = {
    type: "chronicle.googleapis.com/DataAccessScope"
    pattern: "projects/{project}/locations/{location}/instances/{instance}/dataAccessScopes/{data_access_scope}"
  };

  // Required. The unique full name of the data access scope.
  // The name should comply with https://google.aip.dev/122 standards.
  string name = 1 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.resource_reference) = {
      type: "chronicle.googleapis.com/DataAccessScope"
    }
  ];

  // Optional. The allowed labels for the scope.
  // Either allow_all or allowed_data_access_labels needs to be provided.
  // When provided, there has to be at least one label allowed for the scope to
  // be valid.
  // The logical operator for evaluation of the allowed labels is OR.
  // E.g.: A customer with scope with allowed labels A and B will be able
  // to see data with labeled with A or B or (A and B).
  repeated DataAccessLabelReference allowed_data_access_labels = 2
      [(google.api.field_behavior) = OPTIONAL];

  // Optional. The denied labels for the scope.
  // The logical operator for evaluation of the denied labels is AND.
  // E.g.: A customer with scope with denied labels A and B won't be able
  // to see data labeled with A and data labeled with B
  // and data with labels A and B.
  repeated DataAccessLabelReference denied_data_access_labels = 3
      [(google.api.field_behavior) = OPTIONAL];

  // Output only. The name to be used for display to customers of the data
  // access scope.
  string display_name = 4 [(google.api.field_behavior) = OUTPUT_ONLY];

  // Output only. The time at which the data access scope was created.
  google.protobuf.Timestamp create_time = 5
      [(google.api.field_behavior) = OUTPUT_ONLY];

  // Output only. The time at which the data access scope was last updated.
  google.protobuf.Timestamp update_time = 6
      [(google.api.field_behavior) = OUTPUT_ONLY];

  // Output only. The user who created the data access scope.
  string author = 7 [(google.api.field_behavior) = OUTPUT_ONLY];

  // Output only. The user who last updated the data access scope.
  string last_editor = 8 [(google.api.field_behavior) = OUTPUT_ONLY];

  // Optional. A description of the data access scope for a human reader.
  string description = 9 [(google.api.field_behavior) = OPTIONAL];

  // Optional. Whether or not the scope allows all labels, allow_all and
  // allowed_data_access_labels are mutually exclusive and one of them must be
  // present. denied_data_access_labels can still be used along with allow_all.
  // When combined with denied_data_access_labels, access will be granted to all
  // data that doesn't have labels mentioned in denied_data_access_labels. E.g.:
  // A customer with scope with denied labels A and B and allow_all will be able
  // to see all data except data labeled with A and data labeled with B and data
  // with labels A and B.
  bool allow_all = 10 [(google.api.field_behavior) = OPTIONAL];
}

// Reference object to a data access label.
message DataAccessLabelReference {
  // The unique identifier for the label.
  oneof label {
    // The name of the data access label.
    string data_access_label = 1;

    // The name of the log type.
    string log_type = 2;

    // The asset namespace configured in the forwarder
    // of the customer's events.
    string asset_namespace = 3;

    // The ingestion label configured in the forwarder of the customer's events.
    IngestionLabel ingestion_label = 4;
  }

  // Output only. The display name of the label.
  // Data access label and log types's name
  // will match the display name of the resource.
  // The asset namespace will match the namespace itself.
  // The ingestion key value pair will match the key of the tuple.
  string display_name = 5 [(google.api.field_behavior) = OUTPUT_ONLY];
}

// Representation of an ingestion label type.
message IngestionLabel {
  // Required. The key of the ingestion label. Always required.
  string ingestion_label_key = 1 [(google.api.field_behavior) = REQUIRED];

  // Optional. The value of the ingestion label. Optional. An object
  // with no provided value and some key provided would match
  // against the given key and ANY value.
  string ingestion_label_value = 2 [(google.api.field_behavior) = OPTIONAL];
}
