// 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.chat.v1;

import "google/api/field_behavior.proto";
import "google/api/resource.proto";
import "google/chat/v1/group.proto";
import "google/chat/v1/user.proto";
import "google/protobuf/field_mask.proto";
import "google/protobuf/timestamp.proto";

option csharp_namespace = "Google.Apps.Chat.V1";
option go_package = "cloud.google.com/go/chat/apiv1/chatpb;chatpb";
option java_multiple_files = true;
option java_outer_classname = "MembershipProto";
option java_package = "com.google.chat.v1";
option objc_class_prefix = "DYNAPIProto";
option php_namespace = "Google\\Apps\\Chat\\V1";
option ruby_package = "Google::Apps::Chat::V1";

// Represents a membership relation in Google Chat, such as whether a user or
// Chat app is invited to, part of, or absent from a space.
message Membership {
  option (google.api.resource) = {
    type: "chat.googleapis.com/Membership"
    pattern: "spaces/{space}/members/{member}"
  };

  // Specifies the member's relationship with a space. Other membership states
  // might be supported in the future.
  enum MembershipState {
    // Default value. Don't use.
    MEMBERSHIP_STATE_UNSPECIFIED = 0;

    // The user is added to the space, and can participate in the space.
    JOINED = 1;

    // The user is invited to join the space, but hasn't joined it.
    INVITED = 2;

    // The user doesn't belong to the space and doesn't have a pending
    // invitation to join the space.
    NOT_A_MEMBER = 3;
  }

  // Represents a user's permitted actions in a Chat space. More enum values
  // might be added in the future.
  enum MembershipRole {
    // Default value. For [users][google.chat.v1.Membership.member]: they
    // aren't a member of the space, but can be invited. For
    // [Google Groups][google.chat.v1.Membership.group_member]: they're always
    //  assigned this role (other enum values might be used in the future).
    MEMBERSHIP_ROLE_UNSPECIFIED = 0;

    // A member of the space. The user has basic permissions, like sending
    // messages to the space. In 1:1 and unnamed group conversations, everyone
    // has this role.
    ROLE_MEMBER = 1;

    // A space manager. The user has all basic permissions plus administrative
    // permissions that let them manage the space, like adding or removing
    // members. Only supported in
    // [SpaceType.SPACE][google.chat.v1.Space.SpaceType].
    ROLE_MANAGER = 2;
  }

  // Identifier. Resource name of the membership, assigned by the server.
  //
  // Format: `spaces/{space}/members/{member}`
  string name = 1 [(google.api.field_behavior) = IDENTIFIER];

  // Output only. State of the membership.
  MembershipState state = 2 [(google.api.field_behavior) = OUTPUT_ONLY];

  // Optional. User's role within a Chat space, which determines their permitted
  // actions in the space.
  //
  // This field can only be used as input in `UpdateMembership`.
  MembershipRole role = 7 [(google.api.field_behavior) = OPTIONAL];

  // Member associated with this membership. Other member types might be
  // supported in the future.
  oneof memberType {
    // Optional. The Google Chat user or app the membership corresponds to.
    // If your Chat app [authenticates as a
    // user](https://developers.google.com/workspace/chat/authenticate-authorize-chat-user),
    // the output populates the
    // [user](https://developers.google.com/workspace/chat/api/reference/rest/v1/User)
    // `name` and `type`.
    User member = 3 [(google.api.field_behavior) = OPTIONAL];

    // Optional. The Google Group the membership corresponds to.
    //
    // Reading or mutating memberships for Google Groups requires [user
    // authentication](https://developers.google.com/workspace/chat/authenticate-authorize-chat-user).
    Group group_member = 5 [(google.api.field_behavior) = OPTIONAL];
  }

  // Optional. Immutable. The creation time of the membership, such as when a
  // member joined or was invited to join a space. This field is output only,
  // except when used to import historical memberships in import mode spaces.
  google.protobuf.Timestamp create_time = 4 [
    (google.api.field_behavior) = IMMUTABLE,
    (google.api.field_behavior) = OPTIONAL
  ];

  // Optional. Immutable. The deletion time of the membership, such as when a
  // member left or was removed from a space. This field is output only, except
  // when used to import historical memberships in import mode spaces.
  google.protobuf.Timestamp delete_time = 8 [
    (google.api.field_behavior) = IMMUTABLE,
    (google.api.field_behavior) = OPTIONAL
  ];
}

