syntax = "proto3";

import "google/protobuf/timestamp.proto";
import "google/protobuf/wrappers.proto";
package twitch.fulton.beefcake;
option go_package = "code.justin.tv/amzn/TwitchBeefcakeTwirp";

service TwitchBeefcake {
  // GetRoles gets all role
  rpc GetRoles(GetRolesRequest) returns (GetRolesResponse);
  // CreateRole creates a role
  rpc CreateRole(CreateRoleRequest) returns (CreateRoleResponse);
  // GetRole gets a role
  rpc GetRole(GetRoleRequest) returns (Role);
  // UpdateRole updates an existing role
  rpc UpdateRole(UpdateRoleRequest) returns (UpdateRoleResponse);
  // OverrideRole overrides all permissions for a role
  rpc OverrideRole(OverrideRoleRequest) returns (OverrideRoleResponse);
  // DeleteRole deletes a role
  rpc DeleteRole(DeleteRoleRequest) returns (DeleteRoleResponse);

  // AddRolePermission adds a permission for a role
  rpc AddRolePermission(AddRolePermissionRequest) returns (AddRolePermissionResponse);
  // RemoveRolePermission removes a permission for a role
  rpc RemoveRolePermission(RemoveRolePermissionRequest) returns (RemoveRolePermissionResponse);

  // UpdateRolePermissionScope updates the scope of a permission for a role.
  // Permissions by default apply to all objects but this will scope a permission
  // to a list of beefcake.PermissionScope.
  //
  // An example would be the Support role with the tos_ban permission. They will
  // be able to tos_ban anyone. If the scope were limited to
  // PermissionScope_ChannelPayoutType_NO_PAYOUT_TYPE, they would only be able
  // to tos_ban on users that have no payout type (i.e. non-partner,
  // non-affiliate, non-developer).
  rpc UpdateRolePermissionScope(UpdateRolePermissionScopeRequest) returns (UpdateRolePermissionScopeResponse);

  // Add a legacy string permission to a role
  rpc AddLegacyPermissionToRole(AddLegacyPermissionToRoleRequest) returns (AddLegacyPermissionToRoleResponse);
  // Remove a legacy string permission to a role
  rpc RemoveLegacyPermissionFromRole(RemoveLegacyPermissionFromRoleRequest) returns (RemoveLegacyPermissionFromRoleResponse);

  // AddUserToRole adds a user to a role
  rpc AddUserToRole(AddUserToRoleRequest) returns (AddUserToRoleResponse);
  // RemoveUserFromRole removes a user to a role
  rpc RemoveUserFromRole(RemoveUserFromRoleRequest) returns (RemoveUserFromRoleResponse);

  // User returns a user
  rpc GetUser(GetUserRequest) returns (User);

  // ReactiveUser - activates an inactive user.
  rpc ReactivateUser(ReactivateUserRequest) returns (ReactivateUserResponse);

  // GetLegacyPermissions returns a single legacy permission
  rpc GetLegacyPermissions(GetLegacyPermissionsRequest) returns (GetLegacyPermissionsResponse);
  // CreateLegacyPermission creates a legacy permission
  rpc CreateLegacyPermission(CreateLegacyPermissionRequest) returns (CreateLegacyPermissionResponse);
  // GetLegacyPermission returns a single legacy permission
  rpc GetLegacyPermission(GetLegacyPermissionRequest) returns (LegacyPermission);
  // UpdateLegacyPermission updates a legacy permission
  rpc UpdateLegacyPermission(UpdateLegacyPermissionRequest) returns (UpdateLegacyPermissionResponse);
  // DeleteLegacyPermission deletes a legacy permission
  rpc DeleteLegacyPermission(DeleteLegacyPermissionRequest) returns (DeleteLegacyPermissionResponse);
}

// Method requests and responses.
message CreateRoleRequest {
  // friendly name
  string name = 1;
}

message CreateRoleResponse {
  string id = 1;
  string name = 2;
}

message AddRolePermissionRequest {
  // role id to give permission to
  string role_id = 1;
  // permission to give
  Permission permission = 2;
}

message AddRolePermissionResponse {
}

message AddLegacyPermissionToRoleRequest {
  string role_id = 1;
  string legacy_permission_id = 2;
}

message AddLegacyPermissionToRoleResponse {
}

message RemoveLegacyPermissionFromRoleRequest {
  string role_id = 1;
  string legacy_permission_id = 2;
}

message RemoveLegacyPermissionFromRoleResponse {
}

message OverrideRoleRequest {
  // role to override
  string id = 1;
  // name to give to role
  string name = 2;
  // permissions to set
  repeated Permission permissions = 3;
  // memberships to set
  repeated Role.UserMembership user_memberships = 4;
}

message OverrideRoleResponse {
}

message GetRolesRequest {
}

message GetRolesResponse {
  message Role {
    string id = 1;
    string name = 2;
  }

  repeated Role roles = 1;
}

message GetRoleRequest {
  // role to retrieve
  string id = 1;
}

