11use crate :: protocol:: {
2- City , Country , Date , Email , File , Identification , Name , PostalAddress ,
3- blockchain:: company:: {
4- CompanyBlockPayload , CompanyCreateBlockData , CompanySignatoryBlockData , SignatoryType ,
5- } ,
2+ City , Country , Date , Email , EmailIdentityProofData , File , Identification , Name , PostalAddress ,
3+ SignedIdentityProof , Timestamp ,
4+ blockchain:: company:: { CompanyBlockPayload , CompanyCreateBlockData , SignatoryType } ,
65} ;
76use bcr_common:: core:: NodeId ;
87
@@ -20,57 +19,71 @@ pub struct Company {
2019 pub registration_date : Option < Date > ,
2120 pub proof_of_registration_file : Option < File > ,
2221 pub logo_file : Option < File > ,
22+ pub creation_time : Timestamp ,
2323 pub signatories : Vec < CompanySignatory > ,
24- pub active : bool ,
24+ pub status : CompanyStatus ,
2525}
2626
27- impl From < Company > for CompanyCreateBlockData {
28- fn from ( value : Company ) -> Self {
29- Self {
30- id : value. id ,
31- name : value. name ,
32- country_of_registration : value. country_of_registration ,
33- city_of_registration : value. city_of_registration ,
34- postal_address : value. postal_address ,
35- email : value. email ,
36- registration_number : value. registration_number ,
37- registration_date : value. registration_date ,
38- proof_of_registration_file : value. proof_of_registration_file ,
39- logo_file : value. logo_file ,
40- signatories : value. signatories . into_iter ( ) . map ( |s| s. into ( ) ) . collect ( ) ,
41- }
27+ impl Company {
28+ // checks if the given node id is an authorized signer for this company
29+ pub fn is_authorized_signer ( & self , node_id : & NodeId ) -> bool {
30+ self . signatories . iter ( ) . any ( |s| {
31+ & s. node_id == node_id
32+ && matches ! (
33+ s. status,
34+ CompanySignatoryStatus :: InviteAcceptedIdentityProven { .. }
35+ )
36+ } )
4237 }
4338}
4439
40+ #[ derive( Debug , Serialize , Deserialize , Clone , PartialEq , Eq , Copy ) ]
41+ pub enum CompanyStatus {
42+ Invited ,
43+ Active ,
44+ None ,
45+ }
46+
4547#[ derive( Debug , Serialize , Deserialize , Clone ) ]
4648pub struct CompanySignatory {
49+ pub t : SignatoryType ,
4750 pub node_id : NodeId ,
48- pub email : Email ,
51+ pub status : CompanySignatoryStatus ,
4952}
5053
51- impl From < CompanySignatory > for CompanySignatoryBlockData {
52- fn from ( value : CompanySignatory ) -> Self {
53- Self {
54- t : SignatoryType :: Solo ,
55- node_id : value. node_id ,
56- email : value. email ,
57- }
58- }
59- }
60-
61- impl From < CompanySignatoryBlockData > for CompanySignatory {
62- fn from ( value : CompanySignatoryBlockData ) -> Self {
63- Self {
64- node_id : value. node_id ,
65- email : value. email ,
66- }
67- }
54+ #[ derive( Debug , Serialize , Deserialize , Clone , PartialEq , Eq ) ]
55+ pub enum CompanySignatoryStatus {
56+ Invited {
57+ ts : Timestamp ,
58+ inviter : NodeId ,
59+ } ,
60+ InviteAccepted {
61+ ts : Timestamp ,
62+ } ,
63+ InviteRejected {
64+ ts : Timestamp ,
65+ } ,
66+ InviteAcceptedIdentityProven {
67+ ts : Timestamp ,
68+ data : EmailIdentityProofData ,
69+ proof : SignedIdentityProof ,
70+ } ,
71+ Removed {
72+ ts : Timestamp ,
73+ remover : NodeId ,
74+ } ,
6875}
6976
7077impl Company {
7178 /// Creates a new company from a block data payload
7279 pub fn from_block_data ( data : CompanyCreateBlockData , our_node_id : & NodeId ) -> Self {
73- let active = data. signatories . iter ( ) . any ( |s| & s. node_id == our_node_id) ;
80+ // if we're the creator, the company is active, otherwise we have no status in the company at this point
81+ let status = if our_node_id == & data. creator {
82+ CompanyStatus :: Active
83+ } else {
84+ CompanyStatus :: None
85+ } ;
86+
7487 Self {
7588 id : data. id ,
7689 name : data. name ,
@@ -82,12 +95,24 @@ impl Company {
8295 registration_date : data. registration_date ,
8396 proof_of_registration_file : data. proof_of_registration_file ,
8497 logo_file : data. logo_file ,
85- signatories : data. signatories . into_iter ( ) . map ( |s| s. into ( ) ) . collect ( ) ,
86- active,
98+ creation_time : data. creation_time ,
99+ signatories : vec ! [ CompanySignatory {
100+ t: SignatoryType :: Solo ,
101+ node_id: data. creator,
102+ status: CompanySignatoryStatus :: InviteAccepted {
103+ ts: data. creation_time,
104+ } ,
105+ } ] ,
106+ status,
87107 }
88108 }
89109 /// Applies data from a block to this company.
90- pub fn apply_block_data ( & mut self , data : & CompanyBlockPayload , our_node_id : & NodeId ) {
110+ pub fn apply_block_data (
111+ & mut self ,
112+ data : & CompanyBlockPayload ,
113+ our_node_id : & NodeId ,
114+ timestamp : Timestamp ,
115+ ) {
91116 match data {
92117 CompanyBlockPayload :: Update ( payload) => {
93118 self . name = payload. name . to_owned ( ) . unwrap_or ( self . name . to_owned ( ) ) ;
@@ -134,32 +159,137 @@ impl Company {
134159 . to_owned ( )
135160 . or ( self . proof_of_registration_file . to_owned ( ) ) ;
136161 }
137- CompanyBlockPayload :: AddSignatory ( payload) => {
138- if !self
162+ CompanyBlockPayload :: InviteSignatory ( payload) => {
163+ // if we're invited, set our status to invited, if we're not already invited or accepted
164+ if CompanyStatus :: None == self . status && our_node_id == & payload. invitee {
165+ self . status = CompanyStatus :: Invited ;
166+ }
167+
168+ // update signatory data
169+ if let Some ( signatory) = self
139170 . signatories
140- . iter ( )
141- . any ( |s| s. node_id == payload. signatory )
171+ . iter_mut ( )
172+ . find ( |s| s. node_id == payload. invitee )
142173 {
143- self . signatories . push (
144- CompanySignatoryBlockData {
145- t : SignatoryType :: Solo ,
146- node_id : payload. signatory . to_owned ( ) ,
147- email : payload. signatory_email . to_owned ( ) ,
174+ match signatory. status {
175+ CompanySignatoryStatus :: InviteRejected { .. }
176+ | CompanySignatoryStatus :: Removed { .. } => {
177+ // invite again
178+ signatory. status = CompanySignatoryStatus :: Invited {
179+ ts : timestamp,
180+ inviter : payload. inviter . clone ( ) ,
181+ }
148182 }
149- . into ( ) ,
150- ) ;
151- if & payload. signatory == our_node_id {
152- self . active = true ;
183+ _ => ( ) , // already invited / accepted - ignore,
153184 }
185+ } else {
186+ // if the signatory wasn't in the list before - add as invited
187+ self . signatories . push ( CompanySignatory {
188+ t : SignatoryType :: Solo ,
189+ node_id : payload. invitee . to_owned ( ) ,
190+ status : CompanySignatoryStatus :: Invited {
191+ ts : timestamp,
192+ inviter : payload. inviter . clone ( ) ,
193+ } ,
194+ } ) ;
195+ }
196+ }
197+ CompanyBlockPayload :: SignatoryAcceptInvite ( payload) => {
198+ // if we're invited, set our status to active
199+ if CompanyStatus :: Invited == self . status && our_node_id == & payload. accepter {
200+ self . status = CompanyStatus :: Active ;
201+ }
202+
203+ // update signatory data
204+ if let Some ( signatory) = self
205+ . signatories
206+ . iter_mut ( )
207+ . find ( |s| s. node_id == payload. accepter )
208+ {
209+ signatory. status = CompanySignatoryStatus :: InviteAccepted { ts : timestamp } ;
210+ }
211+ }
212+ CompanyBlockPayload :: SignatoryRejectInvite ( payload) => {
213+ // if we're invited, set our status to None
214+ if CompanyStatus :: Invited == self . status && our_node_id == & payload. rejecter {
215+ self . status = CompanyStatus :: None ;
216+ }
217+
218+ // update signatory data
219+ if let Some ( signatory) = self
220+ . signatories
221+ . iter_mut ( )
222+ . find ( |s| s. node_id == payload. rejecter )
223+ {
224+ signatory. status = CompanySignatoryStatus :: InviteRejected { ts : timestamp } ;
154225 }
155226 }
156227 CompanyBlockPayload :: RemoveSignatory ( payload) => {
157- self . signatories . retain ( |i| i. node_id != payload. signatory ) ;
158- if & payload. signatory == our_node_id {
159- self . active = false ;
228+ // if we're removed, set our status to none
229+ if our_node_id == & payload. removee {
230+ self . status = CompanyStatus :: None ;
231+ }
232+
233+ // update signatory data
234+ if let Some ( signatory) = self
235+ . signatories
236+ . iter_mut ( )
237+ . find ( |s| s. node_id == payload. removee )
238+ {
239+ signatory. status = CompanySignatoryStatus :: Removed {
240+ ts : timestamp,
241+ remover : payload. remover . clone ( ) ,
242+ } ;
243+ }
244+ }
245+ CompanyBlockPayload :: IdentityProof ( payload) => {
246+ if let Some ( signatory) = self
247+ . signatories
248+ . iter_mut ( )
249+ . find ( |s| s. node_id == payload. data . node_id )
250+ {
251+ // Part of adding a signatory via Accept, or Create
252+ if payload. reference_block . is_some ( ) {
253+ match signatory. status {
254+ CompanySignatoryStatus :: InviteAccepted { .. }
255+ | CompanySignatoryStatus :: InviteAcceptedIdentityProven { .. } => {
256+ signatory. status =
257+ CompanySignatoryStatus :: InviteAcceptedIdentityProven {
258+ ts : timestamp,
259+ data : payload. data . clone ( ) ,
260+ proof : payload. proof . clone ( ) ,
261+ }
262+ }
263+ _ => ( ) , // invalid / irrelevant cases
264+ }
265+ } else {
266+ // only update data
267+ if let CompanySignatoryStatus :: InviteAcceptedIdentityProven { ts, .. } =
268+ signatory. status
269+ {
270+ signatory. status =
271+ CompanySignatoryStatus :: InviteAcceptedIdentityProven {
272+ ts,
273+ data : payload. data . clone ( ) ,
274+ proof : payload. proof . clone ( ) ,
275+ }
276+ }
277+ }
160278 }
161279 }
162280 _ => { }
163281 }
164282 }
165283}
284+
285+ #[ derive( Debug , Clone ) ]
286+ pub struct LocalSignatoryOverride {
287+ pub company_id : NodeId ,
288+ pub node_id : NodeId ,
289+ pub status : LocalSignatoryOverrideStatus ,
290+ }
291+
292+ #[ derive( Debug , Clone , PartialEq , Eq , Serialize , Deserialize ) ]
293+ pub enum LocalSignatoryOverrideStatus {
294+ Hidden , // hide a company signatory locally
295+ }
0 commit comments