syntax = "proto3";

package openapi.v1beta1;

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 "protoc-gen-openapiv2/options/annotations.proto";

// (-- api-linter: core::0191::java-outer-classname=disabled
//     aip.dev/not-precedent: We need to do this because we don't need this proto be used in Java. --)
// (-- api-linter: core::0191::java-multiple-files=disabled
//     aip.dev/not-precedent: We need to do this because we don't need this proto be used in Java. --)
// (-- api-linter: core::0191::java-package=disabled
//     aip.dev/not-precedent: We need to do this because we don't need this proto be used in Java. --)
option go_package = "github.com/tidbcloud/account/idl/pbgen/proto/openapi;openapi";
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_swagger) = {
  swagger: "2.0"
  host: "tcpn.tidbapi.com"
  // base_path: "/v1beta1"
  info: {
    version: "v1beta1"
    title: "TiDB Cloud TCPN Open API"
    description: "TiDB Cloud TCPN Open API."
  }
  schemes: HTTPS

  // Define the common error responses.
  responses: {
    key: "400"
    value: {
      description: "Bad Request"
      schema: {
        json_schema: {ref: ".google.rpc.Status"}
      }
    }
  }
  responses: {
    key: "401"
    value: {
      description: "Unauthorized"
      schema: {
        json_schema: {ref: ".google.rpc.Status"}
      }
    }
  }
  responses: {
    key: "403"
    value: {
      description: "Forbidden"
      schema: {
        json_schema: {ref: ".google.rpc.Status"}
      }
    }
  }
  responses: {
    key: "404"
    value: {
      description: "Not Found"
      schema: {
        json_schema: {ref: ".google.rpc.Status"}
      }
    }
  }
  responses: {
    key: "429"
    value: {
      description: "Too Many Requests"
      schema: {
        json_schema: {ref: ".google.rpc.Status"}
      }
    }
  }
  responses: {
    key: "500"
    value: {
      description: "Internal Server Error"
      schema: {
        json_schema: {ref: ".google.rpc.Status"}
      }
    }
  }
};

// Create/Get/List/Delete API key
service ApiKeyService {
  // Create a new API key
  rpc CreateApiKey(CreateApiKeyRequest) returns (ApiKey) {
    option (google.api.http) = {
      post: "/v1beta1/apiKeys",
      body: "api_key"
    };
    option (google.api.method_signature) = "api_key";
    option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
      summary: "Create a new API key"
      tags: ["API Key"]
    };

  }
  // (-- api-linter: core::0131::http-uri-name=disabled
  //     aip.dev/not-precedent: We need to do this because reasons. --)
  // (-- api-linter: core::0127::resource-name-extraction=disabled
  //     aip.dev/not-precedent: We need to do this because reasons. --)
  // (-- api-linter: core::0131::method-signature=disabled
  //     aip.dev/not-precedent: We need to do this because reasons. --)
  // Get an API key
  rpc GetApiKey(GetApiKeyRequest) returns (ApiKey) {
    option (google.api.http) = {
      get: "/v1beta1/apiKeys/{access_key}"
    };
    option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
      summary: "Get an API key"
      tags: ["API Key"]
    };

  }
  // List API keys
  rpc ListApiKeys(ListApiKeysRequest) returns (ListApiKeysResponse) {
    option (google.api.http) = {
      get: "/v1beta1/apiKeys"
    };
    option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
      summary: "List API keys"
      tags: ["API Key"]
    };
  }
  // (-- api-linter: core::0132::request-message-name=disabled
  //     aip.dev/not-precedent: We need to do this because reasons. --)
  // List API key roles
  rpc ListApiKeyRoles(google.protobuf.Empty) returns (ListApiKeyRolesResponse) {
    option (google.api.http) = {
      get: "/v1beta1/apiKeys/roles"
    };
    option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
      summary: "List API key roles"
      tags: ["API Key"]
    };
  }
  // (-- api-linter: core::0135::method-signature=disabled
  //     aip.dev/not-precedent: We need to do this because reasons. --)
  // (-- api-linter: core::0127::resource-name-extraction=disabled
  //     aip.dev/not-precedent: We need to do this because reasons. --)
  // (-- api-linter: core::0135::http-uri-name=disabled
  //     aip.dev/not-precedent: We need to do this because reasons. --)
  // Delete an API key
  rpc DeleteApiKey(DeleteApiKeyRequest) returns (google.protobuf.Empty) {
    option (google.api.http) = {
      delete: "/v1beta1/apiKeys/{access_key}"
    };
    option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
      summary: "Delete an API key"
      tags: ["API Key"]
    };
  }
}

