1use crate::prelude::*;
2
3use crate::migration_data;
4use kanidm_proto::internal::{
5 DomainUpgradeCheckItem as ProtoDomainUpgradeCheckItem,
6 DomainUpgradeCheckReport as ProtoDomainUpgradeCheckReport,
7 DomainUpgradeCheckStatus as ProtoDomainUpgradeCheckStatus,
8};
9
10use super::ServerPhase;
11
12impl QueryServer {
13 #[instrument(level = "info", name = "system_initialisation", skip_all)]
14 pub async fn initialise_helper(
15 &self,
16 ts: Duration,
17 domain_target_level: DomainVersion,
18 ) -> Result<(), OperationError> {
19 let mut write_txn = self.write(ts).await?;
22
23 write_txn.upgrade_reindex(SYSTEM_INDEX_VERSION)?;
27
28 write_txn
38 .initialise_schema_core()
39 .and_then(|_| write_txn.reload())?;
40
41 let db_domain_version = match write_txn.internal_search_uuid(UUID_DOMAIN_INFO) {
44 Ok(e) => Ok(e.get_ava_single_uint32(Attribute::Version).unwrap_or(0)),
45 Err(OperationError::NoMatchingEntries) => Ok(0),
46 Err(r) => Err(r),
47 }?;
48
49 debug!(?db_domain_version, "Before setting internal domain info");
50
51 if db_domain_version == 0 {
52 debug_assert!(domain_target_level <= DOMAIN_MAX_LEVEL);
56
57 match domain_target_level {
60 DOMAIN_LEVEL_10 => write_txn.migrate_domain_9_to_10()?,
61 DOMAIN_LEVEL_11 => write_txn.migrate_domain_10_to_11()?,
62 DOMAIN_LEVEL_12 => write_txn.migrate_domain_11_to_12()?,
63 DOMAIN_LEVEL_13 => write_txn.migrate_domain_12_to_13()?,
64 DOMAIN_LEVEL_14 => write_txn.migrate_domain_13_to_14()?,
65 _ => {
66 error!("Invalid requested domain target level for server bootstrap");
67 debug_assert!(false);
68 return Err(OperationError::MG0009InvalidTargetLevelForBootstrap);
69 }
70 }
71 } else {
72 write_txn.force_domain_reload();
81
82 write_txn.reload()?;
83
84 write_txn.set_phase(ServerPhase::SchemaReady);
87
88 write_txn.force_schema_reload();
97
98 write_txn.reload()?;
100
101 write_txn.set_phase(ServerPhase::DomainInfoReady);
103 }
104
105 let domain_info_version = write_txn.get_domain_version();
112 let domain_patch_level = write_txn.get_domain_patch_level();
113 let domain_development_taint = write_txn.get_domain_development_taint();
114 debug!(
115 ?db_domain_version,
116 ?domain_patch_level,
117 ?domain_development_taint,
118 "After setting internal domain info"
119 );
120
121 let mut reload_required = false;
122
123 if domain_info_version < domain_target_level {
125 write_txn
126 .internal_apply_domain_migration(domain_target_level)
127 .map(|()| {
128 warn!("Domain level has been raised to {}", domain_target_level);
129 })?;
130 if domain_info_version != 0 {
136 reload_required = true;
137 }
138 } else if domain_development_taint {
139 write_txn.domain_remigrate(DOMAIN_PREVIOUS_TGT_LEVEL)?;
150
151 reload_required = true;
152 }
153
154 if domain_patch_level < DOMAIN_TGT_PATCH_LEVEL {
157 write_txn
158 .internal_modify_uuid(
159 UUID_DOMAIN_INFO,
160 &ModifyList::new_purge_and_set(
161 Attribute::PatchLevel,
162 Value::new_uint32(DOMAIN_TGT_PATCH_LEVEL),
163 ),
164 )
165 .map(|()| {
166 warn!(
167 "Domain patch level has been raised to {}",
168 domain_patch_level
169 );
170 })?;
171
172 reload_required = true;
173 };
174
175 if reload_required {
179 write_txn.reload()?;
180 }
181
182 let current_devel_flag = option_env!("KANIDM_PRE_RELEASE").is_some();
185 if current_devel_flag {
186 warn!("Domain Development Taint mode is enabled");
187 }
188 if domain_development_taint != current_devel_flag {
189 write_txn.internal_modify_uuid(
190 UUID_DOMAIN_INFO,
191 &ModifyList::new_purge_and_set(
192 Attribute::DomainDevelopmentTaint,
193 Value::Bool(current_devel_flag),
194 ),
195 )?;
196 }
197
198 write_txn.set_phase(ServerPhase::Running);
200
201 write_txn.commit()?;
204
205 debug!("Database version check and migrations success! ☀️ ");
206 Ok(())
207 }
208}
209
210impl QueryServerWriteTransaction<'_> {
211 pub(crate) fn internal_apply_domain_migration(
214 &mut self,
215 to_level: u32,
216 ) -> Result<(), OperationError> {
217 assert!(to_level > self.get_domain_version());
218 self.internal_modify_uuid(
219 UUID_DOMAIN_INFO,
220 &ModifyList::new_purge_and_set(Attribute::Version, Value::new_uint32(to_level)),
221 )
222 .and_then(|()| self.reload())
223 }
224
225 fn internal_migrate_or_create_batch(
226 &mut self,
227 msg: &str,
228 entries: Vec<EntryInitNew>,
229 ) -> Result<(), OperationError> {
230 let r: Result<(), _> = entries
231 .into_iter()
232 .try_for_each(|entry| self.internal_migrate_or_create(entry));
233
234 if let Err(err) = r {
235 error!(?err, msg);
236 debug_assert!(false);
237 }
238
239 Ok(())
240 }
241
242 #[instrument(level = "debug", skip_all)]
243 fn internal_migrate_or_create(
253 &mut self,
254 e: Entry<EntryInit, EntryNew>,
255 ) -> Result<(), OperationError> {
256 self.internal_migrate_or_create_ignore_attrs(e, &[])
257 }
258
259 #[instrument(level = "debug", skip_all)]
260 fn internal_delete_batch(
261 &mut self,
262 msg: &str,
263 entries: Vec<Uuid>,
264 ) -> Result<(), OperationError> {
265 let filter = entries
266 .into_iter()
267 .map(|uuid| f_eq(Attribute::Uuid, PartialValue::Uuid(uuid)))
268 .collect();
269
270 let filter = filter_all!(f_or(filter));
271
272 let result = self.internal_delete(&filter);
273
274 match result {
275 Ok(_) | Err(OperationError::NoMatchingEntries) => Ok(()),
276 Err(err) => {
277 error!(?err, msg);
278 Err(err)
279 }
280 }
281 }
282
283 #[instrument(level = "trace", skip_all)]
287 fn internal_migrate_or_create_ignore_attrs(
288 &mut self,
289 mut e: Entry<EntryInit, EntryNew>,
290 attrs: &[Attribute],
291 ) -> Result<(), OperationError> {
292 trace!("operating on {:?}", e.get_uuid());
293
294 let Some(filt) = e.filter_from_attrs(&[Attribute::Uuid]) else {
295 return Err(OperationError::FilterGeneration);
296 };
297
298 trace!("search {:?}", filt);
299
300 let results = self.internal_search(filt.clone())?;
301
302 if results.is_empty() {
303 self.internal_create(vec![e])
305 } else if results.len() == 1 {
306 for attr in attrs.iter() {
308 e.remove_ava(attr);
309 }
310
311 match e.gen_modlist_assert(&self.schema) {
313 Ok(modlist) => {
314 trace!(?modlist);
316 self.internal_modify(&filt, &modlist)
317 }
318 Err(e) => Err(OperationError::SchemaViolation(e)),
319 }
320 } else {
321 admin_error!(
322 "Invalid Result Set - Expected One Entry for {:?} - {:?}",
323 filt,
324 results
325 );
326 Err(OperationError::InvalidDbState)
327 }
328 }
329
330 #[instrument(level = "info", skip_all)]
359 pub(crate) fn migrate_domain_9_to_10(&mut self) -> Result<(), OperationError> {
360 if !cfg!(test) && DOMAIN_TGT_LEVEL < DOMAIN_LEVEL_9 {
361 error!("Unable to raise domain level from 9 to 10.");
362 return Err(OperationError::MG0004DomainLevelInDevelopment);
363 }
364
365 self.internal_migrate_or_create_batch(
367 "phase 1 - schema attrs",
368 migration_data::dl10::phase_1_schema_attrs(),
369 )?;
370
371 self.internal_migrate_or_create_batch(
372 "phase 2 - schema classes",
373 migration_data::dl10::phase_2_schema_classes(),
374 )?;
375
376 self.reload()?;
378
379 self.reindex(false)?;
382
383 self.set_phase(ServerPhase::SchemaReady);
387
388 self.internal_migrate_or_create_batch(
389 "phase 3 - key provider",
390 migration_data::dl10::phase_3_key_provider(),
391 )?;
392
393 self.reload()?;
395
396 self.internal_migrate_or_create_batch(
397 "phase 4 - system entries",
398 migration_data::dl10::phase_4_system_entries(),
399 )?;
400
401 self.reload()?;
403
404 self.set_phase(ServerPhase::DomainInfoReady);
406
407 self.internal_migrate_or_create_batch(
409 "phase 5 - builtin admin entries",
410 migration_data::dl10::phase_5_builtin_admin_entries()?,
411 )?;
412
413 self.internal_migrate_or_create_batch(
414 "phase 6 - builtin not admin entries",
415 migration_data::dl10::phase_6_builtin_non_admin_entries()?,
416 )?;
417
418 self.internal_migrate_or_create_batch(
419 "phase 7 - builtin access control profiles",
420 migration_data::dl10::phase_7_builtin_access_control_profiles(),
421 )?;
422
423 self.reload()?;
424
425 debug!("START OAUTH2 MIGRATION");
428
429 let all_oauth2_rs_entries = self.internal_search(filter!(f_eq(
431 Attribute::Class,
432 EntryClass::OAuth2ResourceServer.into()
433 )))?;
434
435 if !all_oauth2_rs_entries.is_empty() {
436 let entry_iter = all_oauth2_rs_entries.iter().map(|tgt_entry| {
437 let entry_uuid = tgt_entry.get_uuid();
438 let mut modlist = ModifyList::new_list(vec![
439 Modify::Present(Attribute::Class, EntryClass::KeyObject.to_value()),
440 Modify::Present(Attribute::Class, EntryClass::KeyObjectJwtEs256.to_value()),
441 Modify::Present(Attribute::Class, EntryClass::KeyObjectJweA128GCM.to_value()),
442 Modify::Purged(Attribute::OAuth2RsTokenKey),
444 Modify::Purged(Attribute::Es256PrivateKeyDer),
445 Modify::Purged(Attribute::Rs256PrivateKeyDer),
446 ]);
447
448 trace!(?tgt_entry);
449
450 if let Some(es256_private_der) =
452 tgt_entry.get_ava_single_private_binary(Attribute::Es256PrivateKeyDer)
453 {
454 modlist.push_mod(Modify::Present(
455 Attribute::KeyActionImportJwsEs256,
456 Value::PrivateBinary(es256_private_der.to_vec()),
457 ))
458 } else {
459 warn!("Unable to migrate es256 key");
460 }
461
462 let has_rs256 = tgt_entry
463 .get_ava_single_bool(Attribute::OAuth2JwtLegacyCryptoEnable)
464 .unwrap_or(false);
465
466 if has_rs256 {
469 modlist.push_mod(Modify::Present(
470 Attribute::Class,
471 EntryClass::KeyObjectJwtEs256.to_value(),
472 ));
473
474 if let Some(rs256_private_der) =
475 tgt_entry.get_ava_single_private_binary(Attribute::Rs256PrivateKeyDer)
476 {
477 modlist.push_mod(Modify::Present(
478 Attribute::KeyActionImportJwsRs256,
479 Value::PrivateBinary(rs256_private_der.to_vec()),
480 ))
481 } else {
482 warn!("Unable to migrate rs256 key");
483 }
484 }
485
486 (entry_uuid, modlist)
487 });
488
489 self.internal_batch_modify(entry_iter)?;
490 }
491
492 self.reload()?;
494
495 Ok(())
498 }
499
500 #[instrument(level = "info", skip_all)]
502 pub(crate) fn migrate_domain_10_to_11(&mut self) -> Result<(), OperationError> {
503 if !cfg!(test) && DOMAIN_TGT_LEVEL < DOMAIN_LEVEL_10 {
504 error!("Unable to raise domain level from 10 to 11.");
505 return Err(OperationError::MG0004DomainLevelInDevelopment);
506 }
507
508 self.internal_migrate_or_create_batch(
510 "phase 1 - schema attrs",
511 migration_data::dl11::phase_1_schema_attrs(),
512 )?;
513
514 self.internal_migrate_or_create_batch(
515 "phase 2 - schema classes",
516 migration_data::dl11::phase_2_schema_classes(),
517 )?;
518
519 self.reload()?;
521
522 self.reindex(false)?;
525
526 self.set_phase(ServerPhase::SchemaReady);
530
531 self.internal_migrate_or_create_batch(
532 "phase 3 - key provider",
533 migration_data::dl11::phase_3_key_provider(),
534 )?;
535
536 self.reload()?;
538
539 self.internal_migrate_or_create_batch(
540 "phase 4 - system entries",
541 migration_data::dl11::phase_4_system_entries(),
542 )?;
543
544 self.reload()?;
546
547 self.set_phase(ServerPhase::DomainInfoReady);
549
550 self.internal_migrate_or_create_batch(
552 "phase 5 - builtin admin entries",
553 migration_data::dl11::phase_5_builtin_admin_entries()?,
554 )?;
555
556 self.internal_migrate_or_create_batch(
557 "phase 6 - builtin not admin entries",
558 migration_data::dl11::phase_6_builtin_non_admin_entries()?,
559 )?;
560
561 self.internal_migrate_or_create_batch(
562 "phase 7 - builtin access control profiles",
563 migration_data::dl11::phase_7_builtin_access_control_profiles(),
564 )?;
565
566 self.reload()?;
567
568 Ok(())
569 }
570
571 #[instrument(level = "info", skip_all)]
573 pub(crate) fn migrate_domain_11_to_12(&mut self) -> Result<(), OperationError> {
574 if !cfg!(test) && DOMAIN_TGT_LEVEL < DOMAIN_LEVEL_11 {
575 error!("Unable to raise domain level from 11 to 12.");
576 return Err(OperationError::MG0004DomainLevelInDevelopment);
577 }
578
579 self.internal_migrate_or_create_batch(
581 "phase 1 - schema attrs",
582 migration_data::dl12::phase_1_schema_attrs(),
583 )?;
584
585 self.internal_migrate_or_create_batch(
586 "phase 2 - schema classes",
587 migration_data::dl12::phase_2_schema_classes(),
588 )?;
589
590 self.reload()?;
592
593 self.reindex(false)?;
596
597 self.set_phase(ServerPhase::SchemaReady);
601
602 self.internal_migrate_or_create_batch(
603 "phase 3 - key provider",
604 migration_data::dl12::phase_3_key_provider(),
605 )?;
606
607 self.reload()?;
609
610 self.internal_migrate_or_create_batch(
611 "phase 4 - system entries",
612 migration_data::dl12::phase_4_system_entries(),
613 )?;
614
615 self.reload()?;
617
618 self.set_phase(ServerPhase::DomainInfoReady);
620
621 self.internal_migrate_or_create_batch(
623 "phase 5 - builtin admin entries",
624 migration_data::dl12::phase_5_builtin_admin_entries()?,
625 )?;
626
627 self.internal_migrate_or_create_batch(
628 "phase 6 - builtin not admin entries",
629 migration_data::dl12::phase_6_builtin_non_admin_entries()?,
630 )?;
631
632 self.internal_migrate_or_create_batch(
633 "phase 7 - builtin access control profiles",
634 migration_data::dl12::phase_7_builtin_access_control_profiles(),
635 )?;
636
637 self.reload()?;
638
639 let modlist = ModifyList::new_purge(Attribute::IdVerificationEcKey);
641 let filter = filter_all!(f_pres(Attribute::IdVerificationEcKey));
642
643 self.internal_modify(&filter, &modlist)?;
644
645 Ok(())
646 }
647
648 #[instrument(level = "info", skip_all)]
650 pub(crate) fn migrate_domain_12_to_13(&mut self) -> Result<(), OperationError> {
651 if !cfg!(test) && DOMAIN_TGT_LEVEL < DOMAIN_LEVEL_12 {
652 error!("Unable to raise domain level from 12 to 13.");
653 return Err(OperationError::MG0004DomainLevelInDevelopment);
654 }
655
656 self.internal_migrate_or_create_batch(
658 "phase 1 - schema attrs",
659 migration_data::dl13::phase_1_schema_attrs(),
660 )?;
661
662 self.internal_migrate_or_create_batch(
663 "phase 2 - schema classes",
664 migration_data::dl13::phase_2_schema_classes(),
665 )?;
666
667 self.reload()?;
669
670 self.reindex(false)?;
673
674 self.set_phase(ServerPhase::SchemaReady);
678
679 self.internal_migrate_or_create_batch(
680 "phase 3 - key provider",
681 migration_data::dl13::phase_3_key_provider(),
682 )?;
683
684 self.reload()?;
686
687 self.internal_migrate_or_create_batch(
688 "phase 4 - system entries",
689 migration_data::dl13::phase_4_system_entries(),
690 )?;
691
692 self.reload()?;
694
695 self.set_phase(ServerPhase::DomainInfoReady);
697
698 self.internal_migrate_or_create_batch(
700 "phase 5 - builtin admin entries",
701 migration_data::dl13::phase_5_builtin_admin_entries()?,
702 )?;
703
704 self.internal_migrate_or_create_batch(
705 "phase 6 - builtin not admin entries",
706 migration_data::dl13::phase_6_builtin_non_admin_entries()?,
707 )?;
708
709 self.internal_migrate_or_create_batch(
710 "phase 7 - builtin access control profiles",
711 migration_data::dl13::phase_7_builtin_access_control_profiles(),
712 )?;
713
714 self.internal_delete_batch(
715 "phase 8 - delete UUIDS",
716 migration_data::dl13::phase_8_delete_uuids(),
717 )?;
718
719 self.reload()?;
720
721 Ok(())
722 }
723
724 #[instrument(level = "info", skip_all)]
726 pub(crate) fn migrate_domain_13_to_14(&mut self) -> Result<(), OperationError> {
727 if !cfg!(test) && DOMAIN_TGT_LEVEL < DOMAIN_LEVEL_13 {
728 error!("Unable to raise domain level from 13 to 14.");
729 return Err(OperationError::MG0004DomainLevelInDevelopment);
730 }
731
732 Ok(())
733 }
734
735 #[instrument(level = "info", skip_all)]
736 pub(crate) fn initialise_schema_core(&mut self) -> Result<(), OperationError> {
737 admin_debug!("initialise_schema_core -> start ...");
738 let entries = self.schema.to_entries();
740
741 let r: Result<_, _> = entries.into_iter().try_for_each(|e| {
745 trace!(?e, "init schema entry");
746 self.internal_migrate_or_create(e)
747 });
748 if r.is_ok() {
749 admin_debug!("initialise_schema_core -> Ok!");
750 } else {
751 admin_error!(?r, "initialise_schema_core -> Error");
752 }
753 debug_assert!(r.is_ok());
755 r
756 }
757}
758
759impl QueryServerReadTransaction<'_> {
760 pub fn domain_upgrade_check(
762 &mut self,
763 ) -> Result<ProtoDomainUpgradeCheckReport, OperationError> {
764 let d_info = &self.d_info;
765
766 let name = d_info.d_name.clone();
767 let uuid = d_info.d_uuid;
768 let current_level = d_info.d_vers;
769 let upgrade_level = DOMAIN_TGT_NEXT_LEVEL;
770
771 let mut report_items = Vec::with_capacity(1);
772
773 if current_level <= DOMAIN_LEVEL_7 && upgrade_level >= DOMAIN_LEVEL_8 {
774 let item = self
775 .domain_upgrade_check_7_to_8_security_keys()
776 .map_err(|err| {
777 error!(
778 ?err,
779 "Failed to perform domain upgrade check 7 to 8 - security-keys"
780 );
781 err
782 })?;
783 report_items.push(item);
784
785 let item = self
786 .domain_upgrade_check_7_to_8_oauth2_strict_redirect_uri()
787 .map_err(|err| {
788 error!(
789 ?err,
790 "Failed to perform domain upgrade check 7 to 8 - oauth2-strict-redirect_uri"
791 );
792 err
793 })?;
794 report_items.push(item);
795 }
796
797 Ok(ProtoDomainUpgradeCheckReport {
798 name,
799 uuid,
800 current_level,
801 upgrade_level,
802 report_items,
803 })
804 }
805
806 pub(crate) fn domain_upgrade_check_7_to_8_security_keys(
807 &mut self,
808 ) -> Result<ProtoDomainUpgradeCheckItem, OperationError> {
809 let filter = filter!(f_and!([
810 f_eq(Attribute::Class, EntryClass::Account.into()),
811 f_pres(Attribute::PrimaryCredential),
812 ]));
813
814 let results = self.internal_search(filter)?;
815
816 let affected_entries = results
817 .into_iter()
818 .filter_map(|entry| {
819 if entry
820 .get_ava_single_credential(Attribute::PrimaryCredential)
821 .map(|cred| cred.has_securitykey())
822 .unwrap_or_default()
823 {
824 Some(entry.get_display_id())
825 } else {
826 None
827 }
828 })
829 .collect::<Vec<_>>();
830
831 let status = if affected_entries.is_empty() {
832 ProtoDomainUpgradeCheckStatus::Pass7To8SecurityKeys
833 } else {
834 ProtoDomainUpgradeCheckStatus::Fail7To8SecurityKeys
835 };
836
837 Ok(ProtoDomainUpgradeCheckItem {
838 status,
839 from_level: DOMAIN_LEVEL_7,
840 to_level: DOMAIN_LEVEL_8,
841 affected_entries,
842 })
843 }
844
845 pub(crate) fn domain_upgrade_check_7_to_8_oauth2_strict_redirect_uri(
846 &mut self,
847 ) -> Result<ProtoDomainUpgradeCheckItem, OperationError> {
848 let filter = filter!(f_and!([
849 f_eq(Attribute::Class, EntryClass::OAuth2ResourceServer.into()),
850 f_andnot(f_pres(Attribute::OAuth2StrictRedirectUri)),
851 ]));
852
853 let results = self.internal_search(filter)?;
854
855 let affected_entries = results
856 .into_iter()
857 .map(|entry| entry.get_display_id())
858 .collect::<Vec<_>>();
859
860 let status = if affected_entries.is_empty() {
861 ProtoDomainUpgradeCheckStatus::Pass7To8Oauth2StrictRedirectUri
862 } else {
863 ProtoDomainUpgradeCheckStatus::Fail7To8Oauth2StrictRedirectUri
864 };
865
866 Ok(ProtoDomainUpgradeCheckItem {
867 status,
868 from_level: DOMAIN_LEVEL_7,
869 to_level: DOMAIN_LEVEL_8,
870 affected_entries,
871 })
872 }
873}
874
875#[cfg(test)]
876mod tests {
877 use crate::prelude::*;
879
880 #[qs_test]
881 async fn test_init_idempotent_schema_core(server: &QueryServer) {
882 {
883 let mut server_txn = server.write(duration_from_epoch_now()).await.unwrap();
885 assert!(server_txn.initialise_schema_core().is_ok());
886 }
887 {
888 let mut server_txn = server.write(duration_from_epoch_now()).await.unwrap();
889 assert!(server_txn.initialise_schema_core().is_ok());
890 assert!(server_txn.initialise_schema_core().is_ok());
891 assert!(server_txn.commit().is_ok());
892 }
893 {
894 let mut server_txn = server.write(duration_from_epoch_now()).await.unwrap();
896 assert!(server_txn.initialise_schema_core().is_ok());
897 }
898 {
899 let mut server_txn = server.write(duration_from_epoch_now()).await.unwrap();
901 assert!(server_txn.initialise_schema_core().is_ok());
902 assert!(server_txn.commit().is_ok());
903 }
904 }
905
906 #[qs_test(domain_level=DOMAIN_LEVEL_10)]
907 async fn test_migrations_dl10_dl11(server: &QueryServer) {
908 let mut write_txn = server.write(duration_from_epoch_now()).await.unwrap();
909
910 let db_domain_version = write_txn
911 .internal_search_uuid(UUID_DOMAIN_INFO)
912 .expect("unable to access domain entry")
913 .get_ava_single_uint32(Attribute::Version)
914 .expect("Attribute Version not present");
915
916 assert_eq!(db_domain_version, DOMAIN_LEVEL_10);
917
918 write_txn.commit().expect("Unable to commit");
919
920 let mut write_txn = server.write(duration_from_epoch_now()).await.unwrap();
927
928 write_txn
932 .internal_apply_domain_migration(DOMAIN_LEVEL_11)
933 .expect("Unable to set domain level to version 11");
934
935 write_txn.commit().expect("Unable to commit");
938 }
939
940 #[qs_test(domain_level=DOMAIN_LEVEL_11)]
941 async fn test_migrations_dl11_dl12(server: &QueryServer) {
942 let mut write_txn = server.write(duration_from_epoch_now()).await.unwrap();
943
944 let db_domain_version = write_txn
945 .internal_search_uuid(UUID_DOMAIN_INFO)
946 .expect("unable to access domain entry")
947 .get_ava_single_uint32(Attribute::Version)
948 .expect("Attribute Version not present");
949
950 assert_eq!(db_domain_version, DOMAIN_LEVEL_11);
951
952 let tuuid = Uuid::new_v4();
954 let e1 = entry_init!(
955 (Attribute::Class, EntryClass::Object.to_value()),
956 (Attribute::Class, EntryClass::Person.to_value()),
957 (Attribute::Class, EntryClass::Account.to_value()),
958 (Attribute::Name, Value::new_iname("testperson1")),
959 (Attribute::Uuid, Value::Uuid(tuuid)),
960 (Attribute::Description, Value::new_utf8s("testperson1")),
961 (Attribute::DisplayName, Value::new_utf8s("testperson1"))
962 );
963
964 write_txn
965 .internal_create(vec![e1])
966 .expect("Unable to create user");
967
968 let user = write_txn
969 .internal_search_uuid(tuuid)
970 .expect("Unable to load user");
971
972 assert!(user.get_ava_set(Attribute::IdVerificationEcKey).is_some());
974
975 write_txn.commit().expect("Unable to commit");
976
977 let mut write_txn = server.write(duration_from_epoch_now()).await.unwrap();
984
985 write_txn
989 .internal_apply_domain_migration(DOMAIN_LEVEL_12)
990 .expect("Unable to set domain level to version 12");
991
992 let user = write_txn
994 .internal_search_uuid(tuuid)
995 .expect("Unable to load user");
996
997 assert!(user.get_ava_set(Attribute::IdVerificationEcKey).is_none());
999
1000 let t2uuid = Uuid::new_v4();
1002 let e2 = entry_init!(
1003 (Attribute::Class, EntryClass::Object.to_value()),
1004 (Attribute::Class, EntryClass::Person.to_value()),
1005 (Attribute::Class, EntryClass::Account.to_value()),
1006 (Attribute::Name, Value::new_iname("testperson2")),
1007 (Attribute::Uuid, Value::Uuid(t2uuid)),
1008 (Attribute::Description, Value::new_utf8s("testperson2")),
1009 (Attribute::DisplayName, Value::new_utf8s("testperson2"))
1010 );
1011
1012 write_txn
1013 .internal_create(vec![e2])
1014 .expect("Unable to create user");
1015
1016 let user = write_txn
1017 .internal_search_uuid(t2uuid)
1018 .expect("Unable to load user");
1019
1020 assert!(user.get_ava_set(Attribute::IdVerificationEcKey).is_none());
1022
1023 write_txn.commit().expect("Unable to commit");
1024 }
1025
1026 #[qs_test(domain_level=DOMAIN_LEVEL_12)]
1027 async fn test_migrations_dl12_dl13(server: &QueryServer) {
1028 let mut write_txn = server.write(duration_from_epoch_now()).await.unwrap();
1029
1030 let db_domain_version = write_txn
1031 .internal_search_uuid(UUID_DOMAIN_INFO)
1032 .expect("unable to access domain entry")
1033 .get_ava_single_uint32(Attribute::Version)
1034 .expect("Attribute Version not present");
1035
1036 assert_eq!(db_domain_version, DOMAIN_LEVEL_12);
1037
1038 write_txn.commit().expect("Unable to commit");
1039
1040 let mut write_txn = server.write(duration_from_epoch_now()).await.unwrap();
1047
1048 write_txn
1052 .internal_apply_domain_migration(DOMAIN_LEVEL_13)
1053 .expect("Unable to set domain level to version 13");
1054
1055 write_txn.commit().expect("Unable to commit");
1058 }
1059}