// Request message for creating a membership.
message CreateMembershipRequest {
  // Required. The resource name of the space for which to create the
  // membership.
  //
  // Format: spaces/{space}
  string parent = 1 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.resource_reference) = {
      child_type: "chat.googleapis.com/Membership"
    }
  ];

  // Required. The membership relation to create.
  //
  // The `memberType` field must contain a user with the `user.name` and
  // `user.type` fields populated. The server will assign a resource name
  // and overwrite anything specified.
  //
  // When a Chat app creates a membership relation for a human user, it must use
  // certain authorization scopes and set specific values for certain fields:
  //
  // - When [authenticating as a
  // user](https://developers.google.com/workspace/chat/authenticate-authorize-chat-user),
  // the `chat.memberships` authorization scope is required.
  //
  // - When [authenticating as an
  // app](https://developers.google.com/workspace/chat/authenticate-authorize-chat-app),
  // the `chat.app.memberships` authorization scope is required.
  // Authenticating as an app is available in [Developer
  // Preview](https://developers.google.com/workspace/preview).
  //
  // - Set `user.type` to `HUMAN`, and set `user.name` with format
  // `users/{user}`, where `{user}` can be the email address for the user. For
  // users in the same Workspace organization `{user}` can also be the `id` of
  // the [person](https://developers.google.com/people/api/rest/v1/people) from
  // the People API, or the `id` for the user in the Directory API. For example,
  // if the People API Person profile ID for `user@example.com` is `123456789`,
  // you can add the user to the space by setting the `membership.member.name`
  // to `users/user@example.com` or `users/123456789`.
  //
  // Inviting users external to the Workspace organization that owns the space
  // requires [user
  // authentication](https://developers.google.com/workspace/chat/authenticate-authorize-chat-user).
  //
  // When a Chat app creates a membership relation for itself, it must
  // [authenticate as a
  // user](https://developers.google.com/workspace/chat/authenticate-authorize-chat-user)
  // and use the `chat.memberships.app` scope, set `user.type` to `BOT`, and set
  // `user.name` to `users/app`.
  Membership membership = 2 [(google.api.field_behavior) = REQUIRED];

  // Optional. When `true`, the method runs using the user's Google Workspace
  // administrator privileges.
  //
  // The calling user must be a Google Workspace administrator with the
  // [manage chat and spaces conversations
  // privilege](https://support.google.com/a/answer/13369245).
  //
  // Requires the `chat.admin.memberships` [OAuth 2.0
  // scope](https://developers.google.com/workspace/chat/authenticate-authorize#chat-api-scopes).
  //
  // Creating app memberships or creating memberships for users outside the
  // administrator's Google Workspace organization isn't supported using admin
  // access.
  bool use_admin_access = 5 [(google.api.field_behavior) = OPTIONAL];
}

// Request message for updating a membership.
message UpdateMembershipRequest {
  // Required. The membership to update. Only fields specified by `update_mask`
  // are updated.
  Membership membership = 1 [(google.api.field_behavior) = REQUIRED];

  // Required. The field paths to update. Separate multiple values with commas
  // or use `*` to update all field paths.
  //
  // Currently supported field paths:
  //
  // - `role`
  google.protobuf.FieldMask update_mask = 2
      [(google.api.field_behavior) = REQUIRED];

  // Optional. When `true`, the method runs using the user's Google Workspace
  // administrator privileges.
  //
  // The calling user must be a Google Workspace administrator with the
  // [manage chat and spaces conversations
  // privilege](https://support.google.com/a/answer/13369245).
  //
  // Requires the `chat.admin.memberships` [OAuth 2.0
  // scope](https://developers.google.com/workspace/chat/authenticate-authorize#chat-api-scopes).
  bool use_admin_access = 3 [(google.api.field_behavior) = OPTIONAL];
}