// Get Org
service OrgService {
  // (-- api-linter: core::0131::http-uri-name=disabled
  //     aip.dev/not-precedent: We need to do this because reasons. --)
  // (-- api-linter: core::0131::method-signature=disabled
  //     aip.dev/not-precedent: We need to do this because reasons. --)
  // Get a Org
  rpc GetOrg(GetOrgRequest) returns (Org) {
    option (google.api.http) = {
      get: "/v1beta1/org"
    };
    option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
      summary: "Get a Org"
      tags: ["Org"]
    };
  }
  // List Partner Orgs
  rpc ListPartnerOrgs(ListPartnerOrgsRequest) returns (ListPartnerOrgsResponse) {
    option (google.api.http) = {
      get: "/v1beta1/partners/orgs"
    };
    option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
      summary: "List Partner Orgs"
      tags: ["Org"]
    };
  }
}

// Get/Update/Delete/List User
service UserService {
  // (-- api-linter: core::0131::method-signature=disabled
  //     aip.dev/not-precedent: We need to do this because reasons. --)
  // (-- api-linter: core::0131::http-uri-name=disabled
  //     aip.dev/not-precedent: We need to do this because reasons. --)
  // (-- api-linter: core::0131::response-message-name=disabled
  //     aip.dev/not-precedent: We need to do this because reasons. --)
  // (-- api-linter: core::0131::request-message-name=disabled
  //     aip.dev/not-precedent: We need to do this because reasons. --)
  // Get Current User from Token
  rpc GetCurrentUser(google.protobuf.Empty) returns (User) {
    option (google.api.http) = {
      get: "/v1beta1/users/me"
    };
    option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
      summary: "Get Current User from Token"
      tags: ["User"]
    };
  }
  // (-- api-linter: core::0134::http-uri-name=disabled
  //     aip.dev/not-precedent: We need to do this because reasons. --)
  // (-- api-linter: core::0127::resource-name-extraction=disabled
  //     aip.dev/not-precedent: We need to do this because reasons. --)
  // (-- api-linter: core::0134::request-message-name=disabled
  //     aip.dev/not-precedent: We need to do this because reasons. --)
  // (-- api-linter: core::0134::method-signature=disabled
  //     aip.dev/not-precedent: We need to do this because reasons. --)
  // (-- api-linter: core::0134::response-message-name=disabled
  //     aip.dev/not-precedent: We need to do this because reasons. --)
  // (-- api-linter: core::0134::http-body=disabled
  //     aip.dev/not-precedent: We need to do this because reasons. --)
  // Update User Profile
  rpc UpdateCurrentUser(UpdateUserRequest) returns (User) {
    option (google.api.http) = {
      patch: "/v1beta1/users/me"
      body: "user"
    };
    option (google.api.method_signature) = "user,update_mask";
    option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
      summary: "Update User Profile"
      tags: ["User"]
    };
  }
  // (-- api-linter: core::0135::method-signature=disabled
  //     aip.dev/not-precedent: We need to do this because reasons. --)
  // (-- api-linter: core::0135::http-uri-name=disabled
  //     aip.dev/not-precedent: We need to do this because reasons. --)
  // (-- api-linter: core::0127::resource-name-extraction=disabled
  //     aip.dev/not-precedent: We need to do this because reasons. --)
  // Delete User from Org
  rpc DeleteOrgUser(DeleteOrgUserRequest) returns (google.protobuf.Empty) {
    option (google.api.http) = {
      delete: "/v1beta1/users/{user_id}"
    };
    option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
      summary: "Remove User from Org"
      tags: ["User"]
    };
  }
  // (-- api-linter: core::0127::http-template-pattern=disabled
  //     aip.dev/not-precedent: We need to do this because reasons. --)
  // (-- api-linter: core::0135::http-uri-name=disabled
  //     aip.dev/not-precedent: We need to do this because reasons. --)
  // (-- api-linter: core::0135::method-signature=disabled
  //     aip.dev/not-precedent: We need to do this because reasons. --)
  // (-- api-linter: core::0127::resource-name-extraction=disabled
  //     aip.dev/not-precedent: We need to do this because reasons. --)
  // Delete User from Project
  rpc DeleteProjectUser(DeleteProjectUserRequest) returns (google.protobuf.Empty) {
    option (google.api.http) = {
      delete: "/v1beta1/projects/{project_id}/users/{user_id}"
    };
    option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
      summary: "Remove User from Project"
      tags: ["User"]
    };
  }
  // List Users
  rpc ListUsers(ListUsersRequest) returns (ListUsersResponse) {
    option (google.api.http) = {
      get: "/v1beta1/users"
    };
    option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
      summary: "List Users"
      tags: ["User"]
    };
  }
}

