// Copyright 2020-2026 Buf Technologies, Inc.
//
// 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 buf.alpha.registry.v1alpha1;

import "buf/alpha/registry/v1alpha1/role.proto";
import "buf/alpha/registry/v1alpha1/verification_status.proto";
import "google/protobuf/timestamp.proto";

message Organization {
  // primary key, unique, immutable
  string id = 1;
  // immutable
  google.protobuf.Timestamp create_time = 2;
  // mutable
  google.protobuf.Timestamp update_time = 3;
  // unique, mutable
  string name = 4;
  // description is the user configurable description of the organization.
  string description = 5;
  // url is the user configurable URL in the description of the organization,
  // always included the scheme and will not have a #fragment suffix.
  string url = 6;
  // verification status of the organization, configurable by server admin.
  VerificationStatus verification_status = 7;
}

// OrganizationMembership is a nested structure that contains
// the organization and user membership information on that organization.
message OrganizationMembership {
  Organization organization = 1;
  OrganizationRole organization_role = 2;
}

// OrganizationService is the Organization service.
service OrganizationService {
  // GetOrganization gets a organization by ID.
  rpc GetOrganization(GetOrganizationRequest) returns (GetOrganizationResponse) {
    option idempotency_level = NO_SIDE_EFFECTS;
  }
  // GetOrganizationByName gets a organization by name.
  rpc GetOrganizationByName(GetOrganizationByNameRequest) returns (GetOrganizationByNameResponse) {
    option idempotency_level = NO_SIDE_EFFECTS;
  }
  // ListOrganizations lists all organizations.
  rpc ListOrganizations(ListOrganizationsRequest) returns (ListOrganizationsResponse) {
    option idempotency_level = NO_SIDE_EFFECTS;
  }
  // ListUserOrganizations lists all organizations a user is member of.
  rpc ListUserOrganizations(ListUserOrganizationsRequest) returns (ListUserOrganizationsResponse) {
    option idempotency_level = NO_SIDE_EFFECTS;
  }
  rpc GetUserOrganization(GetUserOrganizationRequest) returns (GetUserOrganizationResponse) {
    option idempotency_level = NO_SIDE_EFFECTS;
  }
  // CreateOrganization creates a new organization.
  rpc CreateOrganization(CreateOrganizationRequest) returns (CreateOrganizationResponse) {
    option idempotency_level = IDEMPOTENT;
  }
  // DeleteOrganization deletes a organization.
  rpc DeleteOrganization(DeleteOrganizationRequest) returns (DeleteOrganizationResponse) {
    option idempotency_level = IDEMPOTENT;
  }
  // DeleteOrganizationByName deletes a organization by name.
  rpc DeleteOrganizationByName(DeleteOrganizationByNameRequest) returns (DeleteOrganizationByNameResponse) {
    option idempotency_level = IDEMPOTENT;
  }
  // AddOrganizationMember add a role to an user in the organization.
  rpc AddOrganizationMember(AddOrganizationMemberRequest) returns (AddOrganizationMemberResponse) {
    option idempotency_level = IDEMPOTENT;
  }
  // UpdateOrganizationMember update the user's membership information in the organization.
  rpc UpdateOrganizationMember(UpdateOrganizationMemberRequest) returns (UpdateOrganizationMemberResponse);
  // RemoveOrganizationMember remove the role of an user in the organization.
  rpc RemoveOrganizationMember(RemoveOrganizationMemberRequest) returns (RemoveOrganizationMemberResponse) {
    option idempotency_level = IDEMPOTENT;
  }
  // GetOrganizationSettings gets the settings of an organization, including organization base roles.
  rpc GetOrganizationSettings(GetOrganizationSettingsRequest) returns (GetOrganizationSettingsResponse) {
    option idempotency_level = NO_SIDE_EFFECTS;
  }
  // UpdateOrganizationSettings update the organization settings including base roles.
  rpc UpdateOrganizationSettings(UpdateOrganizationSettingsRequest) returns (UpdateOrganizationSettingsResponse);
  // AddOrganizationGroup adds an IdP Group to the organization.
  rpc AddOrganizationGroup(AddOrganizationGroupRequest) returns (AddOrganizationGroupResponse) {
    option idempotency_level = IDEMPOTENT;
  }
  // UpdateOrganizationGroup updates an IdP Group for the organization.
  rpc UpdateOrganizationGroup(UpdateOrganizationGroupRequest) returns (UpdateOrganizationGroupResponse) {
    option idempotency_level = IDEMPOTENT;
  }
  // RemoveOrganizationGroup removes an IdP Group from the organization.
  rpc RemoveOrganizationGroup(RemoveOrganizationGroupRequest) returns (RemoveOrganizationGroupResponse) {
    option idempotency_level = IDEMPOTENT;
  }
}