// Request message for listing memberships.
message ListMembershipsRequest {
  // Required. The resource name of the space for which to fetch a membership
  // list.
  //
  // Format: spaces/{space}
  string parent = 1 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.resource_reference) = {
      child_type: "chat.googleapis.com/Membership"
    }
  ];

  // Optional. The maximum number of memberships to return. The service might
  // return fewer than this value.
  //
  // If unspecified, at most 100 memberships are returned.
  //
  // The maximum value is 1000. If you use a value more than 1000, it's
  // automatically changed to 1000.
  //
  // Negative values return an `INVALID_ARGUMENT` error.
  int32 page_size = 2 [(google.api.field_behavior) = OPTIONAL];

  // Optional. A page token, received from a previous call to list memberships.
  // Provide this parameter to retrieve the subsequent page.
  //
  // When paginating, all other parameters provided should match the call that
  // provided the page token. Passing different values to the other parameters
  // might lead to unexpected results.
  string page_token = 3 [(google.api.field_behavior) = OPTIONAL];

  // Optional. A query filter.
  //
  // You can filter memberships by a member's role
  // ([`role`](https://developers.google.com/workspace/chat/api/reference/rest/v1/spaces.members#membershiprole))
  // and type
  // ([`member.type`](https://developers.google.com/workspace/chat/api/reference/rest/v1/User#type)).
  //
  // To filter by role, set `role` to `ROLE_MEMBER` or `ROLE_MANAGER`.
  //
  // To filter by type, set `member.type` to `HUMAN` or `BOT`. You can also
  // filter for `member.type` using the `!=` operator.
  //
  // To filter by both role and type, use the `AND` operator. To filter by
  // either role or type, use the `OR` operator.
  //
  // Either `member.type = "HUMAN"` or `member.type != "BOT"` is required
  // when `use_admin_access` is set to true. Other member type filters will be
  // rejected.
  //
  // For example, the following queries are valid:
  //
  // ```
  // role = "ROLE_MANAGER" OR role = "ROLE_MEMBER"
  // member.type = "HUMAN" AND role = "ROLE_MANAGER"
  //
  // member.type != "BOT"
  // ```
  //
  // The following queries are invalid:
  //
  // ```
  // member.type = "HUMAN" AND member.type = "BOT"
  // role = "ROLE_MANAGER" AND role = "ROLE_MEMBER"
  // ```
  //
  // Invalid queries are rejected by the server with an `INVALID_ARGUMENT`
  // error.
  string filter = 5 [(google.api.field_behavior) = OPTIONAL];

  // Optional. When `true`, also returns memberships associated with a
  // [Google Group][google.chat.v1.Membership.group_member], in
  // addition to other types of memberships. If a
  // [filter][google.chat.v1.ListMembershipsRequest.filter] is set,
  // [Google Group][google.chat.v1.Membership.group_member]
  // memberships that don't match the filter criteria aren't returned.
  bool show_groups = 6 [(google.api.field_behavior) = OPTIONAL];

  // Optional. When `true`, also returns memberships associated with
  // [invited][google.chat.v1.Membership.MembershipState.INVITED] members, in
  // addition to other types of memberships. If a
  // filter is set,
  // [invited][google.chat.v1.Membership.MembershipState.INVITED] memberships
  // that don't match the filter criteria aren't returned.
  //
  // Currently requires [user
  // authentication](https://developers.google.com/workspace/chat/authenticate-authorize-chat-user).
  bool show_invited = 7 [(google.api.field_behavior) = OPTIONAL];

  // Optional. When `true`, the method runs using the user's Google Workspace
  // administrator privileges.
  //
  // The calling user must be a Google Workspace administrator with the
  // [manage chat and spaces conversations
  // privilege](https://support.google.com/a/answer/13369245).
  //
  // Requires either the `chat.admin.memberships.readonly` or
  // `chat.admin.memberships` [OAuth 2.0
  // scope](https://developers.google.com/workspace/chat/authenticate-authorize#chat-api-scopes).
  //
  // Listing app memberships in a space isn't supported when using admin access.
  bool use_admin_access = 8 [(google.api.field_behavior) = OPTIONAL];
}

