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 #[cfg(test)]
378 pub fn new_impersonate_identity(
379 ident: Identity,
380 entries: Vec<Entry<EntryInit, EntryNew>>,
381 ) -> Self {
382 CreateEvent {
383 ident,
384 entries,
385 return_created_uuids: false,
386 }
387 }
388
389 pub fn new_internal(entries: Vec<Entry<EntryInit, EntryNew>>) -> Self {
390 CreateEvent {
391 ident: Identity::from_internal(),
392 entries,
393 return_created_uuids: false,
394 }
395 }
396}
397
398#[derive(Debug)]
399pub struct ExistsEvent {
400 pub ident: Identity,
401 pub filter: Filter<FilterValid>,
403 pub filter_orig: Filter<FilterValid>,
405}
406
407impl ExistsEvent {
408 pub fn new_internal(filter: Filter<FilterValid>) -> Self {
409 ExistsEvent {
410 ident: Identity::from_internal(),
411 filter: filter.clone(),
412 filter_orig: filter,
413 }
414 }
415
416 #[cfg(test)]
419 pub fn new_internal_invalid(filter: Filter<FilterInvalid>) -> Self {
420 ExistsEvent {
421 ident: Identity::from_internal(),
422 filter: filter.clone().into_valid(),
423 filter_orig: filter.into_valid(),
424 }
425 }
426}
427
428#[derive(Debug)]
429pub struct DeleteEvent {
430 pub ident: Identity,
431 pub filter: Filter<FilterValid>,
433 pub filter_orig: Filter<FilterValid>,
435}
436
437impl DeleteEvent {
438 pub fn from_message(
439 ident: Identity,
440 req: &DeleteRequest,
441 qs: &mut QueryServerWriteTransaction,
442 ) -> Result<Self, OperationError> {
443 let f = Filter::from_rw(&ident, &req.filter, qs)?;
444 let filter_orig = f
445 .validate(qs.get_schema())
446 .map_err(OperationError::SchemaViolation)?;
447 let filter = filter_orig.clone().into_ignore_hidden();
448 Ok(DeleteEvent {
449 ident,
450 filter,
451 filter_orig,
452 })
453 }
454
455 pub fn from_parts(
456 ident: Identity,
457 f: &Filter<FilterInvalid>,
458 qs: &mut QueryServerWriteTransaction,
459 ) -> Result<Self, OperationError> {
460 let filter_orig = f
461 .validate(qs.get_schema())
462 .map_err(OperationError::SchemaViolation)?;
463 let filter = filter_orig.clone().into_ignore_hidden();
464 Ok(DeleteEvent {
465 ident,
466 filter,
467 filter_orig,
468 })
469 }
470
471 #[cfg(test)]
474 pub fn new_impersonate_entry(
475 e: Arc<Entry<EntrySealed, EntryCommitted>>,
476 filter: Filter<FilterInvalid>,
477 ) -> Self {
478 DeleteEvent {
479 ident: Identity::from_impersonate_entry_readwrite(e),
480 filter: filter.clone().into_valid(),
481 filter_orig: filter.into_valid(),
482 }
483 }
484
485 #[cfg(test)]
488 pub fn new_impersonate_identity(ident: Identity, filter: Filter<FilterInvalid>) -> Self {
489 DeleteEvent {
490 ident,
491 filter: filter.clone().into_valid(),
492 filter_orig: filter.into_valid(),
493 }
494 }
495
496 #[cfg(test)]
499 pub fn new_internal_invalid(filter: Filter<FilterInvalid>) -> Self {
500 DeleteEvent {
501 ident: Identity::from_internal(),
502 filter: filter.clone().into_valid(),
503 filter_orig: filter.into_valid(),
504 }
505 }
506
507 pub fn new_internal(filter: Filter<FilterValid>) -> Self {
508 DeleteEvent {
509 ident: Identity::from_internal(),
510 filter: filter.clone(),
511 filter_orig: filter,
512 }
513 }
514}
515
516#[derive(Debug)]
517pub struct ModifyEvent {
518 pub ident: Identity,
519 pub filter: Filter<FilterValid>,
521 pub filter_orig: Filter<FilterValid>,
523 pub modlist: ModifyList<ModifyValid>,
524}
525
526impl ModifyEvent {
527 pub fn from_message(
528 ident: Identity,
529 req: &ModifyRequest,
530 qs: &mut QueryServerWriteTransaction,
531 ) -> Result<Self, OperationError> {
532 let f = Filter::from_rw(&ident, &req.filter, qs)?;
533 let m = ModifyList::from(&req.modlist, qs)?;
534 let filter_orig = f
535 .validate(qs.get_schema())
536 .map_err(OperationError::SchemaViolation)?;
537 let filter = filter_orig.clone().into_ignore_hidden();
538 let modlist = m
539 .validate(qs.get_schema())
540 .map_err(OperationError::SchemaViolation)?;
541 Ok(ModifyEvent {
542 ident,
543 filter,
544 filter_orig,
545 modlist,
546 })
547 }
548
549 pub fn from_parts(
550 ident: Identity,
551 target_uuid: Uuid,
552 proto_ml: &ProtoModifyList,
553 filter: Filter<FilterInvalid>,
554 qs: &mut QueryServerWriteTransaction,
555 ) -> Result<Self, OperationError> {
556 let f_uuid = filter_all!(f_eq(Attribute::Uuid, PartialValue::Uuid(target_uuid)));
557 let f = Filter::join_parts_and(f_uuid, filter);
559
560 let m = ModifyList::from(proto_ml, qs)?;
561 let filter_orig = f
562 .validate(qs.get_schema())
563 .map_err(OperationError::SchemaViolation)?;
564 let filter = filter_orig.clone().into_ignore_hidden();
565 let modlist = m
566 .validate(qs.get_schema())
567 .map_err(OperationError::SchemaViolation)?;
568
569 Ok(ModifyEvent {
570 ident,
571 filter,
572 filter_orig,
573 modlist,
574 })
575 }
576
577 pub fn from_internal_parts(
578 ident: Identity,
579 ml: &ModifyList<ModifyInvalid>,
580 filter: &Filter<FilterInvalid>,
581 qs: &QueryServerWriteTransaction,
582 ) -> Result<Self, OperationError> {
583 let filter_orig = filter
584 .validate(qs.get_schema())
585 .map_err(OperationError::SchemaViolation)?;
586 let filter = filter_orig.clone().into_ignore_hidden();
587 let modlist = ml
588 .validate(qs.get_schema())
589 .map_err(OperationError::SchemaViolation)?;
590
591 Ok(ModifyEvent {
592 ident,
593 filter,
594 filter_orig,
595 modlist,
596 })
597 }
598
599 pub fn from_target_uuid_attr_purge(
600 ident: Identity,
601 target_uuid: Uuid,
602 attr: Attribute,
603 filter: Filter<FilterInvalid>,
604 qs: &QueryServerWriteTransaction,
605 ) -> Result<Self, OperationError> {
606 let ml = ModifyList::new_purge(attr);
607 let f_uuid = filter_all!(f_eq(Attribute::Uuid, PartialValue::Uuid(target_uuid)));
608 let f = Filter::join_parts_and(f_uuid, filter);
610
611 let filter_orig = f
612 .validate(qs.get_schema())
613 .map_err(OperationError::SchemaViolation)?;
614 let filter = filter_orig.clone().into_ignore_hidden();
615 let modlist = ml
616 .validate(qs.get_schema())
617 .map_err(OperationError::SchemaViolation)?;
618 Ok(ModifyEvent {
619 ident,
620 filter,
621 filter_orig,
622 modlist,
623 })
624 }
625
626 pub fn new_internal(filter: Filter<FilterValid>, modlist: ModifyList<ModifyValid>) -> Self {
627 ModifyEvent {
628 ident: Identity::from_internal(),
629 filter: filter.clone(),
630 filter_orig: filter,
631 modlist,
632 }
633 }
634
635 #[cfg(test)]
638 pub fn new_internal_invalid(
639 filter: Filter<FilterInvalid>,
640 modlist: ModifyList<ModifyInvalid>,
641 ) -> Self {
642 ModifyEvent {
643 ident: Identity::from_internal(),
644 filter: filter.clone().into_valid(),
645 filter_orig: filter.into_valid(),
646 modlist: modlist.into_valid(),
647 }
648 }
649
650 #[cfg(test)]
653 pub fn new_impersonate_identity(
654 ident: Identity,
655 filter: Filter<FilterInvalid>,
656 modlist: ModifyList<ModifyInvalid>,
657 ) -> Self {
658 ModifyEvent {
659 ident,
660 filter: filter.clone().into_valid(),
661 filter_orig: filter.into_valid(),
662 modlist: modlist.into_valid(),
663 }
664 }
665
666 #[cfg(test)]
669 pub fn new_impersonate_entry(
670 e: Arc<Entry<EntrySealed, EntryCommitted>>,
671 filter: Filter<FilterInvalid>,
672 modlist: ModifyList<ModifyInvalid>,
673 ) -> Self {
674 ModifyEvent {
675 ident: Identity::from_impersonate_entry_readwrite(e),
676 filter: filter.clone().into_valid(),
677 filter_orig: filter.into_valid(),
678 modlist: modlist.into_valid(),
679 }
680 }
681
682 pub fn new_impersonate(
683 ident: &Identity,
684 filter: Filter<FilterValid>,
685 filter_orig: Filter<FilterValid>,
686 modlist: ModifyList<ModifyValid>,
687 ) -> Self {
688 ModifyEvent {
689 ident: Identity::from_impersonate(ident),
690 filter,
691 filter_orig,
692 modlist,
693 }
694 }
695}
696
697pub struct WhoamiResult {
698 youare: ProtoEntry,
699}
700
701impl WhoamiResult {
702 pub fn new(
703 qs: &mut QueryServerReadTransaction,
704 e: &Entry<EntryReduced, EntryCommitted>,
705 ) -> Result<Self, OperationError> {
706 Ok(WhoamiResult {
707 youare: e.to_pe(qs)?,
708 })
709 }
710
711 pub fn response(self) -> WhoamiResponse {
712 WhoamiResponse {
713 youare: self.youare,
714 }
715 }
716}
717
718#[derive(Debug)]
719pub struct PurgeTombstoneEvent {
720 pub ident: Identity,
721 pub eventid: Uuid,
722}
723
724impl Default for PurgeTombstoneEvent {
725 fn default() -> Self {
726 Self::new()
727 }
728}
729
730impl PurgeTombstoneEvent {
731 pub fn new() -> Self {
732 PurgeTombstoneEvent {
733 ident: Identity::from_internal(),
734 eventid: Uuid::new_v4(),
735 }
736 }
737}
738
739#[derive(Debug)]
740pub struct PurgeRecycledEvent {
741 pub ident: Identity,
742 pub eventid: Uuid,
743}
744
745impl Default for PurgeRecycledEvent {
746 fn default() -> Self {
747 Self::new()
748 }
749}
750
751impl PurgeRecycledEvent {
752 pub fn new() -> Self {
753 PurgeRecycledEvent {
754 ident: Identity::from_internal(),
755 eventid: Uuid::new_v4(),
756 }
757 }
758}
759
760#[derive(Debug)]
761pub struct OnlineBackupEvent {
762 pub ident: Identity,
763 pub eventid: Uuid,
764}
765
766impl Default for OnlineBackupEvent {
767 fn default() -> Self {
768 Self::new()
769 }
770}
771
772impl OnlineBackupEvent {
773 pub fn new() -> Self {
774 OnlineBackupEvent {
775 ident: Identity::from_internal(),
776 eventid: Uuid::new_v4(),
777 }
778 }
779}
780
781#[derive(Debug)]
782pub struct ReviveRecycledEvent {
783 pub ident: Identity,
784 pub filter: Filter<FilterValid>,
786 }
791
792impl ReviveRecycledEvent {
793 pub fn from_parts(
794 ident: Identity,
795 filter: &Filter<FilterInvalid>,
796 qs: &QueryServerWriteTransaction,
797 ) -> Result<Self, OperationError> {
798 let filter = filter
799 .validate(qs.get_schema())
800 .map(|f| f.into_recycled())
801 .map_err(OperationError::SchemaViolation)?;
802 Ok(ReviveRecycledEvent { ident, filter })
803 }
804
805 #[cfg(test)]
808 pub fn new_impersonate_entry(
809 e: Arc<Entry<EntrySealed, EntryCommitted>>,
810 filter: Filter<FilterInvalid>,
811 ) -> Self {
812 ReviveRecycledEvent {
813 ident: Identity::from_impersonate_entry_readwrite(e),
814 filter: filter.into_valid(),
815 }
816 }
817
818 #[cfg(test)]
819 pub(crate) fn new_internal(filter: Filter<FilterValid>) -> Self {
820 ReviveRecycledEvent {
821 ident: Identity::from_internal(),
822 filter,
823 }
824 }
825}