schul_cloud_api/requests/
chats.rs1use crate::errors::Errors;
2use crate::request_types::about::RSAPublicKey;
3use crate::request_types::{chats, AuthOnlyRequest};
4use crate::requests::about::get_other_user_info;
5use crate::requests::post_request;
6use crate::state::State;
7use crate::types::chats::channels::Channel;
8use crate::types::chats::conversations::Conversation;
9use crate::types::chats::messages::{File, Message, PossibleSender};
10use crate::types::user::others::User;
11use crate::Result;
12use base64::Engine;
13use openssl::rsa::Padding;
14use openssl::symm::{decrypt, Cipher};
15use std::fmt::{Display, Formatter};
16
17pub async fn get_channels(state: &State, company_id: impl ToString) -> Result<Vec<Channel>> {
18 Ok(post_request::<chats::ChannelsResponse>(state,
19 "/channels/subscripted",
20 chats::ChannelRequest::new(state, company_id.to_string())?)
21 .await?.channels)
22}
23pub async fn get_conversations(state: &State, limit: usize, offset: usize, archive: usize, sorting: Vec<String>) -> Result<Vec<Conversation>> {
24 Ok(post_request::<chats::ConversationResponse>(state,
25 "/message/conversations",
26 chats::ConversationsRequest::new(state, limit, offset, archive, sorting)?)
27 .await?.conversations)
28}
29
30pub async fn get_messages(state: &State, id: String, chat_type: ChatType, limit: usize, offset: usize, key: Option<Vec<u8>>) -> Result<Vec<Message>> {
31 let mut messages = post_request::<chats::MessageResponse>(state,
32 "/message/content",
33 chats::MessageRequest::new(state, id, chat_type.to_string(), limit, offset)?)
34 .await?.messages;
35 let _ = messages.iter_mut().map(|m| m.original_text = m.text.clone()).collect::<Vec<()>>();
36 let Some(key) = key else {
37 return Ok(messages);
38 };
39 for message in &mut messages {
40 if message.encrypted != Some(true) || message.text.is_none() || message.text == Some("".to_string()) {
41 continue;
42 }
43 let encrypted = hex::decode(message.text.clone().unwrap()).map_err(|e| Errors::HexError(e))?;
44 let iv_ = match &message.iv {
45 Some(iv) => Some(hex::decode(iv).map_err(|e| Errors::HexError(e))?),
46 None => None,
47 };
48 let iv = match &iv_ {
49 Some(iv) => Some(&**iv),
50 None => None
51 };
52 let decrypted = decrypt(Cipher::aes_256_cbc(), &*key, iv, &*encrypted)
53 .map_err(|e| Errors::EncryptionError(e))?;
54 let text = String::from_utf8(decrypted).map_err(|e| Errors::StringDecodeError(e))?;
55 message.text = Some(text);
56 }
57 Ok(messages)
58}
59pub async fn download_file(state: &State, key: Option<Vec<u8>>, file: File) -> Result<Vec<u8>> {
60 let raw_data = reqwest::Client::new()
61 .post(state.build_url("/file/download"))
62 .query(&chats::FileDownloadQuery { id: file.id })
63 .form(&AuthOnlyRequest::new(state)?)
64 .send().await
65 .map_err(|e| Errors::RequestError(e))?
66 .bytes().await
67 .map_err(|e| Errors::RequestError(e))?
68 .to_vec();
69 if !file.encrypted || key.is_none() {
70 return Ok(raw_data);
71 }
72 let iv_ = match file.e2e_iv {
73 Some(iv) => Some(hex::decode(iv).map_err(|e| Errors::HexError(e))?),
74 None => None
75 };
76 let iv = match &iv_ {
77 Some(iv) => Some(&**iv),
78 None => None,
79 };
80 decrypt(Cipher::aes_256_cbc(), key.unwrap().as_ref(), iv, &*raw_data)
81 .map_err(|e| Errors::EncryptionError(e))
82}
83#[cfg(feature = "experimental")]
84pub async fn verify_signature(state: &State, message: &Message) -> Result<bool> {
85 if message.verification.is_none() {
86 return Ok(true);
87 }
88 let sender_id = match &message.sender {
89 PossibleSender::MessageSender(s) => s.id.clone().unwrap(),
90 PossibleSender::String(_s) => return Err(Errors::OtherErrors("Can't verify hash of unknown sender.".to_string()))
91 };
92 let target = hex::decode(message.verification.clone().unwrap())?;
93 let user_info: User = get_other_user_info(state, sender_id).await?;
94 let rsa_key = RSAPublicKey::from_str(&*user_info.public_signing_key)?.to_key()?;
95 let key = openssl::pkey::PKey::from_rsa(rsa_key.clone())?;
96 let data = message.text.clone().unwrap().into_bytes();
97 if message.encrypted == Some(true) {
98 hex::decode(message.original_text.clone().unwrap())?
99 } else {
100 message.original_text.clone().unwrap().into_bytes()
101 };
102 let target_hash = base64::engine::general_purpose::STANDARD.decode(message.hash.clone().unwrap())?;
103 let generated_hash = openssl::hash::hash(openssl::hash::MessageDigest::sha256(), &*data)?.to_vec();
104 println!("{}", generated_hash == target_hash);
105 let mut buff = vec![0; rsa_key.size() as usize];
106 let buff_len = rsa_key.public_decrypt(&*generated_hash, &mut buff, Padding::NONE)?;
107 buff.truncate(buff_len);
108 println!("{}", buff == target);
109 println!("{:?}", buff);
110 println!("{buff_len}");
111
112 let mut verifier = openssl::sign::Verifier::new(openssl::hash::MessageDigest::sha256(), &key)?;
113 verifier.update(&*data)?;
114 let res = verifier.verify(&*target).map_err(Errors::from);
115 res
116}
117pub enum ChatType {
118 Channel,
119 Conversation,
120}
121impl Display for ChatType {
122 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
123 write!(f, "{}", match self {
124 ChatType::Channel => "channel",
125 ChatType::Conversation => "conversation",
126 })
127 }
128}