// Response to list memberships of the space.
message ListMembershipsResponse {
  // Unordered list. List of memberships in the requested (or first) page.
  repeated Membership memberships = 1
      [(google.api.field_behavior) = UNORDERED_LIST];

  // A token that you can send as `pageToken` to retrieve the next page of
  // results. If empty, there are no subsequent pages.
  string next_page_token = 2;
}

// Request to get a membership of a space.
message GetMembershipRequest {
  // Required. Resource name of the membership to retrieve.
  //
  // To get the app's own membership [by using user
  // authentication](https://developers.google.com/workspace/chat/authenticate-authorize-chat-user),
  // you can optionally use `spaces/{space}/members/app`.
  //
  // Format: `spaces/{space}/members/{member}` or `spaces/{space}/members/app`
  //
  // You can use the user's email as an alias for `{member}`. For example,
  // `spaces/{space}/members/example@gmail.com` where `example@gmail.com` is the
  // email of the Google Chat user.
  string name = 1 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.resource_reference) = { type: "chat.googleapis.com/Membership" }
  ];

  // Optional. When `true`, the method runs using the user's Google Workspace
  // administrator privileges.
  //
  // The calling user must be a Google Workspace administrator with the
  // [manage chat and spaces conversations
  // privilege](https://support.google.com/a/answer/13369245).
  //
  // Requires the `chat.admin.memberships` or `chat.admin.memberships.readonly`
  // [OAuth 2.0
  // scopes](https://developers.google.com/workspace/chat/authenticate-authorize#chat-api-scopes).
  //
  // Getting app memberships in a space isn't supported when using admin access.
  bool use_admin_access = 3 [(google.api.field_behavior) = OPTIONAL];
}

// Request to delete a membership in a space.
message DeleteMembershipRequest {
  // Required. Resource name of the membership to delete. Chat apps can delete
  // human users' or their own memberships. Chat apps can't delete other apps'
  // memberships.
  //
  // When deleting a human membership, requires the `chat.memberships` scope and
  // `spaces/{space}/members/{member}` format. You can use the email as an
  // alias for `{member}`. For example,
  // `spaces/{space}/members/example@gmail.com` where `example@gmail.com` is the
  // email of the Google Chat user.
  //
  // When deleting an app membership, requires the `chat.memberships.app` scope
  // and `spaces/{space}/members/app` format.
  //
  // Format: `spaces/{space}/members/{member}` or `spaces/{space}/members/app`.
  string name = 1 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.resource_reference) = { type: "chat.googleapis.com/Membership" }
  ];

  // Optional. When `true`, the method runs using the user's Google Workspace
  // administrator privileges.
  //
  // The calling user must be a Google Workspace administrator with the
  // [manage chat and spaces conversations
  // privilege](https://support.google.com/a/answer/13369245).
  //
  // Requires the `chat.admin.memberships` [OAuth 2.0
  // scope](https://developers.google.com/workspace/chat/authenticate-authorize#chat-api-scopes).
  //
  // Deleting app memberships in a space isn't supported using admin access.
  bool use_admin_access = 2 [(google.api.field_behavior) = OPTIONAL];
}
