@@ -46,6 +46,7 @@ UserRecord* user_record_new(void) {
4646 .nice_level = INT_MAX ,
4747 .not_before_usec = UINT64_MAX ,
4848 .not_after_usec = UINT64_MAX ,
49+ .birth_date = BIRTH_DATE_UNSET ,
4950 .locked = -1 ,
5051 .storage = _USER_STORAGE_INVALID ,
5152 .access_mode = MODE_INVALID ,
@@ -417,6 +418,28 @@ static int json_dispatch_filename_or_path(const char *name, sd_json_variant *var
417418 return 0 ;
418419}
419420
421+ static int json_dispatch_birth_date (const char * name , sd_json_variant * variant , sd_json_dispatch_flags_t flags , void * userdata ) {
422+ struct tm * ret = ASSERT_PTR (userdata );
423+ const char * s ;
424+ int r ;
425+
426+ if (sd_json_variant_is_null (variant )) {
427+ * ret = BIRTH_DATE_UNSET ;
428+ return 0 ;
429+ }
430+
431+ if (!sd_json_variant_is_string (variant ))
432+ return json_log (variant , flags , SYNTHETIC_ERRNO (EINVAL ), "JSON field '%s' is not a string." , strna (name ));
433+
434+ s = sd_json_variant_string (variant );
435+
436+ r = parse_birth_date (s , ret );
437+ if (r < 0 )
438+ return json_log (variant , flags , r , "JSON field '%s' is not a valid ISO 8601 date (expected YYYY-MM-DD)." , strna (name ));
439+
440+ return 0 ;
441+ }
442+
420443static int json_dispatch_home_directory (const char * name , sd_json_variant * variant , sd_json_dispatch_flags_t flags , void * userdata ) {
421444 char * * s = userdata ;
422445 const char * n ;
@@ -1500,7 +1523,8 @@ int user_group_record_mangle(
15001523 /* Personally Identifiable Information (PII) — avoid leaking in logs */
15011524 "realName" ,
15021525 "location" ,
1503- "emailAddress" )
1526+ "emailAddress" ,
1527+ "birthDate" )
15041528 sd_json_variant_sensitive (sd_json_variant_by_key (v , key ));
15051529
15061530 /* Check if we have the special sections and if they match our flags set */
@@ -1595,6 +1619,7 @@ int user_record_load(UserRecord *h, sd_json_variant *v, UserRecordLoadFlags load
15951619 { "emailAddress" , SD_JSON_VARIANT_STRING , sd_json_dispatch_string , offsetof(UserRecord , email_address ), SD_JSON_STRICT },
15961620 { "iconName" , SD_JSON_VARIANT_STRING , sd_json_dispatch_string , offsetof(UserRecord , icon_name ), SD_JSON_STRICT },
15971621 { "location" , SD_JSON_VARIANT_STRING , sd_json_dispatch_string , offsetof(UserRecord , location ), 0 },
1622+ { "birthDate" , SD_JSON_VARIANT_STRING , json_dispatch_birth_date , offsetof(UserRecord , birth_date ), 0 },
15981623 { "disposition" , SD_JSON_VARIANT_STRING , json_dispatch_user_disposition , offsetof(UserRecord , disposition ), 0 },
15991624 { "lastChangeUSec" , _SD_JSON_VARIANT_TYPE_INVALID , sd_json_dispatch_uint64 , offsetof(UserRecord , last_change_usec ), 0 },
16001625 { "lastPasswordChangeUSec" , _SD_JSON_VARIANT_TYPE_INVALID , sd_json_dispatch_uint64 , offsetof(UserRecord , last_password_change_usec ), 0 },
0 commit comments