1use std::time::Duration;
4
5use rasn_ldap::{ChangeOperation, ModifyRequestChanges};
6
7use crate::{
8 error::Error,
9 filter::parse_filter,
10 model::{SearchRequestDerefAliases, SearchRequestScope},
11 Attribute,
12};
13
14#[derive(Debug, Clone, Eq, PartialEq)]
16pub struct SearchRequestBuilder {
17 base_dn: String,
18 scope: SearchRequestScope,
19 deref_aliases: SearchRequestDerefAliases,
20 size_limit: u32,
21 time_limit: Duration,
22 types_only: bool,
23 filter: String,
24 attributes: Vec<String>,
25}
26
27impl SearchRequestBuilder {
28 pub(crate) fn new() -> Self {
29 Self {
30 base_dn: Default::default(),
31 scope: SearchRequestScope::BaseObject,
32 deref_aliases: SearchRequestDerefAliases::NeverDerefAliases,
33 size_limit: 0,
34 time_limit: Duration::default(),
35 types_only: false,
36 filter: Default::default(),
37 attributes: Vec::new(),
38 }
39 }
40
41 pub fn base_dn<S: AsRef<str>>(mut self, base_dn: S) -> Self {
43 base_dn.as_ref().clone_into(&mut self.base_dn);
44 self
45 }
46
47 pub fn scope(mut self, scope: SearchRequestScope) -> Self {
49 self.scope = scope;
50 self
51 }
52
53 pub fn deref_aliases(mut self, deref_aliases: SearchRequestDerefAliases) -> Self {
55 self.deref_aliases = deref_aliases;
56 self
57 }
58
59 pub fn size_limit(mut self, size_limit: u32) -> Self {
61 self.size_limit = size_limit;
62 self
63 }
64
65 pub fn time_limit(mut self, time_limit: Duration) -> Self {
67 self.time_limit = time_limit;
68 self
69 }
70
71 pub fn types_only(mut self, types_only: bool) -> Self {
73 self.types_only = types_only;
74 self
75 }
76
77 pub fn filter<S: AsRef<str>>(mut self, filter: S) -> Self {
79 filter.as_ref().clone_into(&mut self.filter);
80 self
81 }
82
83 pub fn attributes<I, S>(mut self, attributes: I) -> Self
85 where
86 I: IntoIterator<Item = S>,
87 S: AsRef<str>,
88 {
89 self.attributes
90 .extend(attributes.into_iter().map(|a| a.as_ref().to_owned()));
91 self
92 }
93
94 pub fn attribute<S>(mut self, attribute: S) -> Self
96 where
97 S: AsRef<str>,
98 {
99 self.attributes.push(attribute.as_ref().to_owned());
100 self
101 }
102
103 pub fn build(self) -> Result<SearchRequest, Error> {
105 Ok(SearchRequest(rasn_ldap::SearchRequest::new(
106 self.base_dn.into(),
107 self.scope,
108 self.deref_aliases,
109 self.size_limit,
110 self.time_limit.as_secs() as u32,
111 self.types_only,
112 parse_filter(self.filter)?,
113 self.attributes.into_iter().map(Into::into).collect(),
114 )))
115 }
116}
117
118#[derive(Clone, Debug, Eq, PartialEq)]
120pub struct SearchRequest(pub(crate) rasn_ldap::SearchRequest);
121
122impl SearchRequest {
123 pub fn builder() -> SearchRequestBuilder {
125 SearchRequestBuilder::new()
126 }
127
128 pub fn root_dse() -> Self {
130 Self::builder().filter("(objectClass=*)").build().unwrap()
131 }
132}
133
134impl From<SearchRequest> for rasn_ldap::SearchRequest {
135 fn from(req: SearchRequest) -> Self {
136 req.0
137 }
138}
139
140#[derive(Clone, Debug, Eq, PartialEq)]
142pub struct ModifyRequest(pub(crate) rasn_ldap::ModifyRequest);
143
144impl ModifyRequest {
145 pub fn builder<S: AsRef<str>>(object: S) -> ModifyRequestBuilder {
147 ModifyRequestBuilder::new(object)
148 }
149}
150
151impl From<ModifyRequest> for rasn_ldap::ModifyRequest {
152 fn from(req: ModifyRequest) -> Self {
153 req.0
154 }
155}
156
157#[derive(Debug, Clone, Eq, PartialEq)]
159pub struct ModifyRequestBuilder {
160 object: String,
161 operations: Vec<(ChangeOperation, Attribute)>,
162}
163
164impl ModifyRequestBuilder {
165 pub(crate) fn new<S: AsRef<str>>(object: S) -> Self {
166 Self {
167 object: object.as_ref().to_owned(),
168 operations: Vec::new(),
169 }
170 }
171
172 pub fn add_op(mut self, attribute: Attribute) -> Self {
174 self.operations.push((ChangeOperation::Add, attribute));
175 self
176 }
177
178 pub fn delete_op(mut self, attribute: Attribute) -> Self {
180 self.operations.push((ChangeOperation::Delete, attribute));
181 self
182 }
183
184 pub fn replace_op(mut self, attribute: Attribute) -> Self {
186 self.operations.push((ChangeOperation::Replace, attribute));
187 self
188 }
189
190 pub fn build(self) -> ModifyRequest {
192 let req = rasn_ldap::ModifyRequest {
193 object: self.object.into(),
194 changes: self
195 .operations
196 .into_iter()
197 .map(|(operation, attribute)| ModifyRequestChanges {
198 operation,
199 modification: attribute.into(),
200 })
201 .collect(),
202 };
203 ModifyRequest(req)
204 }
205}