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