message Role {
  message UserMembership {
    string user_id = 1;
    // time when the user's membership will expire
    google.protobuf.Timestamp expiration = 2;
    // time when the user's membership was added
    google.protobuf.Timestamp date_added = 3;
  }

  string id = 1;
  string name = 2;
  repeated UserMembership user_memberships = 3;
  repeated AttachedPermission permissions = 4;
}

message StringArrayValue {
  repeated string value = 1;
}

message UpdateRoleRequest {
  // role to update. all parameters MUST be provided.
  string id = 1;
  // new value for name
  google.protobuf.StringValue name = 2;
  // new value for legacy permission ids
  StringArrayValue legacy_permission_ids = 3;
}

message UpdateRoleResponse {
}

message RemoveRolePermissionRequest {
  // role id to give permission to
  string role_id = 1;
  // the role's permission to remove
  string role_permission_id = 2;
}

message RemoveRolePermissionResponse {
}

message UpdateRolePermissionScopeRequest {
  // role id to update permission scope for
  string role_id = 1;
  // role's permission to update scope for
  string role_permission_id = 2;
  // new permission scope
  repeated PermissionScope scope = 3;
}

message UpdateRolePermissionScopeResponse {
}

message AddUserToRoleRequest {
  // role id to give permission to
  string role_id = 1;
  // user to give permission to
  string user_id = 2;
  // time when the user's membership will expire
  google.protobuf.Timestamp membership_expiration = 3;
}

message AddUserToRoleResponse {
}

message RemoveUserFromRoleRequest {
  // role id to give permission to
  string role_id = 1;
  // user to give permission to
  string user_id = 2;
}

message RemoveUserFromRoleResponse {
}

message DeleteRoleRequest {
  // role to delete
  string id = 1;
}

message DeleteRoleResponse {
}

message GetUserRequest {
  string id = 1;
}

message User {
  message RoleMembership {
    string id = 1;
    string name = 2;
    // time when the user's membership will expire
    google.protobuf.Timestamp membership_expiration = 3;
    repeated AttachedPermission permissions = 4;
    // time when the user's membership was added
    google.protobuf.Timestamp date_added = 5;
  }

  string id = 1;
  repeated RoleMembership role_memberships = 2;
  repeated AttachedPermission permissions = 3;
  bool active = 4;
}

message ReactivateUserRequest {
  string id = 1;
}

message ReactivateUserResponse {
}

message GetLegacyPermissionsRequest {
}

message GetLegacyPermissionsResponse {
  message LegacyPermission {
    string id = 1;
    string name = 2;
    string description = 3;
  }

  repeated LegacyPermission legacy_permissions = 1;
}

message CreateLegacyPermissionRequest {
  string id = 1;
  string name = 2;
  string description = 3;
}

message CreateLegacyPermissionResponse {
}

message GetLegacyPermissionRequest {
  string id = 1;
}

message LegacyPermission {
  message Role {
    message UserMembership {
      string user_id = 1;
      // time when the user's membership will expire
      google.protobuf.Timestamp expiration = 2;
      // time when the user's membership was added
      google.protobuf.Timestamp date_added = 3;
    }

    string id = 1;
    string name = 2;
    repeated UserMembership user_memberships = 3;
  }

  message User {
    string id = 1;
  }

  string id = 1;
  string name = 2;
  string description = 3;

  repeated Role roles = 4;
  repeated User users = 5;
}


message UpdateLegacyPermissionRequest {
  string id = 1;
  google.protobuf.StringValue name = 2;
  google.protobuf.StringValue description = 3;
}

message UpdateLegacyPermissionResponse {
}

message DeleteLegacyPermissionRequest {
  string id = 1;
}

message DeleteLegacyPermissionResponse {
}

message Permission {
  message LegacyPermission {
    string id = 1;
    string name = 2;
  }

  message TwitchUserPermission {
    enum ActionType {
      ANY = 0;  // any user action
      GET_PII = 1; // Get personally idefifying info
    }

    message AnyResource {}

    ActionType action = 1; // a specific user action

    oneof resource {
      AnyResource any = 2; // any user
      string twitch_user_id = 3; // a specific twitch user
    }
  }

  oneof value {
    LegacyPermission legacy = 1;
    TwitchUserPermission twitch_user = 2;
  }
}

message AttachedPermission {
  string id = 1;
  Permission permission = 2;
  repeated PermissionScope scope = 3;
}

// PermissionScope defines a limit of what a permission can do.
// An example is view user but only non-partner, non-affiliate, non-developer.
message PermissionScope {
  // Scope a permission to the ripley PayoutType of a channel
  // based code.justin.tv.revenue.ripley.PayoutType
  enum ChannelPayoutType {
    // is_affiliate, is_developer, is_parter all return false
    NO_PAYOUT_TYPE = 0;
    // is_affiliate is true
    AFFILIATE = 1;
    // is_partner is true
    PARTNER = 2;
    // is_developer is true
    DEVELOPER = 3;
  }

  oneof scope {
    ChannelPayoutType channel_payout = 1;
  }
}
