syntax = "proto3";
option java_multiple_files = true;
option java_package = "com.github.saturn_xiv.palm.plugins.nut.v1";
package palm.nut.v1;

import "google/protobuf/empty.proto";
import "google/protobuf/timestamp.proto";
import "google/protobuf/duration.proto";

message IdRequest {
  int32 id = 1;
}

message Pager {
  int64 page = 1;
  int64 size = 2;
}

message Pagination {
  int64 page = 1;
  int64 size = 2;
  int64 total = 3;
  bool has_next = 11;
  bool has_previous = 12;
}

message MediaContent {
  enum Editor {
    TEXTAREA = 0;
    QUILL = 1;
  }

  enum Status {
    Published = 0;
    Draft = 1;
    Pending = 2;
    Private = 3;
    Future = 4;
    Trash = 99;
  }
  Editor editor = 1;
  string body = 2;
  Status status = 3;

  optional google.protobuf.Timestamp published_at = 11;
}

message UserDetail {
  int32 id = 1;
  string uid = 2;
  string nickname = 3;
  string real_name = 4;
  string email = 5;
}

message Resource {
  string type = 1;
  optional int32 id = 2;
}

message Permission {
  oneof subject {
    int32 user = 1;
    int32 role = 2;
  }
  string operation = 11;
  Resource resource = 12;
}

// ----------------------------------------------------------------------------

service User {
  rpc SignIn(UserSignInRequest) returns (UserSignInResponse) {}
  rpc SignUp(UserSignUpRequest) returns (google.protobuf.Empty) {}
  rpc ConfirmByEmail(UserQueryRequest) returns (google.protobuf.Empty) {}
  rpc ConfirmByToken(UserTokenRequest) returns (google.protobuf.Empty) {}
  rpc UnlockByEmail(UserQueryRequest) returns (google.protobuf.Empty) {}
  rpc UnlockByToken(UserTokenRequest) returns (google.protobuf.Empty) {}
  rpc ForgotPassword(UserQueryRequest) returns (google.protobuf.Empty) {}
  rpc ResetPassword(UserResetPasswordRequest) returns (google.protobuf.Empty) {}

  rpc Refresh(google.protobuf.Duration) returns (UserSignInResponse) {}
  rpc Logs(Pager) returns (UserLogsResponse) {}
  rpc SetProfile(UserSetProfileRequest) returns (google.protobuf.Empty) {}
  rpc ChangePassword(UserChangePasswordRequest)
      returns (google.protobuf.Empty) {}
  rpc SignOut(google.protobuf.Empty) returns (google.protobuf.Empty) {}

  rpc Index(Pager) returns (UserIndexResponse) {}
  rpc Show(IdRequest) returns (UserIndexResponse.Item) {}
  rpc Disable(IdRequest) returns (google.protobuf.Empty) {}
  rpc Enable(IdRequest) returns (google.protobuf.Empty) {}
  rpc Lock(IdRequest) returns (google.protobuf.Empty) {}
  rpc Unlock(IdRequest) returns (google.protobuf.Empty) {}
  rpc Confirm(IdRequest) returns (google.protobuf.Empty) {}
  rpc SetPassword(UserSetPasswordRequest) returns (google.protobuf.Empty) {}
}

message UserSignInRequest {
  UserQueryRequest query = 1;
  string password = 2;
  google.protobuf.Duration ttl = 11;
}

message UserQueryRequest {
  oneof user {
    string nickname = 1;
    string email = 2;
  }
  string home = 9;
}

message UserSignInResponse {
  message Payload {
    string nickname = 1;
    string email = 2;
    string real_name = 11;
    string lang = 12;
    string time_zone = 13;
    string avatar = 99;
  }
  string token = 1;
  Payload payload = 2;
  repeated string roles = 11;
  repeated Permission permissions = 12;
}

message UserSignUpRequest {
  string real_name = 1;
  string nickname = 2;
  string email = 3;
  string password = 4;
  string lang = 11;
  string time_zone = 12;
  string home = 21;
}

message UserTokenRequest {
  string payload = 1;
}

message UserResetPasswordRequest {
  string token = 1;
  string password = 2;
}

message UserSetPasswordRequest {
  int32 id = 1;
  string password = 2;
}

message UserSetProfileRequest {
  string real_name = 1;
  string avatar = 2;
  string time_zone = 8;
  string lang = 9;
  string wechat = 11;
  string phone = 12;
}

