syntax = "proto3";
package anytype;
option go_package = "pb";

// the element of change tree used to store and internal apply smartBlock history
message ACLChange {
  repeated string treeHeadIds = 1;
  repeated string aclHeadIds = 2;
  string snapshotBaseId = 3; // we will only have one base snapshot for both
  ACLData aclData = 4;
  // the data is encoded with read key and should be read in ChangesData format
  bytes changesData = 5;
  uint64 currentReadKeyHash = 6;
  int64 timestamp = 7;
  string identity = 8;

  message ACLContentValue {
    oneof value {
      UserAdd userAdd = 1;
      UserRemove userRemove = 2;
      UserPermissionChange userPermissionChange = 3;
      UserInvite userInvite = 4;
      UserJoin userJoin = 5;
      UserConfirm userConfirm = 6;
    }
  }

  message ACLData {
    ACLSnapshot aclSnapshot = 1;
    repeated ACLContentValue aclContent = 2;
  }

  message ACLSnapshot {
    // We don't need ACLState as a separate message now, because we simplified the snapshot model
    ACLState aclState = 1;
  }

  message ACLState {
    repeated uint64 readKeyHashes = 1;
    repeated UserState userStates = 2;
    map<string, UserInvite> invites = 3; // TODO: later
    //    repeated string unconfirmedUsers = 4; // TODO: later
  }

  message UserState {
    string identity = 1;
    bytes encryptionKey = 2;
    repeated bytes encryptedReadKeys = 3; // all read keys that we know
    UserPermissions permissions = 4;
    bool IsConfirmed = 5;
  }

  // we already know identity and encryptionKey
  message UserAdd {
    string identity = 1; // public signing key
    bytes encryptionKey = 2; // public encryption key
    repeated bytes encryptedReadKeys = 3; // all read keys that we know for the user
    UserPermissions permissions = 4;
  }

  // TODO: this is not used as of now
  message UserConfirm { // not needed for read permissions
    string identity = 1; // not needed
    string userAddId = 2;
  }

  message UserInvite {
    bytes acceptPublicKey = 1;
    bytes encryptPublicKey = 2;
    repeated bytes encryptedReadKeys = 3; // all read keys that we know for the user
    UserPermissions permissions = 4;
    string InviteId = 5;
  }

  message UserJoin {
    string identity = 1;
    bytes encryptionKey = 2;
    bytes acceptSignature = 3; // sign acceptPublicKey
    string userInviteId = 4;
    repeated bytes encryptedReadKeys = 5; // the idea is that user should itself reencrypt the keys with the pub key
  }

  message UserRemove {
    string identity = 1;
    repeated ReadKeyReplace readKeyReplaces = 3; // new read key encrypted for all users
  }

  message ReadKeyReplace {
    string identity = 1;
    bytes encryptionKey = 2;
    bytes encryptedReadKey = 3;
  }

  message UserPermissionChange {
    string identity = 1;
    UserPermissions permissions = 2;
  }

  enum UserPermissions {
    Admin = 0;
    Writer = 1;
    Reader = 2;
    Removed = 3;
  }
}