// (-- api-linter: core::0121::resource-must-support-get=disabled
//     aip.dev/not-precedent: We need to do this because reasons. --)
// (-- api-linter: core::0121::resource-must-support-list=disabled
//     aip.dev/not-precedent: We need to do this because reasons. --)
// Create/Delete Org/Project Invitation
service InvitationService {
  // (-- api-linter: core::0133::method-signature=disabled
  //     aip.dev/not-precedent: We need to do this because reasons. --)
  // (-- api-linter: core::0133::http-body=disabled
  //     aip.dev/not-precedent: We need to do this because reasons. --)
  // (-- api-linter: core::0133::http-uri-parent=disabled
  //     aip.dev/not-precedent: We need to do this because reasons. --)
  // (-- api-linter: core::0133::response-message-name=disabled
  //     aip.dev/not-precedent: We need to do this because reasons. --)
  // Create an Org Invitation
  rpc CreateOrgInvitation(CreateOrgInvitationRequest) returns (CreateInvitationResponse) {
    option (google.api.http) = {
      post: "/v1beta1/users:invite"
      body: "*"
    };
    option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
      summary: "Create an Org Invitation"
      tags: ["Invitation"]
    };
  }
  // (-- api-linter: core::0133::method-signature=disabled
  //     aip.dev/not-precedent: We need to do this because reasons. --)
  // (-- api-linter: core::0133::http-body=disabled
  //     aip.dev/not-precedent: We need to do this because reasons. --)
  // (-- api-linter: core::0133::response-message-name=disabled
  //     aip.dev/not-precedent: We need to do this because reasons. --)
  // (-- api-linter: core::0133::http-uri-parent=disabled
  //     aip.dev/not-precedent: We need to do this because reasons. --)
  // (-- api-linter: core::0127::resource-name-extraction=disabled
  //     aip.dev/not-precedent: We need to do this because reasons. --)
  // Create a Project Invitation
  rpc CreateProjectInvitation(CreateProjectInvitationRequest) returns (CreateInvitationResponse) {
    option (google.api.http) = {
      post: "/v1beta1/projects/{project_id}/users:invite"
      body: "*"
    };
    option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
      summary: "Create a Project Invitation"
      tags: ["Invitation"]
    };
  }
}

// Service for PartNer (MSP、CPPO)
service PartnerService {
  // (-- api-linter: core::0133::http-uri-parent=disabled
  //     aip.dev/not-precedent: We need to do this because reasons. --)
  // (-- api-linter: core::0133::response-message-name=disabled
  //     aip.dev/not-precedent: We need to do this because reasons. --)
  // (-- api-linter: core::0133::http-body=disabled
  //     aip.dev/not-precedent: We need to do this because reasons. --)
  // (-- api-linter: core::0133::method-signature=disabled
  //     aip.dev/not-precedent: We need to do this because reasons. --)
  // Create a Signup URL
  rpc CreateSignupUrl(CreateSignupUrlRequest) returns (CreateSignupUrlResponse) {
    option (google.api.http) = {
      post: "/v1beta1/partners/msp/signupUrl"
    };
    option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
      summary: "Create a Signup URL"
      tags: ["Partner"]
    };
  }
  // List Partner Customers
  rpc ListCustomers(ListCustomersRequest) returns (ListCustomersResponse) {
    option (google.api.http) = {
      get: "/v1beta1/partners/customers"
    };
    option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
      summary: "List Partner Customers"
      tags: ["Partner"]
    };
  }
  // (-- api-linter: core::0131::http-uri-name=disabled
  //     aip.dev/not-precedent: We need to do this because reasons. --)
  // (-- api-linter: core::0131::method-signature=disabled
  //     aip.dev/not-precedent: We need to do this because reasons. --)
  // Get Partner Profile
  rpc GetPartnerProfile(GetPartnerProfileRequest) returns (PartnerProfile) {
    option (google.api.http) = {
      get: "/v1beta1/partners/partnerProfile"
    };
    option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
      summary: "Get Partner Profile"
      tags: ["Partner"]
    };
  }
  // (-- api-linter: core::0134::http-uri-name=disabled
  //     aip.dev/not-precedent: We need to do this because reasons. --)
  // Update Partner Profile
  rpc UpdatePartnerProfile(UpdatePartnerProfileRequest) returns (PartnerProfile) {
    option (google.api.http) = {
      patch: "/v1beta1/partners/partnerProfile"
      body: "partner_profile"
    };
    option (google.api.method_signature) = "partner_profile,update_mask";
    option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
      summary: "Update Partner Profile"
      tags: ["Partner"]
    };
  }
}

// Service for Upload File
service FileUploadService {
  // Upload Partner Logo
  rpc UploadLogo(UploadLogoRequest) returns (UploadLogoResponse) {
    option (google.api.http) = {
      post: "/v1beta1/partners/logo:upload"
      body: "*"
    };
    option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
      summary: "Upload Partner Logo"
      tags: ["Partner"]
    };
  }
}

// (-- api-linter: core::0131::request-name-required=disabled
//     aip.dev/not-precedent: This is named "book" for historical reasons. --)
// Request for GetPartnerProfile
message GetPartnerProfileRequest {

}

// (-- api-linter: core::0134::request-mask-required=disabled
//     aip.dev/not-precedent: We need to do this because reasons. --)
// Request for UpdatePartnerProfile
message UpdatePartnerProfileRequest {
  // The Profile of the Partner
  PartnerProfile partner_profile = 1 [(google.api.field_behavior) = REQUIRED];
}