message UserGetProfileResponse {
  string real_name = 1;
  string avatar = 2;
  string nickname = 3;
  string email = 4;
  string time_zone = 8;
  string lang = 9;
  string wechat = 11;
  string phone = 12;
}

message UserLogsResponse {
  message Item {
    enum Level {
      DEBUG = 0;
      INFO = 1;
      WARNING = 2;
      ERROR = 3;
      PANIC = 4;
    }
    int32 id = 1;
    int32 user_id = 2;
    string ip = 3;
    Level level = 4;
    string message = 5;
    Resource resource = 6;
    google.protobuf.Timestamp created_at = 11;
  }

  Pagination pagination = 1;
  repeated Item items = 11;
}
message UserChangePasswordRequest {
  string current_password = 1;
  string new_password = 2;
}

message UserProvider {
  enum Type {
    EMAIL = 0;
    GMAIL = 1;
    WECHAT = 2;
    FACEBOOK = 3;
    GITHUB = 4;
  }
  Type type = 1;
  string id = 2;
}

message UserIndexResponse {
  message Item {
    int32 id = 1;
    string uid = 2;
    string email = 3;
    string nickname = 4;
    string real_name = 5;
    UserProvider.Type provider_type = 6;
    google.protobuf.Timestamp updated_at = 9;
    optional google.protobuf.Timestamp last_sign_in_at = 11;
    optional string last_sign_in_ip = 12;
    optional google.protobuf.Timestamp current_sign_in_at = 13;
    optional string current_sign_in_ip = 14;
    int32 sign_in_count = 19;
    string lang = 21;
    string time_zone = 22;
    string avatar = 23;
    optional google.protobuf.Timestamp confirmed_at = 27;
    optional google.protobuf.Timestamp locked_at = 28;
    optional google.protobuf.Timestamp deleted_at = 29;
  }

  Pagination pagination = 1;
  repeated Item items = 11;
}

// ----------------------------------------------------------------------------

service Attachment {
  rpc Index(Pager) returns (AttachmentIndexResponse) {}
  rpc Destroy(IdRequest) returns (google.protobuf.Empty) {}
  rpc Show(AttachmentShowRequest) returns (AttachmentShowResponse) {}
}
message AttachmentShowRequest {
  int32 id = 1;
  google.protobuf.Duration ttl = 2;
}
message AttachmentShowResponse {
  AttachmentIndexResponse.Item item = 1;
  string url = 2;
}

message AttachmentIndexResponse {
  message Item {
    int32 id = 1;
    string bucket = 2;
    string name = 3;
    string title = 4;
    int64 size = 5;
    string content_type = 6;
    MediaContent.Status status = 7;

    google.protobuf.Timestamp updated_at = 11;
  }
  Pagination pagination = 1;
  repeated Item items = 11;
}

// ----------------------------------------------------------------------------

service Policy {
  rpc AddRole(PolicyAddRoleRequest) returns (google.protobuf.Empty) {}
  rpc GetAllRoles(google.protobuf.Empty) returns (PolicyRoleListResponse) {}
  rpc DeleteRole(IdRequest) returns (google.protobuf.Empty) {}
  rpc GetRolesForUser(IdRequest) returns (PolicyRolesForUserResponse) {}
  rpc GetUsersForRole(IdRequest) returns (PolicyUsersForRoleResponse) {}
  rpc AddRolesForUser(PolicyAddRolesForUserRequest)
      returns (google.protobuf.Empty) {}
  rpc DeleteRolesForUser(PolicyDeleteRolesForUserRequest)
      returns (google.protobuf.Empty) {}
  rpc GetImplicitRolesForUser(IdRequest)
      returns (PolicyImplicitRolesForUserResponse) {}
  rpc GetImplicitUsersForRole(IdRequest)
      returns (PolicyImplicitUsersForRoleResponse) {}

  rpc GetPermissionsForUser(IdRequest) returns (PolicyPermissionList) {}
  rpc GetPermissionsForRole(IdRequest) returns (PolicyPermissionList) {}
  rpc GetImplicitPermissionsForUser(IdRequest) returns (PolicyPermissionList) {}
  rpc GetImplicitPermissionsForRole(IdRequest) returns (PolicyPermissionList) {}

  rpc AddPermissions(PolicyPermissionList) returns (google.protobuf.Empty) {}
  rpc DeletePermissions(PolicyPermissionList) returns (google.protobuf.Empty) {}
}

