1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
//! Defines the types required by the confidential docs pallet
use super::*;
use frame_support::pallet_prelude::*;

/// Defines the type used by fields that store an IPFS CID
pub type CID = BoundedVec<u8, ConstU32<100>>;
/// Defines the type used by fields that store a public key
pub type PublicKey = [u8; 32];
/// Defines the type used by fields that store a UserId
pub type UserId = [u8; 32];
/// Defines the type used by fields that store a document name
pub type DocName<T> = BoundedVec<u8, <T as Config>::DocNameMaxLen>;
/// Defines the type used by fields that store a document description
pub type DocDesc<T> = BoundedVec<u8, <T as Config>::DocDescMaxLen>;
/// Defines the type used by fields that store a group name
pub type GroupName<T> = BoundedVec<u8, <T as Config>::GroupNameMaxLen>;

/// User vault, the vault stores the cipher private key used to cipher the user documents.
/// The way the user vault is ciphered depends on the login method used by the user
#[derive(
  CloneNoBound, Encode, Decode, RuntimeDebugNoBound, Default, TypeInfo, MaxEncodedLen, PartialEq,
)]
#[scale_info(skip_type_params(T))]
#[codec(mel_bound())]
pub struct Vault<T: Config> {
  /// IPFS CID where the vault data is stored
  pub cid: CID,
  /// Owner of the vault
  pub owner: T::AccountId,
}

/// Owned confidential document
#[derive(
  CloneNoBound, Encode, Decode, RuntimeDebugNoBound, Default, TypeInfo, MaxEncodedLen, PartialEq,
)]
#[scale_info(skip_type_params(T))]
#[codec(mel_bound())]
pub struct OwnedDoc<T: Config> {
  /// IPFS CID where the document data is stored
  pub cid: CID,
  /// User provided name for the document
  pub name: DocName<T>,
  /// User provided description for the document
  pub description: DocDesc<T>,
  /// Owner of the document
  pub owner: T::AccountId,
}

/// Shared confidential document
#[derive(
  CloneNoBound, Encode, Decode, RuntimeDebugNoBound, Default, TypeInfo, MaxEncodedLen, PartialEq,
)]
#[scale_info(skip_type_params(T))]
#[codec(mel_bound())]
pub struct SharedDoc<T: Config> {
  /// IPFS CID where the document data is stored
  pub cid: CID,
  /// User provided name for the document
  pub name: DocName<T>,
  /// User provided description for the document
  pub description: DocDesc<T>,
  /// User that shared the document
  pub from: T::AccountId,
  /// User to which the document was shared
  pub to: T::AccountId,
}

/// Group member role
#[derive(
  CloneNoBound, Encode, Decode, RuntimeDebugNoBound, Default, TypeInfo, MaxEncodedLen, PartialEq,
)]
#[scale_info(skip_type_params(T))]
#[codec(mel_bound())]
pub enum GroupRole {
  Admin,
  #[default]
  Member,
  Owner,
}

#[derive(
  CloneNoBound, Encode, Decode, RuntimeDebugNoBound, Default, TypeInfo, MaxEncodedLen, PartialEq,
)]
#[scale_info(skip_type_params(T))]
#[codec(mel_bound())]
pub struct Group<T: Config> {
  /// Account id of the group
  pub group: T::AccountId,
  /// User that created the group
  pub creator: T::AccountId,
  /// Group Name
  pub name: GroupName<T>,
}

/// Group member
#[derive(
  CloneNoBound, Encode, Decode, RuntimeDebugNoBound, Default, TypeInfo, MaxEncodedLen, PartialEq,
)]
#[scale_info(skip_type_params(T))]
#[codec(mel_bound())]
pub struct GroupMember<T: Config> {
  /// IPFS CID where the group key is stored
  pub cid: CID,
  /// User that is part of the group
  pub group: T::AccountId,
  /// User that is part of the group
  pub member: T::AccountId,
  /// User that authorized the member to the group
  pub authorizer: T::AccountId,
  /// Role of the member within the group
  pub role: GroupRole,
}

impl<T: Config> GroupMember<T> {
  pub fn can_add_group_member(&self) -> bool {
    self.role == GroupRole::Admin || self.role == GroupRole::Owner
  }

  pub fn can_remove_group_member(&self, group_member: &GroupMember<T>) -> bool {
    group_member.role != GroupRole::Owner
      && (self.role == GroupRole::Owner
        || (self.role == GroupRole::Admin && group_member.authorizer == self.member))
  }
}