// Partner Profile
message PartnerProfile {
  // The Org ID of the Partner
  string org_id = 1 [(google.api.field_behavior) = OUTPUT_ONLY];
  // The Light Logo of the Partner
  string light_logo = 2 [(google.api.field_behavior) = REQUIRED];
  // The Advertising of the Partner
  repeated Advertising advertising = 3 [(google.api.field_behavior) = REQUIRED];
  // The Dark Logo of the Partner
  string dark_logo = 4 [(google.api.field_behavior) = REQUIRED];
}

// Advertising of Partner
message Advertising {
  // Index of Advertising
  string index = 1 [(google.api.field_behavior) = REQUIRED];
  // Heading of Advertising
  string heading = 2 [(google.api.field_behavior) = REQUIRED];
  // Body of Advertising
  string body = 3 [(google.api.field_behavior) = REQUIRED];
}

// (-- api-linter: core::0158::request-page-size-field=disabled
//     aip.dev/not-precedent: We need to do this because reasons. --)
// (-- api-linter: core::0158::request-page-token-field=disabled
//     aip.dev/not-precedent: We need to do this because reasons. --)
// (-- api-linter: core::0132::request-parent-required=disabled
//     aip.dev/not-precedent: We need to do this because reasons. --)
// Request for ListCustomers
message ListCustomersRequest {

}

// (-- api-linter: core::0158::response-next-page-token-field=disabled
//     aip.dev/not-precedent: We need to do this because reasons. --)
// Response for ListCustomers
message ListCustomersResponse {
  // The Customers in the Partner
  repeated Customer customers = 1 [(google.api.field_behavior) = OUTPUT_ONLY];
}

// (-- api-linter: core::0122::name-suffix=disabled
//     aip.dev/not-precedent: We need to do this because reasons. --)
// (-- api-linter: core::0142::time-field-type=disabled
//     aip.dev/not-precedent: We need to do this because reasons. --)
// A Partner Customer
message Customer {
  option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_schema) = {
    json_schema: {
      title: "A Partner Customer"
    }
  };
  // The EffectedTime of Customer
  string effected_time = 1 [(google.api.field_behavior) = OUTPUT_ONLY];
  // The Email of Customer
  string email = 2 [(google.api.field_behavior) = OUTPUT_ONLY];
  // The ExpiredTime of Customer
  string expired_time = 3 [(google.api.field_behavior) = OUTPUT_ONLY];
  // The Org ID of Customer
  string org_id = 4 [(google.api.field_behavior) = OUTPUT_ONLY];
  // The OrgName of Customer
  string org_name = 5 [(google.api.field_behavior) = OUTPUT_ONLY];
  // The State of Customer
  string state = 6 [(google.api.field_behavior) = OUTPUT_ONLY];
}

// (-- api-linter: core::0133::request-resource-field=disabled
//     aip.dev/not-precedent: We need to do this because reasons. --)
// (-- api-linter: core::0133::request-id-field=disabled
//     aip.dev/not-precedent: We need to do this because reasons. --)
// (-- api-linter: core::0133::request-parent-required=disabled
//     aip.dev/not-precedent: We need to do this because reasons. --)
// Request for CreateSignupUrl
message CreateSignupUrlRequest {

}

// (-- api-linter: core::0122::name-suffix=disabled
//     aip.dev/not-precedent: We need to do this because reasons. --)
// Request for UploadLogo
message UploadLogoRequest {
  // The File Name of Upload file
  string file_name = 1 [(google.api.field_behavior) = REQUIRED];
  // The Content of Upload file
  bytes content = 2 [(google.api.field_behavior) = REQUIRED];
  // The Header of Upload file
  map<string, string> headers = 3 [(google.api.field_behavior) = REQUIRED];

}

// (-- api-linter: core::0140::uri=disabled
//     aip.dev/not-precedent: We need to do this because reasons. --)
// (-- api-linter: core::0122::name-suffix=disabled
//     aip.dev/not-precedent: We need to do this because reasons. --)
// Response for UploadLogo
message UploadLogoResponse {
  // The Logo Name of Uploaded file
  string logo_name = 1;
  // The Logo Url of Uploaded file
  string logo_url = 2;
}

// (-- api-linter: core::0142::time-field-type=disabled
//     aip.dev/not-precedent: We need to do this because reasons. --)
// (-- api-linter: core::0140::uri=disabled
//     aip.dev/not-precedent: We need to do this because reasons. --)
// Response for CreateSignupUrl
message CreateSignupUrlResponse {
  // The Signup URL for Partner Customer
  string customer_signup_url = 1 [(google.api.field_behavior) = OUTPUT_ONLY];
  // The Expired Time for Signup URL
  string expired_time = 2 [(google.api.field_behavior) = OUTPUT_ONLY];
}