message PolicyAddRoleRequest {
  string code = 1;
  oneof nested {
    int32 left = 2;
    int32 parent = 3;
  }
}

message PolicyUsersForRoleResponse {
  message Item {
    UserDetail user = 1;
    google.protobuf.Timestamp not_before = 11;
    google.protobuf.Timestamp expired_at = 12;
  }
  repeated Item items = 1;
}
message PolicyImplicitUsersForRoleResponse {
  repeated UserDetail items = 1;
}

message PolicyRolesForUserResponse {
  message Item {
    int32 id = 1;
    string code = 2;
    google.protobuf.Timestamp not_before = 11;
    google.protobuf.Timestamp expired_at = 12;
  }
  repeated Item items = 1;
}

message PolicyImplicitRolesForUserResponse {
  repeated string items = 1;
}

message PolicyRoleListResponse {
  message Item {
    int32 id = 1;
    string code = 2;
    int32 left = 3;
    int32 right = 4;
    google.protobuf.Timestamp updated_at = 9;
  }
  repeated Item items = 1;
}

message PolicyAddRolesForUserRequest {
  int32 user = 1;
  repeated int32 roles = 2;
  google.protobuf.Timestamp not_before = 11;
  google.protobuf.Timestamp expired_at = 12;
}

message PolicyDeleteRolesForUserRequest {
  int32 user = 1;
  repeated int32 roles = 2;
}

message PolicyPermissionList {
  repeated Permission items = 1;
}

// ----------------------------------------------------------------------------

service Locale {
  rpc Set(LocaleSetRequest) returns (google.protobuf.Empty) {}
  rpc Get(LocaleGetRequest) returns (LocaleIndexResponse.Item) {}
  rpc ByLang(LocaleByLangRequest) returns (LocaleByLangResponse) {}
  rpc Index(Pager) returns (LocaleIndexResponse) {}
  rpc Destroy(IdRequest) returns (google.protobuf.Empty) {}
}

message LocaleByLangRequest {
  string lang = 1;
}

message LocaleByLangResponse {
  repeated LocaleIndexResponse.Item items = 1;
}

message LocaleIndexResponse {
  message Item {
    int32 id = 1;
    string lang = 2;
    string code = 3;
    string message = 4;
    google.protobuf.Timestamp updated_at = 9;
  }
  repeated Item items = 1;
  Pagination pagination = 9;
}

message LocaleGetRequest {
  string lang = 1;
  string code = 2;
}
message LocaleSetRequest {
  string lang = 1;
  string code = 2;
  string message = 3;
}
// ----------------------------------------------------------------------------
service Notification {
  rpc Index(Pager) returns (IndexNotificationResponse) {}
}

message IndexNotificationResponse {
  message Item {
    oneof message {
      EmailTask email = 1;
      SmsTask sms = 2;
    }
    google.protobuf.Timestamp created_at = 19;
  }
  repeated Item items = 1;
  Pagination pagination = 9;
}

// ----------------------------------------------------------------------------

service LeaveWord {
  rpc Create(MediaContent) returns (google.protobuf.Empty) {}
  rpc Index(Pager) returns (LeaveWordIndexResponse) {}
  rpc Destroy(IdRequest) returns (google.protobuf.Empty) {}
}

message LeaveWordIndexResponse {
  message Item {
    int32 id = 1;
    string lang = 2;
    string ip = 3;
    MediaContent content = 8;
    google.protobuf.Timestamp updated_at = 11;
    google.protobuf.Timestamp created_at = 12;
  }
  repeated Item items = 1;
  Pagination pagination = 9;
}

// ----------------------------------------------------------------------------

