Automatically populate the target instance field from the request using MessageTarget trait
parent: tbd commit: 37da513
Showing 12 changed files with 159 insertions and 39 deletions
giterated-daemon/src/backend/user.rs
@@ -5,7 +5,6 @@ use anyhow::Error; | ||
5 | 5 | use aes_gcm::{aead::Aead, AeadCore, Aes256Gcm, Key, KeyInit}; |
6 | 6 | use argon2::{password_hash::SaltString, Argon2, PasswordHasher}; |
7 | 7 | use base64::{engine::general_purpose::STANDARD, Engine as _}; |
8 | use futures_util::StreamExt; | |
9 | 8 | use giterated_models::{ |
10 | 9 | messages::{ |
11 | 10 | authentication::{ |
giterated-daemon/src/connection/authentication.rs
@@ -1,5 +1,3 @@ | ||
1 | use std::sync::Arc; | |
2 | ||
3 | 1 | use anyhow::Error; |
4 | 2 | use thiserror::Error; |
5 | 3 | use tokio::{fs::File, io::AsyncReadExt}; |
@@ -7,7 +5,8 @@ use tokio::{fs::File, io::AsyncReadExt}; | ||
7 | 5 | use crate::message::{AuthenticatedInstance, Message, MessageHandler, NetworkMessage, State}; |
8 | 6 | use giterated_models::{ |
9 | 7 | messages::authentication::{ |
10 | AuthenticationTokenRequest, RegisterAccountRequest, TokenExtensionRequest, AuthenticationTokenResponse, | |
8 | AuthenticationTokenRequest, AuthenticationTokenResponse, RegisterAccountRequest, | |
9 | TokenExtensionRequest, | |
11 | 10 | }, |
12 | 11 | model::authenticated::InstanceAuthenticator, |
13 | 12 | }; |
@@ -20,21 +19,21 @@ pub async fn authentication_handle( | ||
20 | 19 | state: &ConnectionState, |
21 | 20 | ) -> Result<bool, Error> { |
22 | 21 | match message_type { |
23 | "&giterated_models::messages::authentication::RegisterAccountRequest" => { | |
22 | "giterated_models::messages::authentication::RegisterAccountRequest" => { | |
24 | 23 | register_account_request |
25 | 24 | .handle_message(&message, state) |
26 | 25 | .await?; |
27 | 26 | |
28 | 27 | Ok(true) |
29 | 28 | } |
30 | "&giterated_models::messages::authentication::AuthenticationTokenRequest" => { | |
29 | "giterated_models::messages::authentication::AuthenticationTokenRequest" => { | |
31 | 30 | authentication_token_request |
32 | 31 | .handle_message(&message, state) |
33 | 32 | .await?; |
34 | 33 | |
35 | 34 | Ok(true) |
36 | 35 | } |
37 | "&giterated_models::messages::authentication::TokenExtensionRequest" => { | |
36 | "giterated_models::messages::authentication::TokenExtensionRequest" => { | |
38 | 37 | token_extension_request |
39 | 38 | .handle_message(&message, state) |
40 | 39 | .await?; |
@@ -83,14 +82,22 @@ async fn authentication_token_request( | ||
83 | 82 | let connection = connections.get_or_open(&request.instance).unwrap(); |
84 | 83 | |
85 | 84 | let private_key = { |
86 | let mut file = File::open(connection_state.config["giterated"]["keys"]["private"].as_str().unwrap()).await.unwrap(); | |
85 | let mut file = File::open( | |
86 | connection_state.config["giterated"]["keys"]["private"] | |
87 | .as_str() | |
88 | .unwrap(), | |
89 | ) | |
90 | .await | |
91 | .unwrap(); | |
87 | 92 | |
88 | 93 | let mut key = String::new(); |
89 | 94 | file.read_to_string(&mut key).await.unwrap(); |
90 | ||
95 | ||
91 | 96 | key |
92 | 97 | }; |
93 | 98 | |
99 | info!("Our private key: {}", private_key); | |
100 | ||
94 | 101 | let authenticator = InstanceAuthenticator { |
95 | 102 | instance: connection_state.instance.clone(), |
96 | 103 | private_key, |
@@ -99,10 +106,14 @@ async fn authentication_token_request( | ||
99 | 106 | let response = giterated_api::request::request_local(request) |
100 | 107 | .authenticate(authenticator) |
101 | 108 | .execute_expect::<AuthenticationTokenResponse>(&connection) |
102 | .await.unwrap(); | |
109 | .await | |
110 | .unwrap(); | |
103 | 111 | drop(connection); |
104 | 112 | |
105 | connection_state.send(response).await.map_err(|e| AuthenticationConnectionError::Sending(e))?; | |
113 | connection_state | |
114 | .send(response) | |
115 | .await | |
116 | .map_err(|e| AuthenticationConnectionError::Sending(e))?; | |
106 | 117 | |
107 | 118 | return Ok(()); |
108 | 119 | } |
@@ -159,12 +170,3 @@ pub enum AuthenticationConnectionError { | ||
159 | 170 | #[error("error issuing token")] |
160 | 171 | TokenIssuance(Error), |
161 | 172 | } |
162 | ||
163 | async fn private_key(path: &str) -> Vec<u8> { | |
164 | let mut file = File::open(path).await.unwrap(); | |
165 | ||
166 | let mut key = vec![]; | |
167 | file.read_to_end(&mut key).await.unwrap(); | |
168 | ||
169 | key | |
170 | } |
giterated-daemon/src/connection/repository.rs
@@ -17,34 +17,34 @@ pub async fn repository_handle( | ||
17 | 17 | state: &ConnectionState, |
18 | 18 | ) -> Result<bool, Error> { |
19 | 19 | match message_type { |
20 | "&giterated_models::messages::repository::RepositoryCreateRequest" => { | |
20 | "giterated_models::messages::repository::RepositoryCreateRequest" => { | |
21 | 21 | create_repository.handle_message(&message, state).await?; |
22 | 22 | |
23 | 23 | Ok(true) |
24 | 24 | } |
25 | "&giterated_models::messages::repository::RepositoryFileInspectRequest" => { | |
25 | "giterated_models::messages::repository::RepositoryFileInspectRequest" => { | |
26 | 26 | repository_file_inspect |
27 | 27 | .handle_message(&message, state) |
28 | 28 | .await?; |
29 | 29 | |
30 | 30 | Ok(true) |
31 | 31 | } |
32 | "&giterated_models::messages::repository::RepositoryInfoRequest" => { | |
32 | "giterated_models::messages::repository::RepositoryInfoRequest" => { | |
33 | 33 | repository_info.handle_message(&message, state).await?; |
34 | 34 | |
35 | 35 | Ok(true) |
36 | 36 | } |
37 | "&giterated_models::messages::repository::RepositoryIssuesCountRequest" => { | |
37 | "giterated_models::messages::repository::RepositoryIssuesCountRequest" => { | |
38 | 38 | issues_count.handle_message(&message, state).await?; |
39 | 39 | |
40 | 40 | Ok(true) |
41 | 41 | } |
42 | "&giterated_models::messages::repository::RepositoryIssueLabelsRequest" => { | |
42 | "giterated_models::messages::repository::RepositoryIssueLabelsRequest" => { | |
43 | 43 | issue_labels.handle_message(&message, state).await?; |
44 | 44 | |
45 | 45 | Ok(true) |
46 | 46 | } |
47 | "&giterated_models::messages::repository::RepositoryIssuesRequest" => { | |
47 | "giterated_models::messages::repository::RepositoryIssuesRequest" => { | |
48 | 48 | issues.handle_message(&message, state).await?; |
49 | 49 | |
50 | 50 | Ok(true) |
giterated-daemon/src/connection/user.rs
@@ -18,32 +18,32 @@ pub async fn user_handle( | ||
18 | 18 | state: &ConnectionState, |
19 | 19 | ) -> Result<bool, Error> { |
20 | 20 | match message_type { |
21 | "&giterated_models::messages::user::UserDisplayNameRequest" => { | |
21 | "giterated_models::messages::user::UserDisplayNameRequest" => { | |
22 | 22 | display_name.handle_message(&message, state).await?; |
23 | 23 | |
24 | 24 | Ok(true) |
25 | 25 | } |
26 | "&giterated_models::messages::user::UserDisplayImageRequest" => { | |
26 | "giterated_models::messages::user::UserDisplayImageRequest" => { | |
27 | 27 | display_image.handle_message(&message, state).await?; |
28 | 28 | |
29 | 29 | Ok(true) |
30 | 30 | } |
31 | "&giterated_models::messages::user::UserBioRequest" => { | |
31 | "giterated_models::messages::user::UserBioRequest" => { | |
32 | 32 | bio.handle_message(&message, state).await?; |
33 | 33 | |
34 | 34 | Ok(true) |
35 | 35 | } |
36 | "&giterated_models::messages::user::UserRepositoriesRequest" => { | |
36 | "giterated_models::messages::user::UserRepositoriesRequest" => { | |
37 | 37 | repositories.handle_message(&message, state).await?; |
38 | 38 | |
39 | 39 | Ok(true) |
40 | 40 | } |
41 | "&giterated_models::messages::user::UserSettingsRequest" => { | |
41 | "giterated_models::messages::user::UserSettingsRequest" => { | |
42 | 42 | user_settings.handle_message(&message, state).await?; |
43 | 43 | |
44 | 44 | Ok(true) |
45 | 45 | } |
46 | "&giterated_models::messages::user::UserWriteSettingsRequest" => { | |
46 | "giterated_models::messages::user::UserWriteSettingsRequest" => { | |
47 | 47 | write_user_settings.handle_message(&message, state).await?; |
48 | 48 | |
49 | 49 | Ok(true) |
giterated-daemon/src/main.rs
@@ -115,7 +115,7 @@ async fn main() -> Result<(), Error> { | ||
115 | 115 | token_granter.clone(), |
116 | 116 | settings.clone(), |
117 | 117 | address, |
118 | Instance::from_str("giterated.dev").unwrap(), | |
118 | Instance::from_str(config["giterated"]["instance"].as_str().unwrap()).unwrap(), | |
119 | 119 | instance_connections.clone(), |
120 | 120 | config.clone(), |
121 | 121 | )), |
giterated-daemon/src/message.rs
@@ -9,7 +9,7 @@ use giterated_models::model::{ | ||
9 | 9 | }; |
10 | 10 | use jsonwebtoken::{decode, Algorithm, DecodingKey, TokenData, Validation}; |
11 | 11 | use rsa::{ |
12 | pkcs1::{DecodeRsaPrivateKey, DecodeRsaPublicKey}, | |
12 | pkcs1::DecodeRsaPublicKey, | |
13 | 13 | pss::{Signature, VerifyingKey}, |
14 | 14 | sha2::Sha256, |
15 | 15 | signature::Verifier, |
@@ -110,6 +110,8 @@ impl FromMessage<ConnectionState> for AuthenticatedInstance { | ||
110 | 110 | let message: AuthenticatedPayload = |
111 | 111 | serde_json::from_slice(&network_message).map_err(|e| Error::from(e))?; |
112 | 112 | |
113 | info!("Authenticated payload: {:?}", message); | |
114 | ||
113 | 115 | let (instance, signature) = message |
114 | 116 | .source |
115 | 117 | .iter() |
@@ -128,6 +130,10 @@ impl FromMessage<ConnectionState> for AuthenticatedInstance { | ||
128 | 130 | // TODO: Instance authentication error |
129 | 131 | .ok_or_else(|| UserAuthenticationError::Missing)?; |
130 | 132 | |
133 | info!("Instance: {}", instance.clone().to_string()); | |
134 | ||
135 | info!("Instance public key: {}", state.public_key(instance).await?); | |
136 | ||
131 | 137 | let public_key = RsaPublicKey::from_pkcs1_pem(&state.public_key(instance).await?).unwrap(); |
132 | 138 | |
133 | 139 | let verifying_key: VerifyingKey<Sha256> = VerifyingKey::new(public_key); |
giterated-models/src/messages/authentication.rs
@@ -2,6 +2,8 @@ use serde::{Deserialize, Serialize}; | ||
2 | 2 | |
3 | 3 | use crate::model::{authenticated::UserAuthenticationToken, instance::Instance}; |
4 | 4 | |
5 | use super::MessageTarget; | |
6 | ||
5 | 7 | /// An account registration request. |
6 | 8 | /// |
7 | 9 | /// # Authentication |
@@ -37,6 +39,12 @@ pub struct AuthenticationTokenRequest { | ||
37 | 39 | pub password: String, |
38 | 40 | } |
39 | 41 | |
42 | impl MessageTarget for AuthenticationTokenRequest { | |
43 | fn target(&self) -> Option<Instance> { | |
44 | Some(self.instance.clone()) | |
45 | } | |
46 | } | |
47 | ||
40 | 48 | #[derive(Clone, Debug, Serialize, Deserialize)] |
41 | 49 | pub struct AuthenticationTokenResponse { |
42 | 50 | pub token: UserAuthenticationToken, |
@@ -57,6 +65,13 @@ pub struct TokenExtensionRequest { | ||
57 | 65 | pub token: UserAuthenticationToken, |
58 | 66 | } |
59 | 67 | |
68 | impl MessageTarget for TokenExtensionRequest { | |
69 | fn target(&self) -> Option<Instance> { | |
70 | // todo! | |
71 | None | |
72 | } | |
73 | } | |
74 | ||
60 | 75 | #[derive(Clone, Debug, Serialize, Deserialize)] |
61 | 76 | pub struct TokenExtensionResponse { |
62 | 77 | pub new_token: Option<String>, |
giterated-models/src/messages/discovery.rs
@@ -3,6 +3,8 @@ use serde::{Deserialize, Serialize}; | ||
3 | 3 | |
4 | 4 | use crate::model::discovery::DiscoveryItem; |
5 | 5 | |
6 | use super::MessageTarget; | |
7 | ||
6 | 8 | #[derive(Clone, Hash, PartialEq, Eq, Debug, Serialize, Deserialize)] |
7 | 9 | pub struct DiscoveryOffer { |
8 | 10 | pub earliest: DateTime<Utc>, |
@@ -15,6 +17,12 @@ pub struct DiscoveryRequest { | ||
15 | 17 | pub hashes: Vec<u128>, |
16 | 18 | } |
17 | 19 | |
20 | impl MessageTarget for DiscoveryRequest { | |
21 | fn target(&self) -> Option<crate::model::instance::Instance> { | |
22 | None | |
23 | } | |
24 | } | |
25 | ||
18 | 26 | #[derive(Clone, Hash, PartialEq, Eq, Debug, Serialize, Deserialize)] |
19 | 27 | pub struct Discoveries { |
20 | 28 | pub discoveries: Vec<DiscoveryItem>, |
giterated-models/src/messages/mod.rs
@@ -1,7 +1,7 @@ | ||
1 | 1 | use serde::{Deserialize, Serialize}; |
2 | 2 | use std::fmt::Debug; |
3 | 3 | |
4 | use crate::model::user::User; | |
4 | use crate::model::{instance::Instance, user::User}; | |
5 | 5 | |
6 | 6 | pub mod authentication; |
7 | 7 | pub mod discovery; |
@@ -18,3 +18,9 @@ pub enum ErrorMessage { | ||
18 | 18 | #[error("internal error: shutdown")] |
19 | 19 | Shutdown, |
20 | 20 | } |
21 | ||
22 | pub trait MessageTarget { | |
23 | fn target(&self) -> Option<Instance> { | |
24 | None | |
25 | } | |
26 | } |
giterated-models/src/messages/repository.rs
@@ -3,6 +3,7 @@ use std::collections::HashMap; | ||
3 | 3 | use serde::de::DeserializeOwned; |
4 | 4 | use serde::{Deserialize, Serialize}; |
5 | 5 | |
6 | use crate::model::instance::Instance; | |
6 | 7 | use crate::model::repository::RepositoryVisibility; |
7 | 8 | use crate::model::settings::Setting; |
8 | 9 | use crate::model::{ |
@@ -10,6 +11,8 @@ use crate::model::{ | ||
10 | 11 | user::User, |
11 | 12 | }; |
12 | 13 | |
14 | use super::MessageTarget; | |
15 | ||
13 | 16 | /// A request to create a repository. |
14 | 17 | /// |
15 | 18 | /// # Authentication |
@@ -25,6 +28,7 @@ use crate::model::{ | ||
25 | 28 | /// - Potential User permissions checks |
26 | 29 | #[derive(Clone, Debug, Serialize, Deserialize)] |
27 | 30 | pub struct RepositoryCreateRequest { |
31 | pub instance: Option<Instance>, | |
28 | 32 | pub name: String, |
29 | 33 | pub description: Option<String>, |
30 | 34 | pub visibility: RepositoryVisibility, |
@@ -32,6 +36,12 @@ pub struct RepositoryCreateRequest { | ||
32 | 36 | pub owner: User, |
33 | 37 | } |
34 | 38 | |
39 | impl MessageTarget for RepositoryCreateRequest { | |
40 | fn target(&self) -> Option<crate::model::instance::Instance> { | |
41 | self.instance.clone() | |
42 | } | |
43 | } | |
44 | ||
35 | 45 | #[derive(Clone, Debug, Serialize, Deserialize)] |
36 | 46 | pub struct RepositoryCreateResponse; |
37 | 47 | |
@@ -46,9 +56,16 @@ pub struct RepositoryCreateResponse; | ||
46 | 56 | /// - Potential User permissions checks |
47 | 57 | #[derive(Clone, Debug, Serialize, Deserialize)] |
48 | 58 | pub struct RepositoryFileInspectRequest { |
59 | pub repository: Repository, | |
49 | 60 | pub path: RepositoryTreeEntry, |
50 | 61 | } |
51 | 62 | |
63 | impl MessageTarget for RepositoryFileInspectRequest { | |
64 | fn target(&self) -> Option<Instance> { | |
65 | Some(self.repository.instance.clone()) | |
66 | } | |
67 | } | |
68 | ||
52 | 69 | #[derive(Clone, Debug, Serialize, Deserialize)] |
53 | 70 | pub enum RepositoryFileInspectionResponse { |
54 | 71 | File { |
@@ -75,6 +92,8 @@ pub enum RepositoryFileInspectionResponse { | ||
75 | 92 | #[derive(Clone, Debug, Serialize, Deserialize)] |
76 | 93 | pub struct RepositoryIssuesCountRequest; |
77 | 94 | |
95 | impl MessageTarget for RepositoryIssuesCountRequest {} | |
96 | ||
78 | 97 | #[derive(Clone, Debug, Serialize, Deserialize)] |
79 | 98 | pub struct RepositoryIssuesCountResponse { |
80 | 99 | pub count: u64, |
@@ -92,6 +111,8 @@ pub struct RepositoryIssuesCountResponse { | ||
92 | 111 | #[derive(Clone, Debug, Serialize, Deserialize)] |
93 | 112 | pub struct RepositoryIssueLabelsRequest; |
94 | 113 | |
114 | impl MessageTarget for RepositoryIssueLabelsRequest {} | |
115 | ||
95 | 116 | #[derive(Clone, Debug, Serialize, Deserialize)] |
96 | 117 | pub struct RepositoryIssueLabelsResponse { |
97 | 118 | pub labels: Vec<IssueLabel>, |
@@ -115,6 +136,8 @@ pub struct IssueLabel { | ||
115 | 136 | #[derive(Clone, Debug, Serialize, Deserialize)] |
116 | 137 | pub struct RepositoryIssuesRequest; |
117 | 138 | |
139 | impl MessageTarget for RepositoryIssuesRequest {} | |
140 | ||
118 | 141 | #[derive(Clone, Debug, Serialize, Deserialize)] |
119 | 142 | pub struct RepositoryIssuesResponse { |
120 | 143 | pub issues: Vec<RepositoryIssue>, |
@@ -149,11 +172,23 @@ pub struct RepositoryInfoRequest { | ||
149 | 172 | pub path: Option<String>, |
150 | 173 | } |
151 | 174 | |
175 | impl MessageTarget for RepositoryInfoRequest { | |
176 | fn target(&self) -> Option<Instance> { | |
177 | Some(self.repository.instance.clone()) | |
178 | } | |
179 | } | |
180 | ||
152 | 181 | #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] |
153 | 182 | pub struct RepositorySettingsRequest { |
154 | 183 | pub repository: Repository, |
155 | 184 | } |
156 | 185 | |
186 | impl MessageTarget for RepositorySettingsRequest { | |
187 | fn target(&self) -> Option<Instance> { | |
188 | Some(self.repository.instance.clone()) | |
189 | } | |
190 | } | |
191 | ||
157 | 192 | #[derive(Clone, Debug, PartialEq, Eq, Serialize, Default, Deserialize)] |
158 | 193 | pub struct RepositorySettingsResponse { |
159 | 194 | pub settings: HashMap<String, serde_json::Value>, |
@@ -177,6 +212,12 @@ pub struct RepositoryWriteSettingsRequest { | ||
177 | 212 | pub settings: Vec<(String, String)>, |
178 | 213 | } |
179 | 214 | |
215 | impl MessageTarget for RepositoryWriteSettingsRequest { | |
216 | fn target(&self) -> Option<Instance> { | |
217 | Some(self.repository.instance.clone()) | |
218 | } | |
219 | } | |
220 | ||
180 | 221 | impl RepositoryWriteSettingsRequest { |
181 | 222 | pub fn new(repository: impl ToOwned<Owned = Repository>) -> Self { |
182 | 223 | Self { |
giterated-models/src/messages/user.rs
@@ -2,13 +2,23 @@ use std::collections::HashMap; | ||
2 | 2 | |
3 | 3 | use serde::{de::DeserializeOwned, Deserialize, Serialize}; |
4 | 4 | |
5 | use crate::model::{repository::RepositorySummary, settings::Setting, user::User}; | |
5 | use crate::model::{ | |
6 | instance::Instance, repository::RepositorySummary, settings::Setting, user::User, | |
7 | }; | |
8 | ||
9 | use super::MessageTarget; | |
6 | 10 | |
7 | 11 | #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] |
8 | 12 | pub struct UserDisplayNameRequest { |
9 | 13 | pub user: User, |
10 | 14 | } |
11 | 15 | |
16 | impl MessageTarget for UserDisplayNameRequest { | |
17 | fn target(&self) -> Option<Instance> { | |
18 | Some(self.user.instance.clone()) | |
19 | } | |
20 | } | |
21 | ||
12 | 22 | #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] |
13 | 23 | pub struct UserDisplayNameResponse { |
14 | 24 | pub display_name: Option<String>, |
@@ -19,6 +29,12 @@ pub struct UserDisplayImageRequest { | ||
19 | 29 | pub user: User, |
20 | 30 | } |
21 | 31 | |
32 | impl MessageTarget for UserDisplayImageRequest { | |
33 | fn target(&self) -> Option<Instance> { | |
34 | Some(self.user.instance.clone()) | |
35 | } | |
36 | } | |
37 | ||
22 | 38 | #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] |
23 | 39 | pub struct UserDisplayImageResponse { |
24 | 40 | pub image_url: Option<String>, |
@@ -29,6 +45,12 @@ pub struct UserBioRequest { | ||
29 | 45 | pub user: User, |
30 | 46 | } |
31 | 47 | |
48 | impl MessageTarget for UserBioRequest { | |
49 | fn target(&self) -> Option<Instance> { | |
50 | Some(self.user.instance.clone()) | |
51 | } | |
52 | } | |
53 | ||
32 | 54 | #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] |
33 | 55 | pub struct UserBioResponse { |
34 | 56 | pub bio: Option<String>, |
@@ -36,9 +58,16 @@ pub struct UserBioResponse { | ||
36 | 58 | |
37 | 59 | #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] |
38 | 60 | pub struct UserRepositoriesRequest { |
61 | pub instance: Instance, | |
39 | 62 | pub user: User, |
40 | 63 | } |
41 | 64 | |
65 | impl MessageTarget for UserRepositoriesRequest { | |
66 | fn target(&self) -> Option<Instance> { | |
67 | Some(self.instance.clone()) | |
68 | } | |
69 | } | |
70 | ||
42 | 71 | #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] |
43 | 72 | pub struct UserRepositoriesResponse { |
44 | 73 | pub repositories: Vec<RepositorySummary>, |
@@ -49,6 +78,12 @@ pub struct UserSettingsRequest { | ||
49 | 78 | pub user: User, |
50 | 79 | } |
51 | 80 | |
81 | impl MessageTarget for UserSettingsRequest { | |
82 | fn target(&self) -> Option<Instance> { | |
83 | Some(self.user.instance.clone()) | |
84 | } | |
85 | } | |
86 | ||
52 | 87 | #[derive(Clone, Debug, PartialEq, Eq, Serialize, Default, Deserialize)] |
53 | 88 | pub struct UserSettingsResponse { |
54 | 89 | pub settings: HashMap<String, serde_json::Value>, |
@@ -72,6 +107,12 @@ pub struct UserWriteSettingsRequest { | ||
72 | 107 | pub settings: Vec<(String, String)>, |
73 | 108 | } |
74 | 109 | |
110 | impl MessageTarget for UserWriteSettingsRequest { | |
111 | fn target(&self) -> Option<Instance> { | |
112 | Some(self.user.instance.clone()) | |
113 | } | |
114 | } | |
115 | ||
75 | 116 | impl UserWriteSettingsRequest { |
76 | 117 | pub fn new(user: impl ToOwned<Owned = User>) -> Self { |
77 | 118 | Self { |
giterated-models/src/model/authenticated.rs
@@ -10,6 +10,8 @@ use rsa::{ | ||
10 | 10 | use serde::{Deserialize, Serialize}; |
11 | 11 | use tracing::info; |
12 | 12 | |
13 | use crate::messages::MessageTarget; | |
14 | ||
13 | 15 | use super::{instance::Instance, user::User}; |
14 | 16 | |
15 | 17 | #[derive(Debug, Serialize, Deserialize)] |
@@ -81,13 +83,13 @@ where | ||
81 | 83 | } |
82 | 84 | } |
83 | 85 | |
84 | impl<T: Serialize + Debug> Authenticated<T> { | |
86 | impl<T: Serialize + Debug + MessageTarget> Authenticated<T> { | |
85 | 87 | pub fn new(message: T) -> Self { |
86 | 88 | Self { |
87 | 89 | source: vec![], |
88 | 90 | message_type: type_name::<T>().to_string(), |
91 | target_instance: message.target(), | |
89 | 92 | message, |
90 | target_instance: None, | |
91 | 93 | } |
92 | 94 | } |
93 | 95 | |
@@ -104,8 +106,8 @@ impl<T: Serialize + Debug> Authenticated<T> { | ||
104 | 106 | Self { |
105 | 107 | source: vec![], |
106 | 108 | message_type: type_name::<T>().to_string(), |
109 | target_instance: message.target(), | |
107 | 110 | message, |
108 | target_instance: None, | |
109 | 111 | } |
110 | 112 | } |
111 | 113 |