// (-- api-linter: core::0133::request-resource-field=disabled
//     aip.dev/not-precedent: We need to do this because reasons. --)
// (-- api-linter: core::0133::request-parent-required=disabled
//     aip.dev/not-precedent: We need to do this because reasons. --)
// (-- api-linter: core::0133::request-id-field=disabled
//     aip.dev/not-precedent: We need to do this because reasons. --)
// Request for CreateOrgInvitation
message CreateOrgInvitationRequest {
  // (-- api-linter: core::0133::request-unknown-fields=disabled
  //     aip.dev/not-precedent: We really need this field because reasons. --)
  // (-- api-linter: core::0133::request-required-fields=disabled
  //     aip.dev/not-precedent: We really need this field to be required because
  // reasons. --)
  // The Invitees Emails of Invitation
  repeated string invitees_emails = 1 [
    (google.api.field_behavior) = REQUIRED,
    (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
      title: "The Invitees Emails of Invitation."
    }
  ];
  // (-- api-linter: core::0133::request-unknown-fields=disabled
  //     aip.dev/not-precedent: We really need this field because reasons. --)
  // (-- api-linter: core::0133::request-required-fields=disabled
  //     aip.dev/not-precedent: We really need this field to be required because
  // reasons. --)
  // The Role of Invitation
  string role = 2 [
    (google.api.field_behavior) = REQUIRED,
    (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
      title: "The Role of Invitation"
      enum: ["partner:admin", "org:owner", "org:member", "org:audit_admin", "org:billing_admin"]
    }
  ];
}

