// SPDX-License-Identifier: Apache-2.0
// Identity: login, sessions, roles, permissions.
syntax = "proto3";

package kyvernon.v1;

import "kyvernon/v1/common.proto";

// Sign-in, sessions, roles and permissions.
service IdentityService {
  // Signs in with a user name and password; may ask for a second factor.
  rpc Login(LoginRequest) returns (LoginResponse);
  // Completes a sign-in with the second factor.
  rpc CompleteMfa(CompleteMfaRequest) returns (SessionInfo);
  // Ends the caller's session.
  rpc Logout(Empty) returns (Empty);
  // The caller's user, groups and session.
  rpc WhoAmI(Empty) returns (WhoAmIResponse);
  // Every role with its privileges.
  rpc ListRoles(Empty) returns (ListRolesResponse);
  // Permissions of an object.
  rpc ListPermissions(ListPermissionsRequest) returns (ListPermissionsResponse);
  // Assigns a role to a user or group on an object.
  rpc SetPermission(SetPermissionRequest) returns (Permission);
  // Removes a permission from an object.
  rpc RemovePermission(RemovePermissionRequest) returns (Empty);
  // Whether the caller holds `privilege` on `entity`.
  rpc CheckPrivilege(CheckPrivilegeRequest) returns (CheckPrivilegeResponse);
}

// Kind of session a login opens.
enum SessionKind {
  SESSION_KIND_INTERACTIVE = 0;
  SESSION_KIND_API = 1;
}

// Password login.
message LoginRequest {
  // User name.
  string username = 1;
  // Password.
  string password = 2;
  // Kind of session to open.
  SessionKind kind = 3;
}

// A user account.
message UserView {
  // User name.
  string username = 1;
  // Name to show.
  string display_name = 2;
  // Email address.
  string email = 3;
  // The account may sign in.
  bool enabled = 4;
  // Groups the user belongs to.
  repeated string groups = 5;
  // Two-step verification is set up.
  bool mfa_enrolled = 6;
  // Break-glass account for emergency access.
  bool break_glass = 7;
  // The password must be changed at the next sign-in.
  bool password_rotation_required = 8;
}

// An open session.
message SessionInfo {
  // Bearer token; shown once.
  string token = 1;
  // Id of the session; the bearer token of later calls.
  string session_id = 2;
  // End of the session, RFC 3339.
  string expires_at = 3;
  // The signed-in user.
  UserView user = 4;
  // The session is restricted until the password is changed.
  bool password_rotation_required = 5;
  // The session may only reach MFA self-service until enrolment completes.
  bool mfa_enrolment_required = 6;
}

// The login needs a second factor.
message MfaChallenge {
  // Token to send with the code to `CompleteMfa`.
  string pending_token = 1;
}

// A session, or a challenge for the second factor.
message LoginResponse {
  oneof outcome {
    // The open session.
    SessionInfo session = 1;
    // The second factor is needed first.
    MfaChallenge mfa_required = 2;
  }
}

// The second factor of a login.
message CompleteMfaRequest {
  // Token of the challenge.
  string pending_token = 1;
  // Six-digit code or a recovery code.
  string code = 2;
}

// The caller and its session.
message WhoAmIResponse {
  // User name.
  string username = 1;
  // Groups of the user.
  repeated string groups = 2;
  // Id of the session.
  string session_id = 3;
  // Kind of session.
  SessionKind kind = 4;
  // The session waits for the second factor.
  bool mfa_pending = 5;
  // The password must be changed before anything else works.
  bool password_rotation_required = 6;
  // The session belongs to a break-glass account.
  bool break_glass = 7;
}

// A role.
message Role {
  // Id of the role.
  string id = 1;
  // Name.
  string name = 2;
  // What the role is for.
  string description = 3;
  // Privilege ids the role holds.
  repeated string privileges = 4;
  // Built-in role, not editable.
  bool system = 5;
}

// The roles.
message ListRolesResponse {
  // Every role.
  repeated Role items = 1;
}

// A user or a group.
message Principal {
  // Kind of principal.
  enum Type {
    TYPE_USER = 0;
    TYPE_GROUP = 1;
  }
  // User or group.
  Type type = 1;
  // User name or group name.
  string name = 2;
}

// A role granted to a principal on an object.
message Permission {
  // Id of the permission.
  string id = 1;
  // Id of the object.
  string entity = 2;
  // Who gets the role.
  Principal principal = 3;
  // Id of the role.
  string role = 4;
  // The permission also applies to the objects below.
  bool propagate = 5;
}

// Lists permissions.
message ListPermissionsRequest {
  // Id of the object.
  string entity = 1;
}

// The permissions.
message ListPermissionsResponse {
  // Permissions of the object.
  repeated Permission items = 1;
}

// Grants a role on an object.
message SetPermissionRequest {
  // Id of the object.
  string entity = 1;
  // Who gets the role.
  Principal principal = 2;
  // Id of the role.
  string role = 3;
  // Also apply to the objects below.
  bool propagate = 4;
}

// Removes a permission.
message RemovePermissionRequest {
  // Id of the permission.
  string id = 1;
}

// Asks whether the caller holds a privilege.
message CheckPrivilegeRequest {
  // Id of the object.
  string entity = 1;
  // Privilege id.
  string privilege = 2;
}

// Answer of a privilege check.
message CheckPrivilegeResponse {
  // The caller holds the privilege on the object.
  bool granted = 1;
}