service Site {
  rpc SetMaintenanceMode(SiteMaintenanceModeRequest)
      returns (google.protobuf.Empty) {}

  rpc Install(SiteInstallRequest) returns (google.protobuf.Empty) {}

  rpc ClearCache(google.protobuf.Empty) returns (google.protobuf.Empty) {}

  rpc Layout(google.protobuf.Empty) returns (SiteLayoutResponse) {}
  rpc SetAuthor(SiteLayoutResponse.Author) returns (google.protobuf.Empty) {}
  rpc SetCopyright(SiteSetCopyrightRequest) returns (google.protobuf.Empty) {}
  rpc SetKeywords(SiteSetKeywordsRequest) returns (google.protobuf.Empty) {}
  rpc SetInfo(SiteSetInfoRequest) returns (google.protobuf.Empty) {}
  rpc SetLogo(SiteSetLogoRequest) returns (google.protobuf.Empty) {}

  rpc SetMinio(MinioProfile) returns (google.protobuf.Empty) {}
  rpc GetMinio(google.protobuf.Empty) returns (MinioProfile) {}
  rpc TestMinio(MinioProfile) returns (SiteMinioTestResponse) {}

  rpc SetTwilio(TwilioProfile) returns (google.protobuf.Empty) {}
  rpc GetTwilio(google.protobuf.Empty) returns (TwilioProfile) {}
  rpc TestTwilio(SiteTwilioTestRequest) returns (google.protobuf.Empty) {}

  rpc SetSmtp(SmtpProfile) returns (google.protobuf.Empty) {}
  rpc GetSmtp(google.protobuf.Empty) returns (SmtpProfile) {}
  rpc TestSmtp(SiteSmtpTestRequest) returns (google.protobuf.Empty) {}

  rpc SetBing(BingProfile) returns (google.protobuf.Empty) {}
  rpc GetBing(google.protobuf.Empty) returns (BingProfile) {}

  rpc SetIndexNow(IndexNowProfile) returns (google.protobuf.Empty) {}
  rpc GetIndexNow(google.protobuf.Empty) returns (IndexNowProfile) {}
  rpc PingIndexNow(IndexNowPingRequest) returns (google.protobuf.Empty) {}

  rpc SetGoogle(GoogleProfile) returns (google.protobuf.Empty) {}
  rpc GetGoogle(google.protobuf.Empty) returns (GoogleProfile) {}
  rpc PingGoogle(SitemapPingRequest) returns (google.protobuf.Empty) {}

  rpc SetBaidu(BaiduProfile) returns (google.protobuf.Empty) {}
  rpc GetBaidu(google.protobuf.Empty) returns (BaiduProfile) {}
  rpc PingBaidu(SitemapPingRequest) returns (google.protobuf.Empty) {}

  rpc Status(google.protobuf.Empty) returns (SiteStatusResponse) {}
}

message IndexNowProfile {
  string key = 1;
}

message IndexNowPingRequest {
  string key = 1;
  string home = 9;
}

message SitemapPingRequest {
  string home = 1;
}

message SiteMaintenanceModeRequest {
  message Item {
    google.protobuf.Duration duration = 1;
    string reason = 2;
  }
  optional Item item = 1;
}

message SiteInstallRequest {
  UserSignUpRequest user = 1;
}

message MinioProfile {
  optional string region = 1;
  string host = 2;
  int32 port = 3;
  bool https = 4;
  string access_key = 8;
  string secret_key = 9;
}

message SiteMinioTestResponse {
  repeated string buckets = 1;
}

message TwilioProfile {
  string from = 1;
  string account_sid = 2;
  string auth_token = 3;
  optional string sms_status_callback = 9;
}

message SmtpProfile {
  // https://github.com/karastojko/mailio/blob/master/include/mailio/smtp.hpp#L229
  enum AuthMethod {
    None = 0;
    Login = 1;
    StartTls = 2;
  }
  string host = 1;
  uint32 port = 2;
  AuthMethod auth_method = 3;
  repeated EmailTask.Address cc = 8;
  repeated EmailTask.Address bcc = 9;

  EmailTask.Address user = 11;
  string password = 12;
}

message EmailTask {
  message Address {
    string name = 1;
    string email = 2;
  }
  enum ContentType {
    Plain = 0;
    Html = 1;
  }
  message Attachment {
    string name = 1;
    string content_type = 2;
    bytes payload = 3;
  }
  string subject = 1;
  string content = 2;
  ContentType content_type = 3;

  Address to = 11;
  repeated Address cc = 12;
  repeated Address bcc = 13;
  repeated Attachment attachments = 21;
}

message SiteTwilioTestRequest {
  string to = 1;
  string message = 2;
  TwilioProfile profile = 9;
}

message SiteSmtpTestRequest {
  EmailTask.Address to = 1;
  string subject = 2;
  string content = 3;
  SmtpProfile profile = 9;
}

message SiteSetLogoRequest {
  string url = 1;
}
message SiteSetCopyrightRequest {
  string payload = 1;
}
message SiteSetKeywordsRequest {
  repeated string items = 1;
}
message SiteSetInfoRequest {
  string lang = 1;
  string title = 11;
  string subhead = 12;
  string description = 13;
}