// Response for CreateOrgInvitation CreateProjectInvitation
message CreateInvitationResponse {
  // (-- api-linter: core::0133::request-unknown-fields=disabled
  //     aip.dev/not-precedent: We really need this field because reasons. --)
  // (-- api-linter: core::0133::request-required-fields=disabled
  //     aip.dev/not-precedent: We really need this field to be required because
  // reasons. --)
  // The invitation Result
  repeated Invitation invitations = 1 [
    (google.api.field_behavior) = OUTPUT_ONLY,
    (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {title: "The Invitation Result"}
  ];
}

// (-- api-linter: core::0133::request-resource-field=disabled
//     aip.dev/not-precedent: We need to do this because reasons. --)
// (-- api-linter: core::0133::request-id-field=disabled
//     aip.dev/not-precedent: We need to do this because reasons. --)
// (-- api-linter: core::0133::request-parent-required=disabled
//     aip.dev/not-precedent: We need to do this because reasons. --)
// Request for CreateProjectInvitation
message CreateProjectInvitationRequest {
  // (-- api-linter: core::0141::forbidden-types=disabled
  //     aip.dev/not-precedent: We need to do this because reasons. --)
  // (-- api-linter: core::0133::request-required-fields=disabled
  //     aip.dev/not-precedent: We really need this field to be required because
  // reasons. --)
  // (-- api-linter: core::0133::request-unknown-fields=disabled
  //     aip.dev/not-precedent: We really need this field because reasons. --)
  // Project ID
  uint64 project_id = 1 [
    (google.api.field_behavior) = REQUIRED,
    (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {description: "Project ID."}
  ];
  // (-- api-linter: core::0133::request-unknown-fields=disabled
  //     aip.dev/not-precedent: We really need this field because reasons. --)
  // (-- api-linter: core::0133::request-required-fields=disabled
  //     aip.dev/not-precedent: We really need this field to be required because
  // reasons. --)
  // The Invitees Emails of Invitation
  repeated string invitees_emails = 2 [
    (google.api.field_behavior) = REQUIRED,
    (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {title: "The Invitees Emails of Invitation"}
  ];
  // (-- api-linter: core::0133::request-unknown-fields=disabled
  //     aip.dev/not-precedent: We really need this field because reasons. --)
  // (-- api-linter: core::0133::request-required-fields=disabled
  //     aip.dev/not-precedent: We really need this field to be required because
  // reasons. --)
  // The Role of Invitation
  string role = 3 [
    (google.api.field_behavior) = REQUIRED,
    (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
      title: "The Role of Invitation"
      enum: ["project:owner", "project:dev", "project:readonly"]
    }
  ];
}

// (-- api-linter: core::0142::time-field-type=disabled
//     aip.dev/not-precedent: We need to do this because reasons. --)
// (-- api-linter: core::0123::resource-name-field=disabled
//     aip.dev/not-precedent: We need to do this because reasons. --)
// An Invitation
message Invitation {
  option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_schema) = {
    json_schema: {
      title: "An Invitation"
    }
  };
  option (google.api.resource) = {
    type: "iam.tidbapi.com/Invitation"
    pattern: "invitations/{invitation}"
    singular: "invitation",
    plural: "invitations",
  };

  // Result for Invitation
  enum Result {
    // Unspecified. Do not use
    RESULT_UNSPECIFIED = 0;
    // Success
    RESULT_SUCCESS = 1;
    // Fail
    RESULT_FAIL = 2;
  }

  // The Invitees Email of Invitation
  string invitees_email = 1 [(google.api.field_behavior) = OUTPUT_ONLY];
  // The Org ID of Invitation
  string org_id = 2 [(google.api.field_behavior) = OUTPUT_ONLY];
  // The Project ID of Invitation
  string project_id = 3 [(google.api.field_behavior) = OUTPUT_ONLY];
  // The Role of Invitation
  string role = 4 [(google.api.field_behavior) = OUTPUT_ONLY];
  // The Result of Invitation
  Result result = 5 [(google.api.field_behavior) = OUTPUT_ONLY];
  // The tip message of Invitation result
  string message = 6 [(google.api.field_behavior) = OUTPUT_ONLY];
}

// (-- api-linter: core::0131::request-name-required=disabled
//     aip.dev/not-precedent: This is named "book" for historical reasons. --)
// Request for GetUser
message GetUserRequest {
  // (-- api-linter: core::0131::request-unknown-fields=disabled
  //     aip.dev/not-precedent: We really need this field because reasons. --)
  // (-- api-linter: core::0141::forbidden-types=disabled
  //     aip.dev/not-precedent: We need to do this because reasons. --)
  // (-- api-linter: core::0131::request-required-fields=disabled
  //     aip.dev/not-precedent: We really need this field to be required because
  //     reasons. --)
  // ID of the User
  uint64 user_id = 1 [(google.api.field_behavior) = REQUIRED];
}

// (-- api-linter: core::0134::request-mask-required=disabled
//     aip.dev/not-precedent: We need to do this because reasons. --)
// (-- api-linter: core::0135::request-name-required=disabled
//     aip.dev/not-precedent: We need to do this because reasons. --)
// Request for UpdateUser
message UpdateUserRequest {
  // User resource
  User user = 1 [(google.api.field_behavior) = REQUIRED];
}

// (-- api-linter: core::0135::request-name-required=disabled
//     aip.dev/not-precedent: We need to do this because reasons. --)
// Request for DeleteOrgUser
message DeleteOrgUserRequest {
  // (-- api-linter: core::0141::forbidden-types=disabled
  //     aip.dev/not-precedent: We need to do this because reasons. --)
  // (-- api-linter: core::0135::request-unknown-fields=disabled
  //     aip.dev/not-precedent: We really need this field because reasons. --)
  // (-- api-linter: core::0135::request-required-fields=disabled
  //     aip.dev/not-precedent: We really need this field to be required because
  // reasons. --)
  // ID of the User
  uint64 user_id = 1 [
    (google.api.field_behavior) = REQUIRED,
    (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {description: "ID of the User."}
  ];
}

// (-- api-linter: core::0135::request-name-required=disabled
//     aip.dev/not-precedent: We need to do this because reasons. --)
// Request for DeleteProjectUser
message DeleteProjectUserRequest {
  // (-- api-linter: core::0135::request-unknown-fields=disabled
  //     aip.dev/not-precedent: We really need this field because reasons. --)
  // (-- api-linter: core::0135::request-required-fields=disabled
  //     aip.dev/not-precedent: We really need this field to be required because
  // reasons. --)
  // (-- api-linter: core::0141::forbidden-types=disabled
  //     aip.dev/not-precedent: We need to do this because reasons. --)
  // ID of the Project
  uint64 project_id = 1 [
    (google.api.field_behavior) = REQUIRED,
    (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {description: "ID of the Project."}
  ];
  // (-- api-linter: core::0135::request-unknown-fields=disabled
  //     aip.dev/not-precedent: We really need this field because reasons. --)
  // (-- api-linter: core::0135::request-required-fields=disabled
  //     aip.dev/not-precedent: We really need this field to be required because
  // reasons. --)
  // (-- api-linter: core::0141::forbidden-types=disabled
  //     aip.dev/not-precedent: We need to do this because reasons. --)
  // ID of the User
  uint64 user_id = 2 [
    (google.api.field_behavior) = REQUIRED,
    (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {description: "ID of the User."}
  ];
}

// Request for ListUsers
message ListUsersRequest {
  // The maximum number of User to return.
  int32 page_size = 1 [(google.api.field_behavior) = OPTIONAL];
  // A page token, received from a previous `ListApiKeys` call.
  string page_token = 2 [(google.api.field_behavior) = OPTIONAL];
  // (-- api-linter: core::0132::request-unknown-fields=disabled
  //     aip.dev/not-precedent: We really need this field because reasons. --)
 // The Project that User have active Project Role
  int64 project_id = 3 [
    (google.api.field_behavior) = OPTIONAL,
    (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {title: "The Project ID that User have active Project Role."}
  ];
  // (-- api-linter: core::0132::request-unknown-fields=disabled
  //     aip.dev/not-precedent: We really need this field because reasons. --)
  // The Email of User
  string email = 4 [
    (google.api.field_behavior) = OPTIONAL,
    (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {title: "The Email of User."}
  ];
  // Allow the user to skip results.
  int32 skip = 5 [(google.api.field_behavior) = OPTIONAL];
}

// Response for ListUsers
message ListUsersResponse {
  // The list of matching Users.
  repeated User users = 1;
  // nextPageToken can be sent in a subsequent call to fetch more results
  string next_page_token = 2 [
    (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
      title: "nextPageToken"
      description: "nextPageToken can be sent in a subsequent call to fetch more results"
    }
  ];
  // The total size of matching Users.
  int32 total_size = 3;
}

// (-- api-linter: core::0148::human-names=disabled
//     aip.dev/not-precedent: We need to do this because reasons. --)
// (-- api-linter: core::0122::name-suffix=disabled
//     aip.dev/not-precedent: We need to do this because reasons. --)
// (-- api-linter: core::0142::time-field-type=disabled
//     aip.dev/not-precedent: We need to do this because reasons. --)
// A User
message User {
  option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_schema) = {
    json_schema: {
      title: "A User"
    }
  };
  option (google.api.resource) = {
    type: "iam.tidbapi.com/User"
    pattern: "users/{user}"
    singular: "user",
    plural: "users",
  };

  // The First Name of User
  string first_name = 1 [(google.api.field_behavior) = REQUIRED];
  // The Last Name of User
  string last_name = 2 [(google.api.field_behavior) = REQUIRED];
  // The Email of User
  string email = 3 [(google.api.field_behavior) = OUTPUT_ONLY];
  // The ID of User
  string user_id = 4 [(google.api.field_behavior) = OUTPUT_ONLY];
  // (-- api-linter: core::0203::resource-name-identifier=disabled
  //     aip.dev/not-precedent: We need to do this because reasons. --)
  // The Name of User, format: users/{user_id}
  string name = 5 [
    (google.api.field_behavior) = OUTPUT_ONLY,
    (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {title: "The Name of User, format: users/{user_id}."}
  ];
  // The Status of User in Resource
  string role_binding_status = 6 [(google.api.field_behavior) = OUTPUT_ONLY];
  // The Role of User in Resource
  string role_binding_role = 7 [(google.api.field_behavior) = OUTPUT_ONLY];
  // The Invite Time of User in Resource
  string invite_time = 8 [(google.api.field_behavior) = OUTPUT_ONLY];
  // The Last Login Time of User in Resource
  string last_login_time = 9 [(google.api.field_behavior) = OUTPUT_ONLY];
}

// (-- api-linter: core::0131::request-name-required=disabled
//     aip.dev/not-precedent: This is named "book" for historical reasons. --)
// Request for GetOrg
message GetOrgRequest {
}

// (-- api-linter: core::0132::request-parent-required=disabled
//     aip.dev/not-precedent: We need to do this because reasons. --)
// (-- api-linter: core::0158::request-page-size-field=disabled
//     aip.dev/not-precedent: We need to do this because reasons. --)
// (-- api-linter: core::0158::request-page-token-field=disabled
//     aip.dev/not-precedent: We need to do this because reasons. --)
// Request for ListPartnerOrgs
message ListPartnerOrgsRequest {
}

// (-- api-linter: core::0158::response-next-page-token-field=disabled
//     aip.dev/not-precedent: We need to do this because reasons. --)
// Response for ListPartnerOrgs
message ListPartnerOrgsResponse {
  // (-- api-linter: core::0132::response-unknown-fields=disabled
  //     aip.dev/not-precedent: We really need this field because reasons. --)
  // The list of matching Orgs.
  repeated Org orgs = 1 [(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {description: "The list of matching Orgs."}];
  // The total size of matching Orgs.
  int32 total_size = 2;
}

// (-- api-linter: core::0122::name-suffix=disabled
//     aip.dev/not-precedent: We need to do this because reasons. --)
// (-- api-linter: core::0123::resource-name-field=disabled
//     aip.dev/not-precedent: We need to do this because reasons. --)
// (-- api-linter: core::0142::time-field-type=disabled
//     aip.dev/not-precedent: We need to do this because reasons. --)
// A Org
message Org {
  option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_schema) = {
    json_schema: {
      title: "A Org"
    }
  };
  option (google.api.resource) = {
    type: "iam.tidbapi.com/Org"
    pattern: "org"
    singular: "org",
    plural: "orgs",
  };

  // The ID of Org
  string org_id = 1 [(google.api.field_behavior) = OUTPUT_ONLY];
  // The Name of Org
  string org_name = 2 [(google.api.field_behavior) = OUTPUT_ONLY];
  // The Email of Org
  string email = 3 [(google.api.field_behavior) = OUTPUT_ONLY];
  // The Tag of Org
  string org_tag = 4 [(google.api.field_behavior) = OUTPUT_ONLY];
  // The Create Time of Org
  string create_time = 5 [(google.api.field_behavior) = OUTPUT_ONLY];
  // The Email Domain of Org Creator
  string email_domain = 6 [(google.api.field_behavior) = OUTPUT_ONLY];
  // The Partner allowed Email Domains
  repeated string allow_email_domains = 7 [(google.api.field_behavior) = OUTPUT_ONLY];
}

// (-- api-linter: core::0135::request-name-required=disabled
//     aip.dev/not-precedent: We need to do this because reasons. --)
// Request for DeleteApiKey
message DeleteApiKeyRequest {
  // (-- api-linter: core::0135::request-unknown-fields=disabled
  //     aip.dev/not-precedent: We really need this field because reasons. --)
  // (-- api-linter: core::0135::request-required-fields=disabled
  //     aip.dev/not-precedent: We really need this field to be required because
  // reasons. --)
  // Access Key of the API key
  string access_key = 1 [
    (google.api.field_behavior) = REQUIRED,
    (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {description: "Access Key of the API key."}
  ];
}

// Request for ListApiKeys
message ListApiKeysRequest {
  // The maximum number of API keys to return.
  int32 page_size = 1 [(google.api.field_behavior) = OPTIONAL];
  // A page token, received from a previous `ListApiKeys` call.
  string page_token = 2 [(google.api.field_behavior) = OPTIONAL];
  // Allow the user to skip results.
  int32 skip = 3 [(google.api.field_behavior) = OPTIONAL];
}

// Response for ListApiKeys
message ListApiKeysResponse {
  // The list of matching API keys.
  repeated ApiKey api_keys = 1;
  // The page token for the next `ListApiKeys` call
  string next_page_token = 2 [
    (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
      description: "nextPageToken can be sent in a subsequent call to fetch more results"
    }
  ];
  // The total size of matching API keys.
  int32 total_size = 3;
}

// (-- api-linter: core::0158::response-next-page-token-field=disabled
//     aip.dev/not-precedent: We need to do this because reasons. --)
// Response for ListApiKeyRoles
message ListApiKeyRolesResponse {
  // (-- api-linter: core::0132::response-unknown-fields=disabled
  //     aip.dev/not-precedent: We really need this field because reasons. --)
  // The list of roles.
  repeated string org_roles = 1;
}

// (-- api-linter: core::0131::request-name-required=disabled
//     aip.dev/not-precedent: This is named "book" for historical reasons. --)
// Request for GetApiKeyRequest
message GetApiKeyRequest {
  // (-- api-linter: core::0131::request-unknown-fields=disabled
  //     aip.dev/not-precedent: We really need this field because reasons. --)
  // (-- api-linter: core::0131::request-required-fields=disabled
  //     aip.dev/not-precedent: We really need this field to be required because
  //     reasons. --)
  // Access Key of the API key
  string access_key = 1 [
    (google.api.field_behavior) = REQUIRED,
    (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {description: "Access Key of the API key."}];
}

// (-- api-linter: core::0133::request-id-field=disabled
//     aip.dev/not-precedent: We need to do this because we don't allow client to specify api_key_id. --)
// Request for CreateApiKey
message CreateApiKeyRequest {
  // ApiKey resource
  ApiKey api_key = 1 [(google.api.field_behavior) = REQUIRED];
}

// (-- api-linter: core::0142::time-field-type=disabled
//     aip.dev/not-precedent: We need to do this because reasons. --)
// An API key
message ApiKey {
  option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_schema) = {
    json_schema: {
      title: "An API key"
    }
  };
  option (google.api.resource) = {
    type: "iam.tidbapi.com/ApiKey"
    pattern: "apiKeys/{api_key}"
    singular: "apiKey",
    plural: "apiKeys",
  };
  // (-- api-linter: core::0203::resource-name-identifier=disabled
  //     aip.dev/not-precedent: We need to do this because reasons. --)
  // The name of API key, format: orgs/{org_id}/apikeys/{api_key}
  string name = 1 [
    (google.api.field_behavior) = OUTPUT_ONLY,
    (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
      title: "The name of API key"
      description: "The name of API key, format: orgs/{org_id}/apikeys/{api_key}"
    }
  ];
  // Access key of API key
  string access_key = 2 [(google.api.field_behavior) = OUTPUT_ONLY];
  // Secret key of API key, only fully displayed when initially created.
  string secret_key = 3 [
    (google.api.field_behavior) = OUTPUT_ONLY,
    (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
      title: "Secret key of API key"
      description: "Secret key of API key, only fully displayed when initially created."
    }
  ];
  // Description of API key
  string display_name = 4 [(google.api.field_behavior) = REQUIRED];
  // Role of API key
  string role = 5 [
    (google.api.field_behavior) = REQUIRED,
    (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
      enum: ["api:org:owner"]
    }
  ];
  // Creator of API Key
  string creator = 6 [(google.api.field_behavior) = OUTPUT_ONLY];
  // Create time of API Key
  string create_time = 7 [(google.api.field_behavior) = OUTPUT_ONLY];
  // Update time of API Key
  string update_time = 8 [(google.api.field_behavior) = OUTPUT_ONLY];
}
