1use ridl::signing::SignerID;
2use ti64::MsSinceEpoch;
3
4use crate::{
5 changes::RevealSecretToParent, AddRole, CrewChange, EntrustInfo, MakeStatement, Member,
6 RevealSecret,
7};
8
9use crate::CrewState;
10
11pub trait CrewRuleset {
12 fn is_valid_change(
13 &self,
14 state: &CrewState,
15 change: &CrewChange,
16 made_by: &SignerID,
17 mate_at: MsSinceEpoch,
18 ) -> Result<(), String>;
19}
20
21pub struct CrewRulesV1;
22
23pub const READER_ROLE: &str = "reader";
24pub const WRITER_ROLE: &str = "writer";
25pub const ADMIN_ROLE: &str = "admin";
26pub const READ_INVITATION_ROLE: &str = "readInvitation";
27pub const WRITE_INVITATION_ROLE: &str = "writeInvitation";
28pub const ADMIN_INVITATION_ROLE: &str = "adminInvitation";
29
30pub const PARTICIPATION_SECRET: &str = "participation";
31pub const CONTENT_SECRET: &str = "content";
32
33pub const SET_WRITE_ACCESS_INFO_ID: &str = "setWriteAccess";
34
35impl CrewRuleset for CrewRulesV1 {
36 fn is_valid_change(
37 &self,
38 state: &CrewState,
39 change: &CrewChange,
40 made_by: &SignerID,
41 made_at: MsSinceEpoch,
42 ) -> Result<(), String> {
43 match change {
44 CrewChange::AddRole(AddRole { role, .. }) if role == READER_ROLE => {
45 if state.roles_of(made_by).contains(ADMIN_ROLE)
46 || state.roles_of(made_by).contains(READ_INVITATION_ROLE)
47 {
48 Ok(())
49 } else {
50 Err("Only admins can change crew".to_string())
51 }
52 }
53 CrewChange::AddRole(AddRole { role, .. }) if role == WRITER_ROLE => {
54 if state.roles_of(made_by).contains(ADMIN_ROLE)
55 || state.roles_of(made_by).contains(WRITE_INVITATION_ROLE)
56 {
57 Ok(())
58 } else {
59 Err("Only admins can change crew".to_string())
60 }
61 }
62 CrewChange::AddRole(AddRole { role, .. }) if role == ADMIN_ROLE => {
63 if state.roles_of(made_by).contains(ADMIN_ROLE)
64 || state.roles_of(made_by).contains(ADMIN_INVITATION_ROLE)
65 {
66 Ok(())
67 } else {
68 Err("Only admins can change crew".to_string())
69 }
70 }
71 CrewChange::AddRole(_) | CrewChange::RemoveRole(_) => {
72 if state.roles_of(made_by).contains(ADMIN_ROLE) {
73 Ok(())
74 } else {
75 Err("Only admins can change crew".to_string())
76 }
77 }
78 CrewChange::RevealSecret(RevealSecret {
79 secret_kind, to, ..
80 }) => {
81 if secret_kind == PARTICIPATION_SECRET {
82 if state.roles_of(&made_by).contains(ADMIN_ROLE)
83 || state.roles_of(&made_by).contains(WRITE_INVITATION_ROLE)
84 || state.roles_of(&made_by).contains(ADMIN_INVITATION_ROLE)
85 {
86 if state.roles_of(&to).contains(READ_INVITATION_ROLE)
87 || state.roles_of(&to).contains(WRITE_INVITATION_ROLE)
88 || state.roles_of(&to).contains(ADMIN_INVITATION_ROLE)
89 || state.roles_of(&to).contains(WRITER_ROLE)
90 || state.roles_of(&to).contains(ADMIN_ROLE)
91 {
92 Ok(())
93 } else {
94 Err("Only read_invitations, write_invitations, admin_invitations, writers and admins can receive participation secrets".to_string())
95 }
96 } else {
97 Err("Only write_invitations, admin_invitations and admins can reveal participation secrets".to_string())
98 }
99 } else if secret_kind == CONTENT_SECRET {
100 if state.roles_of(&made_by).contains(ADMIN_ROLE)
101 || state.roles_of(&made_by).contains(WRITER_ROLE)
102 || state.roles_of(&made_by).contains(READ_INVITATION_ROLE)
103 || state.roles_of(&made_by).contains(WRITE_INVITATION_ROLE)
104 || state.roles_of(&made_by).contains(ADMIN_INVITATION_ROLE)
105 {
106 if state.roles_of(&to).contains(READ_INVITATION_ROLE)
107 || state.roles_of(&to).contains(WRITE_INVITATION_ROLE)
108 || state.roles_of(&to).contains(ADMIN_INVITATION_ROLE)
109 || state.roles_of(&to).contains(READER_ROLE)
110 || state.roles_of(&to).contains(WRITER_ROLE)
111 || state.roles_of(&to).contains(ADMIN_ROLE)
112 {
113 Ok(())
114 } else {
115 Err("Only read_invitations, write_invitations, readers, writers and admins can receive content secrets".to_string())
116 }
117 } else {
118 Err("Only read_invitations, write_invitations, admin_invitations, writers and admins can reveal content secrets".to_string())
119 }
120 } else {
121 todo!()
122 }
123 }
124 CrewChange::RevealSecretToParent(RevealSecretToParent { .. }) => {
125 if state.roles_of(&made_by).contains(ADMIN_ROLE) {
126 Ok(())
127 } else {
128 Err("Only admins can reveal secrets to parents".to_string())
129 }
130 }
131 CrewChange::EntrustInfo(EntrustInfo { to_secret_kind, .. }) => {
132 if to_secret_kind == PARTICIPATION_SECRET {
133 if state.roles_of(&made_by).contains(ADMIN_ROLE) {
134 Ok(())
135 } else {
136 Err("Only admins can entrust info to participation secrets".to_string())
137 }
138 } else if to_secret_kind == CONTENT_SECRET {
139 if state.roles_of(&made_by).contains(ADMIN_ROLE)
140 || state.roles_of(&made_by).contains(WRITER_ROLE)
141 {
142 Ok(())
143 } else {
144 Err("Only admins or writers can entrust info to content secrets"
145 .to_string())
146 }
147 } else {
148 todo!()
149 }
150 }
151 CrewChange::AddParent { .. } | CrewChange::RemoveParent { .. } => {
152 if state.roles_of(&made_by).contains(ADMIN_ROLE) {
153 Ok(())
154 } else {
155 Err("Only admins can add parent crews".to_string())
156 }
157 }
158 CrewChange::MakeStatement(MakeStatement { .. }) => {
159 if state.roles_of(&made_by).contains(ADMIN_ROLE)
160 || state.roles_of(&made_by).contains(WRITER_ROLE)
161 {
162 Ok(())
163 } else {
164 Err("Only admins and writers can make statements".to_string())
165 }
166 }
167 }
168 }
169}