message SiteLayoutResponse {
  message Author {
    string name = 1;
    string email = 2;
  }
  string title = 1;
  string subhead = 2;
  repeated string keywords = 3;
  string description = 4;
  Author author = 5;
  string copyright = 6;
  string logo = 7;
  repeated string languages = 9;
}

message GoogleProfile {
  // https://developers.google.com/recaptcha/intro
  message ReCaptcha {
    string site_key = 1;
    string secret = 2;
  }
  optional string site_verify_id = 1;
  optional ReCaptcha re_captcha = 2;
}
message BaiduProfile {
  message SiteVerify {
    string id = 1;
    string content = 2;
  }
  optional SiteVerify site_verify = 1;
}
message BingProfile {
  optional string site_verify_id = 1;
}

message SmsTask {
  string from = 1;
  repeated string to = 2;
  string body = 3;
}

message SiteStatusResponse {
  message Database {
    string name = 1;
    string size = 2;
  }
  message PostgreSql {
    string version = 1;
    google.protobuf.Timestamp now = 2;
    repeated Database databases = 9;
  }
  message MySql {
    uint64 size = 1;
    string version = 2;
  }
  message Redis {
    message Item {
      string key = 1;
      int64 ttl = 2;
    };
    string info = 1;
    repeated Item items = 2;
  }
  message RabbitMq {
    string protocol = 1;
  }
  message OpenSearch {
    string url = 1;
    string info = 2;
  }
  message Health {
    string name = 1;
    string status = 2;
  }
  message System {
    string version = 1;
    string cpu = 2;
    string memory = 3;
    string boot = 4;
    string disk = 5;
    string load = 6;
    string fs = 7;
    string swap = 8;
    string uptime = 9;
    string network = 10;
  }

  PostgreSql postgresql = 1;
  MySql mysql = 2;
  Redis redis = 3;
  RabbitMq rabbitmq = 4;
  OpenSearch opensearch = 5;
  System system = 11;
  repeated Health healthes = 21;
}

// ----------------------------------------------------------------------------

service ShorterLink {
  rpc Create(ShorterLinkCreateRequest) returns (google.protobuf.Empty) {}
  rpc Update(ShorterLinkUpdateRequest) returns (google.protobuf.Empty) {}
  rpc Destroy(IdRequest) returns (google.protobuf.Empty) {}
  rpc Index(Pager) returns (ShorterLinkIndexResponse) {}
}

message ShorterLinkIndexResponse {
  message Item {
    int32 id = 1;
    string url = 2;
    string details = 3;
    string code = 9;

    google.protobuf.Timestamp updated_at = 11;
  }
  Pagination pagination = 1;
  repeated Item items = 11;
}

message ShorterLinkCreateRequest {
  string url = 1;
  string details = 2;
}

message ShorterLinkUpdateRequest {
  int32 id = 1;
  string url = 2;
  string details = 3;
}
// ----------------------------------------------------------------------------

service Tag {
  rpc Create(TagCreateRequest) returns (google.protobuf.Empty) {}
  rpc Update(TagUpdateRequest) returns (google.protobuf.Empty) {}
  rpc Destroy(IdRequest) returns (google.protobuf.Empty) {}
  rpc Index(google.protobuf.Empty) returns (TagIndexResponse) {}
}

message TagIndexResponse {
  message Item {
    int32 id = 1;
    string code = 2;
    int32 priority = 3;
    google.protobuf.Timestamp updated_at = 11;
  }
  repeated Item items = 1;
}

message TagCreateRequest {
  string code = 1;
  int32 priority = 11;
}

message TagUpdateRequest {
  int32 id = 1;
  string code = 2;
  int32 priority = 11;
}
// ----------------------------------------------------------------------------

service Category {
  rpc Create(CategoryCreateRequest) returns (google.protobuf.Empty) {}
  rpc Update(CategoryUpdateRequest) returns (google.protobuf.Empty) {}
  rpc Destroy(IdRequest) returns (google.protobuf.Empty) {}
  rpc Index(google.protobuf.Empty) returns (CategoryIndexResponse) {}
}
message CategoryIndexResponse {
  message Item {
    int32 id = 1;
    string code = 2;
    int32 left = 3;
    int32 right = 4;

    google.protobuf.Timestamp updated_at = 11;
  }
  repeated Item items = 1;
}
message CategoryCreateRequest {
  string code = 1;
  oneof by {
    int32 left = 2;
    int32 parent = 3;
  }
}

message CategoryUpdateRequest {
  int32 id = 1;
  string code = 2;
}

// ----------------------------------------------------------------------------