message GetOrganizationRequest {
  string id = 1;
}

message GetOrganizationResponse {
  Organization organization = 1;
}

message GetOrganizationByNameRequest {
  string name = 1;
}

message GetOrganizationByNameResponse {
  Organization organization = 1;
}

message ListOrganizationsRequest {
  uint32 page_size = 1;
  // The first page is returned if this is empty.
  string page_token = 2;
  bool reverse = 3;
}

message ListOrganizationsResponse {
  repeated Organization organizations = 1;
  // There are no more pages if this is empty.
  string next_page_token = 2;
}

message ListUserOrganizationsRequest {
  // The ID of the user whose organizations should be listed.
  string user_id = 1;
  uint32 page_size = 2;
  // The first page is returned if this is empty.
  string page_token = 3;
  bool reverse = 4;
}

message ListUserOrganizationsResponse {
  repeated OrganizationMembership organizations = 1;
  // There are no more pages if this is empty.
  string next_page_token = 2;
}

message GetUserOrganizationRequest {
  // The ID of the user whose membership should be retrieved.
  string user_id = 1;
  // The ID of the organization.
  string organization_id = 2;
}

message GetUserOrganizationResponse {
  OrganizationMembership organization_membership = 1;
}

message CreateOrganizationRequest {
  // Must be unique across organizations.
  string name = 1;
}

message CreateOrganizationResponse {
  Organization organization = 1;
}

message DeleteOrganizationRequest {
  string id = 1;
}

message DeleteOrganizationResponse {}

message DeleteOrganizationByNameRequest {
  string name = 1;
}

message DeleteOrganizationByNameResponse {}

message AddOrganizationMemberRequest {
  // The ID of the organization for which the user will be added to.
  string organization_id = 1;
  // The ID of the user for which to be added to the organization.
  string user_id = 2;
  // The new role of the user in the organization.
  OrganizationRole organization_role = 3;
}

message AddOrganizationMemberResponse {}

message UpdateOrganizationMemberRequest {
  // The ID of the organization for which the member belongs to.
  string organization_id = 1;
  // The ID of the user for which to be updated the role.
  string user_id = 2;
  // The new role of the user in the organization.
  OrganizationRole organization_role = 3;
}

message UpdateOrganizationMemberResponse {}

message RemoveOrganizationMemberRequest {
  // The ID of the organization for which the member belongs to.
  string organization_id = 1;
  // The ID of the user for which to be removed the role.
  string user_id = 2;
}

message RemoveOrganizationMemberResponse {}

message GetOrganizationSettingsRequest {
  // The ID of the organization for which to get the settings.
  string organization_id = 1;
}

message GetOrganizationSettingsResponse {
  message IdPGroup {
    // The name of the IdP group.
    string name = 1;
    // The role override associated with this group.
    OrganizationRole role_override = 2;
  }

  reserved 2, 3;
  reserved "plugin_base_role", "template_base_role";

  RepositoryRole repository_base_role = 1;
  // The number of members in the organization.
  uint32 members_count = 4;
  // The IdP groups associated with the organization.
  repeated IdPGroup idp_groups = 5;
}

message UpdateOrganizationSettingsRequest {
  reserved 3, 4;
  reserved "plugin_base_role", "template_base_role";

  // The ID of the organization for which to update the base roles.
  string organization_id = 1;
  // optional, no update to this base role will be made if this is unspecified.
  RepositoryRole repository_base_role = 2;
  // optional, update to description will only be made when this is present
  optional string description = 5;
  // optional, update to url will only be made when this is present
  optional string url = 6;
}

message UpdateOrganizationSettingsResponse {}

message AddOrganizationGroupRequest {
  // The ID of the organization for which to add the group.
  string organization_id = 1;
  // The name of the group to add.
  string group_name = 2;
  // The role to associate with this organization group.
  //
  // Any user who maps to this organization via this group will be granted this role. If no role is
  // set, the user will be granted the 'member' role.
  OrganizationRole role_override = 3;
}

message AddOrganizationGroupResponse {}

message UpdateOrganizationGroupRequest {
  // The ID of the organization to which this group belongs.
  string organization_id = 1;
  // The name of the group to update.
  string group_name = 2;
  // The role to associate with this organization group.
  //
  // Setting this to 'UNSPECIFIED' will remove the override. Leaving this unset will not update this
  // property.
  optional OrganizationRole role_override = 3;
}

message UpdateOrganizationGroupResponse {}

message RemoveOrganizationGroupRequest {
  // The ID of the organization for which to remove the group.
  string organization_id = 1;
  // The name of the group to remove.
  string group_name = 2;
}

message RemoveOrganizationGroupResponse {}
