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