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_9 => write_txn.migrate_domain_8_to_9()?,
61 DOMAIN_LEVEL_10 => write_txn.migrate_domain_9_to_10()?,
62 DOMAIN_LEVEL_11 => write_txn.migrate_domain_10_to_11()?,
63 DOMAIN_LEVEL_12 => write_txn.migrate_domain_11_to_12()?,
64 DOMAIN_LEVEL_13 => write_txn.migrate_domain_12_to_13()?,
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 = "trace", skip_all)]
263 fn internal_migrate_or_create_ignore_attrs(
264 &mut self,
265 mut e: Entry<EntryInit, EntryNew>,
266 attrs: &[Attribute],
267 ) -> Result<(), OperationError> {
268 trace!("operating on {:?}", e.get_uuid());
269
270 let Some(filt) = e.filter_from_attrs(&[Attribute::Uuid]) else {
271 return Err(OperationError::FilterGeneration);
272 };
273
274 trace!("search {:?}", filt);
275
276 let results = self.internal_search(filt.clone())?;
277
278 if results.is_empty() {
279 self.internal_create(vec![e])
281 } else if results.len() == 1 {
282 for attr in attrs.iter() {
284 e.remove_ava(attr);
285 }
286
287 match e.gen_modlist_assert(&self.schema) {
289 Ok(modlist) => {
290 trace!(?modlist);
292 self.internal_modify(&filt, &modlist)
293 }
294 Err(e) => Err(OperationError::SchemaViolation(e)),
295 }
296 } else {
297 admin_error!(
298 "Invalid Result Set - Expected One Entry for {:?} - {:?}",
299 filt,
300 results
301 );
302 Err(OperationError::InvalidDbState)
303 }
304 }
305
306 #[instrument(level = "info", skip_all)]
308 pub(crate) fn migrate_domain_8_to_9(&mut self) -> Result<(), OperationError> {
309 if !cfg!(test) && DOMAIN_TGT_LEVEL < DOMAIN_LEVEL_9 {
310 error!("Unable to raise domain level from 8 to 9.");
311 return Err(OperationError::MG0004DomainLevelInDevelopment);
312 }
313
314 self.internal_migrate_or_create_batch(
316 "phase 1 - schema attrs",
317 migration_data::dl9::phase_1_schema_attrs(),
318 )?;
319
320 self.internal_migrate_or_create_batch(
321 "phase 2 - schema classes",
322 migration_data::dl9::phase_2_schema_classes(),
323 )?;
324
325 self.reload()?;
327
328 self.reindex(false)?;
330
331 self.set_phase(ServerPhase::SchemaReady);
333
334 self.internal_migrate_or_create_batch(
335 "phase 3 - key provider",
336 migration_data::dl9::phase_3_key_provider(),
337 )?;
338
339 self.reload()?;
341
342 self.internal_migrate_or_create_batch(
343 "phase 4 - system entries",
344 migration_data::dl9::phase_4_system_entries(),
345 )?;
346
347 self.reload()?;
349
350 self.set_phase(ServerPhase::DomainInfoReady);
352
353 self.internal_migrate_or_create_batch(
355 "phase 5 - builtin admin entries",
356 migration_data::dl9::phase_5_builtin_admin_entries()?,
357 )?;
358
359 self.internal_migrate_or_create_batch(
360 "phase 6 - builtin not admin entries",
361 migration_data::dl9::phase_6_builtin_non_admin_entries()?,
362 )?;
363
364 self.internal_migrate_or_create_batch(
365 "phase 7 - builtin access control profiles",
366 migration_data::dl9::phase_7_builtin_access_control_profiles(),
367 )?;
368
369 self.reload()?;
371
372 Ok(())
373 }
374
375 #[instrument(level = "info", skip_all)]
379 pub(crate) fn migrate_domain_patch_level_2(&mut self) -> Result<(), OperationError> {
380 admin_warn!("applying domain patch 2.");
381
382 debug_assert!(*self.phase >= ServerPhase::SchemaReady);
383
384 let idm_data = migration_data::dl9::phase_7_builtin_access_control_profiles();
385
386 idm_data
387 .into_iter()
388 .try_for_each(|entry| self.internal_migrate_or_create(entry))
389 .map_err(|err| {
390 error!(?err, "migrate_domain_patch_level_2 -> Error");
391 err
392 })?;
393
394 self.reload()?;
395
396 Ok(())
397 }
398
399 #[instrument(level = "info", skip_all)]
401 pub(crate) fn migrate_domain_9_to_10(&mut self) -> Result<(), OperationError> {
402 if !cfg!(test) && DOMAIN_TGT_LEVEL < DOMAIN_LEVEL_9 {
403 error!("Unable to raise domain level from 9 to 10.");
404 return Err(OperationError::MG0004DomainLevelInDevelopment);
405 }
406
407 self.internal_migrate_or_create_batch(
409 "phase 1 - schema attrs",
410 migration_data::dl10::phase_1_schema_attrs(),
411 )?;
412
413 self.internal_migrate_or_create_batch(
414 "phase 2 - schema classes",
415 migration_data::dl10::phase_2_schema_classes(),
416 )?;
417
418 self.reload()?;
420
421 self.reindex(false)?;
424
425 self.set_phase(ServerPhase::SchemaReady);
429
430 self.internal_migrate_or_create_batch(
431 "phase 3 - key provider",
432 migration_data::dl10::phase_3_key_provider(),
433 )?;
434
435 self.reload()?;
437
438 self.internal_migrate_or_create_batch(
439 "phase 4 - system entries",
440 migration_data::dl10::phase_4_system_entries(),
441 )?;
442
443 self.reload()?;
445
446 self.set_phase(ServerPhase::DomainInfoReady);
448
449 self.internal_migrate_or_create_batch(
451 "phase 5 - builtin admin entries",
452 migration_data::dl10::phase_5_builtin_admin_entries()?,
453 )?;
454
455 self.internal_migrate_or_create_batch(
456 "phase 6 - builtin not admin entries",
457 migration_data::dl10::phase_6_builtin_non_admin_entries()?,
458 )?;
459
460 self.internal_migrate_or_create_batch(
461 "phase 7 - builtin access control profiles",
462 migration_data::dl10::phase_7_builtin_access_control_profiles(),
463 )?;
464
465 self.reload()?;
466
467 debug!("START OAUTH2 MIGRATION");
470
471 let all_oauth2_rs_entries = self.internal_search(filter!(f_eq(
473 Attribute::Class,
474 EntryClass::OAuth2ResourceServer.into()
475 )))?;
476
477 if !all_oauth2_rs_entries.is_empty() {
478 let entry_iter = all_oauth2_rs_entries.iter().map(|tgt_entry| {
479 let entry_uuid = tgt_entry.get_uuid();
480 let mut modlist = ModifyList::new_list(vec![
481 Modify::Present(Attribute::Class, EntryClass::KeyObject.to_value()),
482 Modify::Present(Attribute::Class, EntryClass::KeyObjectJwtEs256.to_value()),
483 Modify::Present(Attribute::Class, EntryClass::KeyObjectJweA128GCM.to_value()),
484 Modify::Purged(Attribute::OAuth2RsTokenKey),
486 Modify::Purged(Attribute::Es256PrivateKeyDer),
487 Modify::Purged(Attribute::Rs256PrivateKeyDer),
488 ]);
489
490 trace!(?tgt_entry);
491
492 if let Some(es256_private_der) =
494 tgt_entry.get_ava_single_private_binary(Attribute::Es256PrivateKeyDer)
495 {
496 modlist.push_mod(Modify::Present(
497 Attribute::KeyActionImportJwsEs256,
498 Value::PrivateBinary(es256_private_der.to_vec()),
499 ))
500 } else {
501 warn!("Unable to migrate es256 key");
502 }
503
504 let has_rs256 = tgt_entry
505 .get_ava_single_bool(Attribute::OAuth2JwtLegacyCryptoEnable)
506 .unwrap_or(false);
507
508 if has_rs256 {
511 modlist.push_mod(Modify::Present(
512 Attribute::Class,
513 EntryClass::KeyObjectJwtEs256.to_value(),
514 ));
515
516 if let Some(rs256_private_der) =
517 tgt_entry.get_ava_single_private_binary(Attribute::Rs256PrivateKeyDer)
518 {
519 modlist.push_mod(Modify::Present(
520 Attribute::KeyActionImportJwsRs256,
521 Value::PrivateBinary(rs256_private_der.to_vec()),
522 ))
523 } else {
524 warn!("Unable to migrate rs256 key");
525 }
526 }
527
528 (entry_uuid, modlist)
529 });
530
531 self.internal_batch_modify(entry_iter)?;
532 }
533
534 self.reload()?;
536
537 Ok(())
540 }
541
542 #[instrument(level = "info", skip_all)]
544 pub(crate) fn migrate_domain_10_to_11(&mut self) -> Result<(), OperationError> {
545 if !cfg!(test) && DOMAIN_TGT_LEVEL < DOMAIN_LEVEL_10 {
546 error!("Unable to raise domain level from 10 to 11.");
547 return Err(OperationError::MG0004DomainLevelInDevelopment);
548 }
549
550 self.internal_migrate_or_create_batch(
552 "phase 1 - schema attrs",
553 migration_data::dl11::phase_1_schema_attrs(),
554 )?;
555
556 self.internal_migrate_or_create_batch(
557 "phase 2 - schema classes",
558 migration_data::dl11::phase_2_schema_classes(),
559 )?;
560
561 self.reload()?;
563
564 self.reindex(false)?;
567
568 self.set_phase(ServerPhase::SchemaReady);
572
573 self.internal_migrate_or_create_batch(
574 "phase 3 - key provider",
575 migration_data::dl11::phase_3_key_provider(),
576 )?;
577
578 self.reload()?;
580
581 self.internal_migrate_or_create_batch(
582 "phase 4 - system entries",
583 migration_data::dl11::phase_4_system_entries(),
584 )?;
585
586 self.reload()?;
588
589 self.set_phase(ServerPhase::DomainInfoReady);
591
592 self.internal_migrate_or_create_batch(
594 "phase 5 - builtin admin entries",
595 migration_data::dl11::phase_5_builtin_admin_entries()?,
596 )?;
597
598 self.internal_migrate_or_create_batch(
599 "phase 6 - builtin not admin entries",
600 migration_data::dl11::phase_6_builtin_non_admin_entries()?,
601 )?;
602
603 self.internal_migrate_or_create_batch(
604 "phase 7 - builtin access control profiles",
605 migration_data::dl11::phase_7_builtin_access_control_profiles(),
606 )?;
607
608 self.reload()?;
609
610 Ok(())
611 }
612
613 #[instrument(level = "info", skip_all)]
615 pub(crate) fn migrate_domain_11_to_12(&mut self) -> Result<(), OperationError> {
616 if !cfg!(test) && DOMAIN_TGT_LEVEL < DOMAIN_LEVEL_11 {
617 error!("Unable to raise domain level from 11 to 12.");
618 return Err(OperationError::MG0004DomainLevelInDevelopment);
619 }
620
621 self.internal_migrate_or_create_batch(
623 "phase 1 - schema attrs",
624 migration_data::dl12::phase_1_schema_attrs(),
625 )?;
626
627 self.internal_migrate_or_create_batch(
628 "phase 2 - schema classes",
629 migration_data::dl12::phase_2_schema_classes(),
630 )?;
631
632 self.reload()?;
634
635 self.reindex(false)?;
638
639 self.set_phase(ServerPhase::SchemaReady);
643
644 self.internal_migrate_or_create_batch(
645 "phase 3 - key provider",
646 migration_data::dl12::phase_3_key_provider(),
647 )?;
648
649 self.reload()?;
651
652 self.internal_migrate_or_create_batch(
653 "phase 4 - system entries",
654 migration_data::dl12::phase_4_system_entries(),
655 )?;
656
657 self.reload()?;
659
660 self.set_phase(ServerPhase::DomainInfoReady);
662
663 self.internal_migrate_or_create_batch(
665 "phase 5 - builtin admin entries",
666 migration_data::dl12::phase_5_builtin_admin_entries()?,
667 )?;
668
669 self.internal_migrate_or_create_batch(
670 "phase 6 - builtin not admin entries",
671 migration_data::dl12::phase_6_builtin_non_admin_entries()?,
672 )?;
673
674 self.internal_migrate_or_create_batch(
675 "phase 7 - builtin access control profiles",
676 migration_data::dl12::phase_7_builtin_access_control_profiles(),
677 )?;
678
679 self.reload()?;
680
681 let modlist = ModifyList::new_purge(Attribute::IdVerificationEcKey);
683 let filter = filter_all!(f_pres(Attribute::IdVerificationEcKey));
684
685 self.internal_modify(&filter, &modlist)?;
686
687 Ok(())
688 }
689
690 #[instrument(level = "info", skip_all)]
692 pub(crate) fn migrate_domain_12_to_13(&mut self) -> Result<(), OperationError> {
693 if !cfg!(test) && DOMAIN_TGT_LEVEL < DOMAIN_LEVEL_12 {
694 error!("Unable to raise domain level from 12 to 13.");
695 return Err(OperationError::MG0004DomainLevelInDevelopment);
696 }
697
698 Ok(())
699 }
700
701 #[instrument(level = "info", skip_all)]
702 pub(crate) fn initialise_schema_core(&mut self) -> Result<(), OperationError> {
703 admin_debug!("initialise_schema_core -> start ...");
704 let entries = self.schema.to_entries();
706
707 let r: Result<_, _> = entries.into_iter().try_for_each(|e| {
711 trace!(?e, "init schema entry");
712 self.internal_migrate_or_create(e)
713 });
714 if r.is_ok() {
715 admin_debug!("initialise_schema_core -> Ok!");
716 } else {
717 admin_error!(?r, "initialise_schema_core -> Error");
718 }
719 debug_assert!(r.is_ok());
721 r
722 }
723}
724
725impl QueryServerReadTransaction<'_> {
726 pub fn domain_upgrade_check(
728 &mut self,
729 ) -> Result<ProtoDomainUpgradeCheckReport, OperationError> {
730 let d_info = &self.d_info;
731
732 let name = d_info.d_name.clone();
733 let uuid = d_info.d_uuid;
734 let current_level = d_info.d_vers;
735 let upgrade_level = DOMAIN_TGT_NEXT_LEVEL;
736
737 let mut report_items = Vec::with_capacity(1);
738
739 if current_level <= DOMAIN_LEVEL_7 && upgrade_level >= DOMAIN_LEVEL_8 {
740 let item = self
741 .domain_upgrade_check_7_to_8_security_keys()
742 .map_err(|err| {
743 error!(
744 ?err,
745 "Failed to perform domain upgrade check 7 to 8 - security-keys"
746 );
747 err
748 })?;
749 report_items.push(item);
750
751 let item = self
752 .domain_upgrade_check_7_to_8_oauth2_strict_redirect_uri()
753 .map_err(|err| {
754 error!(
755 ?err,
756 "Failed to perform domain upgrade check 7 to 8 - oauth2-strict-redirect_uri"
757 );
758 err
759 })?;
760 report_items.push(item);
761 }
762
763 Ok(ProtoDomainUpgradeCheckReport {
764 name,
765 uuid,
766 current_level,
767 upgrade_level,
768 report_items,
769 })
770 }
771
772 pub(crate) fn domain_upgrade_check_7_to_8_security_keys(
773 &mut self,
774 ) -> Result<ProtoDomainUpgradeCheckItem, OperationError> {
775 let filter = filter!(f_and!([
776 f_eq(Attribute::Class, EntryClass::Account.into()),
777 f_pres(Attribute::PrimaryCredential),
778 ]));
779
780 let results = self.internal_search(filter)?;
781
782 let affected_entries = results
783 .into_iter()
784 .filter_map(|entry| {
785 if entry
786 .get_ava_single_credential(Attribute::PrimaryCredential)
787 .map(|cred| cred.has_securitykey())
788 .unwrap_or_default()
789 {
790 Some(entry.get_display_id())
791 } else {
792 None
793 }
794 })
795 .collect::<Vec<_>>();
796
797 let status = if affected_entries.is_empty() {
798 ProtoDomainUpgradeCheckStatus::Pass7To8SecurityKeys
799 } else {
800 ProtoDomainUpgradeCheckStatus::Fail7To8SecurityKeys
801 };
802
803 Ok(ProtoDomainUpgradeCheckItem {
804 status,
805 from_level: DOMAIN_LEVEL_7,
806 to_level: DOMAIN_LEVEL_8,
807 affected_entries,
808 })
809 }
810
811 pub(crate) fn domain_upgrade_check_7_to_8_oauth2_strict_redirect_uri(
812 &mut self,
813 ) -> Result<ProtoDomainUpgradeCheckItem, OperationError> {
814 let filter = filter!(f_and!([
815 f_eq(Attribute::Class, EntryClass::OAuth2ResourceServer.into()),
816 f_andnot(f_pres(Attribute::OAuth2StrictRedirectUri)),
817 ]));
818
819 let results = self.internal_search(filter)?;
820
821 let affected_entries = results
822 .into_iter()
823 .map(|entry| entry.get_display_id())
824 .collect::<Vec<_>>();
825
826 let status = if affected_entries.is_empty() {
827 ProtoDomainUpgradeCheckStatus::Pass7To8Oauth2StrictRedirectUri
828 } else {
829 ProtoDomainUpgradeCheckStatus::Fail7To8Oauth2StrictRedirectUri
830 };
831
832 Ok(ProtoDomainUpgradeCheckItem {
833 status,
834 from_level: DOMAIN_LEVEL_7,
835 to_level: DOMAIN_LEVEL_8,
836 affected_entries,
837 })
838 }
839}
840
841#[cfg(test)]
842mod tests {
843 use crate::prelude::*;
845
846 #[qs_test]
847 async fn test_init_idempotent_schema_core(server: &QueryServer) {
848 {
849 let mut server_txn = server.write(duration_from_epoch_now()).await.unwrap();
851 assert!(server_txn.initialise_schema_core().is_ok());
852 }
853 {
854 let mut server_txn = server.write(duration_from_epoch_now()).await.unwrap();
855 assert!(server_txn.initialise_schema_core().is_ok());
856 assert!(server_txn.initialise_schema_core().is_ok());
857 assert!(server_txn.commit().is_ok());
858 }
859 {
860 let mut server_txn = server.write(duration_from_epoch_now()).await.unwrap();
862 assert!(server_txn.initialise_schema_core().is_ok());
863 }
864 {
865 let mut server_txn = server.write(duration_from_epoch_now()).await.unwrap();
867 assert!(server_txn.initialise_schema_core().is_ok());
868 assert!(server_txn.commit().is_ok());
869 }
870 }
871
872 #[qs_test(domain_level=DOMAIN_LEVEL_9)]
873 async fn test_migrations_dl9_dl10(server: &QueryServer) {
874 let mut write_txn = server.write(duration_from_epoch_now()).await.unwrap();
875
876 let db_domain_version = write_txn
877 .internal_search_uuid(UUID_DOMAIN_INFO)
878 .expect("unable to access domain entry")
879 .get_ava_single_uint32(Attribute::Version)
880 .expect("Attribute Version not present");
881
882 assert_eq!(db_domain_version, DOMAIN_LEVEL_9);
883
884 write_txn.commit().expect("Unable to commit");
885
886 let mut write_txn = server.write(duration_from_epoch_now()).await.unwrap();
893
894 write_txn
898 .internal_apply_domain_migration(DOMAIN_LEVEL_10)
899 .expect("Unable to set domain level to version 10");
900
901 write_txn.commit().expect("Unable to commit");
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}