cloudillo_profile/
list.rs1use axum::{
7 extract::{Path, Query, State},
8 http::StatusCode,
9 Json,
10};
11use serde::{Deserialize, Serialize};
12use serde_with::skip_serializing_none;
13
14use crate::prelude::*;
15use cloudillo_core::extract::OptionalRequestId;
16use cloudillo_types::meta_adapter::ListProfileOptions;
17use cloudillo_types::types::{ApiResponse, ProfileInfo};
18
19#[skip_serializing_none]
21#[derive(Debug, Serialize)]
22#[serde(rename_all = "camelCase")]
23pub struct ProfileWithStatus {
24 pub id_tag: String,
25 pub name: String,
26 #[serde(rename = "type")]
27 pub r#type: Option<String>,
28 pub profile_pic: Option<String>,
29 pub status: Option<String>,
30 pub connected: Option<bool>,
31 pub following: Option<bool>,
32}
33
34#[derive(Debug, Deserialize)]
35#[serde(rename_all = "camelCase")]
36pub struct ListProfilesQuery {
37 #[serde(alias = "q")]
38 search: Option<String>,
39 #[serde(rename = "type")]
40 typ: Option<cloudillo_types::meta_adapter::ProfileType>,
41}
42
43pub async fn list_profiles(
50 State(app): State<App>,
51 tn_id: TnId,
52 OptionalRequestId(req_id): OptionalRequestId,
53 Query(params): Query<ListProfilesQuery>,
54) -> ClResult<(StatusCode, Json<ApiResponse<Vec<ProfileInfo>>>)> {
55 let opts = ListProfileOptions {
57 typ: params.typ,
58 status: None,
59 connected: None,
60 following: None,
61 q: params.search.as_ref().map(|s| s.to_lowercase()),
62 id_tag: None,
63 };
64
65 let profiles_list = app.meta_adapter.list_profiles(tn_id, &opts).await?;
67
68 let profiles: Vec<ProfileInfo> = profiles_list
70 .into_iter()
71 .map(|p| ProfileInfo {
72 id_tag: p.id_tag.to_string(),
73 name: p.name.to_string(),
74 r#type: Some(
75 match p.typ {
76 cloudillo_types::meta_adapter::ProfileType::Person => "person",
77 cloudillo_types::meta_adapter::ProfileType::Community => "community",
78 }
79 .to_string(),
80 ),
81 profile_pic: p.profile_pic.map(|s| s.to_string()),
82 status: None, connected: Some(p.connected.is_connected()),
84 following: Some(p.following),
85 roles: p.roles.map(|r| r.iter().map(ToString::to_string).collect()),
86 created_at: None, })
88 .collect();
89
90 let response = ApiResponse::new(profiles).with_req_id(req_id.unwrap_or_default());
91
92 Ok((StatusCode::OK, Json(response)))
93}
94
95pub async fn get_profile_by_id_tag(
99 State(app): State<App>,
100 tn_id: TnId,
101 OptionalRequestId(req_id): OptionalRequestId,
102 Path(id_tag): Path<String>,
103) -> ClResult<(StatusCode, Json<ApiResponse<Option<ProfileWithStatus>>>)> {
104 let profile = match app.meta_adapter.read_profile(tn_id, &id_tag).await {
106 Ok((_etag, p)) => {
107 let typ = match p.typ {
108 cloudillo_types::meta_adapter::ProfileType::Person => None,
109 cloudillo_types::meta_adapter::ProfileType::Community => {
110 Some("community".to_string())
111 }
112 };
113 Some(ProfileWithStatus {
114 id_tag: p.id_tag.to_string(),
115 name: p.name.to_string(),
116 r#type: typ,
117 profile_pic: p.profile_pic.map(|s| s.to_string()),
118 status: None, connected: Some(p.connected.is_connected()),
120 following: Some(p.following),
121 })
122 }
123 Err(Error::NotFound) => None, Err(e) => return Err(e),
125 };
126
127 let response = ApiResponse::new(profile).with_req_id(req_id.unwrap_or_default());
128
129 Ok((StatusCode::OK, Json(response)))
130}
131
132