@@ -6,6 +6,7 @@ use crate::{
66 cis4:: { Cis4Contract , Cis4QueryError } ,
77 v2:: { self , BlockIdentifier , IntoBlockIdentifier } ,
88} ;
9+ use chrono:: { Utc , DateTime } ;
910pub use concordium_base:: web3id:: * ;
1011use concordium_base:: {
1112 base:: CredentialRegistrationID , cis4_types:: CredentialStatus , contracts_common:: AccountAddress , id:: { constants:: { ArCurve , IpPairing } , types:: { ArInfos , IpIdentity } } , web3id
@@ -119,13 +120,9 @@ pub async fn verify_credential_metadata(
119120 "Credential creation date is not valid." . into ( ) ,
120121 )
121122 } ) ?;
122- let status = if valid_from > now {
123- CredentialStatus :: NotActivated
124- } else if valid_until < now {
125- CredentialStatus :: Expired
126- } else {
127- CredentialStatus :: Active
128- } ;
123+
124+ let status = determine_credential_status_valid_from_valid_to ( now, valid_from, valid_until) ;
125+
129126 let inputs = CredentialsInputs :: Account {
130127 commitments : commitments. cmm_attributes . clone ( ) ,
131128 } ;
@@ -145,7 +142,6 @@ pub async fn verify_credential_metadata(
145142 Ok ( CredentialWithMetadata { status, inputs } )
146143 }
147144
148- // TODO - Identity handling for credential
149145 CredentialMetadata :: Identity { issuer, validity } => {
150146
151147 // get all the identity providers at current block
@@ -180,28 +176,40 @@ pub async fn verify_credential_metadata(
180176 // build inputs
181177 let inputs = CredentialsInputs :: Identity { ip_info : matching_idp. clone ( ) , ars_infos : ArInfos { anonymity_revokers : anonymity_revoker_infos } } ;
182178
183- // TODO - change me, probably need to do something similar to how we handle the account - where we check the validity created at and valid to
184- // validity.created_at
185- // validity.valid_to
179+ // Credential Status handling
186180 let now = client. get_block_info ( bi) . await ?. response . block_slot_time ;
187181
188- // TODO temporary dummy status for now
189- let status = CredentialStatus :: Active ;
190- /*
191- let status = if &validity.valid_to.year < YearMonth::now() {
192- CredentialStatus::Expired
193- } else if &validity.valid_to >= YearMonth::now() {
194- CredentialStatus::Active
195- } else {
196- CredentialStatus::NotActivated
197- };
198- */
182+ let valid_to = validity. valid_to . upper ( )
183+ . ok_or ( CredentialLookupError :: InvalidResponse ( "Error while getting annonymity revokers." . into ( ) ) ) ?;
184+
185+ let credential_status = determine_credential_status_valid_to ( now, valid_to) ;
199186
200- Ok ( CredentialWithMetadata { inputs : inputs, status : status } )
187+ Ok ( CredentialWithMetadata { inputs : inputs, status : credential_status } )
201188 }
202189 }
203190}
204191
192+
193+ /// determine the credential status where both the valid from and valid to is provided
194+ fn determine_credential_status_valid_from_valid_to ( time_to_compare_to : DateTime < Utc > , valid_from : DateTime < Utc > , valid_to : DateTime < Utc > ) -> CredentialStatus {
195+ if valid_from > time_to_compare_to {
196+ CredentialStatus :: NotActivated
197+ }
198+ else {
199+ determine_credential_status_valid_to ( time_to_compare_to, valid_to)
200+ }
201+ }
202+
203+ /// determine the credential status where you only have a `valid to` field and no valid from (such as identity)
204+ fn determine_credential_status_valid_to ( time_to_compare_to : DateTime < Utc > , valid_to : DateTime < Utc > ) -> CredentialStatus {
205+ if valid_to < time_to_compare_to {
206+ CredentialStatus :: Expired
207+ }
208+ else {
209+ CredentialStatus :: Active
210+ }
211+ }
212+
205213/// Retrieve the public data of credentials validating any metadata that is
206214/// part of the credentials.
207215///
@@ -226,3 +234,61 @@ pub async fn get_public_data(
226234 . collect :: < futures:: stream:: FuturesOrdered < _ > > ( ) ;
227235 stream. try_collect ( ) . await
228236}
237+
238+ #[ cfg( test) ]
239+ mod tests {
240+ use super :: * ;
241+
242+ /// valid from is before now, valid to is in the future, therefore credential status should be `active`
243+ #[ test]
244+ fn test_determine_credential_status_as_active_for_account ( ) {
245+ let now = Utc :: now ( ) ;
246+ let valid_from = now. checked_sub_days ( 20 ) ;
247+ let valid_to = now. checked_add_days ( 30 ) ;
248+
249+ let status = determine_credential_status_valid_from_valid_to ( now, valid_from, valid_to) ;
250+ assert_eq ! ( CredentialStatus :: Active , status) ;
251+ }
252+
253+ /// valid from is after now, valid to is in the future, therefore credential status should be `not activated`
254+ #[ test]
255+ fn test_determine_credential_status_as_not_activated_valid_from_after_today ( ) {
256+ let now = Utc :: now ( ) ;
257+ let valid_from = now. checked_add_days ( 2 ) ;
258+ let valid_to = now. checked_add_days ( 30 ) ;
259+
260+ let status = determine_credential_status_valid_from_valid_to ( now, valid_from, valid_to) ;
261+ assert_eq ! ( CredentialStatus :: NotActivated , status) ;
262+ }
263+
264+ /// valid from is before now, valid to is in the past, therefore credential status should be `expired`
265+ #[ test]
266+ fn test_determine_credential_status_as_not_activated_valid_from_after_today ( ) {
267+ let now = Utc :: now ( ) ;
268+ let valid_from = now. checked_sub_days ( 100 ) ;
269+ let valid_to = now. checked_sub_days ( 30 ) ;
270+
271+ let status = determine_credential_status_valid_from_valid_to ( now, valid_from, valid_to) ;
272+ assert_eq ! ( CredentialStatus :: Expired , status) ;
273+ }
274+
275+ // identity credential status check, returns as active for valid to date in the future
276+ #[ test]
277+ fn test_determine_credential_status_as_active_for_account ( ) {
278+ let now = Utc :: now ( ) ;
279+ let valid_to = now. checked_add_days ( 30 ) ;
280+
281+ let status = determine_credential_status_valid_to ( now, valid_to) ;
282+ assert_eq ! ( CredentialStatus :: Active , status) ;
283+ }
284+
285+ // identity credential status check, returns as expired for valid to date in the past
286+ #[ test]
287+ fn test_determine_credential_status_as_expired_for_account ( ) {
288+ let now = Utc :: now ( ) ;
289+ let valid_to = now. checked_sub_days ( 1 ) ;
290+
291+ let status = determine_credential_status_valid_to ( now, valid_to) ;
292+ assert_eq ! ( CredentialStatus :: Expired , status) ;
293+ }
294+ }
0 commit comments