1use super::errors::WebError;
4use super::middleware::caching::{cache_me_short, dont_cache_me};
5use super::middleware::KOpId;
6use super::ServerState;
7use crate::https::apidocs::response_schema::{ApiResponseWithout200, DefaultApiResponse};
8use crate::https::extractors::{ClientConnInfo, VerifiedClientInformation};
9use axum::extract::{Path, State};
10use axum::http::{HeaderMap, HeaderValue};
11use axum::middleware::from_fn;
12use axum::response::{IntoResponse, Response};
13use axum::routing::{delete, get, post, put};
14use axum::{Extension, Json, Router};
15use axum_extra::extract::cookie::{Cookie, CookieJar, SameSite};
16use compact_jwt::{Jwk, Jws, JwsSigner};
17use kanidm_proto::constants::uri::V1_AUTH_VALID;
18use kanidm_proto::internal::{
19 ApiToken, AppLink, CUIntentToken, CURequest, CUSessionToken, CUStatus, CreateRequest,
20 CredentialStatus, DeleteRequest, IdentifyUserRequest, IdentifyUserResponse, ModifyRequest,
21 RadiusAuthToken, SearchRequest, SearchResponse, UserAuthToken, COOKIE_AUTH_SESSION_ID,
22 COOKIE_BEARER_TOKEN,
23};
24use kanidm_proto::v1::{
25 AccountUnixExtend, ApiTokenGenerate, AuthIssueSession, AuthRequest, AuthResponse,
26 AuthState as ProtoAuthState, Entry as ProtoEntry, GroupUnixExtend, SingleStringRequest,
27 UatStatus, UnixGroupToken, UnixUserToken, WhoamiResponse,
28};
29use kanidmd_lib::idm::event::AuthResult;
30use kanidmd_lib::idm::AuthState;
31use kanidmd_lib::prelude::*;
32use kanidmd_lib::value::PartialValue;
33use std::net::IpAddr;
34use uuid::Uuid;
35
36#[utoipa::path(
37 post,
38 path = "/v1/raw/create",
39 responses(
40 DefaultApiResponse,
41 ),
42 request_body=CreateRequest,
43 security(("token_jwt" = [])),
44 tag = "v1/raw",
45 operation_id="raw_create"
46)]
47pub async fn raw_create(
49 State(state): State<ServerState>,
50 Extension(kopid): Extension<KOpId>,
51 VerifiedClientInformation(client_auth_info): VerifiedClientInformation,
52 Json(msg): Json<CreateRequest>,
53) -> Result<Json<()>, WebError> {
54 state
55 .qe_w_ref
56 .handle_create(client_auth_info, msg, kopid.eventid)
57 .await
58 .map(Json::from)
59 .map_err(WebError::from)
60}
61
62#[utoipa::path(
63 post,
64 path = "/v1/raw/modify",
65 responses(
66 DefaultApiResponse,
67 ),
68 request_body=ModifyRequest,
69 security(("token_jwt" = [])),
70 tag = "v1/raw",
71 operation_id="raw_modify"
72)]
73pub async fn raw_modify(
75 State(state): State<ServerState>,
76 Extension(kopid): Extension<KOpId>,
77 VerifiedClientInformation(client_auth_info): VerifiedClientInformation,
78 Json(msg): Json<ModifyRequest>,
79) -> Result<Json<()>, WebError> {
80 state
81 .qe_w_ref
82 .handle_modify(client_auth_info, msg, kopid.eventid)
83 .await
84 .map(Json::from)
85 .map_err(WebError::from)
86}
87
88#[utoipa::path(
89 post,
90 path = "/v1/raw/delete",
91 responses(
92 DefaultApiResponse,
93 ),
94 request_body=DeleteRequest,
95 security(("token_jwt" = [])),
96 tag = "v1/raw",
97 operation_id = "raw_delete"
98)]
99pub async fn raw_delete(
101 State(state): State<ServerState>,
102 Extension(kopid): Extension<KOpId>,
103 VerifiedClientInformation(client_auth_info): VerifiedClientInformation,
104 Json(msg): Json<DeleteRequest>,
105) -> Result<Json<()>, WebError> {
106 state
107 .qe_w_ref
108 .handle_delete(client_auth_info, msg, kopid.eventid)
109 .await
110 .map(Json::from)
111 .map_err(WebError::from)
112}
113
114#[utoipa::path(
115 post,
116 path = "/v1/raw/search",
117 responses(
118 (status = 200, body=SearchResponse, content_type="application/json"),
119 ApiResponseWithout200,
120 ),
121 request_body=SearchRequest,
122 security(("token_jwt" = [])),
123 tag = "v1/raw",
124 operation_id="raw_search"
125)]
126pub async fn raw_search(
128 State(state): State<ServerState>,
129 Extension(kopid): Extension<KOpId>,
130 VerifiedClientInformation(client_auth_info): VerifiedClientInformation,
131 Json(msg): Json<SearchRequest>,
132) -> Result<Json<SearchResponse>, WebError> {
133 state
134 .qe_r_ref
135 .handle_search(client_auth_info, msg, kopid.eventid)
136 .await
137 .map(Json::from)
138 .map_err(WebError::from)
139}
140
141#[utoipa::path(
142 get,
143 path = "/v1/self",
144 responses(
145 (status = 200, body=WhoamiResponse, content_type="application/json"),
146 ApiResponseWithout200,
147 ),
148 security(("token_jwt" = [])),
149 tag = "v1/self",
150 operation_id="whoami"
151)]
152pub async fn whoami(
154 State(state): State<ServerState>,
155 Extension(kopid): Extension<KOpId>,
156 VerifiedClientInformation(client_auth_info): VerifiedClientInformation,
157) -> Result<Json<WhoamiResponse>, WebError> {
158 state
160 .qe_r_ref
161 .handle_whoami(client_auth_info, kopid.eventid)
162 .await
163 .map(Json::from)
164 .map_err(WebError::from)
165}
166
167#[utoipa::path(
168 get,
169 path = "/v1/self/_uat",
170 responses(
171 (status = 200, description = "Ok", body=UserAuthToken, content_type="application/json"),
172 ApiResponseWithout200,
173 ),
174 security(("token_jwt" = [])),
175 tag = "v1/self",
176 operation_id="whoami_uat"
177)]
178pub async fn whoami_uat(
179 State(state): State<ServerState>,
180 Extension(kopid): Extension<KOpId>,
181 VerifiedClientInformation(client_auth_info): VerifiedClientInformation,
182) -> Result<Json<UserAuthToken>, WebError> {
183 state
184 .qe_r_ref
185 .handle_whoami_uat(&client_auth_info, kopid.eventid)
186 .await
187 .map(Json::from)
188 .map_err(WebError::from)
189}
190
191#[utoipa::path(
192 get,
193 path = "/v1/logout",
194 responses(
195 DefaultApiResponse,
196 ),
197 security(("token_jwt" = [])),
198 tag = "v1/auth",
199 operation_id="logout"
200)]
201pub async fn logout(
202 State(state): State<ServerState>,
203 Extension(kopid): Extension<KOpId>,
204 VerifiedClientInformation(client_auth_info): VerifiedClientInformation,
205 jar: CookieJar,
206) -> Result<Response, WebError> {
207 state
208 .qe_w_ref
209 .handle_logout(client_auth_info, kopid.eventid)
210 .await
211 .map(Json::from)
212 .map(|json| (jar, json).into_response())
213 .map_err(WebError::from)
214}
215
216#[instrument(level = "trace", skip(state, kopid))]
219pub async fn json_rest_event_get(
220 state: ServerState,
221 attrs: Option<Vec<String>>,
222 filter: Filter<FilterInvalid>,
223 kopid: KOpId,
224 client_auth_info: ClientAuthInfo,
225) -> Result<Json<Vec<ProtoEntry>>, WebError> {
226 state
227 .qe_r_ref
228 .handle_internalsearch(client_auth_info, filter, attrs, kopid.eventid)
229 .await
230 .map(Json::from)
231 .map_err(WebError::from)
232}
233
234pub async fn json_rest_event_get_id(
237 state: ServerState,
238 id: String,
239 filter: Filter<FilterInvalid>,
240 attrs: Option<Vec<String>>,
241 kopid: KOpId,
242 client_auth_info: ClientAuthInfo,
243) -> Result<Json<Option<ProtoEntry>>, WebError> {
244 let filter = Filter::join_parts_and(filter, filter_all!(f_id(id.as_str())));
245
246 state
247 .qe_r_ref
248 .handle_internalsearch(client_auth_info, filter, attrs, kopid.eventid)
249 .await
250 .map(|mut r| r.pop())
251 .map(Json::from)
252 .map_err(WebError::from)
253}
254
255pub async fn json_rest_event_get_refers_id(
258 state: ServerState,
259 refers_id: String,
260 filter: Filter<FilterInvalid>,
261 attrs: Option<Vec<String>>,
262 kopid: KOpId,
263 client_auth_info: ClientAuthInfo,
264) -> Result<Json<Vec<ProtoEntry>>, WebError> {
265 state
266 .qe_r_ref
267 .handle_search_refers(client_auth_info, filter, refers_id, attrs, kopid.eventid)
268 .await
269 .map(Json::from)
270 .map_err(WebError::from)
271}
272
273pub async fn json_rest_event_delete_id(
274 state: ServerState,
275 id: String,
276 filter: Filter<FilterInvalid>,
277 kopid: KOpId,
278 client_auth_info: ClientAuthInfo,
279) -> Result<Json<()>, WebError> {
280 let filter = Filter::join_parts_and(filter, filter_all!(f_id(id.as_str())));
281 state
282 .qe_w_ref
283 .handle_internaldelete(client_auth_info, filter, kopid.eventid)
284 .await
285 .map(Json::from)
286 .map_err(WebError::from)
287}
288
289pub async fn json_rest_event_get_attr(
290 state: ServerState,
291 id: &str,
292 attr: String,
293 filter: Filter<FilterInvalid>,
294 kopid: KOpId,
295 client_auth_info: ClientAuthInfo,
296) -> Result<Json<Option<Vec<String>>>, WebError> {
297 let filter = Filter::join_parts_and(filter, filter_all!(f_id(id)));
298 let attrs = Some(vec![attr.clone()]);
299 state
300 .qe_r_ref
301 .handle_internalsearch(client_auth_info, filter, attrs, kopid.eventid)
302 .await
303 .map(|mut event_result| event_result.pop().and_then(|mut e| e.attrs.remove(&attr)))
304 .map(Json::from)
305 .map_err(WebError::from)
306}
307
308pub async fn json_rest_event_get_id_attr(
309 state: ServerState,
310 id: String,
311 attr: String,
312 filter: Filter<FilterInvalid>,
313 kopid: KOpId,
314 client_auth_info: ClientAuthInfo,
315) -> Result<Json<Option<Vec<String>>>, WebError> {
316 json_rest_event_get_attr(state, id.as_str(), attr, filter, kopid, client_auth_info).await
317}
318
319pub async fn json_rest_event_post(
320 state: ServerState,
321 classes: Vec<String>,
322 obj: ProtoEntry,
323 kopid: KOpId,
324 client_auth_info: ClientAuthInfo,
325) -> Result<Json<()>, WebError> {
326 debug_assert!(!classes.is_empty());
327
328 let mut obj = obj;
329 obj.attrs.insert(Attribute::Class.to_string(), classes);
330 let msg = CreateRequest {
331 entries: vec![obj.to_owned()],
332 };
333
334 state
335 .qe_w_ref
336 .handle_create(client_auth_info, msg, kopid.eventid)
337 .await
338 .map(Json::from)
339 .map_err(WebError::from)
340}
341
342pub async fn json_rest_event_post_id_attr(
343 state: ServerState,
344 id: String,
345 attr: String,
346 filter: Filter<FilterInvalid>,
347 values: Vec<String>,
348 kopid: KOpId,
349 client_auth_info: ClientAuthInfo,
350) -> Result<Json<()>, WebError> {
351 state
352 .qe_w_ref
353 .handle_appendattribute(client_auth_info, id, attr, values, filter, kopid.eventid)
354 .await
355 .map(Json::from)
356 .map_err(WebError::from)
357}
358
359pub async fn json_rest_event_put_attr(
369 state: ServerState,
370 id: String,
371 attr: String,
372 filter: Filter<FilterInvalid>,
373 values: Vec<String>,
374 kopid: KOpId,
375 client_auth_info: ClientAuthInfo,
376) -> Result<Json<()>, WebError> {
377 state
378 .qe_w_ref
379 .handle_setattribute(client_auth_info, id, attr, values, filter, kopid.eventid)
380 .await
381 .map_err(WebError::from)
382 .map(Json::from)
383}
384
385pub async fn json_rest_event_post_attr(
386 state: ServerState,
387 id: String,
388 attr: String,
389 filter: Filter<FilterInvalid>,
390 values: Vec<String>,
391 kopid: KOpId,
392 client_auth_info: ClientAuthInfo,
393) -> Result<Json<()>, WebError> {
394 state
395 .qe_w_ref
396 .handle_appendattribute(client_auth_info, id, attr, values, filter, kopid.eventid)
397 .await
398 .map(Json::from)
399 .map_err(WebError::from)
400}
401
402pub async fn json_rest_event_delete_id_attr(
403 state: ServerState,
404 id: String,
405 attr: String,
406 filter: Filter<FilterInvalid>,
407 values: Option<Vec<String>>,
408 kopid: KOpId,
409 client_auth_info: ClientAuthInfo,
410) -> Result<Json<()>, WebError> {
411 json_rest_event_delete_attr(state, id, attr, filter, values, kopid, client_auth_info).await
412}
413
414pub async fn json_rest_event_delete_attr(
415 state: ServerState,
416 uuid_or_name: String,
417 attr: String,
418 filter: Filter<FilterInvalid>,
419 values: Option<Vec<String>>,
420 kopid: KOpId,
421 client_auth_info: ClientAuthInfo,
422) -> Result<Json<()>, WebError> {
423 let values = values.unwrap_or_default();
424
425 if values.is_empty() {
426 state
427 .qe_w_ref
428 .handle_purgeattribute(client_auth_info, uuid_or_name, attr, filter, kopid.eventid)
429 .await
430 } else {
431 state
432 .qe_w_ref
433 .handle_removeattributevalues(
434 client_auth_info,
435 uuid_or_name,
436 attr,
437 values,
438 filter,
439 kopid.eventid,
440 )
441 .await
442 }
443 .map(Json::from)
444 .map_err(WebError::from)
445}
446
447#[utoipa::path(
448 get,
449 path = "/v1/schema",
450 responses(
451 (status=200, content_type="application/json", body=Vec<ProtoEntry>),
452 ApiResponseWithout200,
453 ),
454 security(("token_jwt" = [])),
455 tag = "v1/schema",
456 operation_id = "schema_get",
457)]
458pub async fn schema_get(
460 State(state): State<ServerState>,
461 Extension(kopid): Extension<KOpId>,
462 VerifiedClientInformation(client_auth_info): VerifiedClientInformation,
463) -> Result<Json<Vec<ProtoEntry>>, WebError> {
464 let filter = filter_all!(f_or!([
469 f_eq(Attribute::Class, EntryClass::AttributeType.into()),
470 f_eq(Attribute::Class, EntryClass::ClassType.into())
471 ]));
472 json_rest_event_get(state, None, filter, kopid, client_auth_info).await
473}
474
475#[utoipa::path(
476 get,
477 path = "/v1/schema/attributetype",
478 responses(
479 (status=200, content_type="application/json", body=Vec<ProtoEntry>),
480 ApiResponseWithout200,
481 ),
482 security(("token_jwt" = [])),
483 tag = "v1/schema",
484 operation_id = "schema_attributetype_get",
485)]
486pub async fn schema_attributetype_get(
487 State(state): State<ServerState>,
488 Extension(kopid): Extension<KOpId>,
489 VerifiedClientInformation(client_auth_info): VerifiedClientInformation,
490) -> Result<Json<Vec<ProtoEntry>>, WebError> {
491 let filter = filter_all!(f_eq(Attribute::Class, EntryClass::AttributeType.into()));
492 json_rest_event_get(state, None, filter, kopid, client_auth_info).await
493}
494
495#[utoipa::path(
496 get,
497 path = "/v1/schema/attributetype/{id}",
498 responses(
499 (status=200, body=Option<ProtoEntry>, content_type="application/json"),
500 ApiResponseWithout200,
501 ),
502 security(("token_jwt" = [])),
503 tag = "v1/schema",
504 operation_id = "schema_attributetype_get_id",
505)]
506pub async fn schema_attributetype_get_id(
507 State(state): State<ServerState>,
508 Path(id): Path<String>,
509 Extension(kopid): Extension<KOpId>,
510 VerifiedClientInformation(client_auth_info): VerifiedClientInformation,
511) -> Result<Json<Option<ProtoEntry>>, WebError> {
512 let filter = filter_all!(f_and!([
514 f_eq(Attribute::Class, EntryClass::AttributeType.into()),
515 f_eq(
516 Attribute::AttributeName,
517 PartialValue::new_iutf8(id.as_str())
518 )
519 ]));
520
521 state
522 .qe_r_ref
523 .handle_internalsearch(client_auth_info, filter, None, kopid.eventid)
524 .await
525 .map(|mut r| r.pop())
526 .map(Json::from)
527 .map_err(WebError::from)
528}
529
530#[utoipa::path(
531 get,
532 path = "/v1/schema/classtype",
533 responses(
534 (status=200, body=Vec<ProtoEntry>, content_type="application/json"),
535 ApiResponseWithout200,
536 ),
537 security(("token_jwt" = [])),
538 tag = "v1/schema",
539 operation_id="schema_classtype_get",
540)]
541pub async fn schema_classtype_get(
542 State(state): State<ServerState>,
543 Extension(kopid): Extension<KOpId>,
544 VerifiedClientInformation(client_auth_info): VerifiedClientInformation,
545) -> Result<Json<Vec<ProtoEntry>>, WebError> {
546 let filter = filter_all!(f_eq(Attribute::Class, EntryClass::ClassType.into()));
547 json_rest_event_get(state, None, filter, kopid, client_auth_info).await
548}
549
550#[utoipa::path(
551 get,
552 path = "/v1/schema/classtype/{id}",
553 responses(
554 (status=200, body=Option<ProtoEntry>, content_type="application/json"),
555 ApiResponseWithout200,
556 ),
557 security(("token_jwt" = [])),
558 tag = "v1/schema",
559 operation_id="schema_classtype_get_id",
560)]
561pub async fn schema_classtype_get_id(
562 State(state): State<ServerState>,
563 Extension(kopid): Extension<KOpId>,
564 VerifiedClientInformation(client_auth_info): VerifiedClientInformation,
565 Path(id): Path<String>,
566) -> Result<Json<Option<ProtoEntry>>, WebError> {
567 let filter = filter_all!(f_and!([
569 f_eq(Attribute::Class, EntryClass::ClassType.into()),
570 f_eq(Attribute::ClassName, PartialValue::new_iutf8(id.as_str()))
571 ]));
572 state
573 .qe_r_ref
574 .handle_internalsearch(client_auth_info, filter, None, kopid.eventid)
575 .await
576 .map(|mut r| r.pop())
577 .map(Json::from)
578 .map_err(WebError::from)
579}
580
581#[utoipa::path(
582 get,
583 path = "/v1/person",
584 responses(
585 (status=200, body=Vec<ProtoEntry>, content_type="application/json"),
586 ApiResponseWithout200,
587 ),
588 security(("token_jwt" = [])),
589 tag = "v1/person",
590 operation_id = "person_get",
591)]
592pub async fn person_get(
593 State(state): State<ServerState>,
594 Extension(kopid): Extension<KOpId>,
595 VerifiedClientInformation(client_auth_info): VerifiedClientInformation,
596) -> Result<Json<Vec<ProtoEntry>>, WebError> {
597 let filter = filter_all!(f_eq(Attribute::Class, EntryClass::Person.into()));
598 json_rest_event_get(state, None, filter, kopid, client_auth_info).await
599}
600
601#[utoipa::path(
602 post,
603 path = "/v1/person",
604 responses(
605 DefaultApiResponse,
606 ),
607 request_body=ProtoEntry,
608 security(("token_jwt" = [])),
609 tag = "v1/person",
610 operation_id = "person_post",
611)]
612pub async fn person_post(
614 State(state): State<ServerState>,
615 Extension(kopid): Extension<KOpId>,
616 VerifiedClientInformation(client_auth_info): VerifiedClientInformation,
617 Json(obj): Json<ProtoEntry>,
618) -> Result<Json<()>, WebError> {
619 let classes: Vec<String> = vec![
620 EntryClass::Person.into(),
621 EntryClass::Account.into(),
622 EntryClass::Object.into(),
623 ];
624 json_rest_event_post(state, classes, obj, kopid, client_auth_info).await
625}
626
627#[utoipa::path(
628 get,
629 path = "/v1/person/_search/{id}",
630 responses(
631 (status=200, body=Option<ProtoEntry>, content_type="application/json"),
632 ApiResponseWithout200,
633 ),
634 security(("token_jwt" = [])),
635 tag = "v1/person",
636 operation_id = "person_search_id",
637)]
638pub async fn person_search_id(
639 State(state): State<ServerState>,
640 Path(id): Path<String>,
641 Extension(kopid): Extension<KOpId>,
642 VerifiedClientInformation(client_auth_info): VerifiedClientInformation,
643) -> Result<Json<Vec<ProtoEntry>>, WebError> {
644 let filter = filter_all!(f_and!([
645 f_eq(Attribute::Class, EntryClass::Person.into()),
646 f_sub(Attribute::Name, PartialValue::new_iname(&id))
647 ]));
648 json_rest_event_get(state, None, filter, kopid, client_auth_info).await
649}
650
651#[utoipa::path(
652 get,
653 path = "/v1/person/{id}",
654 responses(
655 (status=200, body=Option<ProtoEntry>, content_type="application/json"),
656 ApiResponseWithout200,
657 ),
658 security(("token_jwt" = [])),
659 tag = "v1/person",
660 operation_id = "person_id_get",
661)]
662pub async fn person_id_get(
663 State(state): State<ServerState>,
664 Path(id): Path<String>,
665 Extension(kopid): Extension<KOpId>,
666 VerifiedClientInformation(client_auth_info): VerifiedClientInformation,
667) -> Result<Json<Option<ProtoEntry>>, WebError> {
668 let filter = filter_all!(f_eq(Attribute::Class, EntryClass::Person.into()));
669 json_rest_event_get_id(state, id, filter, None, kopid, client_auth_info).await
670}
671
672#[utoipa::path(
673 delete,
674 path = "/v1/person/{id}",
675 responses(
676 DefaultApiResponse,
677 ),
678 security(("token_jwt" = [])),
679 tag = "v1/person",
680 operation_id = "person_id_delete",
681)]
682pub async fn person_id_delete(
683 State(state): State<ServerState>,
684 Path(id): Path<String>,
685 Extension(kopid): Extension<KOpId>,
686 VerifiedClientInformation(client_auth_info): VerifiedClientInformation,
687) -> Result<Json<()>, WebError> {
688 let filter = filter_all!(f_eq(Attribute::Class, EntryClass::Person.into()));
689 json_rest_event_delete_id(state, id, filter, kopid, client_auth_info).await
690}
691
692#[utoipa::path(
695 get,
696 path = "/v1/person/{id}/_certificate",
697 responses(
698 (status=200, body=Option<ProtoEntry>, content_type="application/json"),
699 ApiResponseWithout200,
700 ),
701 security(("token_jwt" = [])),
702 tag = "v1/person/certificate",
703 operation_id = "person_get_id_certificate",
704)]
705pub async fn person_get_id_certificate(
706 State(state): State<ServerState>,
707 Path(id): Path<String>,
708 Extension(kopid): Extension<KOpId>,
709 VerifiedClientInformation(client_auth_info): VerifiedClientInformation,
710) -> Result<Json<Vec<ProtoEntry>>, WebError> {
711 let filter = filter_all!(f_eq(Attribute::Class, EntryClass::ClientCertificate.into()));
712 json_rest_event_get_refers_id(state, id, filter, None, kopid, client_auth_info).await
713}
714
715#[utoipa::path(
716 post,
717 path = "/v1/person/{id}/_certificate",
718 responses(
719 DefaultApiResponse,
720 ),
721 request_body=ProtoEntry,
722 security(("token_jwt" = [])),
723 tag = "v1/person/certificate",
724 operation_id = "person_post_id_certificate",
725)]
726pub async fn person_post_id_certificate(
730 State(state): State<ServerState>,
731 Path(id): Path<String>,
732 Extension(kopid): Extension<KOpId>,
733 VerifiedClientInformation(client_auth_info): VerifiedClientInformation,
734 Json(mut obj): Json<ProtoEntry>,
735) -> Result<Json<()>, WebError> {
736 let classes: Vec<String> = vec![
737 EntryClass::ClientCertificate.into(),
738 EntryClass::Object.into(),
739 ];
740 obj.attrs.insert(Attribute::Refers.to_string(), vec![id]);
741
742 json_rest_event_post(state, classes, obj, kopid, client_auth_info).await
743}
744
745#[utoipa::path(
748 get,
749 path = "/v1/service_account",
750 responses(
751 (status=200, body=Vec<ProtoEntry>, content_type="application/json"),
752 ApiResponseWithout200,
753 ),
754 security(("token_jwt" = [])),
755 tag = "v1/service_account",
756 operation_id = "service_account_get",
757)]
758pub async fn service_account_get(
759 State(state): State<ServerState>,
760 Extension(kopid): Extension<KOpId>,
761 VerifiedClientInformation(client_auth_info): VerifiedClientInformation,
762) -> Result<Json<Vec<ProtoEntry>>, WebError> {
763 let filter = filter_all!(f_eq(Attribute::Class, EntryClass::ServiceAccount.into()));
764 json_rest_event_get(state, None, filter, kopid, client_auth_info).await
765}
766
767#[utoipa::path(
768 post,
769 path = "/v1/service_account",
770 request_body=ProtoEntry,
771 responses(
772 DefaultApiResponse,
773 ),
774 security(("token_jwt" = [])),
775 tag = "v1/service_account",
776 operation_id = "service_account_post",
777)]
778pub async fn service_account_post(
779 State(state): State<ServerState>,
780 Extension(kopid): Extension<KOpId>,
781 VerifiedClientInformation(client_auth_info): VerifiedClientInformation,
782 Json(obj): Json<ProtoEntry>,
783) -> Result<Json<()>, WebError> {
784 let classes: Vec<String> = vec![
785 EntryClass::ServiceAccount.into(),
786 EntryClass::Account.into(),
787 EntryClass::Object.into(),
788 ];
789 json_rest_event_post(state, classes, obj, kopid, client_auth_info).await
790}
791
792#[utoipa::path(
793 patch,
794 path = "/v1/service_account/{id}",
795 responses(
796 DefaultApiResponse,
797 ),
798 request_body=ProtoEntry,
799 security(("token_jwt" = [])),
800 tag = "v1/service_account",
801 operation_id = "service_account_id_patch",
802)]
803pub async fn service_account_id_patch(
804 State(state): State<ServerState>,
805 Extension(kopid): Extension<KOpId>,
806 VerifiedClientInformation(client_auth_info): VerifiedClientInformation,
807 Path(id): Path<String>,
808 Json(obj): Json<ProtoEntry>,
809) -> Result<Json<()>, WebError> {
810 let filter = filter_all!(f_eq(Attribute::Class, EntryClass::Account.into()));
812 let filter = Filter::join_parts_and(filter, filter_all!(f_id(id.as_str())));
813 state
814 .qe_w_ref
815 .handle_internalpatch(client_auth_info, filter, obj, kopid.eventid)
816 .await
817 .map(Json::from)
818 .map_err(WebError::from)
819}
820
821#[utoipa::path(
822 get,
823 path = "/v1/service_account/{id}",
824 responses(
825 (status=200, body=Option<ProtoEntry>, content_type="application/json"),
826 ApiResponseWithout200,
827 ),
828 security(("token_jwt" = [])),
829 tag = "v1/service_account",
830 operation_id = "service_account_id_get",
831)]
832pub async fn service_account_id_get(
833 State(state): State<ServerState>,
834 Path(id): Path<String>,
835 Extension(kopid): Extension<KOpId>,
836 VerifiedClientInformation(client_auth_info): VerifiedClientInformation,
837) -> Result<Json<Option<ProtoEntry>>, WebError> {
838 let filter = filter_all!(f_eq(Attribute::Class, EntryClass::ServiceAccount.into()));
839 json_rest_event_get_id(state, id, filter, None, kopid, client_auth_info).await
840}
841
842#[utoipa::path(
843 delete,
844 path = "/v1/service_account/{id}",
845 responses(
846 DefaultApiResponse,
847 ),
848 security(("token_jwt" = [])),
849 tag = "v1/service_account",
850)]
851pub async fn service_account_id_delete(
852 State(state): State<ServerState>,
853 Path(id): Path<String>,
854 Extension(kopid): Extension<KOpId>,
855 VerifiedClientInformation(client_auth_info): VerifiedClientInformation,
856) -> Result<Json<()>, WebError> {
857 let filter = filter_all!(f_eq(Attribute::Class, EntryClass::ServiceAccount.into()));
858 json_rest_event_delete_id(state, id, filter, kopid, client_auth_info).await
859}
860
861#[utoipa::path(
862 get,
863 path = "/v1/service_account/{id}/_credential/_generate",
864 responses(
865 (status=200), ApiResponseWithout200,
867 ),
868 security(("token_jwt" = [])),
869 tag = "v1/service_account",
870)]
871pub async fn service_account_credential_generate(
872 State(state): State<ServerState>,
873 Path(id): Path<String>,
874 Extension(kopid): Extension<KOpId>,
875 VerifiedClientInformation(client_auth_info): VerifiedClientInformation,
876) -> Result<Json<String>, WebError> {
877 state
878 .qe_w_ref
879 .handle_service_account_credential_generate(client_auth_info, id, kopid.eventid)
880 .await
881 .map(Json::from)
882 .map_err(WebError::from)
883}
884
885#[utoipa::path(
886 post,
887 path = "/v1/service_account/{id}/_into_person",
888 responses(
889 DefaultApiResponse,
890 ),
891 security(("token_jwt" = [])),
892 tag = "v1/service_account",
893)]
894#[deprecated]
900pub async fn service_account_into_person(
901 State(state): State<ServerState>,
902 Extension(kopid): Extension<KOpId>,
903 VerifiedClientInformation(client_auth_info): VerifiedClientInformation,
904 Path(id): Path<String>,
905) -> Result<Json<()>, WebError> {
906 state
907 .qe_w_ref
908 .handle_service_account_into_person(client_auth_info, id, kopid.eventid)
909 .await
910 .map(Json::from)
911 .map_err(WebError::from)
912}
913
914#[utoipa::path(
915 get,
916 path = "/v1/service_account/{id}/_api_token",
917 responses(
918 (status=200, body=Vec<ApiToken>, content_type="application/json"),
919 ApiResponseWithout200,
920 ),
921 security(("token_jwt" = [])),
922 tag = "v1/service_account",
923 operation_id = "service_account_api_token_get",
924)]
925pub async fn service_account_api_token_get(
926 State(state): State<ServerState>,
927 Extension(kopid): Extension<KOpId>,
928 VerifiedClientInformation(client_auth_info): VerifiedClientInformation,
929 Path(id): Path<String>,
930) -> Result<Json<Vec<ApiToken>>, WebError> {
931 state
932 .qe_r_ref
933 .handle_service_account_api_token_get(client_auth_info, id, kopid.eventid)
934 .await
935 .map(Json::from)
936 .map_err(WebError::from)
937}
938
939#[utoipa::path(
940 post,
941 path = "/v1/service_account/{id}/_api_token",
942 request_body = ApiTokenGenerate,
943 responses(
944 (status=200, body=String, content_type="application/json"),
945 ApiResponseWithout200,
946 ),
947 security(("token_jwt" = [])),
948 tag = "v1/service_account",
949 operation_id = "service_account_api_token_post",
950)]
951pub async fn service_account_api_token_post(
952 State(state): State<ServerState>,
953 Extension(kopid): Extension<KOpId>,
954 VerifiedClientInformation(client_auth_info): VerifiedClientInformation,
955 Path(id): Path<String>,
956 Json(obj): Json<ApiTokenGenerate>,
957) -> Result<Json<String>, WebError> {
958 state
959 .qe_w_ref
960 .handle_service_account_api_token_generate(
961 client_auth_info,
962 id,
963 obj.label,
964 obj.expiry,
965 obj.read_write,
966 kopid.eventid,
967 )
968 .await
969 .map(Json::from)
970 .map_err(WebError::from)
971}
972
973#[utoipa::path(
974 delete,
975 path = "/v1/service_account/{id}/_api_token/{token_id}",
976 responses(
977 DefaultApiResponse,
978 ),
979 security(("token_jwt" = [])),
980 tag = "v1/service_account",
981 operation_id = "service_account_api_token_delete",
982)]
983pub async fn service_account_api_token_delete(
984 State(state): State<ServerState>,
985 Path((id, token_id)): Path<(String, Uuid)>,
986 Extension(kopid): Extension<KOpId>,
987 VerifiedClientInformation(client_auth_info): VerifiedClientInformation,
988) -> Result<Json<()>, WebError> {
989 state
990 .qe_w_ref
991 .handle_service_account_api_token_destroy(client_auth_info, id, token_id, kopid.eventid)
992 .await
993 .map(Json::from)
994 .map_err(WebError::from)
995}
996
997#[utoipa::path(
998 get,
999 path = "/v1/person/{id}/_attr/{attr}",
1000 responses(
1001 (status=200, body=Option<Vec<String>>, content_type="application/json"),
1002 ApiResponseWithout200,
1003 ),
1004 security(("token_jwt" = [])),
1005 tag = "v1/person/attr",
1006 operation_id = "person_id_get_attr",
1007)]
1008pub async fn person_id_get_attr(
1009 State(state): State<ServerState>,
1010 Path((id, attr)): Path<(String, String)>,
1011 Extension(kopid): Extension<KOpId>,
1012 VerifiedClientInformation(client_auth_info): VerifiedClientInformation,
1013) -> Result<Json<Option<Vec<String>>>, WebError> {
1014 let filter = filter_all!(f_eq(Attribute::Class, EntryClass::Account.into()));
1015 json_rest_event_get_attr(state, id.as_str(), attr, filter, kopid, client_auth_info).await
1016}
1017
1018#[utoipa::path(
1019 get,
1020 path = "/v1/service_account/{id}/_attr/{attr}",
1021 responses(
1022 (status=200, body=Option<Vec<String>>, content_type="application/json"),
1023 ApiResponseWithout200,
1024 ),
1025 security(("token_jwt" = [])),
1026 tag = "v1/service_account",
1027 operation_id = "service_account_id_get_attr",
1028)]
1029pub async fn service_account_id_get_attr(
1030 State(state): State<ServerState>,
1031 Path((id, attr)): Path<(String, String)>,
1032 Extension(kopid): Extension<KOpId>,
1033 VerifiedClientInformation(client_auth_info): VerifiedClientInformation,
1034) -> Result<Json<Option<Vec<String>>>, WebError> {
1035 let filter = filter_all!(f_eq(Attribute::Class, EntryClass::Account.into()));
1036 json_rest_event_get_attr(state, id.as_str(), attr, filter, kopid, client_auth_info).await
1037}
1038
1039#[utoipa::path(
1040 post,
1041 path = "/v1/person/{id}/_attr/{attr}",
1042 request_body= Vec<String>,
1043 responses(
1044 DefaultApiResponse,
1045 ),
1046 security(("token_jwt" = [])),
1047 tag = "v1/person/attr",
1048 operation_id = "person_id_post_attr",
1049)]
1050pub async fn person_id_post_attr(
1051 State(state): State<ServerState>,
1052 Path((id, attr)): Path<(String, String)>,
1053 Extension(kopid): Extension<KOpId>,
1054 VerifiedClientInformation(client_auth_info): VerifiedClientInformation,
1055 Json(values): Json<Vec<String>>,
1056) -> Result<Json<()>, WebError> {
1057 let filter = filter_all!(f_eq(Attribute::Class, EntryClass::Account.into()));
1058 json_rest_event_post_id_attr(state, id, attr, filter, values, kopid, client_auth_info).await
1059}
1060
1061#[utoipa::path(
1062 post,
1063 path = "/v1/service_account/{id}/_attr/{attr}",
1064 request_body=Vec<String>,
1065 responses(
1066 DefaultApiResponse,
1067 ),
1068 security(("token_jwt" = [])),
1069 tag = "v1/service_account",
1070 operation_id = "service_account_id_post_attr",
1071)]
1072pub async fn service_account_id_post_attr(
1073 State(state): State<ServerState>,
1074 Path((id, attr)): Path<(String, String)>,
1075 Extension(kopid): Extension<KOpId>,
1076 VerifiedClientInformation(client_auth_info): VerifiedClientInformation,
1077 Json(values): Json<Vec<String>>,
1078) -> Result<Json<()>, WebError> {
1079 let filter = filter_all!(f_eq(Attribute::Class, EntryClass::Account.into()));
1080 json_rest_event_post_id_attr(state, id, attr, filter, values, kopid, client_auth_info).await
1081}
1082
1083#[utoipa::path(
1084 delete,
1085 path = "/v1/person/{id}/_attr/{attr}",
1086 responses(
1087 DefaultApiResponse,
1088 ),
1089 security(("token_jwt" = [])),
1090 tag = "v1/person/attr",
1091 operation_id = "person_id_delete_attr",
1092)]
1093pub async fn person_id_delete_attr(
1094 State(state): State<ServerState>,
1095 Path((id, attr)): Path<(String, String)>,
1096 Extension(kopid): Extension<KOpId>,
1097 VerifiedClientInformation(client_auth_info): VerifiedClientInformation,
1098) -> Result<Json<()>, WebError> {
1099 let filter = filter_all!(f_eq(Attribute::Class, EntryClass::Account.into()));
1100 json_rest_event_delete_id_attr(state, id, attr, filter, None, kopid, client_auth_info).await
1101}
1102
1103#[utoipa::path(
1104 delete,
1105 path = "/v1/service_account/{id}/_attr/{attr}",
1106 responses(
1107 DefaultApiResponse,
1108 ),
1109 security(("token_jwt" = [])),
1110 tag = "v1/service_account",
1111 operation_id = "service_account_id_delete_attr",
1112)]
1113pub async fn service_account_id_delete_attr(
1114 State(state): State<ServerState>,
1115 Path((id, attr)): Path<(String, String)>,
1116 Extension(kopid): Extension<KOpId>,
1117 VerifiedClientInformation(client_auth_info): VerifiedClientInformation,
1118) -> Result<Json<()>, WebError> {
1119 let filter = filter_all!(f_eq(Attribute::Class, EntryClass::Account.into()));
1120 json_rest_event_delete_id_attr(state, id, attr, filter, None, kopid, client_auth_info).await
1121}
1122
1123#[utoipa::path(
1124 put,
1125 path = "/v1/person/{id}/_attr/{attr}",
1126 responses(
1127 DefaultApiResponse,
1128 ),
1129 security(("token_jwt" = [])),
1130 tag = "v1/person/attr",
1131 operation_id = "person_id_put_attr",
1132)]
1133pub async fn person_id_put_attr(
1134 State(state): State<ServerState>,
1135 Path((id, attr)): Path<(String, String)>,
1136 Extension(kopid): Extension<KOpId>,
1137 VerifiedClientInformation(client_auth_info): VerifiedClientInformation,
1138 Json(values): Json<Vec<String>>,
1139) -> Result<Json<()>, WebError> {
1140 let filter = filter_all!(f_eq(Attribute::Class, EntryClass::Account.into()));
1141 json_rest_event_put_attr(state, id, attr, filter, values, kopid, client_auth_info).await
1142}
1143
1144#[utoipa::path(
1145 put,
1146 path = "/v1/service_account/{id}/_attr/{attr}",
1147 request_body=Vec<String>,
1148 responses(
1149 DefaultApiResponse,
1150 ),
1151 security(("token_jwt" = [])),
1152 tag = "v1/service_account",
1153 operation_id = "service_account_id_put_attr",
1154)]
1155pub async fn service_account_id_put_attr(
1156 State(state): State<ServerState>,
1157 Path((id, attr)): Path<(String, String)>,
1158 Extension(kopid): Extension<KOpId>,
1159 VerifiedClientInformation(client_auth_info): VerifiedClientInformation,
1160 Json(values): Json<Vec<String>>,
1161) -> Result<Json<()>, WebError> {
1162 let filter = filter_all!(f_eq(Attribute::Class, EntryClass::Account.into()));
1163 json_rest_event_put_attr(state, id, attr, filter, values, kopid, client_auth_info).await
1164}
1165
1166#[utoipa::path(
1167 patch,
1168 path = "/v1/person/{id}",
1169 responses(
1170 DefaultApiResponse,
1171 ),
1172 request_body=ProtoEntry,
1173 security(("token_jwt" = [])),
1174 tag = "v1/person",
1175 operation_id = "person_id_patch",
1176)]
1177pub async fn person_id_patch(
1178 State(state): State<ServerState>,
1179 Extension(kopid): Extension<KOpId>,
1180 VerifiedClientInformation(client_auth_info): VerifiedClientInformation,
1181 Path(id): Path<String>,
1182 Json(obj): Json<ProtoEntry>,
1183) -> Result<Json<()>, WebError> {
1184 let filter = filter_all!(f_eq(Attribute::Class, EntryClass::Account.into()));
1186 let filter = Filter::join_parts_and(filter, filter_all!(f_id(id.as_str())));
1187 state
1188 .qe_w_ref
1189 .handle_internalpatch(client_auth_info, filter, obj, kopid.eventid)
1190 .await
1191 .map(Json::from)
1192 .map_err(WebError::from)
1193}
1194
1195#[utoipa::path(
1196 get,
1197 path = "/v1/person/{id}/_credential/_update",
1198 responses(
1199 (status=200), ApiResponseWithout200,
1201 ),
1202 security(("token_jwt" = [])),
1203 tag = "v1/person/credential",
1204)]
1205pub async fn person_id_credential_update_get(
1206 State(state): State<ServerState>,
1207 Extension(kopid): Extension<KOpId>,
1208 VerifiedClientInformation(client_auth_info): VerifiedClientInformation,
1209 Path(id): Path<String>,
1210) -> Result<Json<(CUSessionToken, CUStatus)>, WebError> {
1211 state
1212 .qe_w_ref
1213 .handle_idmcredentialupdate(client_auth_info, id, kopid.eventid)
1214 .await
1215 .map(Json::from)
1216 .map_err(WebError::from)
1217}
1218
1219#[utoipa::path(
1220 get,
1221 path = "/v1/person/{id}/_credential/_update_intent/{ttl}",
1222 params(
1223 ("ttl" = u64, description="The new TTL for the credential?")
1224 ),
1225 responses(
1226 (status=200), ApiResponseWithout200,
1228 ),
1229 security(("token_jwt" = [])),
1230 tag = "v1/person/credential",
1231)]
1232#[instrument(level = "trace", skip(state, kopid))]
1234pub async fn person_id_credential_update_intent_ttl_get(
1235 State(state): State<ServerState>,
1236 Extension(kopid): Extension<KOpId>,
1237 VerifiedClientInformation(client_auth_info): VerifiedClientInformation,
1238 Path((id, ttl)): Path<(String, u64)>,
1239) -> Result<Json<CUIntentToken>, WebError> {
1240 state
1241 .qe_w_ref
1242 .handle_idmcredentialupdateintent(
1243 client_auth_info,
1244 id,
1245 Some(Duration::from_secs(ttl)),
1246 kopid.eventid,
1247 )
1248 .await
1249 .map(Json::from)
1250 .map_err(WebError::from)
1251}
1252
1253#[utoipa::path(
1254 get,
1255 path = "/v1/person/{id}/_credential/_update_intent",
1256 responses(
1257 (status=200), ApiResponseWithout200,
1259 ),
1260 security(("token_jwt" = [])),
1261 tag = "v1/person/credential",
1262)]
1263#[instrument(level = "trace", skip(state, kopid))]
1264pub async fn person_id_credential_update_intent_get(
1265 State(state): State<ServerState>,
1266 Extension(kopid): Extension<KOpId>,
1267 VerifiedClientInformation(client_auth_info): VerifiedClientInformation,
1268 Path(id): Path<String>,
1269) -> Result<Json<CUIntentToken>, WebError> {
1270 state
1271 .qe_w_ref
1272 .handle_idmcredentialupdateintent(client_auth_info, id, None, kopid.eventid)
1273 .await
1274 .map(Json::from)
1275 .map_err(WebError::from)
1276}
1277
1278#[utoipa::path(
1279 get,
1280 path = "/v1/account/{id}/_user_auth_token",
1281 responses(
1282 (status=200), ApiResponseWithout200,
1284 ),
1285 security(("token_jwt" = [])),
1286 tag = "v1/account",
1287)]
1288pub async fn account_id_user_auth_token_get(
1289 State(state): State<ServerState>,
1290 Path(id): Path<String>,
1291 Extension(kopid): Extension<KOpId>,
1292 VerifiedClientInformation(client_auth_info): VerifiedClientInformation,
1293) -> Result<Json<Vec<UatStatus>>, WebError> {
1294 state
1295 .qe_r_ref
1296 .handle_account_user_auth_token_get(client_auth_info, id, kopid.eventid)
1297 .await
1298 .map(Json::from)
1299 .map_err(WebError::from)
1300}
1301
1302#[utoipa::path(
1303 get,
1304 path = "/v1/account/{id}/_user_auth_token/{token_id}",
1305 responses(
1306 DefaultApiResponse,
1307 ),
1308 security(("token_jwt" = [])),
1309 tag = "v1/account",
1310)]
1311pub async fn account_user_auth_token_delete(
1312 State(state): State<ServerState>,
1313 Path((id, token_id)): Path<(String, Uuid)>,
1314 Extension(kopid): Extension<KOpId>,
1315 VerifiedClientInformation(client_auth_info): VerifiedClientInformation,
1316) -> Result<Json<()>, WebError> {
1317 state
1318 .qe_w_ref
1319 .handle_account_user_auth_token_destroy(client_auth_info, id, token_id, kopid.eventid)
1320 .await
1321 .map(Json::from)
1322 .map_err(WebError::from)
1323}
1324
1325#[utoipa::path(
1326 post,
1327 path = "/v1/credential/_exchange_intent",
1328 params(
1329 ),
1330 responses(
1331 (status=200), ApiResponseWithout200,
1333 ),
1334 security(("token_jwt" = [])),
1335 tag = "v1/credential",
1336)] pub async fn credential_update_exchange_intent(
1338 State(state): State<ServerState>,
1339 Extension(kopid): Extension<KOpId>,
1340 Json(intent_token): Json<String>,
1341) -> Result<Json<(CUSessionToken, CUStatus)>, WebError> {
1342 state
1343 .qe_w_ref
1344 .handle_idmcredentialexchangeintent(intent_token, kopid.eventid)
1345 .await
1346 .map(Json::from)
1347 .map_err(WebError::from)
1348}
1349
1350#[utoipa::path(
1351 post,
1352 path = "/v1/credential/_status",
1353 responses(
1354 (status=200), ApiResponseWithout200,
1356 ),
1357 security(("token_jwt" = [])),
1358 tag = "v1/credential",
1359)] pub async fn credential_update_status(
1361 State(state): State<ServerState>,
1362 Extension(kopid): Extension<KOpId>,
1363 Json(session_token): Json<CUSessionToken>,
1364) -> Result<Json<CUStatus>, WebError> {
1365 state
1366 .qe_r_ref
1367 .handle_idmcredentialupdatestatus(session_token, kopid.eventid)
1368 .await
1369 .map(Json::from)
1370 .map_err(WebError::from)
1371}
1372
1373#[utoipa::path(
1374 post,
1375 path = "/v1/credential/_update",
1376 responses(
1377 (status=200, body=CUStatus), ApiResponseWithout200,
1379 ),
1380 security(("token_jwt" = [])),
1381 tag = "v1/credential",
1382)] #[instrument(level = "debug", skip(state, kopid))]
1384pub async fn credential_update_update(
1385 State(state): State<ServerState>,
1386 Extension(kopid): Extension<KOpId>,
1387 Json(cubody): Json<Vec<serde_json::Value>>,
1388) -> Result<Json<CUStatus>, WebError> {
1389 let scr: CURequest = match serde_json::from_value(cubody[0].clone()) {
1390 Ok(val) => val,
1391 Err(err) => {
1392 let errmsg = format!("Failed to deserialize CURequest: {err:?}");
1393 error!("{}", errmsg);
1394 return Err(WebError::InternalServerError(errmsg));
1395 }
1396 };
1397
1398 let session_token = match serde_json::from_value(cubody[1].clone()) {
1399 Ok(val) => val,
1400 Err(err) => {
1401 let errmsg = format!("Failed to deserialize session token: {err:?}");
1402 error!("{}", errmsg);
1403 return Err(WebError::InternalServerError(errmsg));
1404 }
1405 };
1406 debug!("session_token: {:?}", session_token);
1407 debug!("scr: {:?}", scr);
1408
1409 state
1410 .qe_r_ref
1411 .handle_idmcredentialupdate(session_token, scr, kopid.eventid)
1412 .await
1413 .map(Json::from)
1414 .map_err(WebError::from)
1415}
1416
1417#[utoipa::path(
1418 post,
1419 path = "/v1/credential/_commit",
1420 responses(
1421 DefaultApiResponse,
1422 ),
1423 security(("token_jwt" = [])),
1424 tag = "v1/credential",
1425)] pub async fn credential_update_commit(
1427 State(state): State<ServerState>,
1428 Extension(kopid): Extension<KOpId>,
1429 Json(session_token): Json<CUSessionToken>,
1430) -> Result<Json<()>, WebError> {
1431 state
1432 .qe_w_ref
1433 .handle_idmcredentialupdatecommit(session_token, kopid.eventid)
1434 .await
1435 .map(Json::from)
1436 .map_err(WebError::from)
1437}
1438
1439#[utoipa::path(
1440 post,
1441 path = "/v1/credential/_cancel",
1442 request_body=CUSessionToken,
1443 responses(
1444 DefaultApiResponse,
1445 ),
1446 security(("token_jwt" = [])),
1447 tag = "v1/credential",
1448)]
1449pub async fn credential_update_cancel(
1450 State(state): State<ServerState>,
1451 Extension(kopid): Extension<KOpId>,
1452 Json(session_token): Json<CUSessionToken>,
1453) -> Result<Json<()>, WebError> {
1454 state
1455 .qe_w_ref
1456 .handle_idmcredentialupdatecancel(session_token, kopid.eventid)
1457 .await
1458 .map(Json::from)
1459 .map_err(WebError::from)
1460}
1461
1462#[utoipa::path(
1463 get,
1464 path = "/v1/service_account/{id}/_credential/_status",
1465 responses(
1466 (status=200), ApiResponseWithout200,
1468 ),
1469 security(("token_jwt" = [])),
1470 tag = "v1/service_account",
1471)]
1472pub async fn service_account_id_credential_status_get(
1473 State(state): State<ServerState>,
1474 Extension(kopid): Extension<KOpId>,
1475 VerifiedClientInformation(client_auth_info): VerifiedClientInformation,
1476 Path(id): Path<String>,
1477) -> Result<Json<CredentialStatus>, WebError> {
1478 match state
1479 .qe_r_ref
1480 .handle_idmcredentialstatus(client_auth_info, id.clone(), kopid.eventid)
1481 .await
1482 .map(Json::from)
1483 {
1484 Ok(val) => Ok(val),
1485 Err(err) => {
1486 if let OperationError::NoMatchingAttributes = err {
1487 debug!("No credentials set on account {}, returning empty list", id);
1488 Ok(Json(CredentialStatus { creds: Vec::new() }))
1489 } else {
1490 Err(WebError::from(err))
1491 }
1492 }
1493 }
1494}
1495
1496#[utoipa::path(
1497 get,
1498 path = "/v1/person/{id}/_credential/_status",
1499 responses(
1500 (status=200), ApiResponseWithout200,
1502 ),
1503 security(("token_jwt" = [])),
1504 tag = "v1/person/credential",
1505)]
1506pub async fn person_get_id_credential_status(
1507 State(state): State<ServerState>,
1508 Extension(kopid): Extension<KOpId>,
1509 VerifiedClientInformation(client_auth_info): VerifiedClientInformation,
1510 Path(id): Path<String>,
1511) -> Result<Json<CredentialStatus>, WebError> {
1512 match state
1513 .qe_r_ref
1514 .handle_idmcredentialstatus(client_auth_info, id.clone(), kopid.eventid)
1515 .await
1516 .map(Json::from)
1517 {
1518 Ok(val) => Ok(val),
1519 Err(err) => {
1520 if let OperationError::NoMatchingAttributes = err {
1521 debug!("No credentials set on person {}, returning empty list", id);
1522 Ok(Json(CredentialStatus { creds: Vec::new() }))
1523 } else {
1524 Err(WebError::from(err))
1525 }
1526 }
1527 }
1528}
1529
1530#[utoipa::path(
1531 get,
1532 path = "/v1/person/{id}/_ssh_pubkeys",
1533 responses(
1534 (status=200, body=Vec<String>, content_type="application/json"),
1535 ApiResponseWithout200,
1536 ),
1537 security(("token_jwt" = [])),
1538 tag = "v1/person/ssh_pubkeys",
1539 operation_id = "person_id_ssh_pubkeys_get",
1540)]
1541pub async fn person_id_ssh_pubkeys_get(
1542 State(state): State<ServerState>,
1543 Extension(kopid): Extension<KOpId>,
1544 VerifiedClientInformation(client_auth_info): VerifiedClientInformation,
1545 Path(id): Path<String>,
1546) -> Result<Json<Vec<String>>, WebError> {
1547 state
1548 .qe_r_ref
1549 .handle_internalsshkeyread(client_auth_info, id, kopid.eventid)
1550 .await
1551 .map(Json::from)
1552 .map_err(WebError::from)
1553}
1554
1555#[utoipa::path(
1556 get,
1557 path = "/v1/account/{id}/_ssh_pubkeys",
1558 responses(
1559 (status=200, body=Vec<String>, content_type="application/json"),
1560 ApiResponseWithout200,
1561 ),
1562 security(("token_jwt" = [])),
1563 tag = "v1/account",
1564 operation_id = "account_id_ssh_pubkeys_get",
1565)]
1566#[deprecated]
1567pub async fn account_id_ssh_pubkeys_get(
1568 State(state): State<ServerState>,
1569 Extension(kopid): Extension<KOpId>,
1570 VerifiedClientInformation(client_auth_info): VerifiedClientInformation,
1571 Path(id): Path<String>,
1572) -> Result<Json<Vec<String>>, WebError> {
1573 state
1574 .qe_r_ref
1575 .handle_internalsshkeyread(client_auth_info, id, kopid.eventid)
1576 .await
1577 .map(Json::from)
1578 .map_err(WebError::from)
1579}
1580
1581#[utoipa::path(
1582 get,
1583 path = "/v1/service_account/{id}/_ssh_pubkeys",
1584 responses(
1585 (status=200, body=Vec<String>, content_type="application/json"),
1586 ApiResponseWithout200,
1587 ),
1588 security(("token_jwt" = [])),
1589 tag = "v1/service_account",
1590 operation_id = "service_account_id_ssh_pubkeys_get",
1591)]
1592pub async fn service_account_id_ssh_pubkeys_get(
1593 State(state): State<ServerState>,
1594 Extension(kopid): Extension<KOpId>,
1595 VerifiedClientInformation(client_auth_info): VerifiedClientInformation,
1596 Path(id): Path<String>,
1597) -> Result<Json<Vec<String>>, WebError> {
1598 state
1599 .qe_r_ref
1600 .handle_internalsshkeyread(client_auth_info, id, kopid.eventid)
1601 .await
1602 .map(Json::from)
1603 .map_err(WebError::from)
1604}
1605
1606#[utoipa::path(
1607 post,
1608 path = "/v1/person/{id}/_ssh_pubkeys",
1609 responses(
1610 DefaultApiResponse,
1611 (status=422, description="Unprocessable Entity", body=String, content_type="text/plain"),
1612 ),
1613 security(("token_jwt" = [])),
1614 tag = "v1/person/ssh_pubkeys",
1615 operation_id = "person_id_ssh_pubkeys_post",
1616)]
1617pub async fn person_id_ssh_pubkeys_post(
1618 State(state): State<ServerState>,
1619 Extension(kopid): Extension<KOpId>,
1620 VerifiedClientInformation(client_auth_info): VerifiedClientInformation,
1621 Path(id): Path<String>,
1622 Json((tag, key)): Json<(String, String)>,
1623) -> Result<Json<()>, WebError> {
1624 let filter = filter_all!(f_eq(Attribute::Class, EntryClass::Account.into()));
1625 state
1627 .qe_w_ref
1628 .handle_sshkeycreate(client_auth_info, id, &tag, &key, filter, kopid.eventid)
1629 .await
1630 .map(Json::from)
1631 .map_err(WebError::from)
1632}
1633
1634#[utoipa::path(
1635 post,
1636 path = "/v1/service_account/{id}/_ssh_pubkeys",
1637 request_body = (String, String),
1638 responses(
1639 DefaultApiResponse,
1640 (status=422, description="Unprocessable Entity", body=String, content_type="text/plain"),
1641 ),
1642 security(("token_jwt" = [])),
1643 tag = "v1/service_account",
1644 operation_id = "service_account_id_ssh_pubkeys_post",
1645)]
1646pub async fn service_account_id_ssh_pubkeys_post(
1647 State(state): State<ServerState>,
1648 Extension(kopid): Extension<KOpId>,
1649 VerifiedClientInformation(client_auth_info): VerifiedClientInformation,
1650 Path(id): Path<String>,
1651 Json((tag, key)): Json<(String, String)>,
1652) -> Result<Json<()>, WebError> {
1653 let filter = filter_all!(f_eq(Attribute::Class, EntryClass::Account.into()));
1654 state
1656 .qe_w_ref
1657 .handle_sshkeycreate(client_auth_info, id, &tag, &key, filter, kopid.eventid)
1658 .await
1659 .map(Json::from)
1660 .map_err(WebError::from)
1661}
1662
1663#[utoipa::path(
1664 get,
1665 path = "/v1/person/{id}/_ssh_pubkeys/{tag}",
1666 responses(
1667 (status=200, body=String, content_type="application/json"),
1668 ApiResponseWithout200,
1669 ),
1670 security(("token_jwt" = [])),
1671 tag = "v1/person/ssh_pubkeys",
1672 operation_id = "person_id_ssh_pubkeys_tag_get",
1673)]
1674pub async fn person_id_ssh_pubkeys_tag_get(
1675 State(state): State<ServerState>,
1676 Extension(kopid): Extension<KOpId>,
1677 VerifiedClientInformation(client_auth_info): VerifiedClientInformation,
1678 Path((id, tag)): Path<(String, String)>,
1679) -> Result<Json<Option<String>>, WebError> {
1680 state
1681 .qe_r_ref
1682 .handle_internalsshkeytagread(client_auth_info, id, tag, kopid.eventid)
1683 .await
1684 .map(Json::from)
1685 .map_err(WebError::from)
1686}
1687#[utoipa::path(
1688 get,
1689 path = "/v1/account/{id}/_ssh_pubkeys/{tag}",
1690 responses(
1691 (status=200, body=String, content_type="application/json"),
1692 ApiResponseWithout200,
1693 ),
1694 security(("token_jwt" = [])),
1695 tag = "v1/account",
1696 operation_id = "account_id_ssh_pubkeys_tag_get",
1697)]
1698pub async fn account_id_ssh_pubkeys_tag_get(
1699 State(state): State<ServerState>,
1700 Extension(kopid): Extension<KOpId>,
1701 VerifiedClientInformation(client_auth_info): VerifiedClientInformation,
1702 Path((id, tag)): Path<(String, String)>,
1703) -> Result<Json<Option<String>>, WebError> {
1704 state
1705 .qe_r_ref
1706 .handle_internalsshkeytagread(client_auth_info, id, tag, kopid.eventid)
1707 .await
1708 .map(Json::from)
1709 .map_err(WebError::from)
1710}
1711
1712#[utoipa::path(
1713 get,
1714 path = "/v1/service_account/{id}/_ssh_pubkeys/{tag}",
1715 responses(
1716 (status=200, body=String, content_type="application/json"),
1717 ApiResponseWithout200,
1718 ),
1719 security(("token_jwt" = [])),
1720 tag = "v1/service_account",
1721 operation_id = "service_account_id_ssh_pubkeys_tag_get",
1722)]
1723pub async fn service_account_id_ssh_pubkeys_tag_get(
1724 State(state): State<ServerState>,
1725 Extension(kopid): Extension<KOpId>,
1726 VerifiedClientInformation(client_auth_info): VerifiedClientInformation,
1727 Path((id, tag)): Path<(String, String)>,
1728) -> Result<Json<Option<String>>, WebError> {
1729 state
1730 .qe_r_ref
1731 .handle_internalsshkeytagread(client_auth_info, id, tag, kopid.eventid)
1732 .await
1733 .map(Json::from)
1734 .map_err(WebError::from)
1735}
1736
1737#[utoipa::path(
1738 delete,
1739 path = "/v1/person/{id}/_ssh_pubkeys/{tag}",
1740 params(
1741 ("tag" = String, description="The tag of the SSH key"),
1742 ),
1743 responses(
1744 DefaultApiResponse,
1745 ),
1746 security(("token_jwt" = [])),
1747 tag = "v1/person/ssh_pubkeys",
1748 operation_id = "person_id_ssh_pubkeys_tag_delete",
1749)]
1750pub async fn person_id_ssh_pubkeys_tag_delete(
1751 State(state): State<ServerState>,
1752 Extension(kopid): Extension<KOpId>,
1753 VerifiedClientInformation(client_auth_info): VerifiedClientInformation,
1754 Path((id, tag)): Path<(String, String)>,
1755) -> Result<Json<()>, WebError> {
1756 let values = vec![tag];
1757 let filter = filter_all!(f_eq(Attribute::Class, EntryClass::Account.into()));
1758 state
1759 .qe_w_ref
1760 .handle_removeattributevalues(
1761 client_auth_info,
1762 id,
1763 Attribute::SshPublicKey.to_string(),
1764 values,
1765 filter,
1766 kopid.eventid,
1767 )
1768 .await
1769 .map(Json::from)
1770 .map_err(WebError::from)
1771}
1772
1773#[utoipa::path(
1774 delete,
1775 path = "/v1/service_account/{id}/_ssh_pubkeys/{tag}",
1776 params(
1777 ("tag" = String, description="The tag of the SSH key"),
1778 ),
1779 responses(
1780 DefaultApiResponse,
1781 ),
1782 security(("token_jwt" = [])),
1783 tag = "v1/service_account",
1784 operation_id = "service_account_id_ssh_pubkeys_tag_delete",
1785)]
1786pub async fn service_account_id_ssh_pubkeys_tag_delete(
1787 State(state): State<ServerState>,
1788 Extension(kopid): Extension<KOpId>,
1789 VerifiedClientInformation(client_auth_info): VerifiedClientInformation,
1790 Path((id, tag)): Path<(String, String)>,
1791) -> Result<Json<()>, WebError> {
1792 let values = vec![tag];
1793 let filter = filter_all!(f_eq(Attribute::Class, EntryClass::Account.into()));
1794 state
1795 .qe_w_ref
1796 .handle_removeattributevalues(
1797 client_auth_info,
1798 id,
1799 Attribute::SshPublicKey.to_string(),
1800 values,
1801 filter,
1802 kopid.eventid,
1803 )
1804 .await
1805 .map(Json::from)
1806 .map_err(WebError::from)
1807}
1808
1809#[utoipa::path(
1810 get,
1811 path = "/v1/person/{id}/_radius",
1812 responses(
1813 (status=200), ApiResponseWithout200,
1815 ),
1816 security(("token_jwt" = [])),
1817 tag = "v1/person/radius",
1818 operation_id = "person_id_radius_get"
1819)]
1820pub async fn person_id_radius_get(
1822 State(state): State<ServerState>,
1823 Extension(kopid): Extension<KOpId>,
1824 VerifiedClientInformation(client_auth_info): VerifiedClientInformation,
1825 Path(id): Path<String>,
1826) -> Result<Json<Option<String>>, WebError> {
1827 state
1829 .qe_r_ref
1830 .handle_internalradiusread(client_auth_info, id, kopid.eventid)
1831 .await
1832 .map(Json::from)
1833 .map_err(WebError::from)
1834}
1835
1836#[utoipa::path(
1837 post,
1838 path = "/v1/person/{id}/_radius",
1839 responses(
1840 (status=200), ApiResponseWithout200,
1842 ),
1843 security(("token_jwt" = [])),
1844 tag = "v1/person/radius",
1845 operation_id = "person_id_radius_post"
1846)]
1847pub async fn person_id_radius_post(
1848 State(state): State<ServerState>,
1849 Extension(kopid): Extension<KOpId>,
1850 VerifiedClientInformation(client_auth_info): VerifiedClientInformation,
1851 Path(id): Path<String>,
1852) -> Result<Json<String>, WebError> {
1853 state
1855 .qe_w_ref
1856 .handle_regenerateradius(client_auth_info, id, kopid.eventid)
1857 .await
1858 .map(Json::from)
1859 .map_err(WebError::from)
1860}
1861
1862#[utoipa::path(
1863 delete,
1864 path = "/v1/person/{id}/_radius",
1865 responses(
1866 DefaultApiResponse,
1867 ),
1868 security(("token_jwt" = [])),
1869 tag = "v1/person/radius",
1870 operation_id = "person_id_radius_delete"
1871)]
1872pub async fn person_id_radius_delete(
1873 State(state): State<ServerState>,
1874 Path(id): Path<String>,
1875 Extension(kopid): Extension<KOpId>,
1876 VerifiedClientInformation(client_auth_info): VerifiedClientInformation,
1877) -> Result<Json<()>, WebError> {
1878 let attr = "radius_secret".to_string();
1879 let filter = filter_all!(f_eq(Attribute::Class, EntryClass::Account.into()));
1880 json_rest_event_delete_id_attr(state, id, attr, filter, None, kopid, client_auth_info).await
1881}
1882
1883#[utoipa::path(
1884 get,
1885 path = "/v1/person/{id}/_radius/_token",
1886 responses(
1887 (status=200, body=RadiusAuthToken, content_type="application/json"),
1888 ApiResponseWithout200,
1889 ),
1890 security(("token_jwt" = [])),
1891 tag = "v1/person/radius",
1892 operation_id = "person_id_radius_token_get"
1893)]
1894pub async fn person_id_radius_token_get(
1895 State(state): State<ServerState>,
1896 Path(id): Path<String>,
1897 Extension(kopid): Extension<KOpId>,
1898 VerifiedClientInformation(client_auth_info): VerifiedClientInformation,
1899) -> Result<Json<RadiusAuthToken>, WebError> {
1900 person_id_radius_handler(state, id, kopid, client_auth_info).await
1901}
1902
1903#[utoipa::path(
1905 get,
1906 path = "/v1/account/{id}/_radius/_token",
1907 responses(
1908 (status=200, body=RadiusAuthToken, content_type="application/json"),
1909 ApiResponseWithout200,
1910 ),
1911 security(("token_jwt" = [])),
1912 tag = "v1/account",
1913 operation_id = "account_id_radius_token_get"
1914)]
1915pub async fn account_id_radius_token_get(
1916 State(state): State<ServerState>,
1917 Path(id): Path<String>,
1918 Extension(kopid): Extension<KOpId>,
1919 VerifiedClientInformation(client_auth_info): VerifiedClientInformation,
1920) -> Result<Json<RadiusAuthToken>, WebError> {
1921 person_id_radius_handler(state, id, kopid, client_auth_info).await
1922}
1923
1924#[utoipa::path(
1925 post,
1926 path = "/v1/account/{id}/_radius/_token",
1927 responses(
1928 (status=200, body=RadiusAuthToken, content_type="application/json"),
1929 ApiResponseWithout200,
1930 ),
1931 security(("token_jwt" = [])),
1932 tag = "v1/account",
1933 operation_id = "account_id_radius_token_post"
1934)]
1935pub async fn account_id_radius_token_post(
1936 State(state): State<ServerState>,
1937 Path(id): Path<String>,
1938 Extension(kopid): Extension<KOpId>,
1939 VerifiedClientInformation(client_auth_info): VerifiedClientInformation,
1940) -> Result<Json<RadiusAuthToken>, WebError> {
1941 person_id_radius_handler(state, id, kopid, client_auth_info).await
1942}
1943
1944async fn person_id_radius_handler(
1945 state: ServerState,
1946 id: String,
1947 kopid: KOpId,
1948 client_auth_info: ClientAuthInfo,
1949) -> Result<Json<RadiusAuthToken>, WebError> {
1950 state
1951 .qe_r_ref
1952 .handle_internalradiustokenread(client_auth_info, id, kopid.eventid)
1953 .await
1954 .map(Json::from)
1955 .map_err(WebError::from)
1956}
1957
1958#[utoipa::path(
1959 post,
1960 path = "/v1/person/{id}/_unix",
1961 request_body=AccountUnixExtend,
1962 responses(
1963 DefaultApiResponse,
1964 ),
1965 security(("token_jwt" = [])),
1966 tag = "v1/person/unix",
1967)]
1968#[instrument(name = "account_post_id_unix", level = "INFO", skip(id, state, kopid))]
1969pub async fn person_id_unix_post(
1970 State(state): State<ServerState>,
1971 Path(id): Path<String>,
1972 Extension(kopid): Extension<KOpId>,
1973 VerifiedClientInformation(client_auth_info): VerifiedClientInformation,
1974 Json(obj): Json<AccountUnixExtend>,
1975) -> Result<Json<()>, WebError> {
1976 state
1977 .qe_w_ref
1978 .handle_idmaccountunixextend(client_auth_info, id, obj, kopid.eventid)
1979 .await
1980 .map(Json::from)
1981 .map_err(WebError::from)
1982}
1983
1984#[utoipa::path(
1985 post,
1986 path = "/v1/service_account/{id}/_unix",
1987 request_body = AccountUnixExtend,
1988 responses(
1989 DefaultApiResponse,
1990 ),
1991 security(("token_jwt" = [])),
1992 tag = "v1/service_account",
1993)]
1994#[instrument(, level = "INFO", skip(id, state, kopid))]
1995pub async fn service_account_id_unix_post(
1996 State(state): State<ServerState>,
1997 Path(id): Path<String>,
1998 Extension(kopid): Extension<KOpId>,
1999 VerifiedClientInformation(client_auth_info): VerifiedClientInformation,
2000 Json(obj): Json<AccountUnixExtend>,
2001) -> Result<Json<()>, WebError> {
2002 state
2003 .qe_w_ref
2004 .handle_idmaccountunixextend(client_auth_info, id, obj, kopid.eventid)
2005 .await
2006 .map(Json::from)
2007 .map_err(WebError::from)
2008}
2009
2010#[utoipa::path(
2011 get,post,
2012 path = "/v1/account/{id}/_unix/_token",
2013 responses(
2014 (status=200, body=UnixUserToken, content_type="application/json"),
2015 ApiResponseWithout200,
2016 ),
2017 security(("token_jwt" = [])),
2018 tag = "v1/account",
2019 operation_id = "account_id_unix_token"
2020)]
2021#[instrument(level = "INFO", skip_all)]
2022pub async fn account_id_unix_token(
2023 State(state): State<ServerState>,
2024 Extension(kopid): Extension<KOpId>,
2025 VerifiedClientInformation(client_auth_info): VerifiedClientInformation,
2026 Path(id): Path<String>,
2027) -> Result<Json<UnixUserToken>, WebError> {
2028 if id.is_empty() {
2030 return Err(OperationError::EmptyRequest.into());
2031 }
2032
2033 let res = state
2034 .qe_r_ref
2035 .handle_internalunixusertokenread(client_auth_info, id, kopid.eventid)
2036 .await
2037 .map(Json::from);
2038
2039 if let Err(OperationError::MissingClass(class)) = &res {
2041 if class == ENTRYCLASS_POSIX_ACCOUNT {
2042 return Err(OperationError::NoMatchingEntries.into());
2043 }
2044 };
2045 if let Err(OperationError::InvalidValueState) = &res {
2047 return Err(OperationError::NoMatchingEntries.into());
2048 };
2049 res.map_err(WebError::from)
2050}
2051
2052#[utoipa::path(
2053 post,
2054 path = "/v1/account/{id}/_unix/_auth",
2055 responses(
2056 (status=200, body=Option<UnixUserToken>, content_type="application/json"),
2057 ApiResponseWithout200,
2058 ),
2059 security(("token_jwt" = [])),
2060 tag = "v1/account",
2061 operation_id = "account_id_unix_auth_post"
2062)]
2063pub async fn account_id_unix_auth_post(
2064 State(state): State<ServerState>,
2065 Extension(kopid): Extension<KOpId>,
2066 VerifiedClientInformation(client_auth_info): VerifiedClientInformation,
2067 Path(id): Path<String>,
2068 Json(obj): Json<SingleStringRequest>,
2069) -> Result<Json<Option<UnixUserToken>>, WebError> {
2070 state
2071 .qe_r_ref
2072 .handle_idmaccountunixauth(client_auth_info, id, obj.value, kopid.eventid)
2073 .await
2074 .map(Json::from)
2075 .map_err(WebError::from)
2076}
2077
2078#[utoipa::path(
2079 put,
2080 path = "/v1/person/{id}/_unix/_credential",
2081 request_body = SingleStringRequest,
2082 responses(
2083 DefaultApiResponse,
2084 ),
2085 security(("token_jwt" = [])),
2086 tag = "v1/person/unix",
2087 operation_id = "person_id_unix_credential_put"
2088)]
2089pub async fn person_id_unix_credential_put(
2090 State(state): State<ServerState>,
2091 Extension(kopid): Extension<KOpId>,
2092 VerifiedClientInformation(client_auth_info): VerifiedClientInformation,
2093 Path(id): Path<String>,
2094 Json(obj): Json<SingleStringRequest>,
2095) -> Result<Json<()>, WebError> {
2096 state
2097 .qe_w_ref
2098 .handle_idmaccountunixsetcred(client_auth_info, id, obj.value, kopid.eventid)
2099 .await
2100 .map(Json::from)
2101 .map_err(WebError::from)
2102}
2103
2104#[utoipa::path(
2105 delete,
2106 path = "/v1/person/{id}/_unix/_credential",
2107 responses(
2108 DefaultApiResponse,
2109 ),
2110 security(("token_jwt" = [])),
2111 tag = "v1/person/unix",
2112 operation_id = "person_id_unix_credential_delete"
2113)]
2114pub async fn person_id_unix_credential_delete(
2115 State(state): State<ServerState>,
2116 Extension(kopid): Extension<KOpId>,
2117 VerifiedClientInformation(client_auth_info): VerifiedClientInformation,
2118 Path(id): Path<String>,
2119) -> Result<Json<()>, WebError> {
2120 let filter = filter_all!(f_eq(Attribute::Class, EntryClass::PosixAccount.into()));
2121 state
2122 .qe_w_ref
2123 .handle_purgeattribute(
2124 client_auth_info,
2125 id,
2126 "unix_password".to_string(),
2127 filter,
2128 kopid.eventid,
2129 )
2130 .await
2131 .map(Json::from)
2132 .map_err(WebError::from)
2133}
2134
2135#[utoipa::path(
2136 post,
2137 path = "/v1/person/{id}/_identify/_user",
2138 responses(
2139 (status=200, body=IdentifyUserResponse, content_type="application/json"),
2140 ApiResponseWithout200,
2141 ),
2142 security(("token_jwt" = [])),
2143 tag = "v1/person",
2144 operation_id = "person_identify_user_post"
2145)]
2146pub async fn person_identify_user_post(
2147 State(state): State<ServerState>,
2148 Extension(kopid): Extension<KOpId>,
2149 VerifiedClientInformation(client_auth_info): VerifiedClientInformation,
2150 Path(id): Path<String>,
2151 Json(user_request): Json<IdentifyUserRequest>,
2152) -> Result<Json<IdentifyUserResponse>, WebError> {
2153 state
2154 .qe_r_ref
2155 .handle_user_identity_verification(client_auth_info, kopid.eventid, user_request, id)
2156 .await
2157 .map(Json::from)
2158 .map_err(WebError::from)
2159}
2160
2161#[utoipa::path(
2162 get,
2163 path = "/v1/group",
2164 responses(
2165 (status=200,body=Vec<ProtoEntry>, content_type="application/json"),
2166 ApiResponseWithout200,
2167 ),
2168 security(("token_jwt" = [])),
2169 tag = "v1/group",
2170 operation_id = "group_get",
2171)]
2172pub async fn group_get(
2174 State(state): State<ServerState>,
2175 Extension(kopid): Extension<KOpId>,
2176 VerifiedClientInformation(client_auth_info): VerifiedClientInformation,
2177) -> Result<Json<Vec<ProtoEntry>>, WebError> {
2178 let filter = filter_all!(f_eq(Attribute::Class, EntryClass::Group.into()));
2179 json_rest_event_get(state, None, filter, kopid, client_auth_info).await
2180}
2181
2182#[utoipa::path(
2183 get,
2184 path = "/v1/group/_search/{id}",
2185 responses(
2186 (status=200, body=Option<ProtoEntry>, content_type="application/json"),
2187 ApiResponseWithout200,
2188 ),
2189 security(("token_jwt" = [])),
2190 tag = "v1/group",
2191 operation_id = "group_search_id",
2192)]
2193pub async fn group_search_id(
2194 State(state): State<ServerState>,
2195 Extension(kopid): Extension<KOpId>,
2196 VerifiedClientInformation(client_auth_info): VerifiedClientInformation,
2197 Path(id): Path<String>,
2198) -> Result<Json<Vec<ProtoEntry>>, WebError> {
2199 let filter = filter_all!(f_and!([
2200 f_eq(Attribute::Class, EntryClass::Group.into()),
2201 f_sub(Attribute::Name, PartialValue::new_iname(&id))
2202 ]));
2203 json_rest_event_get(state, None, filter, kopid, client_auth_info).await
2204}
2205
2206#[utoipa::path(
2207 post,
2208 path = "/v1/group",
2209 responses(
2210 DefaultApiResponse,
2211 ),
2212 security(("token_jwt" = [])),
2213 tag = "v1/group",
2214 operation_id = "group_post",
2215)]
2216pub async fn group_post(
2217 State(state): State<ServerState>,
2218 Extension(kopid): Extension<KOpId>,
2219 VerifiedClientInformation(client_auth_info): VerifiedClientInformation,
2220 Json(obj): Json<ProtoEntry>,
2221) -> Result<Json<()>, WebError> {
2222 let classes = vec!["group".to_string(), "object".to_string()];
2223 json_rest_event_post(state, classes, obj, kopid, client_auth_info).await
2224}
2225
2226#[utoipa::path(
2227 get,
2228 path = "/v1/group/{id}",
2229 responses(
2230 (status=200, body=Option<ProtoEntry>, content_type="application/json"),
2231 ApiResponseWithout200,
2232 ),
2233 security(("token_jwt" = [])),
2234 tag = "v1/group",
2235 operation_id = "group_id_get",
2236)]
2237pub async fn group_id_get(
2238 State(state): State<ServerState>,
2239 Extension(kopid): Extension<KOpId>,
2240 VerifiedClientInformation(client_auth_info): VerifiedClientInformation,
2241 Path(id): Path<String>,
2242) -> Result<Json<Option<ProtoEntry>>, WebError> {
2243 let filter = filter_all!(f_eq(Attribute::Class, EntryClass::Group.into()));
2244 json_rest_event_get_id(state, id, filter, None, kopid, client_auth_info).await
2245}
2246
2247#[utoipa::path(
2248 patch,
2249 path = "/v1/group/{id}",
2250 responses(
2251 DefaultApiResponse,
2252 ),
2253 request_body=ProtoEntry,
2254 security(("token_jwt" = [])),
2255 tag = "v1/group",
2256 operation_id = "group_id_patch",
2257)]
2258pub async fn group_id_patch(
2259 State(state): State<ServerState>,
2260 Extension(kopid): Extension<KOpId>,
2261 VerifiedClientInformation(client_auth_info): VerifiedClientInformation,
2262 Path(id): Path<String>,
2263 Json(obj): Json<ProtoEntry>,
2264) -> Result<Json<()>, WebError> {
2265 let filter = filter_all!(f_eq(Attribute::Class, EntryClass::Group.into()));
2267 let filter = Filter::join_parts_and(filter, filter_all!(f_id(id.as_str())));
2268 state
2269 .qe_w_ref
2270 .handle_internalpatch(client_auth_info, filter, obj, kopid.eventid)
2271 .await
2272 .map(Json::from)
2273 .map_err(WebError::from)
2274}
2275
2276#[utoipa::path(
2277 delete,
2278 path = "/v1/group/{id}",
2279 responses(
2280 DefaultApiResponse,
2281 ),
2282 security(("token_jwt" = [])),
2283 tag = "v1/group",
2284 operation_id = "group_id_delete",
2285)]
2286pub async fn group_id_delete(
2287 State(state): State<ServerState>,
2288 Extension(kopid): Extension<KOpId>,
2289 VerifiedClientInformation(client_auth_info): VerifiedClientInformation,
2290 Path(id): Path<String>,
2291) -> Result<Json<()>, WebError> {
2292 let filter = filter_all!(f_eq(Attribute::Class, EntryClass::Group.into()));
2293 json_rest_event_delete_id(state, id, filter, kopid, client_auth_info).await
2294}
2295
2296#[utoipa::path(
2297 get,
2298 path = "/v1/group/{id}/_attr/{attr}",
2299 responses(
2300 (status=200, body=Vec<String>, content_type="application/json"),
2301 ApiResponseWithout200,
2302 ),
2303 security(("token_jwt" = [])),
2304 tag = "v1/group/attr",
2305 operation_id = "group_id_attr_get",
2306)]
2307pub async fn group_id_attr_get(
2308 State(state): State<ServerState>,
2309 Path((id, attr)): Path<(String, String)>,
2310 Extension(kopid): Extension<KOpId>,
2311 VerifiedClientInformation(client_auth_info): VerifiedClientInformation,
2312) -> Result<Json<Option<Vec<String>>>, WebError> {
2313 let filter = filter_all!(f_eq(Attribute::Class, EntryClass::Group.into()));
2314 json_rest_event_get_id_attr(state, id, attr, filter, kopid, client_auth_info).await
2315}
2316
2317#[utoipa::path(
2318 post,
2319 path = "/v1/group/{id}/_attr/{attr}",
2320 request_body=Vec<String>,
2321 responses(
2322 DefaultApiResponse,
2323 ),
2324 security(("token_jwt" = [])),
2325 tag = "v1/group/attr",
2326 operation_id = "group_id_attr_post",
2327)]
2328pub async fn group_id_attr_post(
2329 Path((id, attr)): Path<(String, String)>,
2330 State(state): State<ServerState>,
2331 Extension(kopid): Extension<KOpId>,
2332 VerifiedClientInformation(client_auth_info): VerifiedClientInformation,
2333 Json(values): Json<Vec<String>>,
2334) -> Result<Json<()>, WebError> {
2335 let filter = filter_all!(f_eq(Attribute::Class, EntryClass::Group.into()));
2336 json_rest_event_post_id_attr(state, id, attr, filter, values, kopid, client_auth_info).await
2337}
2338
2339#[utoipa::path(
2340 delete,
2341 path = "/v1/group/{id}/_attr/{attr}",
2342 request_body=Option<Vec<String>>,
2343 responses(
2344 DefaultApiResponse,
2345 ),
2346 security(("token_jwt" = [])),
2347 tag = "v1/group/attr",
2348 operation_id = "group_id_attr_delete",
2349)]
2350pub async fn group_id_attr_delete(
2351 Path((id, attr)): Path<(String, String)>,
2352 State(state): State<ServerState>,
2353 Extension(kopid): Extension<KOpId>,
2354 VerifiedClientInformation(client_auth_info): VerifiedClientInformation,
2355 values: Option<Json<Vec<String>>>,
2356) -> Result<Json<()>, WebError> {
2357 let filter = filter_all!(f_eq(Attribute::Class, EntryClass::Group.into()));
2358 let values = values.map(|v| v.0);
2359 json_rest_event_delete_id_attr(state, id, attr, filter, values, kopid, client_auth_info).await
2360}
2361
2362#[utoipa::path(
2363 put,
2364 path = "/v1/group/{id}/_attr/{attr}",
2365 request_body=Vec<String>,
2366 responses(
2367 DefaultApiResponse,
2368 ),
2369 security(("token_jwt" = [])),
2370 tag = "v1/group/attr",
2371 operation_id = "group_id_attr_put",
2372)]
2373pub async fn group_id_attr_put(
2374 Path((id, attr)): Path<(String, String)>,
2375 State(state): State<ServerState>,
2376 Extension(kopid): Extension<KOpId>,
2377 VerifiedClientInformation(client_auth_info): VerifiedClientInformation,
2378 Json(values): Json<Vec<String>>,
2379) -> Result<Json<()>, WebError> {
2380 let filter = filter_all!(f_eq(Attribute::Class, EntryClass::Group.into()));
2381 json_rest_event_put_attr(state, id, attr, filter, values, kopid, client_auth_info).await
2382}
2383
2384#[utoipa::path(
2385 post,
2386 path = "/v1/group/{id}/_unix",
2387 request_body = GroupUnixExtend,
2388 responses(
2389 DefaultApiResponse,
2390 ),
2391 security(("token_jwt" = [])),
2392 tag = "v1/group/unix",
2393 operation_id = "group_id_unix_post",
2394)]
2395pub async fn group_id_unix_post(
2396 State(state): State<ServerState>,
2397 Path(id): Path<String>,
2398 Extension(kopid): Extension<KOpId>,
2399 VerifiedClientInformation(client_auth_info): VerifiedClientInformation,
2400 Json(obj): Json<GroupUnixExtend>,
2401) -> Result<Json<()>, WebError> {
2402 state
2403 .qe_w_ref
2404 .handle_idmgroupunixextend(client_auth_info, id, obj, kopid.eventid)
2405 .await
2406 .map(Json::from)
2407 .map_err(WebError::from)
2408}
2409
2410#[utoipa::path(
2411 get,
2412 path = "/v1/group/{id}/_unix/_token",
2413 responses(
2414 (status=200, body=UnixGroupToken, content_type="application/json"),
2415 ApiResponseWithout200,
2416 ),
2417 security(("token_jwt" = [])),
2418 tag = "v1/group/unix",
2419 operation_id = "group_id_unix_token_get",
2420)]
2421pub async fn group_id_unix_token_get(
2422 State(state): State<ServerState>,
2423 Extension(kopid): Extension<KOpId>,
2424 VerifiedClientInformation(client_auth_info): VerifiedClientInformation,
2425 Path(id): Path<String>,
2426) -> Result<Json<UnixGroupToken>, WebError> {
2427 state
2428 .qe_r_ref
2429 .handle_internalunixgrouptokenread(client_auth_info, id, kopid.eventid)
2430 .await
2431 .map(Json::from)
2432 .map_err(WebError::from)
2433}
2434
2435#[utoipa::path(
2436 get,
2437 path = "/v1/domain",
2438 responses(
2439 (status=200, body=Vec<ProtoEntry>, content_type="application/json"),
2440 ApiResponseWithout200,
2441 ),
2442 security(("token_jwt" = [])),
2443 tag = "v1/domain",
2444 operation_id = "domain_get",
2445)]
2446pub async fn domain_get(
2447 State(state): State<ServerState>,
2448 Extension(kopid): Extension<KOpId>,
2449 VerifiedClientInformation(client_auth_info): VerifiedClientInformation,
2450) -> Result<Json<Vec<ProtoEntry>>, WebError> {
2451 let filter = filter_all!(f_eq(Attribute::Uuid, PartialValue::Uuid(UUID_DOMAIN_INFO)));
2452 json_rest_event_get(state, None, filter, kopid, client_auth_info).await
2453}
2454
2455#[utoipa::path(
2456 get,
2457 path = "/v1/domain/_attr/{attr}",
2458 responses(
2459 (status=200, body=Option<Vec<String>>, content_type="application/json"),
2460 ApiResponseWithout200,
2461 ),
2462 security(("token_jwt" = [])),
2463 tag = "v1/domain",
2464 operation_id = "domain_attr_get",
2465)]
2466pub async fn domain_attr_get(
2467 State(state): State<ServerState>,
2468 Extension(kopid): Extension<KOpId>,
2469 VerifiedClientInformation(client_auth_info): VerifiedClientInformation,
2470 Path(attr): Path<String>,
2471) -> Result<Json<Option<Vec<String>>>, WebError> {
2472 let filter = filter_all!(f_eq(Attribute::Class, EntryClass::DomainInfo.into()));
2473 json_rest_event_get_attr(
2474 state,
2475 STR_UUID_DOMAIN_INFO,
2476 attr,
2477 filter,
2478 kopid,
2479 client_auth_info,
2480 )
2481 .await
2482}
2483
2484#[utoipa::path(
2485 put,
2486 path = "/v1/domain/_attr/{attr}",
2487 request_body=Vec<String>,
2488 responses(
2489 DefaultApiResponse,
2490 ),
2491 security(("token_jwt" = [])),
2492 tag = "v1/domain",
2493 operation_id = "domain_attr_put",
2494)]
2495pub async fn domain_attr_put(
2496 State(state): State<ServerState>,
2497 Extension(kopid): Extension<KOpId>,
2498 VerifiedClientInformation(client_auth_info): VerifiedClientInformation,
2499 Path(attr): Path<String>,
2500 Json(values): Json<Vec<String>>,
2501) -> Result<Json<()>, WebError> {
2502 let filter = filter_all!(f_eq(Attribute::Class, EntryClass::DomainInfo.into()));
2503
2504 json_rest_event_put_attr(
2505 state,
2506 STR_UUID_DOMAIN_INFO.to_string(),
2507 attr,
2508 filter,
2509 values,
2510 kopid,
2511 client_auth_info,
2512 )
2513 .await
2514}
2515
2516#[utoipa::path(
2517 delete,
2518 path = "/v1/domain/_attr/{attr}",
2519 request_body=Option<Vec<String>>,
2520 responses(
2521 DefaultApiResponse,
2522 ),
2523 security(("token_jwt" = [])),
2524 tag = "v1/domain",
2525 operation_id = "domain_attr_delete",
2526)]
2527pub async fn domain_attr_delete(
2528 State(state): State<ServerState>,
2529 Path(attr): Path<String>,
2530 Extension(kopid): Extension<KOpId>,
2531 VerifiedClientInformation(client_auth_info): VerifiedClientInformation,
2532 Json(values): Json<Option<Vec<String>>>,
2533) -> Result<Json<()>, WebError> {
2534 let filter = filter_all!(f_eq(Attribute::Class, EntryClass::DomainInfo.into()));
2535 json_rest_event_delete_attr(
2536 state,
2537 STR_UUID_DOMAIN_INFO.to_string(),
2538 attr,
2539 filter,
2540 values,
2541 kopid,
2542 client_auth_info,
2543 )
2544 .await
2545}
2546
2547#[utoipa::path(
2548 get,
2549 path = "/v1/system",
2550 responses(
2551 (status=200,body=Vec<ProtoEntry>, content_type="application/json"),
2552 ApiResponseWithout200,
2553 ),
2554 security(("token_jwt" = [])),
2555 tag = "v1/system",
2556 operation_id = "system_get",
2557)]
2558pub async fn system_get(
2559 State(state): State<ServerState>,
2560 Extension(kopid): Extension<KOpId>,
2561 VerifiedClientInformation(client_auth_info): VerifiedClientInformation,
2562) -> Result<Json<Vec<ProtoEntry>>, WebError> {
2563 let filter = filter_all!(f_eq(
2564 Attribute::Uuid,
2565 PartialValue::Uuid(UUID_SYSTEM_CONFIG)
2566 ));
2567 json_rest_event_get(state, None, filter, kopid, client_auth_info).await
2568}
2569
2570#[utoipa::path(
2571 get,
2572 path = "/v1/system/_attr/{attr}",
2573 responses(
2574 (status=200, body=Option<Vec<String>>, content_type="application/json"),
2575 ApiResponseWithout200,
2576 ),
2577 security(("token_jwt" = [])),
2578 tag = "v1/system",
2579 operation_id = "system_attr_get",
2580)]
2581pub async fn system_attr_get(
2582 State(state): State<ServerState>,
2583 Path(attr): Path<String>,
2584 Extension(kopid): Extension<KOpId>,
2585 VerifiedClientInformation(client_auth_info): VerifiedClientInformation,
2586) -> Result<Json<Option<Vec<String>>>, WebError> {
2587 let filter = filter_all!(f_eq(Attribute::Class, EntryClass::SystemConfig.into()));
2588 json_rest_event_get_attr(
2589 state,
2590 STR_UUID_SYSTEM_CONFIG,
2591 attr,
2592 filter,
2593 kopid,
2594 client_auth_info,
2595 )
2596 .await
2597}
2598
2599#[utoipa::path(
2600 post,
2601 path = "/v1/system/_attr/{attr}",
2602 request_body=Vec<String>,
2603 responses(
2604 DefaultApiResponse,
2605 ),
2606 security(("token_jwt" = [])),
2607 tag = "v1/system",
2608 operation_id = "system_attr_post",
2609)]
2610pub async fn system_attr_post(
2611 State(state): State<ServerState>,
2612 Path(attr): Path<String>,
2613 Extension(kopid): Extension<KOpId>,
2614 VerifiedClientInformation(client_auth_info): VerifiedClientInformation,
2615 Json(values): Json<Vec<String>>,
2616) -> Result<Json<()>, WebError> {
2617 let filter = filter_all!(f_eq(Attribute::Class, EntryClass::SystemConfig.into()));
2618 json_rest_event_post_attr(
2619 state,
2620 STR_UUID_SYSTEM_CONFIG.to_string(),
2621 attr,
2622 filter,
2623 values,
2624 kopid,
2625 client_auth_info,
2626 )
2627 .await
2628}
2629
2630#[utoipa::path(
2631 delete,
2632 path = "/v1/system/_attr/{attr}",
2633 request_body=Option<Vec<String>>,
2634 responses(
2635 DefaultApiResponse,
2636 ),
2637 security(("token_jwt" = [])),
2638 tag = "v1/system",
2639 operation_id = "system_attr_delete",
2640)]
2641pub async fn system_attr_delete(
2642 State(state): State<ServerState>,
2643 Path(attr): Path<String>,
2644 Extension(kopid): Extension<KOpId>,
2645 VerifiedClientInformation(client_auth_info): VerifiedClientInformation,
2646 Json(values): Json<Option<Vec<String>>>,
2647) -> Result<Json<()>, WebError> {
2648 let filter = filter_all!(f_eq(Attribute::Class, EntryClass::SystemConfig.into()));
2649 json_rest_event_delete_attr(
2650 state,
2651 STR_UUID_SYSTEM_CONFIG.to_string(),
2652 attr,
2653 filter,
2654 values,
2655 kopid,
2656 client_auth_info,
2657 )
2658 .await
2659}
2660
2661#[utoipa::path(
2662 put,
2663 path = "/v1/system/_attr/{attr}",
2664 request_body=Vec<String>,
2665 responses(
2666 DefaultApiResponse,
2667 ),
2668 security(("token_jwt" = [])),
2669 tag = "v1/system",
2670 operation_id = "system_attr_put",
2671)]
2672pub async fn system_attr_put(
2673 State(state): State<ServerState>,
2674 Path(attr): Path<String>,
2675 Extension(kopid): Extension<KOpId>,
2676 VerifiedClientInformation(client_auth_info): VerifiedClientInformation,
2677 Json(values): Json<Vec<String>>,
2678) -> Result<Json<()>, WebError> {
2679 let filter = filter_all!(f_eq(Attribute::Class, EntryClass::SystemConfig.into()));
2680 json_rest_event_put_attr(
2681 state,
2682 STR_UUID_SYSTEM_CONFIG.to_string(),
2683 attr,
2684 filter,
2685 values,
2686 kopid,
2687 client_auth_info,
2688 )
2689 .await
2690}
2691
2692#[utoipa::path(
2693 post,
2694 path = "/v1/recycle_bin",
2695 responses(
2696 (status=200,body=Vec<ProtoEntry>, content_type="application/json"),
2697 ApiResponseWithout200,
2698 ),
2699 security(("token_jwt" = [])),
2700 tag = "v1/recycle_bin",
2701 operation_id="recycle_bin_get",
2702)]
2703pub async fn recycle_bin_get(
2704 State(state): State<ServerState>,
2705 Extension(kopid): Extension<KOpId>,
2706 VerifiedClientInformation(client_auth_info): VerifiedClientInformation,
2707) -> Result<Json<Vec<ProtoEntry>>, WebError> {
2708 let filter = filter_all!(f_pres(Attribute::Class));
2709 let attrs = None;
2710 state
2711 .qe_r_ref
2712 .handle_internalsearchrecycled(client_auth_info, filter, attrs, kopid.eventid)
2713 .await
2714 .map(Json::from)
2715 .map_err(WebError::from)
2716}
2717
2718#[utoipa::path(
2719 get,
2720 path = "/v1/recycle_bin/{id}",
2721 responses(
2722 (status=200, body=Option<ProtoEntry>, content_type="application/json"),
2723 ApiResponseWithout200,
2724 ),
2725 security(("token_jwt" = [])),
2726 tag = "v1/recycle_bin",
2727 operation_id = "recycle_bin_id_get",
2728)]
2729pub async fn recycle_bin_id_get(
2730 State(state): State<ServerState>,
2731 Path(id): Path<String>,
2732 Extension(kopid): Extension<KOpId>,
2733 VerifiedClientInformation(client_auth_info): VerifiedClientInformation,
2734) -> Result<Json<Option<ProtoEntry>>, WebError> {
2735 let filter = filter_all!(f_id(id.as_str()));
2736 let attrs = None;
2737
2738 state
2739 .qe_r_ref
2740 .handle_internalsearchrecycled(client_auth_info, filter, attrs, kopid.eventid)
2741 .await
2742 .map(|mut r| r.pop())
2743 .map(Json::from)
2744 .map_err(WebError::from)
2745}
2746
2747#[utoipa::path(
2748 post,
2749 path = "/v1/recycle_bin/{id}/_revive",
2750 responses(
2751 DefaultApiResponse,
2752 ),
2753 security(("token_jwt" = [])),
2754 tag = "v1/recycle_bin",
2755 operation_id = "recycle_bin_revive_id_post",
2756)]
2757pub async fn recycle_bin_revive_id_post(
2758 State(state): State<ServerState>,
2759 Path(id): Path<String>,
2760 Extension(kopid): Extension<KOpId>,
2761 VerifiedClientInformation(client_auth_info): VerifiedClientInformation,
2762) -> Result<Json<()>, WebError> {
2763 let filter = filter_all!(f_id(id.as_str()));
2764 state
2765 .qe_w_ref
2766 .handle_reviverecycled(client_auth_info, filter, kopid.eventid)
2767 .await
2768 .map(Json::from)
2769 .map_err(WebError::from)
2770}
2771
2772#[utoipa::path(
2773 get,
2774 path = "/v1/self/_applinks",
2775 responses(
2776 (status=200, body=Vec<AppLink>, content_type="application/json"),
2777 ApiResponseWithout200,
2778 ),
2779 security(("token_jwt" = [])),
2780 tag = "v1/self",
2781 operation_id = "self_applinks_get",
2782)]
2783pub async fn applinks_get(
2785 State(state): State<ServerState>,
2786 Extension(kopid): Extension<KOpId>,
2787 VerifiedClientInformation(client_auth_info): VerifiedClientInformation,
2788) -> Result<Json<Vec<AppLink>>, WebError> {
2789 state
2790 .qe_r_ref
2791 .handle_list_applinks(client_auth_info, kopid.eventid)
2792 .await
2793 .map(Json::from)
2794 .map_err(WebError::from)
2795}
2796
2797#[utoipa::path(
2798 post,
2799 path = "/v1/reauth",
2800 responses(
2801 (status=200, content_type="application/json"), ApiResponseWithout200,
2803 ),
2804 request_body = AuthIssueSession,
2805 security(("token_jwt" = [])),
2806 tag = "v1/auth",
2807 operation_id = "reauth_post",
2808)] pub async fn reauth(
2810 State(state): State<ServerState>,
2811 VerifiedClientInformation(client_auth_info): VerifiedClientInformation,
2812 jar: CookieJar,
2813 Extension(kopid): Extension<KOpId>,
2814 Json(obj): Json<AuthIssueSession>,
2815) -> Result<Response, WebError> {
2816 let inter = state
2818 .qe_r_ref
2819 .handle_reauth(client_auth_info, obj, kopid.eventid)
2820 .await;
2821 debug!("ReAuth result: {:?}", inter);
2822 auth_session_state_management(&state, jar, inter)
2823}
2824
2825#[utoipa::path(
2826 post,
2827 path = "/v1/auth",
2828 responses(
2829 (status=200, content_type="application/json"), ApiResponseWithout200,
2831 ),
2832 request_body = AuthRequest,
2833 security(("token_jwt" = [])),
2834 tag = "v1/auth",
2835 operation_id = "auth_post",
2836)]
2837pub async fn auth(
2838 State(state): State<ServerState>,
2839 VerifiedClientInformation(client_auth_info): VerifiedClientInformation,
2840 jar: CookieJar,
2841 headers: HeaderMap,
2842 Extension(kopid): Extension<KOpId>,
2843 Json(obj): Json<AuthRequest>,
2844) -> Result<Response, WebError> {
2845 let maybe_sessionid = state.get_current_auth_session_id(&headers, &jar);
2850 debug!("Session ID: {:?}", maybe_sessionid);
2851
2852 let inter = state .qe_r_ref
2857 .handle_auth(maybe_sessionid, obj, kopid.eventid, client_auth_info)
2858 .await;
2859 debug!("Auth result: {:?}", inter);
2860 auth_session_state_management(&state, jar, inter)
2861}
2862
2863#[instrument(level = "trace", skip_all)]
2865fn auth_session_state_management(
2866 state: &ServerState,
2867 mut jar: CookieJar,
2868 inter: Result<AuthResult, OperationError>,
2869) -> Result<Response, WebError> {
2870 let mut auth_session_id_tok = None;
2871
2872 let res: Result<AuthResponse, _> = match inter {
2873 Ok(AuthResult {
2874 state: auth_state,
2875 sessionid,
2876 }) => {
2877 match auth_state {
2879 AuthState::Choose(allowed) => {
2880 debug!("🧩 -> AuthState::Choose");
2881 let kref = &state.jws_signer;
2882 let jws = Jws::into_json(&sessionid).map_err(|e| {
2883 error!(?e);
2884 OperationError::InvalidSessionState
2885 })?;
2886
2887 kref.sign(&jws)
2889 .map(|jwss| {
2890 auth_session_id_tok = Some(jwss.to_string());
2891 })
2892 .map_err(|e| {
2893 error!(?e);
2894 OperationError::InvalidSessionState
2895 })
2896 .map(|_| ProtoAuthState::Choose(allowed))
2897 }
2898 AuthState::Continue(allowed) => {
2899 debug!("🧩 -> AuthState::Continue");
2900 let kref = &state.jws_signer;
2901 let jws = Jws::into_json(&sessionid).map_err(|e| {
2903 error!(?e);
2904 OperationError::InvalidSessionState
2905 })?;
2906 kref.sign(&jws)
2907 .map(|jwss| {
2908 auth_session_id_tok = Some(jwss.to_string());
2909 })
2910 .map_err(|e| {
2911 error!(?e);
2912 OperationError::InvalidSessionState
2913 })
2914 .map(|_| ProtoAuthState::Continue(allowed))
2915 }
2916 AuthState::Success(token, issue) => {
2917 debug!("🧩 -> AuthState::Success");
2918
2919 match issue {
2920 AuthIssueSession::Token => Ok(ProtoAuthState::Success(token.to_string())),
2921 AuthIssueSession::Cookie => {
2922 let token_str = token.to_string();
2924 let mut bearer_cookie =
2925 Cookie::new(COOKIE_BEARER_TOKEN, token_str.clone());
2926 bearer_cookie.set_secure(state.secure_cookies);
2927 bearer_cookie.set_same_site(SameSite::Lax);
2928 bearer_cookie.set_http_only(true);
2929 bearer_cookie.set_domain(state.domain.clone());
2933 bearer_cookie.set_path("/");
2934 jar = jar
2935 .add(bearer_cookie)
2936 .remove(Cookie::from(COOKIE_AUTH_SESSION_ID));
2937 Ok(ProtoAuthState::Success(token_str))
2938 }
2939 }
2940 }
2941 AuthState::Denied(reason) => {
2942 debug!("🧩 -> AuthState::Denied");
2943 Ok(ProtoAuthState::Denied(reason))
2944 }
2945 }
2946 .map(|state| AuthResponse { sessionid, state })
2947 }
2948 Err(e) => Err(e),
2949 };
2950
2951 res.map(|response| {
2953 jar = if let Some(token) = auth_session_id_tok.clone() {
2954 let mut token_cookie = Cookie::new(COOKIE_AUTH_SESSION_ID, token);
2955 token_cookie.set_secure(state.secure_cookies);
2956 token_cookie.set_same_site(SameSite::Strict);
2957 token_cookie.set_http_only(true);
2958 jar.add(token_cookie)
2962 } else {
2963 jar
2964 };
2965
2966 trace!(?jar);
2967
2968 let mut res = (jar, Json::from(response)).into_response();
2969
2970 match auth_session_id_tok {
2971 Some(tok) => {
2972 match HeaderValue::from_str(&tok) {
2973 Ok(val) => {
2974 res.headers_mut().insert(KSESSIONID, val);
2975 }
2976 Err(err) => {
2977 admin_error!(?err, "Failed to add sessionid {} to header", tok);
2978 }
2979 }
2980 res
2981 }
2982 None => res,
2983 }
2984 })
2985 .map_err(WebError::from)
2986}
2987
2988#[utoipa::path(
2989 get,
2990 path = "/v1/auth/valid",
2991 responses(
2992 DefaultApiResponse,
2993 ),
2994 security(("token_jwt" = [])),
2995 tag = "v1/auth",
2996 operation_id = "auth_valid",
2997)]
2998pub async fn auth_valid(
2999 State(state): State<ServerState>,
3000 Extension(kopid): Extension<KOpId>,
3001 VerifiedClientInformation(client_auth_info): VerifiedClientInformation,
3002) -> Result<Json<()>, WebError> {
3003 state
3004 .qe_r_ref
3005 .handle_auth_valid(client_auth_info, kopid.eventid)
3006 .await
3007 .map(Json::from)
3008 .map_err(WebError::from)
3009}
3010
3011#[utoipa::path(
3012 get,
3013 path = "/v1/debug/ipinfo",
3014 responses(
3015 (status = 200, description = "Ok", body=String, content_type="application/json"),
3016 ),
3017 security(("token_jwt" = [])),
3018 tag = "v1/debug",
3019 operation_id = "debug_ipinfo",
3020)]
3021pub async fn debug_ipinfo(
3022 State(_state): State<ServerState>,
3023 Extension(trusted_client_ip): Extension<ClientConnInfo>,
3024) -> Result<Json<IpAddr>, ()> {
3025 Ok(Json::from(trusted_client_ip.client_ip_addr))
3026}
3027
3028#[utoipa::path(
3029 get,
3030 path = "/v1/jwk/{key_id}",
3031 responses(
3032 (status=200, body=Jwk, content_type="application/json"),
3033 ApiResponseWithout200,
3034 ),
3035 security(("token_jwt" = [])),
3036 tag = "v1/jwk",
3037 operation_id = "public_jwk_key_id_get"
3038)]
3039pub async fn public_jwk_key_id_get(
3040 State(state): State<ServerState>,
3041 Path(key_id): Path<String>,
3042 Extension(kopid): Extension<KOpId>,
3043) -> Result<Json<Jwk>, WebError> {
3044 if key_id.len() > 64 {
3045 return Err(WebError::from(OperationError::NoMatchingEntries));
3047 }
3048 state
3049 .qe_r_ref
3050 .handle_public_jwk_get(key_id, kopid.eventid)
3051 .await
3052 .map(Json::from)
3053 .map_err(WebError::from)
3054}
3055
3056fn cacheable_routes(state: ServerState) -> Router<ServerState> {
3057 Router::new()
3058 .route("/v1/jwk/:key_id", get(public_jwk_key_id_get))
3059 .route(
3060 "/v1/person/:id/_radius/_token",
3061 get(person_id_radius_token_get),
3062 )
3063 .route("/v1/account/:id/_unix/_token", get(account_id_unix_token))
3064 .route(
3065 "/v1/account/:id/_radius/_token",
3066 get(account_id_radius_token_get),
3067 )
3068 .layer(from_fn(cache_me_short))
3069 .with_state(state)
3070}
3071
3072#[instrument(skip(state))]
3073pub(crate) fn route_setup(state: ServerState) -> Router<ServerState> {
3074 Router::new()
3075 .route("/v1/oauth2", get(super::v1_oauth2::oauth2_get))
3076 .route(
3077 "/v1/oauth2/_basic",
3078 post(super::v1_oauth2::oauth2_basic_post),
3079 )
3080 .route(
3081 "/v1/oauth2/_public",
3082 post(super::v1_oauth2::oauth2_public_post),
3083 )
3084 .route(
3085 "/v1/oauth2/:rs_name",
3086 get(super::v1_oauth2::oauth2_id_get)
3087 .patch(super::v1_oauth2::oauth2_id_patch)
3088 .delete(super::v1_oauth2::oauth2_id_delete),
3089 )
3090 .route(
3091 "/v1/oauth2/:rs_name/_attr/:attr",
3092 post(super::v1_oauth2::oauth2_id_attr_post)
3093 .delete(super::v1_oauth2::oauth2_id_attr_delete),
3094 )
3095 .route(
3096 "/v1/oauth2/:rs_name/_image",
3097 post(super::v1_oauth2::oauth2_id_image_post)
3098 .delete(super::v1_oauth2::oauth2_id_image_delete),
3099 )
3100 .route(
3101 "/v1/oauth2/:rs_name/_basic_secret",
3102 get(super::v1_oauth2::oauth2_id_get_basic_secret),
3103 )
3104 .route(
3105 "/v1/oauth2/:rs_name/_scopemap/:group",
3106 post(super::v1_oauth2::oauth2_id_scopemap_post)
3107 .delete(super::v1_oauth2::oauth2_id_scopemap_delete),
3108 )
3109 .route(
3110 "/v1/oauth2/:rs_name/_sup_scopemap/:group",
3111 post(super::v1_oauth2::oauth2_id_sup_scopemap_post)
3112 .delete(super::v1_oauth2::oauth2_id_sup_scopemap_delete),
3113 )
3114 .route(
3115 "/v1/oauth2/:rs_name/_claimmap/:claim_name/:group",
3116 post(super::v1_oauth2::oauth2_id_claimmap_post)
3117 .delete(super::v1_oauth2::oauth2_id_claimmap_delete),
3118 )
3119 .route(
3120 "/v1/oauth2/:rs_name/_claimmap/:claim_name",
3121 post(super::v1_oauth2::oauth2_id_claimmap_join_post),
3122 )
3123 .route("/v1/raw/create", post(raw_create))
3124 .route("/v1/raw/modify", post(raw_modify))
3125 .route("/v1/raw/delete", post(raw_delete))
3126 .route("/v1/raw/search", post(raw_search))
3127 .route("/v1/schema", get(schema_get))
3128 .route(
3129 "/v1/schema/attributetype",
3130 get(schema_attributetype_get), )
3132 .route(
3133 "/v1/schema/attributetype/:id",
3134 get(schema_attributetype_get_id),
3135 )
3136 .route(
3138 "/v1/schema/classtype",
3139 get(schema_classtype_get), )
3141 .route(
3142 "/v1/schema/classtype/:id",
3143 get(schema_classtype_get_id), )
3146 .route("/v1/self", get(whoami))
3147 .route("/v1/self/_uat", get(whoami_uat))
3148 .route("/v1/self/_applinks", get(applinks_get))
3165 .route("/v1/person", get(person_get).post(person_post))
3167 .route("/v1/person/_search/:id", get(person_search_id))
3168 .route(
3169 "/v1/person/:id",
3170 get(person_id_get)
3171 .patch(person_id_patch)
3172 .delete(person_id_delete),
3173 )
3174 .route(
3175 "/v1/person/:id/_attr/:attr",
3176 get(person_id_get_attr)
3177 .put(person_id_put_attr)
3178 .post(person_id_post_attr)
3179 .delete(person_id_delete_attr),
3180 )
3181 .route(
3182 "/v1/person/:id/_certificate",
3183 get(person_get_id_certificate).post(person_post_id_certificate),
3184 )
3185 .route(
3186 "/v1/person/:id/_credential/_status",
3187 get(person_get_id_credential_status),
3188 )
3189 .route(
3190 "/v1/person/:id/_credential/_update",
3191 get(person_id_credential_update_get),
3192 )
3193 .route(
3194 "/v1/person/:id/_credential/_update_intent/:ttl",
3195 get(person_id_credential_update_intent_ttl_get),
3196 )
3197 .route(
3198 "/v1/person/:id/_credential/_update_intent",
3199 get(person_id_credential_update_intent_get),
3200 )
3201 .route(
3202 "/v1/person/:id/_ssh_pubkeys",
3203 get(person_id_ssh_pubkeys_get).post(person_id_ssh_pubkeys_post),
3204 )
3205 .route(
3206 "/v1/person/:id/_ssh_pubkeys/:tag",
3207 get(person_id_ssh_pubkeys_tag_get).delete(person_id_ssh_pubkeys_tag_delete),
3208 )
3209 .route(
3210 "/v1/person/:id/_radius",
3211 get(person_id_radius_get)
3212 .post(person_id_radius_post)
3213 .delete(person_id_radius_delete),
3214 )
3215 .route("/v1/person/:id/_unix", post(person_id_unix_post))
3216 .route(
3217 "/v1/person/:id/_unix/_credential",
3218 put(person_id_unix_credential_put).delete(person_id_unix_credential_delete),
3219 )
3220 .route(
3221 "/v1/person/:id/_identify_user",
3222 post(person_identify_user_post),
3223 )
3224 .route(
3226 "/v1/service_account",
3227 get(service_account_get).post(service_account_post),
3228 )
3229 .route(
3230 "/v1/service_account/",
3231 get(service_account_get).post(service_account_post),
3232 )
3233 .route(
3234 "/v1/service_account/:id",
3235 get(service_account_id_get)
3236 .delete(service_account_id_delete)
3237 .patch(service_account_id_patch),
3238 )
3239 .route(
3240 "/v1/service_account/:id/_attr/:attr",
3241 get(service_account_id_get_attr)
3242 .put(service_account_id_put_attr)
3243 .post(service_account_id_post_attr)
3244 .delete(service_account_id_delete_attr),
3245 )
3246 .route(
3248 "/v1/service_account/:id/_into_person",
3249 #[allow(deprecated)]
3250 post(service_account_into_person),
3251 )
3252 .route(
3253 "/v1/service_account/:id/_api_token",
3254 post(service_account_api_token_post).get(service_account_api_token_get),
3255 )
3256 .route(
3257 "/v1/service_account/:id/_api_token/:token_id",
3258 delete(service_account_api_token_delete),
3259 )
3260 .route(
3265 "/v1/service_account/:id/_credential/_generate",
3266 get(service_account_credential_generate),
3267 )
3268 .route(
3269 "/v1/service_account/:id/_credential/_status",
3270 get(service_account_id_credential_status_get),
3271 )
3272 .route(
3277 "/v1/service_account/:id/_ssh_pubkeys",
3278 get(service_account_id_ssh_pubkeys_get).post(service_account_id_ssh_pubkeys_post),
3279 )
3280 .route(
3281 "/v1/service_account/:id/_ssh_pubkeys/:tag",
3282 get(service_account_id_ssh_pubkeys_tag_get)
3283 .delete(service_account_id_ssh_pubkeys_tag_delete),
3284 )
3285 .route(
3286 "/v1/service_account/:id/_unix",
3287 post(service_account_id_unix_post),
3288 )
3289 .route(
3290 "/v1/account/:id/_unix/_auth",
3291 post(account_id_unix_auth_post),
3292 )
3293 .route("/v1/account/:id/_unix/_token", post(account_id_unix_token))
3294 .route(
3295 "/v1/account/:id/_radius/_token",
3296 post(account_id_radius_token_post),
3297 )
3298 .route(
3299 "/v1/account/:id/_ssh_pubkeys",
3300 #[allow(deprecated)]
3301 get(account_id_ssh_pubkeys_get),
3302 )
3303 .route(
3304 "/v1/account/:id/_ssh_pubkeys/:tag",
3305 get(account_id_ssh_pubkeys_tag_get),
3306 )
3307 .route(
3308 "/v1/account/:id/_user_auth_token",
3309 get(account_id_user_auth_token_get),
3310 )
3311 .route(
3312 "/v1/account/:id/_user_auth_token/:token_id",
3313 delete(account_user_auth_token_delete),
3314 )
3315 .route(
3316 "/v1/credential/_exchange_intent",
3317 post(credential_update_exchange_intent),
3318 )
3319 .route("/v1/credential/_status", post(credential_update_status))
3320 .route("/v1/credential/_update", post(credential_update_update))
3321 .route("/v1/credential/_commit", post(credential_update_commit))
3322 .route("/v1/credential/_cancel", post(credential_update_cancel))
3323 .route("/v1/domain", get(domain_get))
3325 .route(
3326 "/v1/domain/_image",
3327 post(super::v1_domain::image_post).delete(super::v1_domain::image_delete),
3328 )
3329 .route(
3330 "/v1/domain/_attr/:attr",
3331 get(domain_attr_get)
3332 .put(domain_attr_put)
3333 .delete(domain_attr_delete),
3334 )
3335 .route("/v1/group/:id/_unix/_token", get(group_id_unix_token_get))
3336 .route("/v1/group/:id/_unix", post(group_id_unix_post))
3337 .route("/v1/group", get(group_get).post(group_post))
3338 .route("/v1/group/_search/:id", get(group_search_id))
3339 .route(
3340 "/v1/group/:id",
3341 get(group_id_get)
3342 .patch(group_id_patch)
3343 .delete(group_id_delete),
3344 )
3345 .route(
3346 "/v1/group/:id/_attr/:attr",
3347 delete(group_id_attr_delete)
3348 .get(group_id_attr_get)
3349 .put(group_id_attr_put)
3350 .post(group_id_attr_post),
3351 )
3352 .with_state(state.clone())
3353 .route("/v1/system", get(system_get))
3354 .route(
3355 "/v1/system/_attr/:attr",
3356 get(system_attr_get)
3357 .post(system_attr_post)
3358 .put(system_attr_put)
3359 .delete(system_attr_delete),
3360 )
3361 .route("/v1/recycle_bin", get(recycle_bin_get))
3362 .route("/v1/recycle_bin/:id", get(recycle_bin_id_get))
3363 .route(
3364 "/v1/recycle_bin/:id/_revive",
3365 post(recycle_bin_revive_id_post),
3366 )
3367 .route("/v1/auth", post(auth))
3374 .route(V1_AUTH_VALID, get(auth_valid))
3375 .route("/v1/logout", get(logout))
3376 .route("/v1/reauth", post(reauth))
3377 .with_state(state.clone())
3378 .layer(from_fn(dont_cache_me))
3379 .merge(cacheable_routes(state))
3380 .route("/v1/debug/ipinfo", get(debug_ipinfo))
3381}