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 post,
2014 path = "/v1/account/{id}/_unix",
2015 responses(
2016 DefaultApiResponse,
2017 ),
2018 security(("token_jwt" = [])),
2019 tag = "v1/account",
2020)]
2021#[instrument(, level = "INFO", skip(id, state, kopid))]
2023pub async fn account_id_unix_post(
2024 State(state): State<ServerState>,
2025 Path(id): Path<String>,
2026 Extension(kopid): Extension<KOpId>,
2027 VerifiedClientInformation(client_auth_info): VerifiedClientInformation,
2028 Json(obj): Json<AccountUnixExtend>,
2029) -> Result<Json<()>, WebError> {
2030 state
2031 .qe_w_ref
2032 .handle_idmaccountunixextend(client_auth_info, id, obj, kopid.eventid)
2033 .await
2034 .map(Json::from)
2035 .map_err(WebError::from)
2036}
2037
2038#[utoipa::path(
2039 get,post,
2040 path = "/v1/account/{id}/_unix/_token",
2041 responses(
2042 (status=200, body=UnixUserToken, content_type="application/json"),
2043 ApiResponseWithout200,
2044 ),
2045 security(("token_jwt" = [])),
2046 tag = "v1/account",
2047 operation_id = "account_id_unix_token"
2048)]
2049#[instrument(level = "INFO", skip_all)]
2050pub async fn account_id_unix_token(
2051 State(state): State<ServerState>,
2052 Extension(kopid): Extension<KOpId>,
2053 VerifiedClientInformation(client_auth_info): VerifiedClientInformation,
2054 Path(id): Path<String>,
2055) -> Result<Json<UnixUserToken>, WebError> {
2056 if id.is_empty() {
2058 return Err(OperationError::EmptyRequest.into());
2059 }
2060
2061 let res = state
2062 .qe_r_ref
2063 .handle_internalunixusertokenread(client_auth_info, id, kopid.eventid)
2064 .await
2065 .map(Json::from);
2066
2067 if let Err(OperationError::MissingClass(class)) = &res {
2069 if class == ENTRYCLASS_POSIX_ACCOUNT {
2070 return Err(OperationError::NoMatchingEntries.into());
2071 }
2072 };
2073 if let Err(OperationError::InvalidValueState) = &res {
2075 return Err(OperationError::NoMatchingEntries.into());
2076 };
2077 res.map_err(WebError::from)
2078}
2079
2080#[utoipa::path(
2081 post,
2082 path = "/v1/account/{id}/_unix/_auth",
2083 responses(
2084 (status=200, body=Option<UnixUserToken>, content_type="application/json"),
2085 ApiResponseWithout200,
2086 ),
2087 security(("token_jwt" = [])),
2088 tag = "v1/account",
2089 operation_id = "account_id_unix_auth_post"
2090)]
2091pub async fn account_id_unix_auth_post(
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<Option<UnixUserToken>>, WebError> {
2098 state
2099 .qe_r_ref
2100 .handle_idmaccountunixauth(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 put,
2108 path = "/v1/person/{id}/_unix/_credential",
2109 request_body = SingleStringRequest,
2110 responses(
2111 DefaultApiResponse,
2112 ),
2113 security(("token_jwt" = [])),
2114 tag = "v1/person/unix",
2115 operation_id = "person_id_unix_credential_put"
2116)]
2117pub async fn person_id_unix_credential_put(
2118 State(state): State<ServerState>,
2119 Extension(kopid): Extension<KOpId>,
2120 VerifiedClientInformation(client_auth_info): VerifiedClientInformation,
2121 Path(id): Path<String>,
2122 Json(obj): Json<SingleStringRequest>,
2123) -> Result<Json<()>, WebError> {
2124 state
2125 .qe_w_ref
2126 .handle_idmaccountunixsetcred(client_auth_info, id, obj.value, kopid.eventid)
2127 .await
2128 .map(Json::from)
2129 .map_err(WebError::from)
2130}
2131
2132#[utoipa::path(
2133 delete,
2134 path = "/v1/person/{id}/_unix/_credential",
2135 responses(
2136 DefaultApiResponse,
2137 ),
2138 security(("token_jwt" = [])),
2139 tag = "v1/person/unix",
2140 operation_id = "person_id_unix_credential_delete"
2141)]
2142pub async fn person_id_unix_credential_delete(
2143 State(state): State<ServerState>,
2144 Extension(kopid): Extension<KOpId>,
2145 VerifiedClientInformation(client_auth_info): VerifiedClientInformation,
2146 Path(id): Path<String>,
2147) -> Result<Json<()>, WebError> {
2148 let filter = filter_all!(f_eq(Attribute::Class, EntryClass::PosixAccount.into()));
2149 state
2150 .qe_w_ref
2151 .handle_purgeattribute(
2152 client_auth_info,
2153 id,
2154 "unix_password".to_string(),
2155 filter,
2156 kopid.eventid,
2157 )
2158 .await
2159 .map(Json::from)
2160 .map_err(WebError::from)
2161}
2162
2163#[utoipa::path(
2164 post,
2165 path = "/v1/person/{id}/_identify/_user",
2166 responses(
2167 (status=200, body=IdentifyUserResponse, content_type="application/json"),
2168 ApiResponseWithout200,
2169 ),
2170 security(("token_jwt" = [])),
2171 tag = "v1/person",
2172 operation_id = "person_identify_user_post"
2173)]
2174pub async fn person_identify_user_post(
2175 State(state): State<ServerState>,
2176 Extension(kopid): Extension<KOpId>,
2177 VerifiedClientInformation(client_auth_info): VerifiedClientInformation,
2178 Path(id): Path<String>,
2179 Json(user_request): Json<IdentifyUserRequest>,
2180) -> Result<Json<IdentifyUserResponse>, WebError> {
2181 state
2182 .qe_r_ref
2183 .handle_user_identity_verification(client_auth_info, kopid.eventid, user_request, id)
2184 .await
2185 .map(Json::from)
2186 .map_err(WebError::from)
2187}
2188
2189#[utoipa::path(
2190 get,
2191 path = "/v1/group",
2192 responses(
2193 (status=200,body=Vec<ProtoEntry>, content_type="application/json"),
2194 ApiResponseWithout200,
2195 ),
2196 security(("token_jwt" = [])),
2197 tag = "v1/group",
2198 operation_id = "group_get",
2199)]
2200pub async fn group_get(
2202 State(state): State<ServerState>,
2203 Extension(kopid): Extension<KOpId>,
2204 VerifiedClientInformation(client_auth_info): VerifiedClientInformation,
2205) -> Result<Json<Vec<ProtoEntry>>, WebError> {
2206 let filter = filter_all!(f_eq(Attribute::Class, EntryClass::Group.into()));
2207 json_rest_event_get(state, None, filter, kopid, client_auth_info).await
2208}
2209
2210#[utoipa::path(
2211 get,
2212 path = "/v1/group/_search/{id}",
2213 responses(
2214 (status=200, body=Option<ProtoEntry>, content_type="application/json"),
2215 ApiResponseWithout200,
2216 ),
2217 security(("token_jwt" = [])),
2218 tag = "v1/group",
2219 operation_id = "group_search_id",
2220)]
2221pub async fn group_search_id(
2222 State(state): State<ServerState>,
2223 Extension(kopid): Extension<KOpId>,
2224 VerifiedClientInformation(client_auth_info): VerifiedClientInformation,
2225 Path(id): Path<String>,
2226) -> Result<Json<Vec<ProtoEntry>>, WebError> {
2227 let filter = filter_all!(f_and!([
2228 f_eq(Attribute::Class, EntryClass::Group.into()),
2229 f_sub(Attribute::Name, PartialValue::new_iname(&id))
2230 ]));
2231 json_rest_event_get(state, None, filter, kopid, client_auth_info).await
2232}
2233
2234#[utoipa::path(
2235 post,
2236 path = "/v1/group",
2237 responses(
2238 DefaultApiResponse,
2239 ),
2240 security(("token_jwt" = [])),
2241 tag = "v1/group",
2242 operation_id = "group_post",
2243)]
2244pub async fn group_post(
2245 State(state): State<ServerState>,
2246 Extension(kopid): Extension<KOpId>,
2247 VerifiedClientInformation(client_auth_info): VerifiedClientInformation,
2248 Json(obj): Json<ProtoEntry>,
2249) -> Result<Json<()>, WebError> {
2250 let classes = vec!["group".to_string(), "object".to_string()];
2251 json_rest_event_post(state, classes, obj, kopid, client_auth_info).await
2252}
2253
2254#[utoipa::path(
2255 get,
2256 path = "/v1/group/{id}",
2257 responses(
2258 (status=200, body=Option<ProtoEntry>, content_type="application/json"),
2259 ApiResponseWithout200,
2260 ),
2261 security(("token_jwt" = [])),
2262 tag = "v1/group",
2263 operation_id = "group_id_get",
2264)]
2265pub async fn group_id_get(
2266 State(state): State<ServerState>,
2267 Extension(kopid): Extension<KOpId>,
2268 VerifiedClientInformation(client_auth_info): VerifiedClientInformation,
2269 Path(id): Path<String>,
2270) -> Result<Json<Option<ProtoEntry>>, WebError> {
2271 let filter = filter_all!(f_eq(Attribute::Class, EntryClass::Group.into()));
2272 json_rest_event_get_id(state, id, filter, None, kopid, client_auth_info).await
2273}
2274
2275#[utoipa::path(
2276 patch,
2277 path = "/v1/group/{id}",
2278 responses(
2279 DefaultApiResponse,
2280 ),
2281 request_body=ProtoEntry,
2282 security(("token_jwt" = [])),
2283 tag = "v1/group",
2284 operation_id = "group_id_patch",
2285)]
2286pub async fn group_id_patch(
2287 State(state): State<ServerState>,
2288 Extension(kopid): Extension<KOpId>,
2289 VerifiedClientInformation(client_auth_info): VerifiedClientInformation,
2290 Path(id): Path<String>,
2291 Json(obj): Json<ProtoEntry>,
2292) -> Result<Json<()>, WebError> {
2293 let filter = filter_all!(f_eq(Attribute::Class, EntryClass::Group.into()));
2295 let filter = Filter::join_parts_and(filter, filter_all!(f_id(id.as_str())));
2296 state
2297 .qe_w_ref
2298 .handle_internalpatch(client_auth_info, filter, obj, kopid.eventid)
2299 .await
2300 .map(Json::from)
2301 .map_err(WebError::from)
2302}
2303
2304#[utoipa::path(
2305 delete,
2306 path = "/v1/group/{id}",
2307 responses(
2308 DefaultApiResponse,
2309 ),
2310 security(("token_jwt" = [])),
2311 tag = "v1/group",
2312 operation_id = "group_id_delete",
2313)]
2314pub async fn group_id_delete(
2315 State(state): State<ServerState>,
2316 Extension(kopid): Extension<KOpId>,
2317 VerifiedClientInformation(client_auth_info): VerifiedClientInformation,
2318 Path(id): Path<String>,
2319) -> Result<Json<()>, WebError> {
2320 let filter = filter_all!(f_eq(Attribute::Class, EntryClass::Group.into()));
2321 json_rest_event_delete_id(state, id, filter, kopid, client_auth_info).await
2322}
2323
2324#[utoipa::path(
2325 get,
2326 path = "/v1/group/{id}/_attr/{attr}",
2327 responses(
2328 (status=200, body=Vec<String>, content_type="application/json"),
2329 ApiResponseWithout200,
2330 ),
2331 security(("token_jwt" = [])),
2332 tag = "v1/group/attr",
2333 operation_id = "group_id_attr_get",
2334)]
2335pub async fn group_id_attr_get(
2336 State(state): State<ServerState>,
2337 Path((id, attr)): Path<(String, String)>,
2338 Extension(kopid): Extension<KOpId>,
2339 VerifiedClientInformation(client_auth_info): VerifiedClientInformation,
2340) -> Result<Json<Option<Vec<String>>>, WebError> {
2341 let filter = filter_all!(f_eq(Attribute::Class, EntryClass::Group.into()));
2342 json_rest_event_get_id_attr(state, id, attr, filter, kopid, client_auth_info).await
2343}
2344
2345#[utoipa::path(
2346 post,
2347 path = "/v1/group/{id}/_attr/{attr}",
2348 request_body=Vec<String>,
2349 responses(
2350 DefaultApiResponse,
2351 ),
2352 security(("token_jwt" = [])),
2353 tag = "v1/group/attr",
2354 operation_id = "group_id_attr_post",
2355)]
2356pub async fn group_id_attr_post(
2357 Path((id, attr)): Path<(String, String)>,
2358 State(state): State<ServerState>,
2359 Extension(kopid): Extension<KOpId>,
2360 VerifiedClientInformation(client_auth_info): VerifiedClientInformation,
2361 Json(values): Json<Vec<String>>,
2362) -> Result<Json<()>, WebError> {
2363 let filter = filter_all!(f_eq(Attribute::Class, EntryClass::Group.into()));
2364 json_rest_event_post_id_attr(state, id, attr, filter, values, kopid, client_auth_info).await
2365}
2366
2367#[utoipa::path(
2368 delete,
2369 path = "/v1/group/{id}/_attr/{attr}",
2370 request_body=Option<Vec<String>>,
2371 responses(
2372 DefaultApiResponse,
2373 ),
2374 security(("token_jwt" = [])),
2375 tag = "v1/group/attr",
2376 operation_id = "group_id_attr_delete",
2377)]
2378pub async fn group_id_attr_delete(
2379 Path((id, attr)): Path<(String, String)>,
2380 State(state): State<ServerState>,
2381 Extension(kopid): Extension<KOpId>,
2382 VerifiedClientInformation(client_auth_info): VerifiedClientInformation,
2383 values: Option<Json<Vec<String>>>,
2384) -> Result<Json<()>, WebError> {
2385 let filter = filter_all!(f_eq(Attribute::Class, EntryClass::Group.into()));
2386 let values = values.map(|v| v.0);
2387 json_rest_event_delete_id_attr(state, id, attr, filter, values, kopid, client_auth_info).await
2388}
2389
2390#[utoipa::path(
2391 put,
2392 path = "/v1/group/{id}/_attr/{attr}",
2393 request_body=Vec<String>,
2394 responses(
2395 DefaultApiResponse,
2396 ),
2397 security(("token_jwt" = [])),
2398 tag = "v1/group/attr",
2399 operation_id = "group_id_attr_put",
2400)]
2401pub async fn group_id_attr_put(
2402 Path((id, attr)): Path<(String, String)>,
2403 State(state): State<ServerState>,
2404 Extension(kopid): Extension<KOpId>,
2405 VerifiedClientInformation(client_auth_info): VerifiedClientInformation,
2406 Json(values): Json<Vec<String>>,
2407) -> Result<Json<()>, WebError> {
2408 let filter = filter_all!(f_eq(Attribute::Class, EntryClass::Group.into()));
2409 json_rest_event_put_attr(state, id, attr, filter, values, kopid, client_auth_info).await
2410}
2411
2412#[utoipa::path(
2413 post,
2414 path = "/v1/group/{id}/_unix",
2415 request_body = GroupUnixExtend,
2416 responses(
2417 DefaultApiResponse,
2418 ),
2419 security(("token_jwt" = [])),
2420 tag = "v1/group/unix",
2421 operation_id = "group_id_unix_post",
2422)]
2423pub async fn group_id_unix_post(
2424 State(state): State<ServerState>,
2425 Path(id): Path<String>,
2426 Extension(kopid): Extension<KOpId>,
2427 VerifiedClientInformation(client_auth_info): VerifiedClientInformation,
2428 Json(obj): Json<GroupUnixExtend>,
2429) -> Result<Json<()>, WebError> {
2430 state
2431 .qe_w_ref
2432 .handle_idmgroupunixextend(client_auth_info, id, obj, kopid.eventid)
2433 .await
2434 .map(Json::from)
2435 .map_err(WebError::from)
2436}
2437
2438#[utoipa::path(
2439 get,
2440 path = "/v1/group/{id}/_unix/_token",
2441 responses(
2442 (status=200, body=UnixGroupToken, content_type="application/json"),
2443 ApiResponseWithout200,
2444 ),
2445 security(("token_jwt" = [])),
2446 tag = "v1/group/unix",
2447 operation_id = "group_id_unix_token_get",
2448)]
2449pub async fn group_id_unix_token_get(
2450 State(state): State<ServerState>,
2451 Extension(kopid): Extension<KOpId>,
2452 VerifiedClientInformation(client_auth_info): VerifiedClientInformation,
2453 Path(id): Path<String>,
2454) -> Result<Json<UnixGroupToken>, WebError> {
2455 state
2456 .qe_r_ref
2457 .handle_internalunixgrouptokenread(client_auth_info, id, kopid.eventid)
2458 .await
2459 .map(Json::from)
2460 .map_err(WebError::from)
2461}
2462
2463#[utoipa::path(
2464 get,
2465 path = "/v1/domain",
2466 responses(
2467 (status=200, body=Vec<ProtoEntry>, content_type="application/json"),
2468 ApiResponseWithout200,
2469 ),
2470 security(("token_jwt" = [])),
2471 tag = "v1/domain",
2472 operation_id = "domain_get",
2473)]
2474pub async fn domain_get(
2475 State(state): State<ServerState>,
2476 Extension(kopid): Extension<KOpId>,
2477 VerifiedClientInformation(client_auth_info): VerifiedClientInformation,
2478) -> Result<Json<Vec<ProtoEntry>>, WebError> {
2479 let filter = filter_all!(f_eq(Attribute::Uuid, PartialValue::Uuid(UUID_DOMAIN_INFO)));
2480 json_rest_event_get(state, None, filter, kopid, client_auth_info).await
2481}
2482
2483#[utoipa::path(
2484 get,
2485 path = "/v1/domain/_attr/{attr}",
2486 responses(
2487 (status=200, body=Option<Vec<String>>, content_type="application/json"),
2488 ApiResponseWithout200,
2489 ),
2490 security(("token_jwt" = [])),
2491 tag = "v1/domain",
2492 operation_id = "domain_attr_get",
2493)]
2494pub async fn domain_attr_get(
2495 State(state): State<ServerState>,
2496 Extension(kopid): Extension<KOpId>,
2497 VerifiedClientInformation(client_auth_info): VerifiedClientInformation,
2498 Path(attr): Path<String>,
2499) -> Result<Json<Option<Vec<String>>>, WebError> {
2500 let filter = filter_all!(f_eq(Attribute::Class, EntryClass::DomainInfo.into()));
2501 json_rest_event_get_attr(
2502 state,
2503 STR_UUID_DOMAIN_INFO,
2504 attr,
2505 filter,
2506 kopid,
2507 client_auth_info,
2508 )
2509 .await
2510}
2511
2512#[utoipa::path(
2513 put,
2514 path = "/v1/domain/_attr/{attr}",
2515 request_body=Vec<String>,
2516 responses(
2517 DefaultApiResponse,
2518 ),
2519 security(("token_jwt" = [])),
2520 tag = "v1/domain",
2521 operation_id = "domain_attr_put",
2522)]
2523pub async fn domain_attr_put(
2524 State(state): State<ServerState>,
2525 Extension(kopid): Extension<KOpId>,
2526 VerifiedClientInformation(client_auth_info): VerifiedClientInformation,
2527 Path(attr): Path<String>,
2528 Json(values): Json<Vec<String>>,
2529) -> Result<Json<()>, WebError> {
2530 let filter = filter_all!(f_eq(Attribute::Class, EntryClass::DomainInfo.into()));
2531
2532 json_rest_event_put_attr(
2533 state,
2534 STR_UUID_DOMAIN_INFO.to_string(),
2535 attr,
2536 filter,
2537 values,
2538 kopid,
2539 client_auth_info,
2540 )
2541 .await
2542}
2543
2544#[utoipa::path(
2545 delete,
2546 path = "/v1/domain/_attr/{attr}",
2547 request_body=Option<Vec<String>>,
2548 responses(
2549 DefaultApiResponse,
2550 ),
2551 security(("token_jwt" = [])),
2552 tag = "v1/domain",
2553 operation_id = "domain_attr_delete",
2554)]
2555pub async fn domain_attr_delete(
2556 State(state): State<ServerState>,
2557 Path(attr): Path<String>,
2558 Extension(kopid): Extension<KOpId>,
2559 VerifiedClientInformation(client_auth_info): VerifiedClientInformation,
2560 Json(values): Json<Option<Vec<String>>>,
2561) -> Result<Json<()>, WebError> {
2562 let filter = filter_all!(f_eq(Attribute::Class, EntryClass::DomainInfo.into()));
2563 json_rest_event_delete_attr(
2564 state,
2565 STR_UUID_DOMAIN_INFO.to_string(),
2566 attr,
2567 filter,
2568 values,
2569 kopid,
2570 client_auth_info,
2571 )
2572 .await
2573}
2574
2575#[utoipa::path(
2576 get,
2577 path = "/v1/system",
2578 responses(
2579 (status=200,body=Vec<ProtoEntry>, content_type="application/json"),
2580 ApiResponseWithout200,
2581 ),
2582 security(("token_jwt" = [])),
2583 tag = "v1/system",
2584 operation_id = "system_get",
2585)]
2586pub async fn system_get(
2587 State(state): State<ServerState>,
2588 Extension(kopid): Extension<KOpId>,
2589 VerifiedClientInformation(client_auth_info): VerifiedClientInformation,
2590) -> Result<Json<Vec<ProtoEntry>>, WebError> {
2591 let filter = filter_all!(f_eq(
2592 Attribute::Uuid,
2593 PartialValue::Uuid(UUID_SYSTEM_CONFIG)
2594 ));
2595 json_rest_event_get(state, None, filter, kopid, client_auth_info).await
2596}
2597
2598#[utoipa::path(
2599 get,
2600 path = "/v1/system/_attr/{attr}",
2601 responses(
2602 (status=200, body=Option<Vec<String>>, content_type="application/json"),
2603 ApiResponseWithout200,
2604 ),
2605 security(("token_jwt" = [])),
2606 tag = "v1/system",
2607 operation_id = "system_attr_get",
2608)]
2609pub async fn system_attr_get(
2610 State(state): State<ServerState>,
2611 Path(attr): Path<String>,
2612 Extension(kopid): Extension<KOpId>,
2613 VerifiedClientInformation(client_auth_info): VerifiedClientInformation,
2614) -> Result<Json<Option<Vec<String>>>, WebError> {
2615 let filter = filter_all!(f_eq(Attribute::Class, EntryClass::SystemConfig.into()));
2616 json_rest_event_get_attr(
2617 state,
2618 STR_UUID_SYSTEM_CONFIG,
2619 attr,
2620 filter,
2621 kopid,
2622 client_auth_info,
2623 )
2624 .await
2625}
2626
2627#[utoipa::path(
2628 post,
2629 path = "/v1/system/_attr/{attr}",
2630 request_body=Vec<String>,
2631 responses(
2632 DefaultApiResponse,
2633 ),
2634 security(("token_jwt" = [])),
2635 tag = "v1/system",
2636 operation_id = "system_attr_post",
2637)]
2638pub async fn system_attr_post(
2639 State(state): State<ServerState>,
2640 Path(attr): Path<String>,
2641 Extension(kopid): Extension<KOpId>,
2642 VerifiedClientInformation(client_auth_info): VerifiedClientInformation,
2643 Json(values): Json<Vec<String>>,
2644) -> Result<Json<()>, WebError> {
2645 let filter = filter_all!(f_eq(Attribute::Class, EntryClass::SystemConfig.into()));
2646 json_rest_event_post_attr(
2647 state,
2648 STR_UUID_SYSTEM_CONFIG.to_string(),
2649 attr,
2650 filter,
2651 values,
2652 kopid,
2653 client_auth_info,
2654 )
2655 .await
2656}
2657
2658#[utoipa::path(
2659 delete,
2660 path = "/v1/system/_attr/{attr}",
2661 request_body=Option<Vec<String>>,
2662 responses(
2663 DefaultApiResponse,
2664 ),
2665 security(("token_jwt" = [])),
2666 tag = "v1/system",
2667 operation_id = "system_attr_delete",
2668)]
2669pub async fn system_attr_delete(
2670 State(state): State<ServerState>,
2671 Path(attr): Path<String>,
2672 Extension(kopid): Extension<KOpId>,
2673 VerifiedClientInformation(client_auth_info): VerifiedClientInformation,
2674 Json(values): Json<Option<Vec<String>>>,
2675) -> Result<Json<()>, WebError> {
2676 let filter = filter_all!(f_eq(Attribute::Class, EntryClass::SystemConfig.into()));
2677 json_rest_event_delete_attr(
2678 state,
2679 STR_UUID_SYSTEM_CONFIG.to_string(),
2680 attr,
2681 filter,
2682 values,
2683 kopid,
2684 client_auth_info,
2685 )
2686 .await
2687}
2688
2689#[utoipa::path(
2690 put,
2691 path = "/v1/system/_attr/{attr}",
2692 request_body=Vec<String>,
2693 responses(
2694 DefaultApiResponse,
2695 ),
2696 security(("token_jwt" = [])),
2697 tag = "v1/system",
2698 operation_id = "system_attr_put",
2699)]
2700pub async fn system_attr_put(
2701 State(state): State<ServerState>,
2702 Path(attr): Path<String>,
2703 Extension(kopid): Extension<KOpId>,
2704 VerifiedClientInformation(client_auth_info): VerifiedClientInformation,
2705 Json(values): Json<Vec<String>>,
2706) -> Result<Json<()>, WebError> {
2707 let filter = filter_all!(f_eq(Attribute::Class, EntryClass::SystemConfig.into()));
2708 json_rest_event_put_attr(
2709 state,
2710 STR_UUID_SYSTEM_CONFIG.to_string(),
2711 attr,
2712 filter,
2713 values,
2714 kopid,
2715 client_auth_info,
2716 )
2717 .await
2718}
2719
2720#[utoipa::path(
2721 post,
2722 path = "/v1/recycle_bin",
2723 responses(
2724 (status=200,body=Vec<ProtoEntry>, content_type="application/json"),
2725 ApiResponseWithout200,
2726 ),
2727 security(("token_jwt" = [])),
2728 tag = "v1/recycle_bin",
2729 operation_id="recycle_bin_get",
2730)]
2731pub async fn recycle_bin_get(
2732 State(state): State<ServerState>,
2733 Extension(kopid): Extension<KOpId>,
2734 VerifiedClientInformation(client_auth_info): VerifiedClientInformation,
2735) -> Result<Json<Vec<ProtoEntry>>, WebError> {
2736 let filter = filter_all!(f_pres(Attribute::Class));
2737 let attrs = None;
2738 state
2739 .qe_r_ref
2740 .handle_internalsearchrecycled(client_auth_info, filter, attrs, kopid.eventid)
2741 .await
2742 .map(Json::from)
2743 .map_err(WebError::from)
2744}
2745
2746#[utoipa::path(
2747 get,
2748 path = "/v1/recycle_bin/{id}",
2749 responses(
2750 (status=200, body=Option<ProtoEntry>, content_type="application/json"),
2751 ApiResponseWithout200,
2752 ),
2753 security(("token_jwt" = [])),
2754 tag = "v1/recycle_bin",
2755 operation_id = "recycle_bin_id_get",
2756)]
2757pub async fn recycle_bin_id_get(
2758 State(state): State<ServerState>,
2759 Path(id): Path<String>,
2760 Extension(kopid): Extension<KOpId>,
2761 VerifiedClientInformation(client_auth_info): VerifiedClientInformation,
2762) -> Result<Json<Option<ProtoEntry>>, WebError> {
2763 let filter = filter_all!(f_id(id.as_str()));
2764 let attrs = None;
2765
2766 state
2767 .qe_r_ref
2768 .handle_internalsearchrecycled(client_auth_info, filter, attrs, kopid.eventid)
2769 .await
2770 .map(|mut r| r.pop())
2771 .map(Json::from)
2772 .map_err(WebError::from)
2773}
2774
2775#[utoipa::path(
2776 post,
2777 path = "/v1/recycle_bin/{id}/_revive",
2778 responses(
2779 DefaultApiResponse,
2780 ),
2781 security(("token_jwt" = [])),
2782 tag = "v1/recycle_bin",
2783 operation_id = "recycle_bin_revive_id_post",
2784)]
2785pub async fn recycle_bin_revive_id_post(
2786 State(state): State<ServerState>,
2787 Path(id): Path<String>,
2788 Extension(kopid): Extension<KOpId>,
2789 VerifiedClientInformation(client_auth_info): VerifiedClientInformation,
2790) -> Result<Json<()>, WebError> {
2791 let filter = filter_all!(f_id(id.as_str()));
2792 state
2793 .qe_w_ref
2794 .handle_reviverecycled(client_auth_info, filter, kopid.eventid)
2795 .await
2796 .map(Json::from)
2797 .map_err(WebError::from)
2798}
2799
2800#[utoipa::path(
2801 get,
2802 path = "/v1/self/_applinks",
2803 responses(
2804 (status=200, body=Vec<AppLink>, content_type="application/json"),
2805 ApiResponseWithout200,
2806 ),
2807 security(("token_jwt" = [])),
2808 tag = "v1/self",
2809 operation_id = "self_applinks_get",
2810)]
2811pub async fn applinks_get(
2813 State(state): State<ServerState>,
2814 Extension(kopid): Extension<KOpId>,
2815 VerifiedClientInformation(client_auth_info): VerifiedClientInformation,
2816) -> Result<Json<Vec<AppLink>>, WebError> {
2817 state
2818 .qe_r_ref
2819 .handle_list_applinks(client_auth_info, kopid.eventid)
2820 .await
2821 .map(Json::from)
2822 .map_err(WebError::from)
2823}
2824
2825#[utoipa::path(
2826 post,
2827 path = "/v1/reauth",
2828 responses(
2829 (status=200, content_type="application/json"), ApiResponseWithout200,
2831 ),
2832 request_body = AuthIssueSession,
2833 security(("token_jwt" = [])),
2834 tag = "v1/auth",
2835 operation_id = "reauth_post",
2836)] pub async fn reauth(
2838 State(state): State<ServerState>,
2839 VerifiedClientInformation(client_auth_info): VerifiedClientInformation,
2840 jar: CookieJar,
2841 Extension(kopid): Extension<KOpId>,
2842 Json(obj): Json<AuthIssueSession>,
2843) -> Result<Response, WebError> {
2844 let inter = state
2846 .qe_r_ref
2847 .handle_reauth(client_auth_info, obj, kopid.eventid)
2848 .await;
2849 debug!("ReAuth result: {:?}", inter);
2850 auth_session_state_management(state, jar, inter)
2851}
2852
2853#[utoipa::path(
2854 post,
2855 path = "/v1/auth",
2856 responses(
2857 (status=200, content_type="application/json"), ApiResponseWithout200,
2859 ),
2860 request_body = AuthRequest,
2861 security(("token_jwt" = [])),
2862 tag = "v1/auth",
2863 operation_id = "auth_post",
2864)]
2865pub async fn auth(
2866 State(state): State<ServerState>,
2867 VerifiedClientInformation(client_auth_info): VerifiedClientInformation,
2868 jar: CookieJar,
2869 headers: HeaderMap,
2870 Extension(kopid): Extension<KOpId>,
2871 Json(obj): Json<AuthRequest>,
2872) -> Result<Response, WebError> {
2873 let maybe_sessionid = state.get_current_auth_session_id(&headers, &jar);
2878 debug!("Session ID: {:?}", maybe_sessionid);
2879
2880 let inter = state .qe_r_ref
2885 .handle_auth(maybe_sessionid, obj, kopid.eventid, client_auth_info)
2886 .await;
2887 debug!("Auth result: {:?}", inter);
2888 auth_session_state_management(state, jar, inter)
2889}
2890
2891#[instrument(level = "trace", skip_all)]
2893fn auth_session_state_management(
2894 state: ServerState,
2895 mut jar: CookieJar,
2896 inter: Result<AuthResult, OperationError>,
2897) -> Result<Response, WebError> {
2898 let mut auth_session_id_tok = None;
2899
2900 let res: Result<AuthResponse, _> = match inter {
2901 Ok(AuthResult {
2902 state: auth_state,
2903 sessionid,
2904 }) => {
2905 match auth_state {
2907 AuthState::Choose(allowed) => {
2908 debug!("🧩 -> AuthState::Choose");
2909 let kref = &state.jws_signer;
2910 let jws = Jws::into_json(&sessionid).map_err(|e| {
2911 error!(?e);
2912 OperationError::InvalidSessionState
2913 })?;
2914
2915 kref.sign(&jws)
2917 .map(|jwss| {
2918 auth_session_id_tok = Some(jwss.to_string());
2919 })
2920 .map_err(|e| {
2921 error!(?e);
2922 OperationError::InvalidSessionState
2923 })
2924 .map(|_| ProtoAuthState::Choose(allowed))
2925 }
2926 AuthState::Continue(allowed) => {
2927 debug!("🧩 -> AuthState::Continue");
2928 let kref = &state.jws_signer;
2929 let jws = Jws::into_json(&sessionid).map_err(|e| {
2931 error!(?e);
2932 OperationError::InvalidSessionState
2933 })?;
2934 kref.sign(&jws)
2935 .map(|jwss| {
2936 auth_session_id_tok = Some(jwss.to_string());
2937 })
2938 .map_err(|e| {
2939 error!(?e);
2940 OperationError::InvalidSessionState
2941 })
2942 .map(|_| ProtoAuthState::Continue(allowed))
2943 }
2944 AuthState::Success(token, issue) => {
2945 debug!("🧩 -> AuthState::Success");
2946
2947 match issue {
2948 AuthIssueSession::Token => Ok(ProtoAuthState::Success(token.to_string())),
2949 AuthIssueSession::Cookie => {
2950 let token_str = token.to_string();
2952 let mut bearer_cookie =
2953 Cookie::new(COOKIE_BEARER_TOKEN, token_str.clone());
2954 bearer_cookie.set_secure(state.secure_cookies);
2955 bearer_cookie.set_same_site(SameSite::Lax);
2956 bearer_cookie.set_http_only(true);
2957 bearer_cookie.set_domain(state.domain.clone());
2961 bearer_cookie.set_path("/");
2962 jar = jar
2963 .add(bearer_cookie)
2964 .remove(Cookie::from(COOKIE_AUTH_SESSION_ID));
2965 Ok(ProtoAuthState::Success(token_str))
2966 }
2967 }
2968 }
2969 AuthState::Denied(reason) => {
2970 debug!("🧩 -> AuthState::Denied");
2971 Ok(ProtoAuthState::Denied(reason))
2972 }
2973 }
2974 .map(|state| AuthResponse { sessionid, state })
2975 }
2976 Err(e) => Err(e),
2977 };
2978
2979 res.map(|response| {
2981 jar = if let Some(token) = auth_session_id_tok.clone() {
2982 let mut token_cookie = Cookie::new(COOKIE_AUTH_SESSION_ID, token);
2983 token_cookie.set_secure(state.secure_cookies);
2984 token_cookie.set_same_site(SameSite::Strict);
2985 token_cookie.set_http_only(true);
2986 jar.add(token_cookie)
2990 } else {
2991 jar
2992 };
2993
2994 trace!(?jar);
2995
2996 let mut res = (jar, Json::from(response)).into_response();
2997
2998 match auth_session_id_tok {
2999 Some(tok) => {
3000 match HeaderValue::from_str(&tok) {
3001 Ok(val) => {
3002 res.headers_mut().insert(KSESSIONID, val);
3003 }
3004 Err(err) => {
3005 admin_error!(?err, "Failed to add sessionid {} to header", tok);
3006 }
3007 }
3008 res
3009 }
3010 None => res,
3011 }
3012 })
3013 .map_err(WebError::from)
3014}
3015
3016#[utoipa::path(
3017 get,
3018 path = "/v1/auth/valid",
3019 responses(
3020 DefaultApiResponse,
3021 ),
3022 security(("token_jwt" = [])),
3023 tag = "v1/auth",
3024 operation_id = "auth_valid",
3025)]
3026pub async fn auth_valid(
3027 State(state): State<ServerState>,
3028 Extension(kopid): Extension<KOpId>,
3029 VerifiedClientInformation(client_auth_info): VerifiedClientInformation,
3030) -> Result<Json<()>, WebError> {
3031 state
3032 .qe_r_ref
3033 .handle_auth_valid(client_auth_info, kopid.eventid)
3034 .await
3035 .map(Json::from)
3036 .map_err(WebError::from)
3037}
3038
3039#[utoipa::path(
3040 get,
3041 path = "/v1/debug/ipinfo",
3042 responses(
3043 (status = 200, description = "Ok", body=String, content_type="application/json"),
3044 ),
3045 security(("token_jwt" = [])),
3046 tag = "v1/debug",
3047 operation_id = "debug_ipinfo",
3048)]
3049pub async fn debug_ipinfo(
3050 State(_state): State<ServerState>,
3051 TrustedClientIp(ip_addr): TrustedClientIp,
3052) -> Result<Json<IpAddr>, ()> {
3053 Ok(Json::from(ip_addr))
3054}
3055
3056#[utoipa::path(
3057 get,
3058 path = "/v1/jwk/{key_id}",
3059 responses(
3060 (status=200, body=Jwk, content_type="application/json"),
3061 ApiResponseWithout200,
3062 ),
3063 security(("token_jwt" = [])),
3064 tag = "v1/jwk",
3065 operation_id = "public_jwk_key_id_get"
3066)]
3067pub async fn public_jwk_key_id_get(
3068 State(state): State<ServerState>,
3069 Path(key_id): Path<String>,
3070 Extension(kopid): Extension<KOpId>,
3071) -> Result<Json<Jwk>, WebError> {
3072 if key_id.len() > 64 {
3073 return Err(WebError::from(OperationError::NoMatchingEntries));
3075 }
3076 state
3077 .qe_r_ref
3078 .handle_public_jwk_get(key_id, kopid.eventid)
3079 .await
3080 .map(Json::from)
3081 .map_err(WebError::from)
3082}
3083
3084fn cacheable_routes(state: ServerState) -> Router<ServerState> {
3085 Router::new()
3086 .route("/v1/jwk/:key_id", get(public_jwk_key_id_get))
3087 .route(
3088 "/v1/person/:id/_radius/_token",
3089 get(person_id_radius_token_get),
3090 )
3091 .route("/v1/account/:id/_unix/_token", get(account_id_unix_token))
3092 .route(
3093 "/v1/account/:id/_radius/_token",
3094 get(account_id_radius_token_get),
3095 )
3096 .layer(from_fn(cache_me_short))
3097 .with_state(state)
3098}
3099
3100#[instrument(skip(state))]
3101pub(crate) fn route_setup(state: ServerState) -> Router<ServerState> {
3102 Router::new()
3103 .route("/v1/oauth2", get(super::v1_oauth2::oauth2_get))
3104 .route(
3105 "/v1/oauth2/_basic",
3106 post(super::v1_oauth2::oauth2_basic_post),
3107 )
3108 .route(
3109 "/v1/oauth2/_public",
3110 post(super::v1_oauth2::oauth2_public_post),
3111 )
3112 .route(
3113 "/v1/oauth2/:rs_name",
3114 get(super::v1_oauth2::oauth2_id_get)
3115 .patch(super::v1_oauth2::oauth2_id_patch)
3116 .delete(super::v1_oauth2::oauth2_id_delete),
3117 )
3118 .route(
3119 "/v1/oauth2/:rs_name/_attr/:attr",
3120 post(super::v1_oauth2::oauth2_id_attr_post)
3121 .delete(super::v1_oauth2::oauth2_id_attr_delete),
3122 )
3123 .route(
3124 "/v1/oauth2/:rs_name/_image",
3125 post(super::v1_oauth2::oauth2_id_image_post)
3126 .delete(super::v1_oauth2::oauth2_id_image_delete),
3127 )
3128 .route(
3129 "/v1/oauth2/:rs_name/_basic_secret",
3130 get(super::v1_oauth2::oauth2_id_get_basic_secret),
3131 )
3132 .route(
3133 "/v1/oauth2/:rs_name/_scopemap/:group",
3134 post(super::v1_oauth2::oauth2_id_scopemap_post)
3135 .delete(super::v1_oauth2::oauth2_id_scopemap_delete),
3136 )
3137 .route(
3138 "/v1/oauth2/:rs_name/_sup_scopemap/:group",
3139 post(super::v1_oauth2::oauth2_id_sup_scopemap_post)
3140 .delete(super::v1_oauth2::oauth2_id_sup_scopemap_delete),
3141 )
3142 .route(
3143 "/v1/oauth2/:rs_name/_claimmap/:claim_name/:group",
3144 post(super::v1_oauth2::oauth2_id_claimmap_post)
3145 .delete(super::v1_oauth2::oauth2_id_claimmap_delete),
3146 )
3147 .route(
3148 "/v1/oauth2/:rs_name/_claimmap/:claim_name",
3149 post(super::v1_oauth2::oauth2_id_claimmap_join_post),
3150 )
3151 .route("/v1/raw/create", post(raw_create))
3152 .route("/v1/raw/modify", post(raw_modify))
3153 .route("/v1/raw/delete", post(raw_delete))
3154 .route("/v1/raw/search", post(raw_search))
3155 .route("/v1/schema", get(schema_get))
3156 .route(
3157 "/v1/schema/attributetype",
3158 get(schema_attributetype_get), )
3160 .route(
3161 "/v1/schema/attributetype/:id",
3162 get(schema_attributetype_get_id),
3163 )
3164 .route(
3166 "/v1/schema/classtype",
3167 get(schema_classtype_get), )
3169 .route(
3170 "/v1/schema/classtype/:id",
3171 get(schema_classtype_get_id), )
3174 .route("/v1/self", get(whoami))
3175 .route("/v1/self/_uat", get(whoami_uat))
3176 .route("/v1/self/_applinks", get(applinks_get))
3193 .route("/v1/person", get(person_get).post(person_post))
3195 .route("/v1/person/_search/:id", get(person_search_id))
3196 .route(
3197 "/v1/person/:id",
3198 get(person_id_get)
3199 .patch(person_id_patch)
3200 .delete(person_id_delete),
3201 )
3202 .route(
3203 "/v1/person/:id/_attr/:attr",
3204 get(person_id_get_attr)
3205 .put(person_id_put_attr)
3206 .post(person_id_post_attr)
3207 .delete(person_id_delete_attr),
3208 )
3209 .route(
3210 "/v1/person/:id/_certificate",
3211 get(person_get_id_certificate).post(person_post_id_certificate),
3212 )
3213 .route(
3214 "/v1/person/:id/_credential/_status",
3215 get(person_get_id_credential_status),
3216 )
3217 .route(
3218 "/v1/person/:id/_credential/_update",
3219 get(person_id_credential_update_get),
3220 )
3221 .route(
3222 "/v1/person/:id/_credential/_update_intent/:ttl",
3223 get(person_id_credential_update_intent_ttl_get),
3224 )
3225 .route(
3226 "/v1/person/:id/_credential/_update_intent",
3227 get(person_id_credential_update_intent_get),
3228 )
3229 .route(
3230 "/v1/person/:id/_ssh_pubkeys",
3231 get(person_id_ssh_pubkeys_get).post(person_id_ssh_pubkeys_post),
3232 )
3233 .route(
3234 "/v1/person/:id/_ssh_pubkeys/:tag",
3235 get(person_id_ssh_pubkeys_tag_get).delete(person_id_ssh_pubkeys_tag_delete),
3236 )
3237 .route(
3238 "/v1/person/:id/_radius",
3239 get(person_id_radius_get)
3240 .post(person_id_radius_post)
3241 .delete(person_id_radius_delete),
3242 )
3243 .route("/v1/person/:id/_unix", post(person_id_unix_post))
3244 .route(
3245 "/v1/person/:id/_unix/_credential",
3246 put(person_id_unix_credential_put).delete(person_id_unix_credential_delete),
3247 )
3248 .route(
3249 "/v1/person/:id/_identify_user",
3250 post(person_identify_user_post),
3251 )
3252 .route(
3254 "/v1/service_account",
3255 get(service_account_get).post(service_account_post),
3256 )
3257 .route(
3258 "/v1/service_account/",
3259 get(service_account_get).post(service_account_post),
3260 )
3261 .route(
3262 "/v1/service_account/:id",
3263 get(service_account_id_get)
3264 .delete(service_account_id_delete)
3265 .patch(service_account_id_patch),
3266 )
3267 .route(
3268 "/v1/service_account/:id/_attr/:attr",
3269 get(service_account_id_get_attr)
3270 .put(service_account_id_put_attr)
3271 .post(service_account_id_post_attr)
3272 .delete(service_account_id_delete_attr),
3273 )
3274 .route(
3276 "/v1/service_account/:id/_into_person",
3277 #[allow(deprecated)]
3278 post(service_account_into_person),
3279 )
3280 .route(
3281 "/v1/service_account/:id/_api_token",
3282 post(service_account_api_token_post).get(service_account_api_token_get),
3283 )
3284 .route(
3285 "/v1/service_account/:id/_api_token/:token_id",
3286 delete(service_account_api_token_delete),
3287 )
3288 .route(
3293 "/v1/service_account/:id/_credential/_generate",
3294 get(service_account_credential_generate),
3295 )
3296 .route(
3297 "/v1/service_account/:id/_credential/_status",
3298 get(service_account_id_credential_status_get),
3299 )
3300 .route(
3305 "/v1/service_account/:id/_ssh_pubkeys",
3306 get(service_account_id_ssh_pubkeys_get).post(service_account_id_ssh_pubkeys_post),
3307 )
3308 .route(
3309 "/v1/service_account/:id/_ssh_pubkeys/:tag",
3310 get(service_account_id_ssh_pubkeys_tag_get)
3311 .delete(service_account_id_ssh_pubkeys_tag_delete),
3312 )
3313 .route(
3314 "/v1/service_account/:id/_unix",
3315 post(service_account_id_unix_post),
3316 )
3317 .route(
3318 "/v1/account/:id/_unix/_auth",
3319 post(account_id_unix_auth_post),
3320 )
3321 .route("/v1/account/:id/_unix/_token", post(account_id_unix_token))
3322 .route(
3323 "/v1/account/:id/_radius/_token",
3324 post(account_id_radius_token_post),
3325 )
3326 .route(
3327 "/v1/account/:id/_ssh_pubkeys",
3328 #[allow(deprecated)]
3329 get(account_id_ssh_pubkeys_get),
3330 )
3331 .route(
3332 "/v1/account/:id/_ssh_pubkeys/:tag",
3333 get(account_id_ssh_pubkeys_tag_get),
3334 )
3335 .route(
3336 "/v1/account/:id/_user_auth_token",
3337 get(account_id_user_auth_token_get),
3338 )
3339 .route(
3340 "/v1/account/:id/_user_auth_token/:token_id",
3341 delete(account_user_auth_token_delete),
3342 )
3343 .route(
3344 "/v1/credential/_exchange_intent",
3345 post(credential_update_exchange_intent),
3346 )
3347 .route("/v1/credential/_status", post(credential_update_status))
3348 .route("/v1/credential/_update", post(credential_update_update))
3349 .route("/v1/credential/_commit", post(credential_update_commit))
3350 .route("/v1/credential/_cancel", post(credential_update_cancel))
3351 .route("/v1/domain", get(domain_get))
3353 .route(
3354 "/v1/domain/_image",
3355 post(super::v1_domain::image_post).delete(super::v1_domain::image_delete),
3356 )
3357 .route(
3358 "/v1/domain/_attr/:attr",
3359 get(domain_attr_get)
3360 .put(domain_attr_put)
3361 .delete(domain_attr_delete),
3362 )
3363 .route("/v1/group/:id/_unix/_token", get(group_id_unix_token_get))
3364 .route("/v1/group/:id/_unix", post(group_id_unix_post))
3365 .route("/v1/group", get(group_get).post(group_post))
3366 .route("/v1/group/_search/:id", get(group_search_id))
3367 .route(
3368 "/v1/group/:id",
3369 get(group_id_get)
3370 .patch(group_id_patch)
3371 .delete(group_id_delete),
3372 )
3373 .route(
3374 "/v1/group/:id/_attr/:attr",
3375 delete(group_id_attr_delete)
3376 .get(group_id_attr_get)
3377 .put(group_id_attr_put)
3378 .post(group_id_attr_post),
3379 )
3380 .with_state(state.clone())
3381 .route("/v1/system", get(system_get))
3382 .route(
3383 "/v1/system/_attr/:attr",
3384 get(system_attr_get)
3385 .post(system_attr_post)
3386 .put(system_attr_put)
3387 .delete(system_attr_delete),
3388 )
3389 .route("/v1/recycle_bin", get(recycle_bin_get))
3390 .route("/v1/recycle_bin/:id", get(recycle_bin_id_get))
3391 .route(
3392 "/v1/recycle_bin/:id/_revive",
3393 post(recycle_bin_revive_id_post),
3394 )
3395 .route("/v1/auth", post(auth))
3402 .route(V1_AUTH_VALID, get(auth_valid))
3403 .route("/v1/logout", get(logout))
3404 .route("/v1/reauth", post(reauth))
3405 .with_state(state.clone())
3406 .layer(from_fn(dont_cache_me))
3407 .merge(cacheable_routes(state))
3408 .route("/v1/debug/ipinfo", get(debug_ipinfo))
3409}