1use std::collections::BTreeSet;
19#[cfg(test)]
20use std::sync::Arc;
21
22use kanidm_proto::internal::{
23 CreateRequest, DeleteRequest, ModifyList as ProtoModifyList, ModifyRequest, OperationError,
24 SearchRequest, SearchResponse,
25};
26use kanidm_proto::v1::{Entry as ProtoEntry, WhoamiResponse};
27use ldap3_proto::simple::LdapFilter;
28use uuid::Uuid;
29
30use crate::entry::{Entry, EntryCommitted, EntryInit, EntryNew, EntryReduced};
31use crate::filter::{Filter, FilterInvalid, FilterValid};
32use crate::modify::{ModifyInvalid, ModifyList, ModifyValid};
33use crate::prelude::*;
34use crate::schema::SchemaTransaction;
35use crate::value::PartialValue;
36
37#[derive(Debug)]
38pub struct SearchResult {
39 entries: Vec<ProtoEntry>,
40}
41
42impl SearchResult {
43 pub fn new(
44 qs: &mut QueryServerReadTransaction,
45 entries: &[Entry<EntryReduced, EntryCommitted>],
46 ) -> Result<Self, OperationError> {
47 let entries: Result<_, _> = entries
48 .iter()
49 .map(|e| {
50 e.to_pe(qs)
54 })
55 .collect();
56 Ok(SearchResult { entries: entries? })
57 }
58
59 pub fn response(self) -> SearchResponse {
61 SearchResponse {
62 entries: self.entries,
63 }
64 }
65
66 pub fn into_proto_array(self) -> Vec<ProtoEntry> {
68 self.entries
69 }
70}
71
72#[derive(Debug)]
73pub struct SearchEvent {
74 pub ident: Identity,
75 pub filter: Filter<FilterValid>,
77 pub filter_orig: Filter<FilterValid>,
79 pub attrs: Option<BTreeSet<Attribute>>,
80 pub effective_access_check: bool,
81}
82
83impl SearchEvent {
84 pub fn from_message(
85 ident: Identity,
86 req: &SearchRequest,
87 qs: &mut QueryServerReadTransaction,
88 ) -> Result<Self, OperationError> {
89 let f = Filter::from_ro(&ident, &req.filter, qs)?;
90 let filter_orig = f
93 .validate(qs.get_schema())
94 .map_err(OperationError::SchemaViolation)?;
95 let filter = filter_orig.clone().into_ignore_hidden();
96 Ok(SearchEvent {
97 ident,
98 filter,
99 filter_orig,
100 attrs: None,
103 effective_access_check: false,
104 })
105 }
106
107 pub fn from_internal_message(
108 ident: Identity,
109 filter: &Filter<FilterInvalid>,
110 attrs: Option<&[String]>,
111 qs: &mut QueryServerReadTransaction,
112 ) -> Result<Self, OperationError> {
113 let r_attrs: Option<BTreeSet<Attribute>> = attrs.map(|vs| {
114 vs.iter()
115 .filter_map(|a| qs.get_schema().normalise_attr_if_exists(a.as_str()))
116 .collect()
117 });
118
119 if let Some(s) = &r_attrs {
120 if s.is_empty() {
121 request_error!("EmptyRequest for attributes");
122 return Err(OperationError::EmptyRequest);
123 }
124 }
125
126 let filter_orig = filter.validate(qs.get_schema()).map_err(|e| {
127 request_error!(?e, "filter schema violation");
128 OperationError::SchemaViolation(e)
129 })?;
130 let filter = filter_orig.clone().into_ignore_hidden();
131
132 Ok(SearchEvent {
133 ident,
134 filter,
135 filter_orig,
136 attrs: r_attrs,
137 effective_access_check: false,
138 })
139 }
140
141 pub fn from_internal_recycle_message(
142 ident: Identity,
143 filter: &Filter<FilterInvalid>,
144 attrs: Option<&[String]>,
145 qs: &QueryServerReadTransaction,
146 ) -> Result<Self, OperationError> {
147 let r_attrs: Option<BTreeSet<Attribute>> = attrs.map(|vs| {
148 vs.iter()
149 .filter_map(|a| {
150 qs.get_schema()
151 .normalise_attr_if_exists(a.as_str())
152 .map(|a_str| Attribute::from(a_str.as_str()))
153 })
154 .collect()
155 });
156
157 if let Some(s) = &r_attrs {
158 if s.is_empty() {
159 return Err(OperationError::EmptyRequest);
160 }
161 }
162
163 let filter_orig = filter
164 .validate(qs.get_schema())
165 .map(|f| f.into_recycled())
166 .map_err(OperationError::SchemaViolation)?;
167 let filter = filter_orig.clone();
168
169 Ok(SearchEvent {
170 ident,
171 filter,
172 filter_orig,
173 attrs: r_attrs,
174 effective_access_check: false,
175 })
176 }
177
178 pub fn from_whoami_request(
179 ident: Identity,
180 qs: &QueryServerReadTransaction,
181 ) -> Result<Self, OperationError> {
182 let filter_orig = filter_all!(f_self())
183 .validate(qs.get_schema())
184 .map_err(OperationError::SchemaViolation)?;
185 let filter = filter_orig.clone().into_ignore_hidden();
186
187 Ok(SearchEvent {
188 ident,
189 filter,
190 filter_orig,
191 attrs: None,
192 effective_access_check: false,
193 })
194 }
195
196 pub fn from_target_uuid_request(
197 ident: Identity,
198 target_uuid: Uuid,
199 qs: &QueryServerReadTransaction,
200 ) -> Result<Self, OperationError> {
201 let filter_orig = filter_all!(f_eq(Attribute::Uuid, PartialValue::Uuid(target_uuid)))
202 .validate(qs.get_schema())
203 .map_err(OperationError::SchemaViolation)?;
204 let filter = filter_orig.clone().into_ignore_hidden();
205 Ok(SearchEvent {
206 ident,
207 filter,
208 filter_orig,
209 attrs: None,
210 effective_access_check: false,
211 })
212 }
213
214 #[cfg(test)]
217 pub fn new_impersonate_entry(
218 e: Arc<Entry<EntrySealed, EntryCommitted>>,
219 filter: Filter<FilterInvalid>,
220 ) -> Self {
221 SearchEvent {
222 ident: Identity::from_impersonate_entry_readonly(e),
223 filter: filter.clone().into_valid(),
224 filter_orig: filter.into_valid(),
225 attrs: None,
226 effective_access_check: false,
227 }
228 }
229
230 #[cfg(test)]
233 pub fn new_impersonate_identity(ident: Identity, filter: Filter<FilterInvalid>) -> Self {
234 SearchEvent {
235 ident,
236 filter: filter.clone().into_valid(),
237 filter_orig: filter.into_valid(),
238 attrs: None,
239 effective_access_check: false,
240 }
241 }
242
243 pub fn new_impersonate(
244 ident: &Identity,
245 filter: Filter<FilterValid>,
246 filter_orig: Filter<FilterValid>,
247 ) -> Self {
248 SearchEvent {
249 ident: Identity::from_impersonate(ident),
250 filter,
251 filter_orig,
252 attrs: None,
253 effective_access_check: false,
254 }
255 }
256
257 #[cfg(test)]
260 pub fn new_rec_impersonate_entry(
261 e: Arc<Entry<EntrySealed, EntryCommitted>>,
262 filter: Filter<FilterInvalid>,
263 ) -> Self {
264 let filter_orig = filter.into_valid();
266 let filter = filter_orig.clone().into_recycled();
267 SearchEvent {
268 ident: Identity::from_impersonate_entry_readonly(e),
269 filter,
270 filter_orig,
271 attrs: None,
272 effective_access_check: false,
273 }
274 }
275
276 #[cfg(test)]
279 pub fn new_ext_impersonate_entry(
280 e: Arc<Entry<EntrySealed, EntryCommitted>>,
281 filter: Filter<FilterInvalid>,
282 ) -> Self {
283 SearchEvent {
285 ident: Identity::from_impersonate_entry_readonly(e),
286 filter: filter.clone().into_valid().into_ignore_hidden(),
287 filter_orig: filter.into_valid(),
288 attrs: None,
289 effective_access_check: false,
290 }
291 }
292
293 pub(crate) fn new_ext_impersonate_uuid(
294 qs: &mut QueryServerReadTransaction,
295 ident: Identity,
296 lf: &LdapFilter,
297 attrs: Option<BTreeSet<Attribute>>,
298 ) -> Result<Self, OperationError> {
299 let f = Filter::from_ldap_ro(&ident, lf, qs)?;
301 let filter_orig = f
302 .validate(qs.get_schema())
303 .map_err(OperationError::SchemaViolation)?;
304 let filter = filter_orig.clone().into_ignore_hidden();
305 Ok(SearchEvent {
306 ident,
307 filter,
308 filter_orig,
309 attrs,
310 effective_access_check: false,
311 })
312 }
313
314 #[cfg(test)]
317 pub fn new_internal_invalid(filter: Filter<FilterInvalid>) -> Self {
318 SearchEvent {
319 ident: Identity::from_internal(),
320 filter: filter.clone().into_valid(),
321 filter_orig: filter.into_valid(),
322 attrs: None,
323 effective_access_check: false,
324 }
325 }
326
327 pub fn new_internal(filter: Filter<FilterValid>) -> Self {
328 SearchEvent {
329 ident: Identity::from_internal(),
330 filter: filter.clone(),
331 filter_orig: filter,
332 attrs: None,
333 effective_access_check: false,
334 }
335 }
336}
337
338#[derive(Debug)]
342pub struct CreateEvent {
343 pub ident: Identity,
344 pub entries: Vec<Entry<EntryInit, EntryNew>>,
347 pub return_created_uuids: bool,
351}
352
353impl CreateEvent {
354 pub fn from_message(
355 ident: Identity,
356 req: &CreateRequest,
357 qs: &mut QueryServerWriteTransaction,
358 ) -> Result<Self, OperationError> {
359 let rentries: Result<Vec<_>, _> = req
360 .entries
361 .iter()
362 .map(|e| Entry::from_proto_entry(e, qs))
363 .collect();
364 match rentries {
368 Ok(entries) => Ok(CreateEvent {
369 ident,
370 entries,
371 return_created_uuids: false,
372 }),
373 Err(e) => Err(e),
374 }
375 }
376
377 pub fn new_impersonate_identity(
378 ident: Identity,
379 entries: Vec<Entry<EntryInit, EntryNew>>,
380 ) -> Self {
381 CreateEvent {
382 ident,
383 entries,
384 return_created_uuids: false,
385 }
386 }
387
388 pub fn new_internal(entries: Vec<Entry<EntryInit, EntryNew>>) -> Self {
389 CreateEvent {
390 ident: Identity::from_internal(),
391 entries,
392 return_created_uuids: false,
393 }
394 }
395}
396
397#[derive(Debug)]
398pub struct ExistsEvent {
399 pub ident: Identity,
400 pub filter: Filter<FilterValid>,
402 pub filter_orig: Filter<FilterValid>,
404}
405
406impl ExistsEvent {
407 pub fn new_internal(filter: Filter<FilterValid>) -> Self {
408 ExistsEvent {
409 ident: Identity::from_internal(),
410 filter: filter.clone(),
411 filter_orig: filter,
412 }
413 }
414
415 #[cfg(test)]
418 pub fn new_internal_invalid(filter: Filter<FilterInvalid>) -> Self {
419 ExistsEvent {
420 ident: Identity::from_internal(),
421 filter: filter.clone().into_valid(),
422 filter_orig: filter.into_valid(),
423 }
424 }
425}
426
427#[derive(Debug)]
428pub struct DeleteEvent {
429 pub ident: Identity,
430 pub filter: Filter<FilterValid>,
432 pub filter_orig: Filter<FilterValid>,
434}
435
436impl DeleteEvent {
437 pub fn from_message(
438 ident: Identity,
439 req: &DeleteRequest,
440 qs: &mut QueryServerWriteTransaction,
441 ) -> Result<Self, OperationError> {
442 let f = Filter::from_rw(&ident, &req.filter, qs)?;
443 let filter_orig = f
444 .validate(qs.get_schema())
445 .map_err(OperationError::SchemaViolation)?;
446 let filter = filter_orig.clone().into_ignore_hidden();
447 Ok(DeleteEvent {
448 ident,
449 filter,
450 filter_orig,
451 })
452 }
453
454 pub fn from_parts(
455 ident: Identity,
456 f: &Filter<FilterInvalid>,
457 qs: &mut QueryServerWriteTransaction,
458 ) -> Result<Self, OperationError> {
459 let filter_orig = f
460 .validate(qs.get_schema())
461 .map_err(OperationError::SchemaViolation)?;
462 let filter = filter_orig.clone().into_ignore_hidden();
463 Ok(DeleteEvent {
464 ident,
465 filter,
466 filter_orig,
467 })
468 }
469
470 #[cfg(test)]
473 pub fn new_impersonate_entry(
474 e: Arc<Entry<EntrySealed, EntryCommitted>>,
475 filter: Filter<FilterInvalid>,
476 ) -> Self {
477 DeleteEvent {
478 ident: Identity::from_impersonate_entry_readwrite(e),
479 filter: filter.clone().into_valid(),
480 filter_orig: filter.into_valid(),
481 }
482 }
483
484 #[cfg(test)]
487 pub fn new_impersonate_identity(ident: Identity, filter: Filter<FilterInvalid>) -> Self {
488 DeleteEvent {
489 ident,
490 filter: filter.clone().into_valid(),
491 filter_orig: filter.into_valid(),
492 }
493 }
494
495 #[cfg(test)]
498 pub fn new_internal_invalid(filter: Filter<FilterInvalid>) -> Self {
499 DeleteEvent {
500 ident: Identity::from_internal(),
501 filter: filter.clone().into_valid(),
502 filter_orig: filter.into_valid(),
503 }
504 }
505
506 pub fn new_internal(filter: Filter<FilterValid>) -> Self {
507 DeleteEvent {
508 ident: Identity::from_internal(),
509 filter: filter.clone(),
510 filter_orig: filter,
511 }
512 }
513}
514
515#[derive(Debug)]
516pub struct ModifyEvent {
517 pub ident: Identity,
518 pub filter: Filter<FilterValid>,
520 pub filter_orig: Filter<FilterValid>,
522 pub modlist: ModifyList<ModifyValid>,
523}
524
525impl ModifyEvent {
526 pub fn from_message(
527 ident: Identity,
528 req: &ModifyRequest,
529 qs: &mut QueryServerWriteTransaction,
530 ) -> Result<Self, OperationError> {
531 let f = Filter::from_rw(&ident, &req.filter, qs)?;
532 let m = ModifyList::from(&req.modlist, qs)?;
533 let filter_orig = f
534 .validate(qs.get_schema())
535 .map_err(OperationError::SchemaViolation)?;
536 let filter = filter_orig.clone().into_ignore_hidden();
537 let modlist = m
538 .validate(qs.get_schema())
539 .map_err(OperationError::SchemaViolation)?;
540 Ok(ModifyEvent {
541 ident,
542 filter,
543 filter_orig,
544 modlist,
545 })
546 }
547
548 pub fn from_parts(
549 ident: Identity,
550 target_uuid: Uuid,
551 proto_ml: &ProtoModifyList,
552 filter: Filter<FilterInvalid>,
553 qs: &mut QueryServerWriteTransaction,
554 ) -> Result<Self, OperationError> {
555 let f_uuid = filter_all!(f_eq(Attribute::Uuid, PartialValue::Uuid(target_uuid)));
556 let f = Filter::join_parts_and(f_uuid, filter);
558
559 let m = ModifyList::from(proto_ml, qs)?;
560 let filter_orig = f
561 .validate(qs.get_schema())
562 .map_err(OperationError::SchemaViolation)?;
563 let filter = filter_orig.clone().into_ignore_hidden();
564 let modlist = m
565 .validate(qs.get_schema())
566 .map_err(OperationError::SchemaViolation)?;
567
568 Ok(ModifyEvent {
569 ident,
570 filter,
571 filter_orig,
572 modlist,
573 })
574 }
575
576 pub fn from_internal_parts(
577 ident: Identity,
578 ml: &ModifyList<ModifyInvalid>,
579 filter: &Filter<FilterInvalid>,
580 qs: &QueryServerWriteTransaction,
581 ) -> Result<Self, OperationError> {
582 let filter_orig = filter
583 .validate(qs.get_schema())
584 .map_err(OperationError::SchemaViolation)?;
585 let filter = filter_orig.clone().into_ignore_hidden();
586 let modlist = ml
587 .validate(qs.get_schema())
588 .map_err(OperationError::SchemaViolation)?;
589
590 Ok(ModifyEvent {
591 ident,
592 filter,
593 filter_orig,
594 modlist,
595 })
596 }
597
598 pub fn from_target_uuid_attr_purge(
599 ident: Identity,
600 target_uuid: Uuid,
601 attr: Attribute,
602 filter: Filter<FilterInvalid>,
603 qs: &QueryServerWriteTransaction,
604 ) -> Result<Self, OperationError> {
605 let ml = ModifyList::new_purge(attr);
606 let f_uuid = filter_all!(f_eq(Attribute::Uuid, PartialValue::Uuid(target_uuid)));
607 let f = Filter::join_parts_and(f_uuid, filter);
609
610 let filter_orig = f
611 .validate(qs.get_schema())
612 .map_err(OperationError::SchemaViolation)?;
613 let filter = filter_orig.clone().into_ignore_hidden();
614 let modlist = ml
615 .validate(qs.get_schema())
616 .map_err(OperationError::SchemaViolation)?;
617 Ok(ModifyEvent {
618 ident,
619 filter,
620 filter_orig,
621 modlist,
622 })
623 }
624
625 pub fn new_internal(filter: Filter<FilterValid>, modlist: ModifyList<ModifyValid>) -> Self {
626 ModifyEvent {
627 ident: Identity::from_internal(),
628 filter: filter.clone(),
629 filter_orig: filter,
630 modlist,
631 }
632 }
633
634 #[cfg(test)]
637 pub fn new_internal_invalid(
638 filter: Filter<FilterInvalid>,
639 modlist: ModifyList<ModifyInvalid>,
640 ) -> Self {
641 ModifyEvent {
642 ident: Identity::from_internal(),
643 filter: filter.clone().into_valid(),
644 filter_orig: filter.into_valid(),
645 modlist: modlist.into_valid(),
646 }
647 }
648
649 #[cfg(test)]
652 pub fn new_impersonate_identity(
653 ident: Identity,
654 filter: Filter<FilterInvalid>,
655 modlist: ModifyList<ModifyInvalid>,
656 ) -> Self {
657 ModifyEvent {
658 ident,
659 filter: filter.clone().into_valid(),
660 filter_orig: filter.into_valid(),
661 modlist: modlist.into_valid(),
662 }
663 }
664
665 #[cfg(test)]
668 pub fn new_impersonate_entry(
669 e: Arc<Entry<EntrySealed, EntryCommitted>>,
670 filter: Filter<FilterInvalid>,
671 modlist: ModifyList<ModifyInvalid>,
672 ) -> Self {
673 ModifyEvent {
674 ident: Identity::from_impersonate_entry_readwrite(e),
675 filter: filter.clone().into_valid(),
676 filter_orig: filter.into_valid(),
677 modlist: modlist.into_valid(),
678 }
679 }
680
681 pub fn new_impersonate(
682 ident: &Identity,
683 filter: Filter<FilterValid>,
684 filter_orig: Filter<FilterValid>,
685 modlist: ModifyList<ModifyValid>,
686 ) -> Self {
687 ModifyEvent {
688 ident: Identity::from_impersonate(ident),
689 filter,
690 filter_orig,
691 modlist,
692 }
693 }
694}
695
696pub struct WhoamiResult {
697 youare: ProtoEntry,
698}
699
700impl WhoamiResult {
701 pub fn new(
702 qs: &mut QueryServerReadTransaction,
703 e: &Entry<EntryReduced, EntryCommitted>,
704 ) -> Result<Self, OperationError> {
705 Ok(WhoamiResult {
706 youare: e.to_pe(qs)?,
707 })
708 }
709
710 pub fn response(self) -> WhoamiResponse {
711 WhoamiResponse {
712 youare: self.youare,
713 }
714 }
715}
716
717#[derive(Debug)]
718pub struct PurgeTombstoneEvent {
719 pub ident: Identity,
720 pub eventid: Uuid,
721}
722
723impl Default for PurgeTombstoneEvent {
724 fn default() -> Self {
725 Self::new()
726 }
727}
728
729impl PurgeTombstoneEvent {
730 pub fn new() -> Self {
731 PurgeTombstoneEvent {
732 ident: Identity::from_internal(),
733 eventid: Uuid::new_v4(),
734 }
735 }
736}
737
738#[derive(Debug)]
739pub struct PurgeRecycledEvent {
740 pub ident: Identity,
741 pub eventid: Uuid,
742}
743
744impl Default for PurgeRecycledEvent {
745 fn default() -> Self {
746 Self::new()
747 }
748}
749
750impl PurgeRecycledEvent {
751 pub fn new() -> Self {
752 PurgeRecycledEvent {
753 ident: Identity::from_internal(),
754 eventid: Uuid::new_v4(),
755 }
756 }
757}
758
759#[derive(Debug)]
760pub struct PurgeDeleteAfterEvent {
761 pub ident: Identity,
762 pub eventid: Uuid,
763}
764
765impl Default for PurgeDeleteAfterEvent {
766 fn default() -> Self {
767 Self::new()
768 }
769}
770
771impl PurgeDeleteAfterEvent {
772 pub fn new() -> Self {
773 PurgeDeleteAfterEvent {
774 ident: Identity::from_internal(),
775 eventid: Uuid::new_v4(),
776 }
777 }
778}
779
780#[derive(Debug)]
781pub struct OnlineBackupEvent {
782 pub ident: Identity,
783 pub eventid: Uuid,
784}
785
786impl Default for OnlineBackupEvent {
787 fn default() -> Self {
788 Self::new()
789 }
790}
791
792impl OnlineBackupEvent {
793 pub fn new() -> Self {
794 OnlineBackupEvent {
795 ident: Identity::from_internal(),
796 eventid: Uuid::new_v4(),
797 }
798 }
799}
800
801#[derive(Debug)]
802pub struct ReviveRecycledEvent {
803 pub ident: Identity,
804 pub filter: Filter<FilterValid>,
806 }
811
812impl ReviveRecycledEvent {
813 pub fn from_parts(
814 ident: Identity,
815 filter: &Filter<FilterInvalid>,
816 qs: &QueryServerWriteTransaction,
817 ) -> Result<Self, OperationError> {
818 let filter = filter
819 .validate(qs.get_schema())
820 .map(|f| f.into_recycled())
821 .map_err(OperationError::SchemaViolation)?;
822 Ok(ReviveRecycledEvent { ident, filter })
823 }
824
825 #[cfg(test)]
828 pub fn new_impersonate_entry(
829 e: Arc<Entry<EntrySealed, EntryCommitted>>,
830 filter: Filter<FilterInvalid>,
831 ) -> Self {
832 ReviveRecycledEvent {
833 ident: Identity::from_impersonate_entry_readwrite(e),
834 filter: filter.into_valid(),
835 }
836 }
837
838 #[cfg(test)]
839 pub(crate) fn new_internal(filter: Filter<FilterValid>) -> Self {
840 ReviveRecycledEvent {
841 ident: Identity::from_internal(),
842 filter,
843 }
844 }
845}