Unified stack `GetValue` implementation
parent: tbd commit: 325f5af
Showing 22 changed files with 713 insertions and 658 deletions
Cargo.lock
@@ -54,6 +54,17 @@ dependencies = [ | ||
54 | 54 | |
55 | 55 | [[package]] |
56 | 56 | name = "ahash" |
57 | version = "0.7.6" | |
58 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
59 | checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47" | |
60 | dependencies = [ | |
61 | "getrandom", | |
62 | "once_cell", | |
63 | "version_check", | |
64 | ] | |
65 | ||
66 | [[package]] | |
67 | name = "ahash" | |
57 | 68 | version = "0.8.3" |
58 | 69 | source = "registry+https://github.com/rust-lang/crates.io-index" |
59 | 70 | checksum = "2c99f64d1e06488f620f932677e24bc6e2897582980441ae90a671415bd7ec2f" |
@@ -785,6 +796,7 @@ dependencies = [ | ||
785 | 796 | "thiserror", |
786 | 797 | "tokio", |
787 | 798 | "tokio-tungstenite", |
799 | "tokio-util", | |
788 | 800 | "toml", |
789 | 801 | "tracing", |
790 | 802 | "tracing-subscriber", |
@@ -812,6 +824,7 @@ dependencies = [ | ||
812 | 824 | "thiserror", |
813 | 825 | "toml", |
814 | 826 | "tracing", |
827 | "url", | |
815 | 828 | ] |
816 | 829 | |
817 | 830 | [[package]] |
@@ -852,6 +865,9 @@ name = "hashbrown" | ||
852 | 865 | version = "0.12.3" |
853 | 866 | source = "registry+https://github.com/rust-lang/crates.io-index" |
854 | 867 | checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" |
868 | dependencies = [ | |
869 | "ahash 0.7.6", | |
870 | ] | |
855 | 871 | |
856 | 872 | [[package]] |
857 | 873 | name = "hashbrown" |
@@ -859,7 +875,7 @@ version = "0.14.0" | ||
859 | 875 | source = "registry+https://github.com/rust-lang/crates.io-index" |
860 | 876 | checksum = "2c6201b9ff9fd90a5a3bac2e56a830d0caa509576f0e503818ee82c181b3437a" |
861 | 877 | dependencies = [ |
862 | "ahash", | |
878 | "ahash 0.8.3", | |
863 | 879 | "allocator-api2", |
864 | 880 | ] |
865 | 881 | |
@@ -2092,7 +2108,7 @@ version = "0.7.1" | ||
2092 | 2108 | source = "registry+https://github.com/rust-lang/crates.io-index" |
2093 | 2109 | checksum = "dd4cef4251aabbae751a3710927945901ee1d97ee96d757f6880ebb9a79bfd53" |
2094 | 2110 | dependencies = [ |
2095 | "ahash", | |
2111 | "ahash 0.8.3", | |
2096 | 2112 | "atoi", |
2097 | 2113 | "byteorder", |
2098 | 2114 | "bytes", |
@@ -2492,13 +2508,15 @@ dependencies = [ | ||
2492 | 2508 | |
2493 | 2509 | [[package]] |
2494 | 2510 | name = "tokio-util" |
2495 | version = "0.7.8" | |
2511 | version = "0.7.9" | |
2496 | 2512 | source = "registry+https://github.com/rust-lang/crates.io-index" |
2497 | checksum = "806fe8c2c87eccc8b3267cbae29ed3ab2d0bd37fca70ab622e46aaa9375ddb7d" | |
2513 | checksum = "1d68074620f57a0b21594d9735eb2e98ab38b17f80d3fcb189fca266771ca60d" | |
2498 | 2514 | dependencies = [ |
2499 | 2515 | "bytes", |
2500 | 2516 | "futures-core", |
2501 | 2517 | "futures-sink", |
2518 | "futures-util", | |
2519 | "hashbrown 0.12.3", | |
2502 | 2520 | "pin-project-lite", |
2503 | 2521 | "tokio", |
2504 | 2522 | "tracing", |
@@ -2703,6 +2721,7 @@ dependencies = [ | ||
2703 | 2721 | "form_urlencoded", |
2704 | 2722 | "idna", |
2705 | 2723 | "percent-encoding", |
2724 | "serde", | |
2706 | 2725 | ] |
2707 | 2726 | |
2708 | 2727 | [[package]] |
giterated-daemon/Cargo.toml
@@ -27,6 +27,7 @@ giterated-api = { path = "../../giterated-api" } | ||
27 | 27 | giterated-stack = { path = "../giterated-stack" } |
28 | 28 | deadpool = "*" |
29 | 29 | bincode = "*" |
30 | tokio-util = {version = "0.7.9", features = ["rt"]} | |
30 | 31 | |
31 | 32 | toml = { version = "0.7" } |
32 | 33 |
giterated-daemon/src/authorization.rs
@@ -1,3 +1,5 @@ | ||
1 | use std::fmt::Debug; | |
2 | ||
1 | 3 | use crate::connection::wrapper::ConnectionState; |
2 | 4 | use giterated_models::error::OperationError; |
3 | 5 | |
@@ -10,13 +12,10 @@ use giterated_models::repository::{ | ||
10 | 12 | |
11 | 13 | use giterated_models::user::User; |
12 | 14 | |
13 | use giterated_models::{ | |
14 | object::ObjectRequest, | |
15 | settings::SetSetting, | |
16 | value::{GetValue, GiteratedObjectValue}, | |
17 | }; | |
15 | use giterated_models::value::GetValueTyped; | |
16 | use giterated_models::{object::ObjectRequest, settings::SetSetting, value::GiteratedObjectValue}; | |
18 | 17 | #[async_trait::async_trait] |
19 | pub trait AuthorizedOperation<O: GiteratedObject, S: Send + Sync> { | |
18 | pub trait AuthorizedOperation<O: GiteratedObject, S> { | |
20 | 19 | /// Authorizes the operation, returning whether the operation was |
21 | 20 | /// authorized or not. |
22 | 21 | async fn authorize( |
@@ -54,8 +53,8 @@ impl AuthorizedOperation<Repository, ConnectionState> for SetSetting { | ||
54 | 53 | } |
55 | 54 | |
56 | 55 | #[async_trait::async_trait] |
57 | impl<V: GiteratedObjectValue + Send + Sync> AuthorizedOperation<Repository, ConnectionState> | |
58 | for GetValue<V> | |
56 | impl<V: GiteratedObjectValue + Send + Sync + Debug + Clone> | |
57 | AuthorizedOperation<Repository, ConnectionState> for GetValueTyped<V> | |
59 | 58 | { |
60 | 59 | async fn authorize( |
61 | 60 | &self, |
giterated-daemon/src/backend/git.rs
@@ -52,10 +52,6 @@ impl GitRepository { | ||
52 | 52 | user: &Option<AuthenticatedUser>, |
53 | 53 | settings: &Arc<Mutex<dyn MetadataBackend + Send>>, |
54 | 54 | ) -> bool { |
55 | info!( | |
56 | "Can user {:?} view repository {}/{}?", | |
57 | user, self.owner_user, self.name | |
58 | ); | |
59 | 55 | if matches!(self.visibility, RepositoryVisibility::Public) { |
60 | 56 | return true; |
61 | 57 | } |
@@ -73,7 +69,6 @@ impl GitRepository { | ||
73 | 69 | |
74 | 70 | if matches!(self.visibility, RepositoryVisibility::Private) { |
75 | 71 | // Check if the user can view |
76 | info!("private"); | |
77 | 72 | let mut settings = settings.lock().await; |
78 | 73 | |
79 | 74 | let access_list = settings |
@@ -87,8 +82,6 @@ impl GitRepository { | ||
87 | 82 | ) |
88 | 83 | .await; |
89 | 84 | |
90 | info!("Access list returned"); | |
91 | ||
92 | 85 | let access_list: AccessList = match access_list { |
93 | 86 | Ok(list) => serde_json::from_value(list.0).unwrap(), |
94 | 87 | Err(_) => { |
@@ -96,8 +89,6 @@ impl GitRepository { | ||
96 | 89 | } |
97 | 90 | }; |
98 | 91 | |
99 | info!("Access list valid"); | |
100 | ||
101 | 92 | access_list |
102 | 93 | .0 |
103 | 94 | .iter() |
@@ -115,7 +106,7 @@ impl GitRepository { | ||
115 | 106 | ) -> Result<git2::Repository, GitBackendError> { |
116 | 107 | match git2::Repository::open(format!( |
117 | 108 | "{}/{}/{}/{}", |
118 | repository_directory, self.owner_user.instance.url, self.owner_user.username, self.name | |
109 | repository_directory, self.owner_user.instance, self.owner_user.username, self.name | |
119 | 110 | )) { |
120 | 111 | Ok(repository) => Ok(repository), |
121 | 112 | Err(err) => { |
@@ -214,7 +205,7 @@ impl GitBackend { | ||
214 | 205 | ) -> Result<u64, GitBackendError> { |
215 | 206 | if let Err(err) = std::fs::remove_dir_all(PathBuf::from(format!( |
216 | 207 | "{}/{}/{}/{}", |
217 | self.repository_folder, user.instance.url, user.username, repository_name | |
208 | self.repository_folder, user.instance, user.username, repository_name | |
218 | 209 | ))) { |
219 | 210 | let err = GitBackendError::CouldNotDeleteFromDisk(err); |
220 | 211 | error!( |
@@ -245,11 +236,6 @@ impl GitBackend { | ||
245 | 236 | name: &str, |
246 | 237 | requester: &Option<AuthenticatedUser>, |
247 | 238 | ) -> Result<git2::Repository, GitBackendError> { |
248 | info!( | |
249 | "Checking permissions for user {:?} on {}/{}", | |
250 | requester, owner, name | |
251 | ); | |
252 | ||
253 | 239 | let repository = match self |
254 | 240 | .find_by_owner_user_name( |
255 | 241 | // &request.owner.instance.url, |
@@ -389,15 +375,12 @@ impl RepositoryBackend for GitBackend { | ||
389 | 375 | // Create bare (server side) repository on disk |
390 | 376 | match git2::Repository::init_bare(PathBuf::from(format!( |
391 | 377 | "{}/{}/{}/{}", |
392 | self.repository_folder, | |
393 | request.owner.instance.url, | |
394 | request.owner.username, | |
395 | request.name | |
378 | self.repository_folder, request.owner.instance, request.owner.username, request.name | |
396 | 379 | ))) { |
397 | 380 | Ok(_) => { |
398 | 381 | debug!( |
399 | 382 | "Created new repository with the name {}/{}/{}", |
400 | request.owner.instance.url, request.owner.username, request.name | |
383 | request.owner.instance, request.owner.username, request.name | |
401 | 384 | ); |
402 | 385 | |
403 | 386 | let repository = Repository { |
giterated-daemon/src/connection/wrapper.rs
@@ -9,16 +9,10 @@ use futures_util::{SinkExt, StreamExt}; | ||
9 | 9 | |
10 | 10 | use giterated_models::{ |
11 | 11 | authenticated::{AuthenticationSource, UserTokenMetadata}, |
12 | error::OperationError, | |
13 | 12 | instance::Instance, |
14 | 13 | }; |
15 | 14 | |
16 | use giterated_models::object_backend::ObjectBackend; | |
17 | ||
18 | use giterated_models::{ | |
19 | authenticated::AuthenticatedPayload, message::GiteratedMessage, object::AnyObject, | |
20 | operation::AnyOperation, | |
21 | }; | |
15 | use giterated_models::authenticated::AuthenticatedPayload; | |
22 | 16 | use giterated_stack::{ |
23 | 17 | AuthenticatedInstance, AuthenticatedUser, GiteratedStack, StackOperationState, |
24 | 18 | }; |
@@ -129,7 +123,7 @@ pub async fn connection_wrapper( | ||
129 | 123 | verified_instance |
130 | 124 | }; |
131 | 125 | |
132 | let user = { | |
126 | let _user = { | |
133 | 127 | let mut verified_user = None; |
134 | 128 | if let Some(verified_instance) = &instance { |
135 | 129 | for source in &message.source { |
@@ -163,36 +157,14 @@ pub async fn connection_wrapper( | ||
163 | 157 | verified_user |
164 | 158 | }; |
165 | 159 | |
166 | let message: GiteratedMessage<AnyObject, AnyOperation> = message.into_message(); | |
167 | ||
168 | operation_state.user = user; | |
169 | operation_state.instance = instance; | |
170 | ||
171 | 160 | let result = runtime |
172 | .object_operation( | |
173 | message.object, | |
174 | &message.operation, | |
175 | message.payload, | |
176 | &operation_state, | |
177 | ) | |
161 | .handle_network_message(message, &operation_state) | |
178 | 162 | .await; |
179 | 163 | |
180 | 164 | // Asking for exploits here |
181 | 165 | operation_state.user = None; |
182 | 166 | operation_state.instance = None; |
183 | 167 | |
184 | // Map result to Vec<u8> on both | |
185 | let result = match result { | |
186 | Ok(result) => Ok(serde_json::to_vec(&result).unwrap()), | |
187 | Err(err) => Err(match err { | |
188 | OperationError::Operation(err) => { | |
189 | OperationError::Operation(serde_json::to_vec(&err).unwrap()) | |
190 | } | |
191 | OperationError::Internal(err) => OperationError::Internal(err), | |
192 | OperationError::Unhandled => OperationError::Unhandled, | |
193 | }), | |
194 | }; | |
195 | ||
196 | 168 | let mut socket = connection_state.socket.lock().await; |
197 | 169 | let _ = socket |
198 | 170 | .send(Message::Binary(bincode::serialize(&result).unwrap())) |
giterated-daemon/src/database_backend/handler.rs
@@ -1,6 +1,6 @@ | ||
1 | 1 | use std::{error::Error, sync::Arc}; |
2 | 2 | |
3 | use futures_util::{future::BoxFuture, FutureExt}; | |
3 | use futures_util::{future::LocalBoxFuture, FutureExt}; | |
4 | 4 | use giterated_models::{ |
5 | 5 | authenticated::UserAuthenticationToken, |
6 | 6 | error::{GetValueError, InstanceError, OperationError, RepositoryError, UserError}, |
@@ -17,11 +17,9 @@ use giterated_models::{ | ||
17 | 17 | }, |
18 | 18 | settings::{AnySetting, GetSetting, GetSettingError}, |
19 | 19 | user::{Bio, DisplayName, User, UserRepositoriesRequest}, |
20 | value::{AnyValue, GetValue}, | |
21 | }; | |
22 | use giterated_stack::{ | |
23 | AuthenticatedUser, AuthorizedInstance, AuthorizedUser, GiteratedStack, StackOperationState, | |
20 | value::{AnyValue, GetValueTyped}, | |
24 | 21 | }; |
22 | use giterated_stack::{AuthenticatedUser, AuthorizedInstance, GiteratedStack, StackOperationState}; | |
25 | 23 | |
26 | 24 | use super::DatabaseBackend; |
27 | 25 | |
@@ -31,7 +29,7 @@ pub fn user_get_repositories( | ||
31 | 29 | state: DatabaseBackend, |
32 | 30 | _operation_state: StackOperationState, |
33 | 31 | requester: Option<AuthenticatedUser>, |
34 | ) -> BoxFuture<'static, Result<Vec<RepositorySummary>, OperationError<UserError>>> { | |
32 | ) -> LocalBoxFuture<'static, Result<Vec<RepositorySummary>, OperationError<UserError>>> { | |
35 | 33 | let object = object.clone(); |
36 | 34 | |
37 | 35 | async move { |
@@ -57,14 +55,14 @@ pub fn user_get_repositories( | ||
57 | 55 | |
58 | 56 | Ok(repositories) |
59 | 57 | } |
60 | .boxed() | |
58 | .boxed_local() | |
61 | 59 | } |
62 | 60 | |
63 | 61 | pub fn user_get_value( |
64 | 62 | object: &User, |
65 | operation: GetValue<AnyValue<User>>, | |
63 | operation: GetValueTyped<AnyValue<User>>, | |
66 | 64 | state: DatabaseBackend, |
67 | ) -> BoxFuture<'static, Result<AnyValue<User>, OperationError<GetValueError>>> { | |
65 | ) -> LocalBoxFuture<'static, Result<AnyValue<User>, OperationError<GetValueError>>> { | |
68 | 66 | let object = object.clone(); |
69 | 67 | |
70 | 68 | async move { |
@@ -76,14 +74,14 @@ pub fn user_get_value( | ||
76 | 74 | |
77 | 75 | Ok(value) |
78 | 76 | } |
79 | .boxed() | |
77 | .boxed_local() | |
80 | 78 | } |
81 | 79 | |
82 | 80 | pub fn user_get_setting( |
83 | 81 | object: &User, |
84 | 82 | operation: GetSetting, |
85 | 83 | state: DatabaseBackend, |
86 | ) -> BoxFuture<'static, Result<AnySetting, OperationError<GetSettingError>>> { | |
84 | ) -> LocalBoxFuture<'static, Result<AnySetting, OperationError<GetSettingError>>> { | |
87 | 85 | let object = object.clone(); |
88 | 86 | |
89 | 87 | async move { |
@@ -95,7 +93,7 @@ pub fn user_get_setting( | ||
95 | 93 | |
96 | 94 | Ok(value) |
97 | 95 | } |
98 | .boxed() | |
96 | .boxed_local() | |
99 | 97 | } |
100 | 98 | |
101 | 99 | pub fn repository_info( |
@@ -105,7 +103,7 @@ pub fn repository_info( | ||
105 | 103 | operation_state: StackOperationState, |
106 | 104 | backend: Arc<GiteratedStack>, |
107 | 105 | requester: Option<AuthenticatedUser>, |
108 | ) -> BoxFuture<'static, Result<RepositoryView, OperationError<RepositoryError>>> { | |
106 | ) -> LocalBoxFuture<'static, Result<RepositoryView, OperationError<RepositoryError>>> { | |
109 | 107 | let object = object.clone(); |
110 | 108 | |
111 | 109 | async move { |
@@ -113,7 +111,6 @@ pub fn repository_info( | ||
113 | 111 | .get_object::<Repository>(&object.to_string(), &operation_state) |
114 | 112 | .await |
115 | 113 | .unwrap(); |
116 | ||
117 | 114 | let mut repository_backend = state.repository_backend.lock().await; |
118 | 115 | let tree = repository_backend |
119 | 116 | .repository_file_inspect( |
@@ -149,7 +146,7 @@ pub fn repository_info( | ||
149 | 146 | |
150 | 147 | Ok(info) |
151 | 148 | } |
152 | .boxed() | |
149 | .boxed_local() | |
153 | 150 | } |
154 | 151 | |
155 | 152 | pub fn repository_file_from_id( |
@@ -160,7 +157,7 @@ pub fn repository_file_from_id( | ||
160 | 157 | backend: Arc<GiteratedStack>, |
161 | 158 | |
162 | 159 | requester: Option<AuthenticatedUser>, |
163 | ) -> BoxFuture<'static, Result<RepositoryFile, OperationError<RepositoryError>>> { | |
160 | ) -> LocalBoxFuture<'static, Result<RepositoryFile, OperationError<RepositoryError>>> { | |
164 | 161 | let object = object.clone(); |
165 | 162 | |
166 | 163 | async move { |
@@ -182,7 +179,7 @@ pub fn repository_file_from_id( | ||
182 | 179 | |
183 | 180 | Ok(file) |
184 | 181 | } |
185 | .boxed() | |
182 | .boxed_local() | |
186 | 183 | } |
187 | 184 | |
188 | 185 | pub fn repository_file_from_path( |
@@ -192,7 +189,7 @@ pub fn repository_file_from_path( | ||
192 | 189 | operation_state: StackOperationState, |
193 | 190 | backend: Arc<GiteratedStack>, |
194 | 191 | requester: Option<AuthenticatedUser>, |
195 | ) -> BoxFuture<'static, Result<RepositoryFile, OperationError<RepositoryError>>> { | |
192 | ) -> LocalBoxFuture<'static, Result<RepositoryFile, OperationError<RepositoryError>>> { | |
196 | 193 | let object = object.clone(); |
197 | 194 | |
198 | 195 | async move { |
@@ -217,7 +214,7 @@ pub fn repository_file_from_path( | ||
217 | 214 | |
218 | 215 | Ok(file) |
219 | 216 | } |
220 | .boxed() | |
217 | .boxed_local() | |
221 | 218 | } |
222 | 219 | |
223 | 220 | pub fn repository_diff( |
@@ -227,7 +224,7 @@ pub fn repository_diff( | ||
227 | 224 | operation_state: StackOperationState, |
228 | 225 | backend: Arc<GiteratedStack>, |
229 | 226 | requester: Option<AuthenticatedUser>, |
230 | ) -> BoxFuture<'static, Result<RepositoryDiff, OperationError<RepositoryError>>> { | |
227 | ) -> LocalBoxFuture<'static, Result<RepositoryDiff, OperationError<RepositoryError>>> { | |
231 | 228 | let object = object.clone(); |
232 | 229 | |
233 | 230 | async move { |
@@ -245,7 +242,7 @@ pub fn repository_diff( | ||
245 | 242 | |
246 | 243 | Ok(diff) |
247 | 244 | } |
248 | .boxed() | |
245 | .boxed_local() | |
249 | 246 | } |
250 | 247 | |
251 | 248 | pub fn repository_diff_patch( |
@@ -255,7 +252,7 @@ pub fn repository_diff_patch( | ||
255 | 252 | operation_state: StackOperationState, |
256 | 253 | backend: Arc<GiteratedStack>, |
257 | 254 | requester: Option<AuthenticatedUser>, |
258 | ) -> BoxFuture<'static, Result<String, OperationError<RepositoryError>>> { | |
255 | ) -> LocalBoxFuture<'static, Result<String, OperationError<RepositoryError>>> { | |
259 | 256 | let object = object.clone(); |
260 | 257 | |
261 | 258 | async move { |
@@ -273,7 +270,7 @@ pub fn repository_diff_patch( | ||
273 | 270 | |
274 | 271 | Ok(patch) |
275 | 272 | } |
276 | .boxed() | |
273 | .boxed_local() | |
277 | 274 | } |
278 | 275 | |
279 | 276 | pub fn repository_commit_before( |
@@ -283,7 +280,7 @@ pub fn repository_commit_before( | ||
283 | 280 | operation_state: StackOperationState, |
284 | 281 | backend: Arc<GiteratedStack>, |
285 | 282 | requester: Option<AuthenticatedUser>, |
286 | ) -> BoxFuture<'static, Result<Commit, OperationError<RepositoryError>>> { | |
283 | ) -> LocalBoxFuture<'static, Result<Commit, OperationError<RepositoryError>>> { | |
287 | 284 | let object = object.clone(); |
288 | 285 | |
289 | 286 | async move { |
@@ -301,14 +298,14 @@ pub fn repository_commit_before( | ||
301 | 298 | |
302 | 299 | Ok(file) |
303 | 300 | } |
304 | .boxed() | |
301 | .boxed_local() | |
305 | 302 | } |
306 | 303 | |
307 | 304 | pub fn repository_get_value( |
308 | 305 | object: &Repository, |
309 | operation: GetValue<AnyValue<Repository>>, | |
306 | operation: GetValueTyped<AnyValue<Repository>>, | |
310 | 307 | state: DatabaseBackend, |
311 | ) -> BoxFuture<'static, Result<AnyValue<Repository>, OperationError<GetValueError>>> { | |
308 | ) -> LocalBoxFuture<'static, Result<AnyValue<Repository>, OperationError<GetValueError>>> { | |
312 | 309 | let object = object.clone(); |
313 | 310 | |
314 | 311 | async move { |
@@ -322,14 +319,14 @@ pub fn repository_get_value( | ||
322 | 319 | |
323 | 320 | Ok(value) |
324 | 321 | } |
325 | .boxed() | |
322 | .boxed_local() | |
326 | 323 | } |
327 | 324 | |
328 | 325 | pub fn repository_get_setting( |
329 | 326 | object: &Repository, |
330 | 327 | operation: GetSetting, |
331 | 328 | state: DatabaseBackend, |
332 | ) -> BoxFuture<'static, Result<AnySetting, OperationError<GetSettingError>>> { | |
329 | ) -> LocalBoxFuture<'static, Result<AnySetting, OperationError<GetSettingError>>> { | |
333 | 330 | let object = object.clone(); |
334 | 331 | |
335 | 332 | async move { |
@@ -341,7 +338,7 @@ pub fn repository_get_setting( | ||
341 | 338 | |
342 | 339 | Ok(value) |
343 | 340 | } |
344 | .boxed() | |
341 | .boxed_local() | |
345 | 342 | } |
346 | 343 | |
347 | 344 | pub fn instance_authentication_request( |
@@ -350,7 +347,7 @@ pub fn instance_authentication_request( | ||
350 | 347 | state: DatabaseBackend, |
351 | 348 | // Authorizes the request for SAME-INSTANCE |
352 | 349 | _authorized_instance: AuthorizedInstance, |
353 | ) -> BoxFuture<'static, Result<UserAuthenticationToken, OperationError<InstanceError>>> { | |
350 | ) -> LocalBoxFuture<'static, Result<UserAuthenticationToken, OperationError<InstanceError>>> { | |
354 | 351 | let object = object.clone(); |
355 | 352 | async move { |
356 | 353 | let mut backend = state.user_backend.lock().await; |
@@ -360,7 +357,7 @@ pub fn instance_authentication_request( | ||
360 | 357 | .await |
361 | 358 | .map_err(|e| OperationError::Internal(e.to_string())) |
362 | 359 | } |
363 | .boxed() | |
360 | .boxed_local() | |
364 | 361 | } |
365 | 362 | |
366 | 363 | pub fn instance_registration_request( |
@@ -369,7 +366,7 @@ pub fn instance_registration_request( | ||
369 | 366 | state: DatabaseBackend, |
370 | 367 | // Authorizes the request for SAME-INSTANCE |
371 | 368 | _authorized_instance: AuthorizedInstance, |
372 | ) -> BoxFuture<'static, Result<UserAuthenticationToken, OperationError<InstanceError>>> { | |
369 | ) -> LocalBoxFuture<'static, Result<UserAuthenticationToken, OperationError<InstanceError>>> { | |
373 | 370 | async move { |
374 | 371 | let mut backend = state.user_backend.lock().await; |
375 | 372 | |
@@ -378,7 +375,7 @@ pub fn instance_registration_request( | ||
378 | 375 | .await |
379 | 376 | .map_err(|e| OperationError::Internal(e.to_string())) |
380 | 377 | } |
381 | .boxed() | |
378 | .boxed_local() | |
382 | 379 | } |
383 | 380 | |
384 | 381 | pub fn instance_create_repository_request( |
@@ -388,7 +385,7 @@ pub fn instance_create_repository_request( | ||
388 | 385 | requester: AuthenticatedUser, |
389 | 386 | // Authorizes the request for SAME-INSTANCE |
390 | 387 | _authorized_instance: AuthorizedInstance, |
391 | ) -> BoxFuture<'static, Result<Repository, OperationError<InstanceError>>> { | |
388 | ) -> LocalBoxFuture<'static, Result<Repository, OperationError<InstanceError>>> { | |
392 | 389 | async move { |
393 | 390 | let mut backend = state.repository_backend.lock().await; |
394 | 391 | |
@@ -397,15 +394,15 @@ pub fn instance_create_repository_request( | ||
397 | 394 | .await |
398 | 395 | .map_err(|e| OperationError::Internal(e.to_string())) |
399 | 396 | } |
400 | .boxed() | |
397 | .boxed_local() | |
401 | 398 | } |
402 | 399 | |
403 | 400 | pub fn user_get_value_display_name( |
404 | 401 | object: &User, |
405 | operation: GetValue<DisplayName>, | |
402 | operation: GetValueTyped<DisplayName>, | |
406 | 403 | state: DatabaseBackend, |
407 | _requester: AuthorizedUser, | |
408 | ) -> BoxFuture<'static, Result<DisplayName, OperationError<GetValueError>>> { | |
404 | // _requester: AuthorizedUser, | |
405 | ) -> LocalBoxFuture<'static, Result<DisplayName, OperationError<GetValueError>>> { | |
409 | 406 | let object = object.clone(); |
410 | 407 | |
411 | 408 | async move { |
@@ -419,14 +416,14 @@ pub fn user_get_value_display_name( | ||
419 | 416 | Ok(serde_json::from_value(raw_value.into_inner()) |
420 | 417 | .map_err(|e| OperationError::Internal(e.to_string()))?) |
421 | 418 | } |
422 | .boxed() | |
419 | .boxed_local() | |
423 | 420 | } |
424 | 421 | |
425 | 422 | pub fn user_get_value_bio( |
426 | 423 | object: &User, |
427 | operation: GetValue<Bio>, | |
424 | operation: GetValueTyped<Bio>, | |
428 | 425 | state: DatabaseBackend, |
429 | ) -> BoxFuture<'static, Result<Bio, OperationError<GetValueError>>> { | |
426 | ) -> LocalBoxFuture<'static, Result<Bio, OperationError<GetValueError>>> { | |
430 | 427 | let object = object.clone(); |
431 | 428 | |
432 | 429 | async move { |
@@ -440,14 +437,14 @@ pub fn user_get_value_bio( | ||
440 | 437 | Ok(serde_json::from_value(raw_value.into_inner()) |
441 | 438 | .map_err(|e| OperationError::Internal(e.to_string()))?) |
442 | 439 | } |
443 | .boxed() | |
440 | .boxed_local() | |
444 | 441 | } |
445 | 442 | |
446 | 443 | pub fn repository_get_value_description( |
447 | 444 | object: &Repository, |
448 | operation: GetValue<Description>, | |
445 | operation: GetValueTyped<Description>, | |
449 | 446 | state: DatabaseBackend, |
450 | ) -> BoxFuture<'static, Result<Description, OperationError<GetValueError>>> { | |
447 | ) -> LocalBoxFuture<'static, Result<Description, OperationError<GetValueError>>> { | |
451 | 448 | let object = object.clone(); |
452 | 449 | |
453 | 450 | async move { |
@@ -461,14 +458,56 @@ pub fn repository_get_value_description( | ||
461 | 458 | Ok(serde_json::from_value(raw_value.into_inner()) |
462 | 459 | .map_err(|e| OperationError::Internal(e.to_string()))?) |
463 | 460 | } |
464 | .boxed() | |
461 | .boxed_local() | |
465 | 462 | } |
466 | 463 | |
467 | 464 | pub fn repository_get_value_visibility( |
468 | 465 | object: &Repository, |
469 | operation: GetValue<Visibility>, | |
466 | operation: GetValueTyped<Visibility>, | |
467 | state: DatabaseBackend, | |
468 | ) -> LocalBoxFuture<'static, Result<Visibility, OperationError<GetValueError>>> { | |
469 | let object = object.clone(); | |
470 | ||
471 | async move { | |
472 | let mut backend = state.repository_backend.lock().await; | |
473 | ||
474 | let raw_value = backend | |
475 | .get_value(&object, &operation.value_name) | |
476 | .await | |
477 | .map_err(|e| OperationError::Internal(e.to_string()))?; | |
478 | ||
479 | Ok(serde_json::from_value(raw_value.into_inner()) | |
480 | .map_err(|e| OperationError::Internal(e.to_string()))?) | |
481 | } | |
482 | .boxed_local() | |
483 | } | |
484 | ||
485 | pub fn repository_get_default_branch( | |
486 | object: &Repository, | |
487 | operation: GetValueTyped<DefaultBranch>, | |
488 | state: DatabaseBackend, | |
489 | ) -> LocalBoxFuture<'static, Result<DefaultBranch, OperationError<GetValueError>>> { | |
490 | let object = object.clone(); | |
491 | ||
492 | async move { | |
493 | let mut backend = state.repository_backend.lock().await; | |
494 | ||
495 | let raw_value = backend | |
496 | .get_value(&object, &operation.value_name) | |
497 | .await | |
498 | .map_err(|e| OperationError::Internal(e.to_string()))?; | |
499 | ||
500 | Ok(serde_json::from_value(raw_value.into_inner()) | |
501 | .map_err(|e| OperationError::Internal(e.to_string()))?) | |
502 | } | |
503 | .boxed_local() | |
504 | } | |
505 | ||
506 | pub fn repository_get_latest_commit( | |
507 | object: &Repository, | |
508 | operation: GetValueTyped<LatestCommit>, | |
470 | 509 | state: DatabaseBackend, |
471 | ) -> BoxFuture<'static, Result<Visibility, OperationError<GetValueError>>> { | |
510 | ) -> LocalBoxFuture<'static, Result<LatestCommit, OperationError<GetValueError>>> { | |
472 | 511 | let object = object.clone(); |
473 | 512 | |
474 | 513 | async move { |
@@ -482,5 +521,5 @@ pub fn repository_get_value_visibility( | ||
482 | 521 | Ok(serde_json::from_value(raw_value.into_inner()) |
483 | 522 | .map_err(|e| OperationError::Internal(e.to_string()))?) |
484 | 523 | } |
485 | .boxed() | |
524 | .boxed_local() | |
486 | 525 | } |
giterated-daemon/src/database_backend/mod.rs
@@ -21,14 +21,15 @@ use self::handler::{ | ||
21 | 21 | instance_authentication_request, instance_create_repository_request, |
22 | 22 | instance_registration_request, repository_commit_before, repository_diff, |
23 | 23 | repository_diff_patch, repository_file_from_id, repository_file_from_path, |
24 | repository_get_value_description, repository_get_value_visibility, repository_info, | |
25 | user_get_value_bio, user_get_value_display_name, | |
24 | repository_get_default_branch, repository_get_latest_commit, repository_get_value_description, | |
25 | repository_get_value_visibility, repository_info, user_get_repositories, user_get_value_bio, | |
26 | user_get_value_display_name, | |
26 | 27 | }; |
27 | 28 | |
28 | 29 | #[derive(Clone, Debug)] |
29 | 30 | pub struct Foobackend {} |
30 | 31 | |
31 | #[async_trait::async_trait] | |
32 | #[async_trait::async_trait(?Send)] | |
32 | 33 | impl ObjectBackend<StackOperationState> for Foobackend { |
33 | 34 | async fn object_operation<O: GiteratedObject + Debug, D: GiteratedOperation<O> + Debug>( |
34 | 35 | &self, |
@@ -72,13 +73,13 @@ impl DatabaseBackend { | ||
72 | 73 | } |
73 | 74 | } |
74 | 75 | |
75 | pub fn into_backend(&self) -> SubstackBuilder<Self> { | |
76 | let mut builder = SubstackBuilder::<Self>::new(); | |
76 | pub fn into_substack(self) -> SubstackBuilder<Self> { | |
77 | let mut builder = SubstackBuilder::<Self>::new(self); | |
77 | 78 | |
78 | 79 | builder |
79 | .object::<Instance>() | |
80 | 80 | .object::<Repository>() |
81 | .object::<User>(); | |
81 | .object::<User>() | |
82 | .object::<Instance>(); | |
82 | 83 | |
83 | 84 | builder |
84 | 85 | .setting::<DisplayName>() |
@@ -88,12 +89,15 @@ impl DatabaseBackend { | ||
88 | 89 | .setting::<DefaultBranch>(); |
89 | 90 | |
90 | 91 | builder |
91 | .value(user_get_value_display_name) | |
92 | 92 | .value(user_get_value_bio) |
93 | .value(user_get_value_display_name) | |
93 | 94 | .value(repository_get_value_description) |
94 | .value(repository_get_value_visibility); | |
95 | .value(repository_get_value_visibility) | |
96 | .value(repository_get_default_branch) | |
97 | .value(repository_get_latest_commit); | |
95 | 98 | |
96 | 99 | builder |
100 | .operation(user_get_repositories) | |
97 | 101 | .operation(repository_info) |
98 | 102 | .operation(repository_file_from_id) |
99 | 103 | .operation(repository_file_from_path) |
giterated-daemon/src/keys.rs
@@ -14,7 +14,7 @@ impl PublicKeyCache { | ||
14 | 14 | if let Some(key) = self.keys.get(instance) { |
15 | 15 | return Ok(key.clone()); |
16 | 16 | } else { |
17 | let key = reqwest::get(format!("https://{}/.giterated/pubkey.pem", instance.url)) | |
17 | let key = reqwest::get(format!("https://{}/.giterated/pubkey.pem", instance)) | |
18 | 18 | .await? |
19 | 19 | .text() |
20 | 20 | .await?; |
giterated-daemon/src/lib.rs
@@ -10,7 +10,6 @@ pub mod connection; | ||
10 | 10 | pub mod database_backend; |
11 | 11 | pub mod federation; |
12 | 12 | pub mod keys; |
13 | pub mod message; | |
14 | 13 | |
15 | 14 | #[macro_use] |
16 | 15 | extern crate tracing; |
giterated-daemon/src/main.rs
@@ -20,8 +20,10 @@ use tokio::{ | ||
20 | 20 | io::{AsyncRead, AsyncReadExt, AsyncWrite}, |
21 | 21 | net::{TcpListener, TcpStream}, |
22 | 22 | sync::Mutex, |
23 | task::LocalSet, | |
23 | 24 | }; |
24 | 25 | use tokio_tungstenite::{accept_async, WebSocketStream}; |
26 | use tokio_util::task::LocalPoolHandle; | |
25 | 27 | use toml::Table; |
26 | 28 | |
27 | 29 | #[macro_use] |
@@ -91,7 +93,7 @@ async fn main() -> Result<(), Error> { | ||
91 | 93 | |
92 | 94 | let mut runtime = GiteratedStack::default(); |
93 | 95 | |
94 | let database_backend = database_backend.into_backend(); | |
96 | let database_backend = database_backend.into_substack(); | |
95 | 97 | runtime.merge_builder(database_backend); |
96 | 98 | |
97 | 99 | let runtime = Arc::new(runtime); |
@@ -106,6 +108,8 @@ async fn main() -> Result<(), Error> { | ||
106 | 108 | } |
107 | 109 | }; |
108 | 110 | |
111 | let pool = LocalPoolHandle::new(5); | |
112 | ||
109 | 113 | loop { |
110 | 114 | let stream = accept_stream(&mut listener).await; |
111 | 115 | info!("Connected"); |
@@ -134,22 +138,35 @@ async fn main() -> Result<(), Error> { | ||
134 | 138 | }; |
135 | 139 | |
136 | 140 | info!("Websocket connection established with {}", address); |
137 | ||
138 | let connection = RawConnection { | |
139 | task: tokio::spawn(connection_wrapper( | |
141 | let connections_cloned = connections.clone(); | |
142 | let repository_backend = repository_backend.clone(); | |
143 | let user_backend = user_backend.clone(); | |
144 | let token_granter = token_granter.clone(); | |
145 | let settings = settings.clone(); | |
146 | let instance_connections = instance_connections.clone(); | |
147 | let config = config.clone(); | |
148 | let runtime = runtime.clone(); | |
149 | let operation_state = operation_state.clone(); | |
150 | ||
151 | pool.spawn_pinned(move || { | |
152 | connection_wrapper( | |
140 | 153 | connection, |
141 | connections.clone(), | |
142 | repository_backend.clone(), | |
143 | user_backend.clone(), | |
144 | token_granter.clone(), | |
145 | settings.clone(), | |
154 | connections_cloned, | |
155 | repository_backend, | |
156 | user_backend, | |
157 | token_granter, | |
158 | settings, | |
146 | 159 | address, |
147 | 160 | Instance::from_str(config["giterated"]["instance"].as_str().unwrap()).unwrap(), |
148 | instance_connections.clone(), | |
149 | config.clone(), | |
150 | runtime.clone(), | |
151 | operation_state.clone(), | |
152 | )), | |
161 | instance_connections, | |
162 | config, | |
163 | runtime, | |
164 | operation_state, | |
165 | ) | |
166 | }); | |
167 | ||
168 | let connection = RawConnection { | |
169 | task: tokio::spawn(async move { () }), | |
153 | 170 | }; |
154 | 171 | |
155 | 172 | connections.lock().await.connections.push(connection); |
giterated-models/Cargo.toml
@@ -24,6 +24,7 @@ git2 = "0.17" | ||
24 | 24 | chrono = { version = "0.4", features = [ "serde" ] } |
25 | 25 | async-trait = "0.1" |
26 | 26 | serde_with = "3.3.0" |
27 | url = {version = "2.4.1", features = ["serde"]} | |
27 | 28 | |
28 | 29 | # Git backend |
29 | 30 | sqlx = { version = "0.7", default-features = false, features = [ "macros", "chrono" ] } |
giterated-models/src/authenticated.rs
@@ -8,13 +8,12 @@ use rsa::{ | ||
8 | 8 | RsaPrivateKey, |
9 | 9 | }; |
10 | 10 | use serde::{Deserialize, Serialize}; |
11 | use serde_json::Value; | |
12 | 11 | |
13 | 12 | use crate::{ |
14 | 13 | instance::Instance, |
15 | 14 | message::GiteratedMessage, |
16 | 15 | object::{AnyObject, GiteratedObject}, |
17 | operation::{AnyOperation, AnyOperationV2, GiteratedOperation}, | |
16 | operation::{AnyOperation, GiteratedOperation}, | |
18 | 17 | user::User, |
19 | 18 | }; |
20 | 19 | |
@@ -41,19 +40,10 @@ pub struct AuthenticatedPayload { | ||
41 | 40 | |
42 | 41 | impl AuthenticatedPayload { |
43 | 42 | pub fn into_message(self) -> GiteratedMessage<AnyObject, AnyOperation> { |
44 | let payload = serde_json::from_slice::<Value>(&self.payload).unwrap(); | |
45 | 43 | GiteratedMessage { |
46 | 44 | object: AnyObject(self.object), |
47 | 45 | operation: self.operation, |
48 | payload: AnyOperation(payload), | |
49 | } | |
50 | } | |
51 | pub fn into_message_v2(self) -> GiteratedMessage<AnyObject, AnyOperationV2> { | |
52 | let _payload = serde_json::from_slice::<Value>(&self.payload).unwrap(); | |
53 | GiteratedMessage { | |
54 | object: AnyObject(self.object), | |
55 | operation: self.operation, | |
56 | payload: AnyOperationV2(serde_json::to_vec(&self.payload).unwrap()), | |
46 | payload: AnyOperation(self.payload), | |
57 | 47 | } |
58 | 48 | } |
59 | 49 | } |
giterated-models/src/instance/mod.rs
@@ -7,6 +7,7 @@ mod operations; | ||
7 | 7 | mod values; |
8 | 8 | |
9 | 9 | pub use operations::*; |
10 | use url::Url; | |
10 | 11 | pub use values::*; |
11 | 12 | |
12 | 13 | use crate::object::GiteratedObject; |
@@ -34,9 +35,7 @@ pub struct InstanceMeta { | ||
34 | 35 | /// assert_eq!(Instance::from_str("giterated.dev").unwrap(), instance); |
35 | 36 | /// ``` |
36 | 37 | #[derive(Clone, Debug, Hash, PartialEq, Eq, Serialize, Deserialize)] |
37 | pub struct Instance { | |
38 | pub url: String, | |
39 | } | |
38 | pub struct Instance(pub String); | |
40 | 39 | |
41 | 40 | impl GiteratedObject for Instance { |
42 | 41 | fn object_name() -> &'static str { |
@@ -50,7 +49,7 @@ impl GiteratedObject for Instance { | ||
50 | 49 | |
51 | 50 | impl Display for Instance { |
52 | 51 | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { |
53 | f.write_str(&self.url) | |
52 | f.write_str(&self.0.to_string()) | |
54 | 53 | } |
55 | 54 | } |
56 | 55 | |
@@ -58,7 +57,13 @@ impl FromStr for Instance { | ||
58 | 57 | type Err = InstanceParseError; |
59 | 58 | |
60 | 59 | fn from_str(s: &str) -> Result<Self, Self::Err> { |
61 | Ok(Self { url: s.to_string() }) | |
60 | let with_protocol = format!("wss://{}", s); | |
61 | ||
62 | if Url::parse(&with_protocol).is_ok() { | |
63 | Ok(Self(s.to_string())) | |
64 | } else { | |
65 | Err(InstanceParseError::InvalidFormat) | |
66 | } | |
62 | 67 | } |
63 | 68 | } |
64 | 69 |
giterated-models/src/message.rs
@@ -47,7 +47,7 @@ impl GiteratedMessage<AnyObject, AnyOperation> { | ||
47 | 47 | &self, |
48 | 48 | ) -> Result<GiteratedMessage<O, V>, ()> { |
49 | 49 | let object = O::from_object_str(&self.object.0).map_err(|_| ())?; |
50 | let payload = serde_json::from_value::<V>(self.payload.0.clone()).map_err(|_| ())?; | |
50 | let payload = serde_json::from_slice::<V>(&self.payload.0).map_err(|_| ())?; | |
51 | 51 | |
52 | 52 | Ok(GiteratedMessage { |
53 | 53 | object, |
giterated-models/src/object.rs
@@ -11,7 +11,7 @@ use crate::{ | ||
11 | 11 | object_backend::ObjectBackend, |
12 | 12 | operation::GiteratedOperation, |
13 | 13 | settings::{AnySetting, GetSetting, GetSettingError, SetSetting, SetSettingError, Setting}, |
14 | value::{GetValue, GiteratedObjectValue}, | |
14 | value::{GetValueTyped, GiteratedObjectValue}, | |
15 | 15 | }; |
16 | 16 | |
17 | 17 | mod operations; |
@@ -22,7 +22,7 @@ pub struct Object< | ||
22 | 22 | 'b, |
23 | 23 | S: Clone + Send + Sync, |
24 | 24 | O: GiteratedObject, |
25 | B: ObjectBackend<S> + 'b + Send + Sync + Clone, | |
25 | B: ObjectBackend<S> + 'b + Send + Clone, | |
26 | 26 | > { |
27 | 27 | pub(crate) inner: O, |
28 | 28 | pub(crate) backend: B, |
@@ -56,7 +56,7 @@ impl< | ||
56 | 56 | } |
57 | 57 | } |
58 | 58 | |
59 | pub trait GiteratedObject: Send + Display + FromStr + Sync { | |
59 | pub trait GiteratedObject: Send + Display + FromStr + Sync + Clone { | |
60 | 60 | fn object_name() -> &'static str; |
61 | 61 | |
62 | 62 | fn from_object_str(object_str: &str) -> Result<Self, Error>; |
@@ -69,21 +69,21 @@ impl< | ||
69 | 69 | B: ObjectBackend<I>, |
70 | 70 | > Object<'b, I, O, B> |
71 | 71 | { |
72 | pub async fn get<V: GiteratedObjectValue<Object = O> + Send + Debug>( | |
72 | pub async fn get<V: GiteratedObjectValue<Object = O> + Send + Debug + 'static>( | |
73 | 73 | &mut self, |
74 | 74 | operation_state: &I, |
75 | 75 | ) -> Result<V, OperationError<GetValueError>> { |
76 | 76 | let result = self |
77 | 77 | .request( |
78 | GetValue { | |
78 | GetValueTyped::<V> { | |
79 | 79 | value_name: V::value_name().to_string(), |
80 | _marker: PhantomData, | |
80 | ty: Default::default(), | |
81 | 81 | }, |
82 | 82 | operation_state, |
83 | 83 | ) |
84 | 84 | .await; |
85 | 85 | |
86 | result | |
86 | Ok(result?) | |
87 | 87 | } |
88 | 88 | |
89 | 89 | pub async fn get_setting<S: Setting + Send + Clone + Debug>( |
@@ -115,7 +115,7 @@ impl< | ||
115 | 115 | .await |
116 | 116 | } |
117 | 117 | |
118 | pub async fn request<R: GiteratedOperation<O> + Debug>( | |
118 | pub async fn request<R: GiteratedOperation<O> + Debug + 'static>( | |
119 | 119 | &mut self, |
120 | 120 | request: R, |
121 | 121 | operation_state: &I, |
giterated-models/src/object_backend.rs
@@ -6,8 +6,8 @@ use crate::{ | ||
6 | 6 | |
7 | 7 | use std::fmt::Debug; |
8 | 8 | |
9 | #[async_trait::async_trait] | |
10 | pub trait ObjectBackend<S: Clone + Send + Sync>: Send + Sync + Sized + Clone { | |
9 | #[async_trait::async_trait(?Send)] | |
10 | pub trait ObjectBackend<S: Clone + Send + Sync>: Sized + Clone + Send { | |
11 | 11 | async fn object_operation<O, D>( |
12 | 12 | &self, |
13 | 13 | object: O, |
@@ -17,9 +17,9 @@ pub trait ObjectBackend<S: Clone + Send + Sync>: Send + Sync + Sized + Clone { | ||
17 | 17 | ) -> Result<D::Success, OperationError<D::Failure>> |
18 | 18 | where |
19 | 19 | O: GiteratedObject + Debug + 'static, |
20 | D: GiteratedOperation<O> + Debug; | |
20 | D: GiteratedOperation<O> + Debug + 'static; | |
21 | 21 | |
22 | async fn get_object<O: GiteratedObject + Debug>( | |
22 | async fn get_object<O: GiteratedObject + Debug + 'static>( | |
23 | 23 | &self, |
24 | 24 | object_str: &str, |
25 | 25 | operation_state: &S, |
giterated-models/src/operation.rs
@@ -1,7 +1,6 @@ | ||
1 | 1 | use std::{any::type_name, fmt::Debug}; |
2 | 2 | |
3 | 3 | use serde::{de::DeserializeOwned, Deserialize, Serialize}; |
4 | use serde_json::Value; | |
5 | 4 | |
6 | 5 | use crate::object::GiteratedObject; |
7 | 6 | |
@@ -19,20 +18,9 @@ pub trait GiteratedOperation<O: GiteratedObject>: | ||
19 | 18 | #[derive(Clone, Debug, Serialize, Deserialize)] |
20 | 19 | #[serde(transparent)] |
21 | 20 | #[repr(transparent)] |
22 | pub struct AnyOperation(pub Value); | |
21 | pub struct AnyOperation(pub Vec<u8>); | |
23 | 22 | |
24 | 23 | impl<O: GiteratedObject> GiteratedOperation<O> for AnyOperation { |
25 | type Success = Value; | |
26 | ||
27 | type Failure = Value; | |
28 | } | |
29 | ||
30 | #[derive(Clone, Debug, Serialize, Deserialize)] | |
31 | #[serde(transparent)] | |
32 | #[repr(transparent)] | |
33 | pub struct AnyOperationV2(pub Vec<u8>); | |
34 | ||
35 | impl<O: GiteratedObject> GiteratedOperation<O> for AnyOperationV2 { | |
36 | 24 | type Success = Vec<u8>; |
37 | 25 | |
38 | 26 | type Failure = Vec<u8>; |
giterated-models/src/user/mod.rs
@@ -53,7 +53,7 @@ impl GiteratedObject for User { | ||
53 | 53 | |
54 | 54 | impl Display for User { |
55 | 55 | fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { |
56 | write!(f, "{}:{}", self.username, self.instance.url) | |
56 | write!(f, "{}:{}", self.username, self.instance.0) | |
57 | 57 | } |
58 | 58 | } |
59 | 59 |
giterated-models/src/value.rs
@@ -12,18 +12,26 @@ pub trait GiteratedObjectValue: Send + Sync + Serialize + DeserializeOwned { | ||
12 | 12 | } |
13 | 13 | |
14 | 14 | #[derive(Serialize, Deserialize, Debug, Clone)] |
15 | pub struct GetValue<V: GiteratedObjectValue> { | |
15 | pub struct GetValue { | |
16 | 16 | pub value_name: String, |
17 | pub(crate) _marker: PhantomData<V>, | |
17 | } | |
18 | ||
19 | impl<O: GiteratedObject + Send> GiteratedOperation<O> for GetValue { | |
20 | fn operation_name() -> &'static str { | |
21 | "get_value" | |
22 | } | |
23 | type Success = Value; | |
24 | type Failure = GetValueError; | |
18 | 25 | } |
19 | 26 | |
20 | 27 | #[derive(Serialize, Deserialize, Debug, Clone)] |
21 | pub struct GetValueV2 { | |
28 | pub struct GetValueTyped<V: GiteratedObjectValue> { | |
22 | 29 | pub value_name: String, |
30 | pub ty: PhantomData<V>, | |
23 | 31 | } |
24 | 32 | |
25 | impl<O: GiteratedObject + Send, V: GiteratedObjectValue<Object = O> + Send> GiteratedOperation<O> | |
26 | for GetValue<V> | |
33 | impl<O: GiteratedObject + Send, V: GiteratedObjectValue<Object = O>> GiteratedOperation<O> | |
34 | for GetValueTyped<V> | |
27 | 35 | { |
28 | 36 | fn operation_name() -> &'static str { |
29 | 37 | "get_value" |
giterated-stack/src/handler.rs
@@ -1,14 +1,18 @@ | ||
1 | 1 | use std::{any::Any, collections::HashMap, sync::Arc}; |
2 | 2 | |
3 | use futures_util::FutureExt; | |
3 | 4 | use giterated_models::{ |
4 | 5 | authenticated::AuthenticatedPayload, |
5 | error::OperationError, | |
6 | error::{GetValueError, OperationError}, | |
7 | instance::Instance, | |
6 | 8 | message::GiteratedMessage, |
7 | object::{AnyObject, GiteratedObject, Object, ObjectRequestError}, | |
9 | object::{ | |
10 | AnyObject, GiteratedObject, Object, ObjectRequest, ObjectRequestError, ObjectResponse, | |
11 | }, | |
8 | 12 | object_backend::ObjectBackend, |
9 | operation::{AnyOperationV2, GiteratedOperation}, | |
13 | operation::{AnyOperation, GiteratedOperation}, | |
10 | 14 | settings::{GetSetting, SetSetting, Setting}, |
11 | value::{GetValue, GetValueV2, GiteratedObjectValue}, | |
15 | value::{AnyValue, GetValue, GetValueTyped, GiteratedObjectValue}, | |
12 | 16 | }; |
13 | 17 | use tracing::trace; |
14 | 18 | |
@@ -77,13 +81,28 @@ impl HandlerTree { | ||
77 | 81 | self.elements.push(handler); |
78 | 82 | } |
79 | 83 | |
80 | pub fn handle( | |
84 | pub async fn handle( | |
81 | 85 | &self, |
82 | _object: &dyn Any, | |
83 | _operation: Box<dyn Any>, | |
84 | _operation_state: &StackOperationState, | |
85 | ) -> Result<Box<dyn Any>, OperationError<Box<dyn Any>>> { | |
86 | todo!() | |
86 | object: &Box<dyn Any + Send + Sync>, | |
87 | operation: &Box<dyn Any + Send + Sync>, | |
88 | operation_state: &StackOperationState, | |
89 | ) -> Result<Box<dyn Any + 'static>, OperationError<Box<dyn Any + 'static>>> { | |
90 | for handler in self.elements.iter() { | |
91 | match handler.handle(object, &operation, operation_state).await { | |
92 | Ok(success) => return Ok(success), | |
93 | Err(err) => match err { | |
94 | OperationError::Operation(failure) => { | |
95 | return Err(OperationError::Operation(failure)) | |
96 | } | |
97 | OperationError::Internal(e) => return Err(OperationError::Internal(e)), | |
98 | _ => { | |
99 | continue; | |
100 | } | |
101 | }, | |
102 | } | |
103 | } | |
104 | ||
105 | Err(OperationError::Unhandled) | |
87 | 106 | } |
88 | 107 | } |
89 | 108 | |
@@ -113,8 +132,14 @@ pub struct SubstackBuilder<S: GiteratedStackState> { | ||
113 | 132 | } |
114 | 133 | |
115 | 134 | impl<S: GiteratedStackState + 'static> SubstackBuilder<S> { |
116 | pub fn new() -> Self { | |
117 | todo!() | |
135 | pub fn new(state: S) -> Self { | |
136 | Self { | |
137 | operation_handlers: Default::default(), | |
138 | value_getters: Default::default(), | |
139 | setting_getters: Default::default(), | |
140 | metadata: Default::default(), | |
141 | state, | |
142 | } | |
118 | 143 | } |
119 | 144 | } |
120 | 145 | |
@@ -127,8 +152,10 @@ impl<S: GiteratedStackState + 'static> SubstackBuilder<S> { | ||
127 | 152 | pub fn operation<A, O, D, H>(&mut self, handler: H) -> &mut Self |
128 | 153 | where |
129 | 154 | O: GiteratedObject + 'static, |
130 | D: GiteratedOperation<O> + 'static, | |
131 | H: GiteratedOperationHandler<A, O, D, S> + 'static + Clone, | |
155 | D: GiteratedOperation<O> + 'static + Clone, | |
156 | H: GiteratedOperationHandler<A, O, D, S> + 'static + Clone + Send + Sync, | |
157 | D::Failure: Send + Sync, | |
158 | D::Success: Send + Sync, | |
132 | 159 | { |
133 | 160 | let object_name = handler.object_name().to_string(); |
134 | 161 | let operation_name = handler.operation_name().to_string(); |
@@ -140,7 +167,7 @@ impl<S: GiteratedStackState + 'static> SubstackBuilder<S> { | ||
140 | 167 | operation_name, |
141 | 168 | }; |
142 | 169 | |
143 | assert!(self.operation_handlers.insert(pair, wrapped).is_none()); | |
170 | self.operation_handlers.insert(pair, wrapped); | |
144 | 171 | |
145 | 172 | self.metadata.register_operation::<O, D>(); |
146 | 173 | |
@@ -154,6 +181,26 @@ impl<S: GiteratedStackState + 'static> SubstackBuilder<S> { | ||
154 | 181 | pub fn object<O: GiteratedObject + 'static>(&mut self) -> &mut Self { |
155 | 182 | self.metadata.register_object::<O>(); |
156 | 183 | |
184 | // Insert handler so ObjectRequest is handled properly | |
185 | let handler = move |_object: &Instance, | |
186 | operation: ObjectRequest, | |
187 | _state: S, | |
188 | _operation_state: StackOperationState, | |
189 | stack: Arc<GiteratedStack>| { | |
190 | async move { | |
191 | for (_object_name, object_meta) in stack.metadata.objects.iter() { | |
192 | if (object_meta.from_str)(&operation.0).is_ok() { | |
193 | return Ok(ObjectResponse(operation.0)); | |
194 | } | |
195 | } | |
196 | ||
197 | Err(OperationError::Unhandled) | |
198 | } | |
199 | .boxed_local() | |
200 | }; | |
201 | ||
202 | self.operation(handler); | |
203 | ||
157 | 204 | self |
158 | 205 | } |
159 | 206 | |
@@ -176,14 +223,61 @@ impl<S: GiteratedStackState + 'static> SubstackBuilder<S> { | ||
176 | 223 | pub fn value<O, V, A, F>(&mut self, handler: F) -> &mut Self |
177 | 224 | where |
178 | 225 | O: GiteratedObject + 'static, |
179 | V: GiteratedObjectValue<Object = O> + 'static, | |
180 | F: GiteratedOperationHandler<A, O, GetValue<V>, S> + Clone + 'static, | |
226 | V: GiteratedObjectValue<Object = O> + 'static + Clone, | |
227 | F: GiteratedOperationHandler<A, O, GetValueTyped<V>, S> + Clone + 'static + Send + Sync, | |
181 | 228 | { |
182 | 229 | let object_name = handler.object_name().to_string(); |
183 | 230 | let value_name = V::value_name().to_string(); |
184 | 231 | |
185 | 232 | let wrapped = OperationWrapper::new(handler, self.state.clone()); |
186 | 233 | |
234 | let handler_object_name = object_name.clone(); | |
235 | let handler_value_name = value_name.clone(); | |
236 | ||
237 | // Insert handler so GetValue is handled properly | |
238 | let _handler = move |object: &O, | |
239 | operation: GetValueTyped<AnyValue<O>>, | |
240 | _state: S, | |
241 | operation_state: StackOperationState, | |
242 | stack: Arc<GiteratedStack>| { | |
243 | let stack = stack.clone(); | |
244 | let object_name = handler_object_name; | |
245 | let value_name = handler_value_name; | |
246 | let object = object.clone(); | |
247 | async move { | |
248 | for (target, getter) in stack.value_getters.iter() { | |
249 | if target.object_kind != object_name { | |
250 | continue; | |
251 | } | |
252 | ||
253 | if target.value_kind != value_name { | |
254 | continue; | |
255 | } | |
256 | ||
257 | return match getter | |
258 | .handle( | |
259 | &(Box::new(object.clone()) as Box<dyn Any + Send + Sync>), | |
260 | &(Box::new(GetValueTyped::<V> { | |
261 | value_name: operation.value_name, | |
262 | ty: Default::default(), | |
263 | }) as Box<dyn Any + Send + Sync>), | |
264 | &operation_state, | |
265 | ) | |
266 | .await { | |
267 | Ok(success) => Ok(*success.downcast::<<GetValueTyped<V> as GiteratedOperation<O>>::Success>().unwrap()), | |
268 | Err(err) => Err(match err { | |
269 | OperationError::Operation(failure) => OperationError::Operation(*failure.downcast::<<GetValueTyped<V> as GiteratedOperation<O>>::Failure>().unwrap()), | |
270 | OperationError::Internal(internal) => OperationError::Internal(internal), | |
271 | OperationError::Unhandled => OperationError::Unhandled, | |
272 | }), | |
273 | } | |
274 | } | |
275 | ||
276 | Err(OperationError::Unhandled) | |
277 | } | |
278 | .boxed_local() | |
279 | }; | |
280 | ||
187 | 281 | assert!(self |
188 | 282 | .value_getters |
189 | 283 | .insert( |
@@ -204,7 +298,7 @@ impl<S: GiteratedStackState + 'static> SubstackBuilder<S> { | ||
204 | 298 | pub fn object_settings<O, A, F>(&mut self, handler: F) -> &mut Self |
205 | 299 | where |
206 | 300 | O: GiteratedObject + 'static, |
207 | F: GiteratedOperationHandler<A, O, GetSetting, S> + Clone + 'static, | |
301 | F: GiteratedOperationHandler<A, O, GetSetting, S> + Clone + 'static + Send + Sync, | |
208 | 302 | { |
209 | 303 | let object_name = handler.object_name().to_string(); |
210 | 304 | |
@@ -253,7 +347,7 @@ impl RuntimeMetadata { | ||
253 | 347 | name: operation_name, |
254 | 348 | object_kind: object_name, |
255 | 349 | deserialize: Box::new(|bytes| { |
256 | Ok(Box::new(serde_json::from_slice::<D>(bytes).unwrap()) | |
350 | Ok(Box::new(serde_json::from_slice::<D>(bytes)?) | |
257 | 351 | as Box<dyn Any + Send + Sync>) |
258 | 352 | }), |
259 | 353 | any_is_same: Box::new(|any_box| any_box.is::<D>()), |
@@ -291,6 +385,7 @@ impl RuntimeMetadata { | ||
291 | 385 | ) { |
292 | 386 | let object_name = O::object_name().to_string(); |
293 | 387 | let value_name = V::value_name().to_string(); |
388 | let value_name_for_get = V::value_name().to_string(); | |
294 | 389 | |
295 | 390 | if self |
296 | 391 | .values |
@@ -300,8 +395,20 @@ impl RuntimeMetadata { | ||
300 | 395 | value_kind: value_name.clone(), |
301 | 396 | }, |
302 | 397 | ValueMeta { |
303 | name: value_name, | |
398 | name: value_name.clone(), | |
304 | 399 | deserialize: Box::new(|bytes| Ok(Box::new(serde_json::from_slice(&bytes)?))), |
400 | serialize: Box::new(|value| { | |
401 | let value = value.downcast::<V>().unwrap(); | |
402 | ||
403 | Ok(serde_json::to_vec(&*value)?) | |
404 | }), | |
405 | typed_get: Box::new(move || { | |
406 | Box::new(GetValueTyped::<V> { | |
407 | value_name: value_name_for_get.clone(), | |
408 | ty: Default::default(), | |
409 | }) | |
410 | }), | |
411 | is_get_value_typed: Box::new(move |typed| typed.is::<GetValueTyped<V>>()), | |
305 | 412 | }, |
306 | 413 | ) |
307 | 414 | .is_some() |
@@ -350,32 +457,201 @@ impl RuntimeMetadata { | ||
350 | 457 | self.settings.extend(other.settings); |
351 | 458 | } |
352 | 459 | } |
460 | impl GiteratedStack { | |
461 | /// Handles a giterated network message, returning either a raw success | |
462 | /// payload or a serialized error payload. | |
463 | pub async fn handle_network_message( | |
464 | &self, | |
465 | message: AuthenticatedPayload, | |
466 | operation_state: &StackOperationState, | |
467 | ) -> Result<Vec<u8>, OperationError<Vec<u8>>> { | |
468 | let message: GiteratedMessage<AnyObject, AnyOperation> = message.into_message(); | |
469 | ||
470 | // Deserialize the object, also getting the object type's name | |
471 | let (object_type, object) = { | |
472 | let mut result = None; | |
473 | ||
474 | for (object_type, object_meta) in self.metadata.objects.iter() { | |
475 | if let Ok(object) = (object_meta.from_str)(&message.object.0) { | |
476 | result = Some((object_type.clone(), object)); | |
477 | break; | |
478 | } | |
479 | } | |
480 | ||
481 | result | |
482 | } | |
483 | .ok_or_else(|| OperationError::Unhandled)?; | |
484 | ||
485 | trace!( | |
486 | "Handling network message {}::<{}>", | |
487 | message.operation, | |
488 | object_type | |
489 | ); | |
490 | ||
491 | if message.operation == "get_value" { | |
492 | // Special case | |
493 | let operation: GetValue = serde_json::from_slice(&message.payload.0).unwrap(); | |
494 | ||
495 | return self | |
496 | .network_get_value(object, object_type.clone(), operation, operation_state) | |
497 | .await; | |
498 | } | |
499 | ||
500 | let target = ObjectOperationPair { | |
501 | object_name: object_type.clone(), | |
502 | operation_name: message.operation.clone(), | |
503 | }; | |
504 | ||
505 | // Resolve the target operations from the handlers table | |
506 | let handler = self | |
507 | .operation_handlers | |
508 | .get(&target) | |
509 | .ok_or_else(|| OperationError::Unhandled)?; | |
510 | ||
511 | trace!( | |
512 | "Resolved operation handler for network message {}::<{}>", | |
513 | message.operation, | |
514 | object_type | |
515 | ); | |
516 | ||
517 | // Deserialize the operation | |
518 | let meta = self | |
519 | .metadata | |
520 | .operations | |
521 | .get(&target) | |
522 | .ok_or_else(|| OperationError::Unhandled)?; | |
523 | ||
524 | let operation = (meta.deserialize)(&message.payload.0) | |
525 | .map_err(|e| OperationError::Internal(e.to_string()))?; | |
526 | ||
527 | trace!( | |
528 | "Deserialized operation for network message {}::<{}>", | |
529 | message.operation, | |
530 | object_type | |
531 | ); | |
532 | ||
533 | trace!( | |
534 | "Calling handler for network message {}::<{}>", | |
535 | message.operation, | |
536 | object_type | |
537 | ); | |
538 | ||
539 | // Get the raw result of the operation, where the return values are boxed. | |
540 | let raw_result = handler.handle(&object, &operation, operation_state).await; | |
541 | ||
542 | trace!( | |
543 | "Finished handling network message {}::<{}>", | |
544 | message.operation, | |
545 | object_type | |
546 | ); | |
547 | ||
548 | // Deserialize the raw result for the network | |
549 | match raw_result { | |
550 | Ok(success) => Ok((meta.serialize_success)(success) | |
551 | .map_err(|e| OperationError::Internal(e.to_string()))?), | |
552 | Err(err) => Err(match err { | |
553 | OperationError::Operation(failure) => OperationError::Operation( | |
554 | (meta.serialize_error)(failure) | |
555 | .map_err(|e| OperationError::Internal(e.to_string()))?, | |
556 | ), | |
557 | OperationError::Internal(internal) => OperationError::Internal(internal), | |
558 | OperationError::Unhandled => OperationError::Unhandled, | |
559 | }), | |
560 | } | |
561 | } | |
562 | ||
563 | pub async fn network_get_value( | |
564 | &self, | |
565 | object: Box<dyn Any + Send + Sync>, | |
566 | object_kind: String, | |
567 | operation: GetValue, | |
568 | operation_state: &StackOperationState, | |
569 | ) -> Result<Vec<u8>, OperationError<Vec<u8>>> { | |
570 | trace!("Handling network get_value for {}", operation.value_name); | |
571 | ||
572 | let value_meta = self | |
573 | .metadata | |
574 | .values | |
575 | .get(&ObjectValuePair { | |
576 | object_kind: object_kind.clone(), | |
577 | value_kind: operation.value_name.clone(), | |
578 | }) | |
579 | .ok_or_else(|| OperationError::Unhandled)?; | |
580 | ||
581 | for (target, getter) in self.value_getters.iter() { | |
582 | if target.object_kind != object_kind { | |
583 | continue; | |
584 | } | |
585 | ||
586 | if target.value_kind != operation.value_name { | |
587 | continue; | |
588 | } | |
353 | 589 | |
354 | #[async_trait::async_trait] | |
355 | impl<L, O, D, S> GiteratedOperationHandler<L, O, D, S> for GiteratedStack | |
356 | where | |
357 | O: GiteratedObject + 'static, | |
358 | D: GiteratedOperation<O> + 'static, | |
359 | S: GiteratedStackState + 'static, | |
360 | { | |
361 | fn operation_name(&self) -> &str { | |
362 | D::operation_name() | |
590 | return match getter | |
591 | .handle(&(object), &((value_meta.typed_get)()), &operation_state) | |
592 | .await | |
593 | { | |
594 | Ok(success) => { | |
595 | // Serialize success, which is the value type itself | |
596 | let serialized = (value_meta.serialize)(success) | |
597 | .map_err(|e| OperationError::Internal(e.to_string()))?; | |
598 | ||
599 | Ok(serialized) | |
600 | } | |
601 | Err(err) => Err(match err { | |
602 | OperationError::Operation(failure) => { | |
603 | // Failure is sourced from GetValue operation, but this is hardcoded for now | |
604 | let failure: GetValueError = *failure.downcast().unwrap(); | |
605 | ||
606 | OperationError::Operation( | |
607 | serde_json::to_vec(&failure) | |
608 | .map_err(|e| OperationError::Internal(e.to_string()))?, | |
609 | ) | |
610 | } | |
611 | OperationError::Internal(internal) => OperationError::Internal(internal), | |
612 | OperationError::Unhandled => OperationError::Unhandled, | |
613 | }), | |
614 | }; | |
615 | } | |
616 | ||
617 | Err(OperationError::Unhandled) | |
618 | } | |
619 | ||
620 | pub async fn network_get_setting( | |
621 | &self, | |
622 | _operation: GetSetting, | |
623 | _operation_state: &StackOperationState, | |
624 | ) -> Result<Vec<u8>, OperationError<Vec<u8>>> { | |
625 | todo!() | |
363 | 626 | } |
364 | 627 | |
365 | fn object_name(&self) -> &str { | |
366 | O::object_name() | |
628 | pub async fn network_set_setting( | |
629 | &self, | |
630 | _operation: SetSetting, | |
631 | _operation_state: &StackOperationState, | |
632 | ) -> Result<Vec<u8>, OperationError<Vec<u8>>> { | |
633 | todo!() | |
367 | 634 | } |
635 | } | |
636 | ||
637 | use core::fmt::Debug; | |
368 | 638 | |
369 | async fn handle( | |
639 | #[async_trait::async_trait(?Send)] | |
640 | impl ObjectBackend<StackOperationState> for Arc<GiteratedStack> { | |
641 | async fn object_operation<O, D>( | |
370 | 642 | &self, |
371 | object: &O, | |
372 | operation: D, | |
373 | _state: S, | |
643 | in_object: O, | |
644 | operation_name: &str, | |
645 | payload: D, | |
374 | 646 | operation_state: &StackOperationState, |
375 | ) -> Result<D::Success, OperationError<D::Failure>> { | |
647 | ) -> Result<D::Success, OperationError<D::Failure>> | |
648 | where | |
649 | O: GiteratedObject + Debug + 'static, | |
650 | D: GiteratedOperation<O> + Debug + 'static, | |
651 | { | |
376 | 652 | // Erase object and operation types. |
377 | let object = object as &dyn Any; | |
378 | let operation = Box::new(operation) as Box<dyn Any>; | |
653 | let object = Box::new(in_object.clone()) as Box<dyn Any + Send + Sync>; | |
654 | let operation = Box::new(payload) as Box<dyn Any + Send + Sync>; | |
379 | 655 | |
380 | 656 | // We need to determine the type of the object, iterate through all known |
381 | 657 | // object types and check if the &dyn Any we have is the same type as the |
@@ -384,7 +660,7 @@ where | ||
384 | 660 | let mut object_type = None; |
385 | 661 | |
386 | 662 | for (object_name, object_meta) in self.metadata.objects.iter() { |
387 | if (object_meta.any_is_same)(object) { | |
663 | if (object_meta.any_is_same)(&in_object) { | |
388 | 664 | object_type = Some(object_name.clone()); |
389 | 665 | break; |
390 | 666 | } |
@@ -395,12 +671,79 @@ where | ||
395 | 671 | .ok_or_else(|| OperationError::Unhandled)?; |
396 | 672 | |
397 | 673 | // We need to hijack get_value, set_setting, and get_setting. |
398 | if operation.is::<GetValueV2>() { | |
399 | todo!() | |
674 | if operation_name == "get_value" { | |
675 | let mut value_meta = None; | |
676 | for (_, meta) in self.metadata.values.iter() { | |
677 | if (meta.is_get_value_typed)(&operation) { | |
678 | value_meta = Some(meta); | |
679 | break; | |
680 | } | |
681 | } | |
682 | ||
683 | let value_meta = value_meta.ok_or_else(|| OperationError::Unhandled)?; | |
684 | ||
685 | let value_name = value_meta.name.clone(); | |
686 | ||
687 | trace!("Handling get_value for {}::{}", object_type, value_name); | |
688 | ||
689 | for (target, getter) in self.value_getters.iter() { | |
690 | if target.object_kind != object_type { | |
691 | continue; | |
692 | } | |
693 | ||
694 | if target.value_kind != value_name { | |
695 | continue; | |
696 | } | |
697 | ||
698 | return match getter | |
699 | .handle(&(object), &((value_meta.typed_get)()), &operation_state) | |
700 | .await | |
701 | { | |
702 | Ok(success) => Ok(*success.downcast().unwrap()), | |
703 | Err(err) => Err(match err { | |
704 | OperationError::Operation(failure) => { | |
705 | OperationError::Operation(*failure.downcast::<D::Failure>().unwrap()) | |
706 | } | |
707 | OperationError::Internal(internal) => OperationError::Internal(internal), | |
708 | OperationError::Unhandled => OperationError::Unhandled, | |
709 | }), | |
710 | }; | |
711 | } | |
712 | ||
713 | return Err(OperationError::Unhandled); | |
400 | 714 | } else if operation.is::<GetSetting>() { |
401 | todo!() | |
715 | let get_setting: Box<GetSetting> = operation.downcast().unwrap(); | |
716 | let setting_name = get_setting.setting_name.clone(); | |
717 | ||
718 | // Get the setting getter for the object type | |
719 | let getter = self | |
720 | .setting_getters | |
721 | .get(&object_type) | |
722 | .ok_or_else(|| OperationError::Unhandled)?; | |
723 | ||
724 | let setting = getter | |
725 | .handle( | |
726 | &(Box::new(in_object.clone()) as _), | |
727 | &(Box::new(get_setting) as _), | |
728 | operation_state, | |
729 | ) | |
730 | .await | |
731 | .map_err(|_e| OperationError::Unhandled)?; | |
732 | ||
733 | let _setting_meta = self | |
734 | .metadata | |
735 | .settings | |
736 | .get(&setting_name) | |
737 | .ok_or_else(|| OperationError::Unhandled)?; | |
738 | ||
739 | let setting_success: <D as GiteratedOperation<O>>::Success = | |
740 | *setting.downcast().unwrap(); | |
741 | ||
742 | return Ok(setting_success); | |
402 | 743 | } else if operation.is::<SetSetting>() { |
403 | 744 | todo!() |
745 | } else if operation.is::<ObjectRequest>() { | |
746 | todo!() | |
404 | 747 | } |
405 | 748 | |
406 | 749 | // Resolve the operation from the known operations table. |
@@ -413,6 +756,10 @@ where | ||
413 | 756 | continue; |
414 | 757 | } |
415 | 758 | |
759 | if target.operation_name != operation_name { | |
760 | continue; | |
761 | } | |
762 | ||
416 | 763 | if (operation_meta.any_is_same)(&operation) { |
417 | 764 | operation_type = Some(target.clone()); |
418 | 765 | break; |
@@ -429,7 +776,9 @@ where | ||
429 | 776 | .get(&operation_type) |
430 | 777 | .ok_or_else(|| OperationError::Unhandled)?; |
431 | 778 | |
432 | let raw_result = handler_tree.handle(object, operation, operation_state); | |
779 | let raw_result = handler_tree | |
780 | .handle(&object, &operation, operation_state) | |
781 | .await; | |
433 | 782 | |
434 | 783 | // Convert the dynamic result back into its concrete type |
435 | 784 | match raw_result { |
@@ -443,97 +792,21 @@ where | ||
443 | 792 | }), |
444 | 793 | } |
445 | 794 | } |
446 | } | |
447 | 795 | |
448 | impl GiteratedStack { | |
449 | /// Handles a giterated network message, returning either a raw success | |
450 | /// payload or a serialized error payload. | |
451 | pub async fn handle_network_message<S: GiteratedStackState>( | |
796 | async fn get_object<O: GiteratedObject + Debug + 'static>( | |
452 | 797 | &self, |
453 | message: AuthenticatedPayload, | |
454 | _state: &S, | |
455 | operation_state: &StackOperationState, | |
456 | ) -> Result<Vec<u8>, OperationError<Vec<u8>>> { | |
457 | let message: GiteratedMessage<AnyObject, AnyOperationV2> = message.into_message_v2(); | |
458 | ||
459 | // Deserialize the object, also getting the object type's name | |
460 | let (object_type, object) = { | |
461 | let mut result = None; | |
462 | ||
463 | for (object_type, object_meta) in self.metadata.objects.iter() { | |
464 | if let Ok(object) = (object_meta.from_str)(&message.object.0) { | |
465 | result = Some((object_type.clone(), object)); | |
466 | break; | |
467 | } | |
798 | object_str: &str, | |
799 | _operation_state: &StackOperationState, | |
800 | ) -> Result<Object<StackOperationState, O, Self>, OperationError<ObjectRequestError>> { | |
801 | // TODO: Authorization? | |
802 | for (_object_name, object_meta) in self.metadata.objects.iter() { | |
803 | if let Ok(object) = (object_meta.from_str)(object_str) { | |
804 | return Ok(unsafe { | |
805 | Object::new_unchecked(*object.downcast::<O>().unwrap(), self.clone()) | |
806 | }); | |
468 | 807 | } |
469 | ||
470 | result | |
471 | } | |
472 | .ok_or_else(|| OperationError::Unhandled)?; | |
473 | ||
474 | let target = ObjectOperationPair { | |
475 | object_name: object_type, | |
476 | operation_name: message.operation, | |
477 | }; | |
478 | ||
479 | // Resolve the target operations from the handlers table | |
480 | let handler = self | |
481 | .operation_handlers | |
482 | .get(&target) | |
483 | .ok_or_else(|| OperationError::Unhandled)?; | |
484 | ||
485 | // Deserialize the operation | |
486 | let meta = self | |
487 | .metadata | |
488 | .operations | |
489 | .get(&target) | |
490 | .ok_or_else(|| OperationError::Unhandled)?; | |
491 | ||
492 | let operation = | |
493 | (meta.deserialize)(&message.payload.0).map_err(|_| OperationError::Unhandled)?; | |
494 | ||
495 | // Get the raw result of the operation, where the return values are boxed. | |
496 | let raw_result = handler.handle(&object, operation, operation_state); | |
497 | ||
498 | // Deserialize the raw result for the network | |
499 | match raw_result { | |
500 | Ok(success) => Ok((meta.serialize_success)(success) | |
501 | .map_err(|e| OperationError::Internal(e.to_string()))?), | |
502 | Err(err) => Err(match err { | |
503 | OperationError::Operation(failure) => OperationError::Operation( | |
504 | (meta.serialize_error)(failure) | |
505 | .map_err(|e| OperationError::Internal(e.to_string()))?, | |
506 | ), | |
507 | OperationError::Internal(internal) => OperationError::Internal(internal), | |
508 | OperationError::Unhandled => OperationError::Unhandled, | |
509 | }), | |
510 | 808 | } |
511 | } | |
512 | } | |
513 | ||
514 | use core::fmt::Debug; | |
515 | ||
516 | #[async_trait::async_trait] | |
517 | impl ObjectBackend<StackOperationState> for Arc<GiteratedStack> { | |
518 | async fn object_operation<O, D>( | |
519 | &self, | |
520 | _object: O, | |
521 | _operation: &str, | |
522 | _payload: D, | |
523 | _operation_state: &StackOperationState, | |
524 | ) -> Result<D::Success, OperationError<D::Failure>> | |
525 | where | |
526 | O: GiteratedObject + Debug + 'static, | |
527 | D: GiteratedOperation<O> + Debug, | |
528 | { | |
529 | todo!() | |
530 | } | |
531 | 809 | |
532 | async fn get_object<O: GiteratedObject + Debug>( | |
533 | &self, | |
534 | _object_str: &str, | |
535 | _operation_state: &StackOperationState, | |
536 | ) -> Result<Object<StackOperationState, O, Self>, OperationError<ObjectRequestError>> { | |
537 | todo!() | |
810 | Err(OperationError::Unhandled) | |
538 | 811 | } |
539 | 812 | } |
giterated-stack/src/lib.rs
@@ -19,40 +19,46 @@ use giterated_models::{ | ||
19 | 19 | repository::{AccessList, Repository}, |
20 | 20 | settings::{GetSetting, SetSetting}, |
21 | 21 | user::User, |
22 | value::{GetValue, GiteratedObjectValue}, | |
22 | value::GetValue, | |
23 | 23 | }; |
24 | 24 | use serde::{de::DeserializeOwned, Serialize}; |
25 | 25 | |
26 | 26 | #[derive(Clone, Debug, Hash, Eq, PartialEq)] |
27 | 27 | struct ObjectOperationPair { |
28 | object_name: String, | |
29 | operation_name: String, | |
28 | pub object_name: String, | |
29 | pub operation_name: String, | |
30 | 30 | } |
31 | 31 | |
32 | 32 | pub struct SettingMeta { |
33 | name: String, | |
34 | deserialize: Box<dyn Fn(&[u8]) -> Result<Box<dyn Any>, serde_json::Error> + Send + Sync>, | |
33 | pub name: String, | |
34 | pub deserialize: Box<dyn Fn(&[u8]) -> Result<Box<dyn Any>, serde_json::Error> + Send + Sync>, | |
35 | 35 | } |
36 | 36 | |
37 | 37 | pub struct ValueMeta { |
38 | name: String, | |
39 | deserialize: Box<dyn Fn(&[u8]) -> Result<Box<dyn Any>, serde_json::Error> + Send + Sync>, | |
38 | pub name: String, | |
39 | pub deserialize: Box<dyn Fn(&[u8]) -> Result<Box<dyn Any>, serde_json::Error> + Send + Sync>, | |
40 | pub serialize: | |
41 | Box<dyn Fn(Box<dyn Any + Send + Sync>) -> Result<Vec<u8>, serde_json::Error> + Send + Sync>, | |
42 | pub typed_get: Box<dyn Fn() -> Box<dyn Any + Send + Sync> + Send + Sync>, | |
43 | pub is_get_value_typed: Box<dyn Fn(&Box<dyn Any + Send + Sync>) -> bool + Send + Sync>, | |
40 | 44 | } |
41 | 45 | |
42 | 46 | pub struct ObjectMeta { |
43 | name: String, | |
44 | from_str: Box<dyn Fn(&str) -> Result<Box<dyn Any + Send + Sync>, ()> + Send + Sync>, | |
45 | any_is_same: Box<dyn Fn(&dyn Any) -> bool + Send + Sync>, | |
47 | pub name: String, | |
48 | pub from_str: Box<dyn Fn(&str) -> Result<Box<dyn Any + Send + Sync>, ()> + Send + Sync>, | |
49 | pub any_is_same: Box<dyn Fn(&dyn Any) -> bool + Send + Sync>, | |
46 | 50 | } |
47 | 51 | |
48 | 52 | pub struct OperationMeta { |
49 | name: String, | |
50 | object_kind: String, | |
51 | deserialize: Box<dyn Fn(&[u8]) -> Result<Box<dyn Any + Send + Sync>, ()> + Send + Sync>, | |
52 | any_is_same: Box<dyn Fn(&dyn Any) -> bool + Send + Sync>, | |
53 | serialize_success: | |
53 | pub name: String, | |
54 | pub object_kind: String, | |
55 | pub deserialize: | |
56 | Box<dyn Fn(&[u8]) -> Result<Box<dyn Any + Send + Sync>, serde_json::Error> + Send + Sync>, | |
57 | pub any_is_same: Box<dyn Fn(&dyn Any) -> bool + Send + Sync>, | |
58 | pub serialize_success: | |
59 | Box<dyn Fn(Box<dyn Any>) -> Result<Vec<u8>, serde_json::Error> + Send + Sync>, | |
60 | pub serialize_error: | |
54 | 61 | Box<dyn Fn(Box<dyn Any>) -> Result<Vec<u8>, serde_json::Error> + Send + Sync>, |
55 | serialize_error: Box<dyn Fn(Box<dyn Any>) -> Result<Vec<u8>, serde_json::Error> + Send + Sync>, | |
56 | 62 | } |
57 | 63 | |
58 | 64 | #[derive(Clone, Debug, Hash, Eq, PartialEq)] |
@@ -61,13 +67,13 @@ pub struct ObjectValuePair { | ||
61 | 67 | pub value_kind: String, |
62 | 68 | } |
63 | 69 | |
64 | #[async_trait::async_trait] | |
70 | #[async_trait::async_trait(?Send)] | |
65 | 71 | pub trait GiteratedOperationHandler< |
66 | 72 | L, |
67 | 73 | O: GiteratedObject, |
68 | 74 | D: GiteratedOperation<O>, |
69 | 75 | S: Send + Sync + Clone, |
70 | >: Send + Sync | |
76 | > | |
71 | 77 | { |
72 | 78 | fn operation_name(&self) -> &str; |
73 | 79 | fn object_name(&self) -> &str; |
@@ -81,16 +87,16 @@ pub trait GiteratedOperationHandler< | ||
81 | 87 | ) -> Result<D::Success, OperationError<D::Failure>>; |
82 | 88 | } |
83 | 89 | |
84 | #[async_trait::async_trait] | |
90 | #[async_trait::async_trait(?Send)] | |
85 | 91 | impl<O, D, F, S> GiteratedOperationHandler<(), O, D, S> for F |
86 | 92 | where |
87 | 93 | F: FnMut( |
88 | 94 | &O, |
89 | 95 | D, |
90 | 96 | S, |
91 | ) -> Pin< | |
92 | Box<dyn Future<Output = Result<D::Success, OperationError<D::Failure>>> + Send>, | |
93 | > + Send | |
97 | ) | |
98 | -> Pin<Box<dyn Future<Output = Result<D::Success, OperationError<D::Failure>>>>> | |
99 | + Send | |
94 | 100 | + Sync |
95 | 101 | + Clone, |
96 | 102 | O: GiteratedObject + Send + Sync, |
@@ -117,7 +123,7 @@ where | ||
117 | 123 | } |
118 | 124 | } |
119 | 125 | |
120 | #[async_trait::async_trait] | |
126 | #[async_trait::async_trait(?Send)] | |
121 | 127 | impl<O, O1, D, F, S> GiteratedOperationHandler<(O1,), O, D, S> for F |
122 | 128 | where |
123 | 129 | F: FnMut( |
@@ -125,9 +131,9 @@ where | ||
125 | 131 | D, |
126 | 132 | S, |
127 | 133 | O1, |
128 | ) -> Pin< | |
129 | Box<dyn Future<Output = Result<D::Success, OperationError<D::Failure>>> + Send>, | |
130 | > + Send | |
134 | ) | |
135 | -> Pin<Box<dyn Future<Output = Result<D::Success, OperationError<D::Failure>>>>> | |
136 | + Send | |
131 | 137 | + Sync |
132 | 138 | + Clone, |
133 | 139 | O: GiteratedObject + Send + Sync, |
@@ -158,7 +164,7 @@ where | ||
158 | 164 | } |
159 | 165 | } |
160 | 166 | |
161 | #[async_trait::async_trait] | |
167 | #[async_trait::async_trait(?Send)] | |
162 | 168 | impl<O, O1, O2, D, F, S> GiteratedOperationHandler<(O1, O2), O, D, S> for F |
163 | 169 | where |
164 | 170 | F: FnMut( |
@@ -167,9 +173,9 @@ where | ||
167 | 173 | S, |
168 | 174 | O1, |
169 | 175 | O2, |
170 | ) -> Pin< | |
171 | Box<dyn Future<Output = Result<D::Success, OperationError<D::Failure>>> + Send>, | |
172 | > + Send | |
176 | ) | |
177 | -> Pin<Box<dyn Future<Output = Result<D::Success, OperationError<D::Failure>>>>> | |
178 | + Send | |
173 | 179 | + Sync |
174 | 180 | + Clone, |
175 | 181 | O: GiteratedObject + Send + Sync, |
@@ -204,7 +210,7 @@ where | ||
204 | 210 | } |
205 | 211 | } |
206 | 212 | |
207 | #[async_trait::async_trait] | |
213 | #[async_trait::async_trait(?Send)] | |
208 | 214 | impl<O, O1, O2, O3, D, F, S> GiteratedOperationHandler<(O1, O2, O3), O, D, S> for F |
209 | 215 | where |
210 | 216 | F: FnMut( |
@@ -214,9 +220,9 @@ where | ||
214 | 220 | O1, |
215 | 221 | O2, |
216 | 222 | O3, |
217 | ) -> Pin< | |
218 | Box<dyn Future<Output = Result<D::Success, OperationError<D::Failure>>> + Send>, | |
219 | > + Send | |
223 | ) | |
224 | -> Pin<Box<dyn Future<Output = Result<D::Success, OperationError<D::Failure>>>>> | |
225 | + Send | |
220 | 226 | + Sync |
221 | 227 | + Clone, |
222 | 228 | O: GiteratedObject + Send + Sync, |
@@ -258,13 +264,20 @@ where | ||
258 | 264 | pub struct OperationWrapper { |
259 | 265 | func: Box< |
260 | 266 | dyn Fn( |
261 | Box<dyn Any + Send + Sync>, | |
262 | Box<dyn Any + Send + Sync>, | |
267 | &(dyn Any + Send + Sync), | |
268 | &(dyn Any + Send + Sync), | |
263 | 269 | &(dyn Any + Send + Sync), |
264 | 270 | StackOperationState, |
265 | ) | |
266 | -> Pin<Box<dyn Future<Output = Result<Vec<u8>, OperationError<Vec<u8>>>> + Send>> | |
267 | + Send | |
271 | ) -> Pin< | |
272 | Box< | |
273 | dyn Future< | |
274 | Output = Result< | |
275 | Box<dyn Any + Send + Sync>, | |
276 | OperationError<Box<dyn Any + Send + Sync>>, | |
277 | >, | |
278 | >, | |
279 | >, | |
280 | > + Send | |
268 | 281 | + Sync, |
269 | 282 | >, |
270 | 283 | state: Box<dyn Any + Send + Sync>, |
@@ -274,31 +287,34 @@ impl OperationWrapper { | ||
274 | 287 | pub fn new< |
275 | 288 | A, |
276 | 289 | O: GiteratedObject + Send + Sync + 'static, |
277 | D: GiteratedOperation<O> + 'static, | |
278 | F: GiteratedOperationHandler<A, O, D, S> + Send + Sync + 'static + Clone, | |
290 | D: GiteratedOperation<O> + 'static + Clone, | |
291 | F: GiteratedOperationHandler<A, O, D, S> + 'static + Send + Sync + Clone, | |
279 | 292 | S: GiteratedStackState + 'static, |
280 | 293 | >( |
281 | 294 | handler: F, |
282 | 295 | state: S, |
283 | ) -> Self { | |
284 | let handler = Arc::new(Box::pin(handler)); | |
296 | ) -> Self | |
297 | where | |
298 | D::Failure: Send + Sync, | |
299 | D::Success: Send + Sync, | |
300 | { | |
285 | 301 | Self { |
286 | 302 | func: Box::new(move |object, operation, state, operation_state| { |
287 | 303 | let handler = handler.clone(); |
288 | 304 | let state = state.downcast_ref::<S>().unwrap().clone(); |
305 | let object: &O = object.downcast_ref().unwrap(); | |
306 | let operation: &D = operation.downcast_ref().unwrap(); | |
307 | let object = object.clone(); | |
308 | let operation = operation.clone(); | |
289 | 309 | async move { |
290 | let handler = handler.clone(); | |
291 | let object: Box<O> = object.downcast().unwrap(); | |
292 | let operation: Box<D> = operation.downcast().unwrap(); | |
293 | ||
294 | 310 | let result = handler |
295 | .handle(&object, *operation, state, &operation_state) | |
311 | .handle(&object, operation, state, &operation_state) | |
296 | 312 | .await; |
297 | 313 | result |
298 | .map(|success| serde_json::to_vec(&success).unwrap()) | |
314 | .map(|success| Box::new(success) as _) | |
299 | 315 | .map_err(|err| match err { |
300 | 316 | OperationError::Operation(err) => { |
301 | OperationError::Operation(serde_json::to_vec(&err).unwrap()) | |
317 | OperationError::Operation(Box::new(err) as _) | |
302 | 318 | } |
303 | 319 | OperationError::Internal(internal) => { |
304 | 320 | OperationError::Internal(internal) |
@@ -306,7 +322,7 @@ impl OperationWrapper { | ||
306 | 322 | OperationError::Unhandled => OperationError::Unhandled, |
307 | 323 | }) |
308 | 324 | } |
309 | .boxed() | |
325 | .boxed_local() | |
310 | 326 | }), |
311 | 327 | state: Box::new(state), |
312 | 328 | } |
@@ -314,18 +330,22 @@ impl OperationWrapper { | ||
314 | 330 | |
315 | 331 | async fn handle( |
316 | 332 | &self, |
317 | object: Box<dyn Any + Send + Sync>, | |
318 | operation: Box<dyn Any + Send + Sync>, | |
333 | object: &Box<dyn Any + Send + Sync>, | |
334 | operation: &Box<dyn Any + Send + Sync>, | |
319 | 335 | operation_state: &StackOperationState, |
320 | ) -> Result<Vec<u8>, OperationError<Vec<u8>>> { | |
321 | (self.func)(object, operation, &self.state, operation_state.clone()).await | |
336 | ) -> Result<Box<dyn Any + Send + Sync>, OperationError<Box<dyn Any + Send + Sync>>> { | |
337 | (self.func)( | |
338 | (*object).as_ref(), | |
339 | (*operation).as_ref(), | |
340 | self.state.as_ref(), | |
341 | operation_state.clone(), | |
342 | ) | |
343 | .await | |
322 | 344 | } |
323 | 345 | } |
324 | 346 | |
325 | #[async_trait::async_trait] | |
326 | pub trait FromOperationState<O: GiteratedObject, D: GiteratedOperation<O> + Send + Sync>: | |
327 | Sized + Clone + Send | |
328 | { | |
347 | #[async_trait::async_trait(?Send)] | |
348 | pub trait FromOperationState<O: GiteratedObject, D: GiteratedOperation<O>>: Sized + Clone { | |
329 | 349 | type Error: Serialize + DeserializeOwned; |
330 | 350 | |
331 | 351 | async fn from_state( |
@@ -335,8 +355,8 @@ pub trait FromOperationState<O: GiteratedObject, D: GiteratedOperation<O> + Send | ||
335 | 355 | ) -> Result<Self, OperationError<Self::Error>>; |
336 | 356 | } |
337 | 357 | |
338 | #[async_trait::async_trait] | |
339 | impl<O: GiteratedObject, D: GiteratedOperation<O> + Send + Sync> FromOperationState<O, D> | |
358 | #[async_trait::async_trait(?Send)] | |
359 | impl<O: GiteratedObject, D: GiteratedOperation<O>> FromOperationState<O, D> | |
340 | 360 | for Arc<GiteratedStack> |
341 | 361 | { |
342 | 362 | type Error = (); |
@@ -350,8 +370,8 @@ impl<O: GiteratedObject, D: GiteratedOperation<O> + Send + Sync> FromOperationSt | ||
350 | 370 | } |
351 | 371 | } |
352 | 372 | |
353 | #[async_trait::async_trait] | |
354 | impl<O: GiteratedObject, D: GiteratedOperation<O> + Send + Sync> FromOperationState<O, D> | |
373 | #[async_trait::async_trait(?Send)] | |
374 | impl<O: GiteratedObject, D: GiteratedOperation<O>> FromOperationState<O, D> | |
355 | 375 | for StackOperationState |
356 | 376 | { |
357 | 377 | type Error = (); |
@@ -365,7 +385,7 @@ impl<O: GiteratedObject, D: GiteratedOperation<O> + Send + Sync> FromOperationSt | ||
365 | 385 | } |
366 | 386 | } |
367 | 387 | |
368 | #[async_trait::async_trait] | |
388 | #[async_trait::async_trait(?Send)] | |
369 | 389 | impl<O: GiteratedObject, D: GiteratedOperation<O> + Send + Sync> FromOperationState<O, D> |
370 | 390 | for AuthenticatedUser |
371 | 391 | { |
@@ -383,7 +403,7 @@ impl<O: GiteratedObject, D: GiteratedOperation<O> + Send + Sync> FromOperationSt | ||
383 | 403 | } |
384 | 404 | } |
385 | 405 | |
386 | #[async_trait::async_trait] | |
406 | #[async_trait::async_trait(?Send)] | |
387 | 407 | impl<O: GiteratedObject, D: GiteratedOperation<O> + Send + Sync> FromOperationState<O, D> |
388 | 408 | for AuthenticatedInstance |
389 | 409 | { |
@@ -401,7 +421,7 @@ impl<O: GiteratedObject, D: GiteratedOperation<O> + Send + Sync> FromOperationSt | ||
401 | 421 | } |
402 | 422 | } |
403 | 423 | |
404 | #[async_trait::async_trait] | |
424 | #[async_trait::async_trait(?Send)] | |
405 | 425 | impl< |
406 | 426 | T: FromOperationState<O, D> + Send + Sync, |
407 | 427 | O: GiteratedObject + Sync, |
@@ -425,7 +445,7 @@ pub struct AuthorizedUser(AuthenticatedUser); | ||
425 | 445 | #[derive(Clone)] |
426 | 446 | pub struct AuthorizedInstance(AuthenticatedInstance); |
427 | 447 | |
428 | #[async_trait::async_trait] | |
448 | #[async_trait::async_trait(?Send)] | |
429 | 449 | pub trait AuthorizedOperation<O: GiteratedObject>: GiteratedOperation<O> { |
430 | 450 | async fn authorize( |
431 | 451 | &self, |
@@ -434,12 +454,8 @@ pub trait AuthorizedOperation<O: GiteratedObject>: GiteratedOperation<O> { | ||
434 | 454 | ) -> Result<bool, OperationError<()>>; |
435 | 455 | } |
436 | 456 | |
437 | #[async_trait::async_trait] | |
438 | impl< | |
439 | O: GiteratedObject + Send + Sync + Debug, | |
440 | V: GiteratedObjectValue<Object = O> + Send + Sync, | |
441 | > AuthorizedOperation<O> for GetValue<V> | |
442 | { | |
457 | #[async_trait::async_trait(?Send)] | |
458 | impl<O: GiteratedObject + Send + Sync + Debug + 'static> AuthorizedOperation<O> for GetValue { | |
443 | 459 | async fn authorize( |
444 | 460 | &self, |
445 | 461 | authorize_for: &O, |
@@ -453,7 +469,7 @@ impl< | ||
453 | 469 | } |
454 | 470 | } |
455 | 471 | |
456 | #[async_trait::async_trait] | |
472 | #[async_trait::async_trait(?Send)] | |
457 | 473 | impl AuthorizedOperation<User> for SetSetting { |
458 | 474 | async fn authorize( |
459 | 475 | &self, |
@@ -469,7 +485,7 @@ impl AuthorizedOperation<User> for SetSetting { | ||
469 | 485 | } |
470 | 486 | } |
471 | 487 | |
472 | #[async_trait::async_trait] | |
488 | #[async_trait::async_trait(?Send)] | |
473 | 489 | impl AuthorizedOperation<User> for GetSetting { |
474 | 490 | async fn authorize( |
475 | 491 | &self, |
@@ -485,7 +501,7 @@ impl AuthorizedOperation<User> for GetSetting { | ||
485 | 501 | } |
486 | 502 | } |
487 | 503 | |
488 | #[async_trait::async_trait] | |
504 | #[async_trait::async_trait(?Send)] | |
489 | 505 | impl AuthorizedOperation<Repository> for SetSetting { |
490 | 506 | async fn authorize( |
491 | 507 | &self, |
@@ -521,7 +537,7 @@ impl AuthorizedOperation<Repository> for SetSetting { | ||
521 | 537 | } |
522 | 538 | } |
523 | 539 | |
524 | #[async_trait::async_trait] | |
540 | #[async_trait::async_trait(?Send)] | |
525 | 541 | impl AuthorizedOperation<Repository> for GetSetting { |
526 | 542 | async fn authorize( |
527 | 543 | &self, |
@@ -557,7 +573,7 @@ impl AuthorizedOperation<Repository> for GetSetting { | ||
557 | 573 | } |
558 | 574 | } |
559 | 575 | |
560 | #[async_trait::async_trait] | |
576 | #[async_trait::async_trait(?Send)] | |
561 | 577 | impl AuthorizedOperation<Instance> for RegisterAccountRequest { |
562 | 578 | async fn authorize( |
563 | 579 | &self, |
@@ -572,7 +588,7 @@ impl AuthorizedOperation<Instance> for RegisterAccountRequest { | ||
572 | 588 | } |
573 | 589 | } |
574 | 590 | |
575 | #[async_trait::async_trait] | |
591 | #[async_trait::async_trait(?Send)] | |
576 | 592 | impl AuthorizedOperation<Instance> for AuthenticationTokenRequest { |
577 | 593 | async fn authorize( |
578 | 594 | &self, |
@@ -587,7 +603,7 @@ impl AuthorizedOperation<Instance> for AuthenticationTokenRequest { | ||
587 | 603 | } |
588 | 604 | } |
589 | 605 | |
590 | #[async_trait::async_trait] | |
606 | #[async_trait::async_trait(?Send)] | |
591 | 607 | impl AuthorizedOperation<Instance> for RepositoryCreateRequest { |
592 | 608 | async fn authorize( |
593 | 609 | &self, |
@@ -602,7 +618,7 @@ impl AuthorizedOperation<Instance> for RepositoryCreateRequest { | ||
602 | 618 | } |
603 | 619 | } |
604 | 620 | |
605 | #[async_trait::async_trait] | |
621 | #[async_trait::async_trait(?Send)] | |
606 | 622 | impl<A: AuthorizedOperation<User> + Send + Sync> FromOperationState<User, A> for AuthorizedUser { |
607 | 623 | type Error = (); |
608 | 624 | |
@@ -624,7 +640,7 @@ impl<A: AuthorizedOperation<User> + Send + Sync> FromOperationState<User, A> for | ||
624 | 640 | } |
625 | 641 | } |
626 | 642 | |
627 | #[async_trait::async_trait] | |
643 | #[async_trait::async_trait(?Send)] | |
628 | 644 | impl<A: AuthorizedOperation<Instance> + Send + Sync> FromOperationState<Instance, A> |
629 | 645 | for AuthorizedInstance |
630 | 646 | { |