JavaScript is disabled, refresh for a better experience. ambee/giterated

ambee/giterated

Git repository hosting, collaboration, and discovery for the Fediverse.

Unified stack `GetValue` implementation

Amber - ⁨2⁩ years ago

parent: tbd commit: ⁨325f5af

Showing ⁨⁨22⁩ changed files⁩ with ⁨⁨713⁩ insertions⁩ and ⁨⁨658⁩ deletions⁩

Cargo.lock

View file
@@ -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

View file
@@ -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

View file
@@ -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

View file
@@ -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

View file
@@ -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

View file
@@ -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

View file
@@ -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

View file
@@ -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

View file
@@ -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

View file
@@ -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

View file
@@ -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

View file
@@ -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

View file
@@ -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

View file
@@ -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

View file
@@ -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

View file
@@ -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

View file
@@ -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

View file
@@ -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

View file
@@ -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

View file
@@ -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

View file
@@ -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 {