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

ambee/giterated

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

Fixes

Amber - ⁨2⁩ years ago

parent: tbd commit: ⁨b87f0a3

Showing ⁨⁨14⁩ changed files⁩ with ⁨⁨187⁩ insertions⁩ and ⁨⁨56⁩ deletions⁩

Cargo.lock

View file
@@ -265,6 +265,33 @@ dependencies = [
265 265 ]
266 266
267 267 [[package]]
268 name = "color-eyre"
269 version = "0.6.2"
270 source = "registry+https://github.com/rust-lang/crates.io-index"
271 checksum = "5a667583cca8c4f8436db8de46ea8233c42a7d9ae424a82d338f2e4675229204"
272 dependencies = [
273 "backtrace",
274 "color-spantrace",
275 "eyre",
276 "indenter",
277 "once_cell",
278 "owo-colors",
279 "tracing-error",
280 ]
281
282 [[package]]
283 name = "color-spantrace"
284 version = "0.2.0"
285 source = "registry+https://github.com/rust-lang/crates.io-index"
286 checksum = "1ba75b3d9449ecdccb27ecbc479fdc0b87fa2dd43d2f8298f9bf0e59aacc8dce"
287 dependencies = [
288 "once_cell",
289 "owo-colors",
290 "tracing-core",
291 "tracing-error",
292 ]
293
294 [[package]]
268 295 name = "const-oid"
269 296 version = "0.9.5"
270 297 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -510,6 +537,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
510 537 checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0"
511 538
512 539 [[package]]
540 name = "eyre"
541 version = "0.6.8"
542 source = "registry+https://github.com/rust-lang/crates.io-index"
543 checksum = "4c2b6b5a29c02cdc822728b7d7b8ae1bab3e3b05d44522770ddd49722eeac7eb"
544 dependencies = [
545 "indenter",
546 "once_cell",
547 ]
548
549 [[package]]
513 550 name = "fastrand"
514 551 version = "2.0.0"
515 552 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -701,6 +738,7 @@ dependencies = [
701 738 "async-trait",
702 739 "bincode",
703 740 "chrono",
741 "color-eyre",
704 742 "deadpool",
705 743 "futures-util",
706 744 "giterated-models",
@@ -978,6 +1016,12 @@ dependencies = [
978 1016 ]
979 1017
980 1018 [[package]]
1019 name = "indenter"
1020 version = "0.3.3"
1021 source = "registry+https://github.com/rust-lang/crates.io-index"
1022 checksum = "ce23b50ad8242c51a442f3ff322d56b02f08852c77e4c0b4d3fd684abc89c683"
1023
1024 [[package]]
981 1025 name = "indexmap"
982 1026 version = "1.9.3"
983 1027 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1381,6 +1425,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
1381 1425 checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39"
1382 1426
1383 1427 [[package]]
1428 name = "owo-colors"
1429 version = "3.5.0"
1430 source = "registry+https://github.com/rust-lang/crates.io-index"
1431 checksum = "c1b04fb49957986fdce4d6ee7a65027d55d4b6d2265e5848bbb507b58ccfdb6f"
1432
1433 [[package]]
1384 1434 name = "parking_lot"
1385 1435 version = "0.12.1"
1386 1436 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2514,6 +2564,16 @@ dependencies = [
2514 2564 ]
2515 2565
2516 2566 [[package]]
2567 name = "tracing-error"
2568 version = "0.2.0"
2569 source = "registry+https://github.com/rust-lang/crates.io-index"
2570 checksum = "d686ec1c0f384b1277f097b2f279a2ecc11afe8c133c1aabf036a27cb4cd206e"
2571 dependencies = [
2572 "tracing",
2573 "tracing-subscriber",
2574 ]
2575
2576 [[package]]
2517 2577 name = "tracing-log"
2518 2578 version = "0.1.3"
2519 2579 source = "registry+https://github.com/rust-lang/crates.io-index"

giterated-daemon/src/cache_backend.rs

View file
@@ -14,7 +14,8 @@ impl ObjectBackend for CacheBackend {
14 14 async fn object_operation<O: GiteratedObject + Debug, D: GiteratedOperation<O> + Debug>(
15 15 &self,
16 16 _object: O,
17 _operation: D,
17 operation: &str,
18 payload: D,
18 19 ) -> Result<D::Success, OperationError<D::Failure>> {
19 20 // We don't handle operations with this backend
20 21 Err(OperationError::Unhandled)

giterated-daemon/src/connection/wrapper.rs

View file
@@ -83,10 +83,17 @@ pub async fn connection_wrapper(
83 83
84 84 let message: GiteratedMessage<AnyObject, AnyOperation> = message.into_message();
85 85
86 backend
87 .object_operation(message.object, message.payload)
88 .await
89 .unwrap();
86 let result = backend
87 .object_operation(message.object, &message.operation, message.payload)
88 .await;
89
90 let mut socket = connection_state.socket.lock().await;
91 let _ = socket
92 .send(Message::Binary(bincode::serialize(&result).unwrap()))
93 .await;
94
95 info!("Done!");
96 drop(socket);
90 97 }
91 98 _ => {
92 99 return;

giterated-daemon/src/database_backend/handler.rs

View file
@@ -2,12 +2,12 @@ use std::{collections::HashMap, pin::Pin, sync::Arc};
2 2
3 3 use futures_util::{future::BoxFuture, Future, FutureExt};
4 4 use giterated_models::{
5 error::{GetValueError, OperationError},
5 error::{GetValueError, OperationError, UserError},
6 6 object::{AnyObject, GiteratedObject},
7 7 operation::{AnyOperation, GiteratedOperation},
8 repository::Repository,
8 repository::{Repository, RepositorySummary},
9 9 settings::{AnySetting, GetSetting, GetSettingError, SetSetting, SetSettingError},
10 user::User,
10 user::{User, UserRepositoriesRequest},
11 11 value::{AnyValue, GetValue},
12 12 };
13 13
@@ -120,6 +120,25 @@ impl<S: Send + Sync + Clone + 'static> OperationWrapper<S> {
120 120 }
121 121 }
122 122
123 pub fn user_get_repositories(
124 object: &User,
125 operation: UserRepositoriesRequest,
126 state: DatabaseBackend,
127 ) -> BoxFuture<'static, Result<Vec<RepositorySummary>, OperationError<UserError>>> {
128 let object = object.clone();
129
130 async move {
131 let mut repositories_backend = state.repository_backend.lock().await;
132 let repositories = repositories_backend
133 .repositories_for_user(None, &object)
134 .await
135 .map_err(|e| OperationError::Internal(e.to_string()))?;
136
137 Ok(repositories)
138 }
139 .boxed()
140 }
141
123 142 pub fn user_get_value(
124 143 object: &User,
125 144 operation: GetValue<AnyValue<User>>,

giterated-daemon/src/database_backend/mod.rs

View file
@@ -6,7 +6,7 @@ use std::{str::FromStr, sync::Arc};
6 6 use giterated_models::error::OperationError;
7 7 use giterated_models::instance::Instance;
8 8 use giterated_models::object::{
9 GiteratedObject, Object, ObjectRequest, ObjectRequestError, ObjectResponse,
9 AnyObject, GiteratedObject, Object, ObjectRequest, ObjectRequestError, ObjectResponse,
10 10 };
11 11 use giterated_models::object_backend::ObjectBackend;
12 12 use giterated_models::operation::{AnyOperation, GiteratedOperation};
@@ -18,8 +18,8 @@ use tokio::sync::Mutex;
18 18 use crate::backend::{RepositoryBackend, UserBackend};
19 19
20 20 use self::handler::{
21 repository_get_setting, repository_get_value, repository_set_setting, user_get_setting,
22 user_get_value, user_set_setting, OperationHandlers,
21 repository_get_setting, repository_get_value, repository_set_setting, user_get_repositories,
22 user_get_setting, user_get_value, user_set_setting, OperationHandlers,
23 23 };
24 24
25 25 #[derive(Clone, Debug)]
@@ -30,7 +30,8 @@ impl ObjectBackend for Foobackend {
30 30 async fn object_operation<O: GiteratedObject + Debug, D: GiteratedOperation<O> + Debug>(
31 31 &self,
32 32 _object: O,
33 _operation: D,
33 operation: &str,
34 payload: D,
34 35 ) -> Result<D::Success, OperationError<D::Failure>> {
35 36 // We don't handle operations with this backend
36 37 Err(OperationError::Unhandled)
@@ -77,15 +78,17 @@ impl ObjectBackend for DatabaseBackend {
77 78 async fn object_operation<O: GiteratedObject + Debug, D: GiteratedOperation<O> + Debug>(
78 79 &self,
79 80 object: O,
80 operation: D,
81 operation: &str,
82 payload: D,
81 83 ) -> Result<D::Success, OperationError<D::Failure>> {
82 84 let serialized =
83 serde_json::to_value(operation).map_err(|e| OperationError::Internal(e.to_string()))?;
85 serde_json::to_value(payload).map_err(|e| OperationError::Internal(e.to_string()))?;
84 86 let object = object.to_string();
85 87 if let Ok(user) = User::from_str(&object) {
86 88 let mut handler = OperationHandlers::default();
87 89
88 90 handler
91 .insert(user_get_repositories)
89 92 .insert(user_get_value)
90 93 .insert(user_get_setting)
91 94 .insert(user_set_setting);
@@ -93,14 +96,16 @@ impl ObjectBackend for DatabaseBackend {
93 96 match handler
94 97 .handle(
95 98 &user,
96 D::operation_name(),
99 operation,
97 100 serde_json::from_value(serialized.clone()).unwrap(),
98 101 self.clone(),
99 102 )
100 103 .await
101 104 {
102 Ok(result) => Ok(serde_json::from_slice(&result)
103 .map_err(|e| OperationError::Internal(e.to_string()))?),
105 Ok(result) => Ok(
106 serde_json::from_slice(&serde_json::to_vec(&result).unwrap())
107 .map_err(|e| OperationError::Internal(e.to_string()))?,
108 ),
104 109 Err(err) => match err {
105 110 OperationError::Internal(internal) => Err(OperationError::Internal(internal)),
106 111 OperationError::Unhandled => Err(OperationError::Unhandled),
@@ -121,14 +126,16 @@ impl ObjectBackend for DatabaseBackend {
121 126 match handler
122 127 .handle(
123 128 &repository,
124 D::operation_name(),
129 operation,
125 130 serde_json::from_value(serialized.clone()).unwrap(),
126 131 self.clone(),
127 132 )
128 133 .await
129 134 {
130 Ok(result) => Ok(serde_json::from_slice(&result)
131 .map_err(|e| OperationError::Internal(e.to_string()))?),
135 Ok(result) => Ok(
136 serde_json::from_slice(&serde_json::to_vec(&result).unwrap())
137 .map_err(|e| OperationError::Internal(e.to_string()))?,
138 ),
132 139 Err(err) => match err {
133 140 OperationError::Internal(internal) => Err(OperationError::Internal(internal)),
134 141 OperationError::Unhandled => Err(OperationError::Unhandled),
@@ -146,18 +153,34 @@ impl ObjectBackend for DatabaseBackend {
146 153
147 154 if let Ok(object_request) = serde_json::from_value::<ObjectRequest>(serialized.clone())
148 155 {
149 // No-op
150 let response = serde_json::to_string(&ObjectResponse(object_request.0)).unwrap();
151
152 info!("Target: {}", type_name::<D>());
153 info!("Meow: {}", response);
154 info!(
155 "Im just a neko! {:?}",
156 serde_json::from_str::<AnyOperation>(&response)
157 );
158
159 Ok(serde_json::from_str(&response)
160 .map_err(|e| OperationError::Internal(e.to_string()))?)
156 let result = self.get_object::<AnyObject>(&object_request.0).await;
157
158 let result = result
159 .map(|success| serde_json::to_vec(&success.object()).unwrap())
160 .map_err(|err| match err {
161 OperationError::Operation(err) => {
162 OperationError::Operation(serde_json::to_vec(&err).unwrap())
163 }
164 OperationError::Internal(internal) => OperationError::Internal(internal),
165 OperationError::Unhandled => OperationError::Unhandled,
166 });
167
168 match result {
169 Ok(result) => Ok(
170 serde_json::from_slice(&serde_json::to_vec(&result).unwrap())
171 .map_err(|e| OperationError::Internal(e.to_string()))?,
172 ),
173 Err(err) => match err {
174 OperationError::Internal(internal) => {
175 Err(OperationError::Internal(internal))
176 }
177 OperationError::Unhandled => Err(OperationError::Unhandled),
178 OperationError::Operation(err) => Err(OperationError::Operation(
179 serde_json::from_slice(&err)
180 .map_err(|e| OperationError::Internal(e.to_string()))?,
181 )),
182 },
183 }
161 184 } else {
162 185 Err(OperationError::Unhandled)
163 186 }

giterated-models/src/error.rs

View file
@@ -21,7 +21,7 @@ pub enum GetValueError {}
21 21 pub enum OperationError<B> {
22 22 #[error("the operation was handled but an error occured")]
23 23 Operation(#[from] B),
24 #[error("an internal error occured")]
24 #[error("an internal error occured: {0}")]
25 25 Internal(String),
26 26 #[error("the operation was unhandled or unrecognized")]
27 27 Unhandled,

giterated-models/src/object.rs

View file
@@ -38,6 +38,14 @@ impl<'b, B: ObjectBackend + Send + Sync + Clone, O: GiteratedObject> Object<'b,
38 38 }
39 39 }
40 40
41 impl<O: GiteratedObject + Display, B: ObjectBackend + Send + Sync + Clone> Display
42 for Object<'_, O, B>
43 {
44 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
45 self.inner.fmt(f)
46 }
47 }
48
41 49 pub trait GiteratedObject: Send + Display + FromStr {
42 50 fn object_name() -> &'static str;
43 51
@@ -81,7 +89,7 @@ impl<'b, O: GiteratedObject + Clone + Debug, B: ObjectBackend> Object<'b, O, B>
81 89 request: R,
82 90 ) -> Result<R::Success, OperationError<R::Failure>> {
83 91 self.backend
84 .object_operation(self.inner.clone(), request)
92 .object_operation(self.inner.clone(), R::operation_name(), request)
85 93 .await
86 94 }
87 95 }

giterated-models/src/object/operations.rs

View file
@@ -25,6 +25,7 @@ pub enum ObjectRequestError {
25 25 }
26 26
27 27 #[derive(Clone, Debug, Serialize, Deserialize)]
28 #[serde(transparent)]
28 29 #[repr(transparent)]
29 30 pub struct AnyObject(pub String);
30 31

giterated-models/src/object_backend.rs

View file
@@ -11,7 +11,8 @@ pub trait ObjectBackend: Send + Sync + Sized + Clone {
11 11 async fn object_operation<O, D>(
12 12 &self,
13 13 object: O,
14 operation: D,
14 operation: &str,
15 payload: D,
15 16 ) -> Result<D::Success, OperationError<D::Failure>>
16 17 where
17 18 O: GiteratedObject + Debug,

giterated-models/src/repository/mod.rs

View file
@@ -78,19 +78,13 @@ impl FromStr for Repository {
78 78
79 79 fn from_str(s: &str) -> Result<Self, Self::Err> {
80 80 let mut by_ampersand = s.split('@');
81 let mut path_split = by_ampersand
82 .next()
83 .ok_or_else(|| RepositoryParseError)?
84 .split('/');
81 let mut path_split = by_ampersand.next().ok_or(RepositoryParseError)?.split('/');
85 82
86 let instance = Instance::from_str(by_ampersand.next().ok_or_else(|| RepositoryParseError)?)
83 let instance = Instance::from_str(by_ampersand.next().ok_or(RepositoryParseError)?)
87 84 .map_err(|_| RepositoryParseError)?;
88 let owner = User::from_str(path_split.next().ok_or_else(|| RepositoryParseError)?)
85 let owner = User::from_str(path_split.next().ok_or(RepositoryParseError)?)
89 86 .map_err(|_| RepositoryParseError)?;
90 let name = path_split
91 .next()
92 .ok_or_else(|| RepositoryParseError)?
93 .to_string();
87 let name = path_split.next().ok_or(RepositoryParseError)?.to_string();
94 88
95 89 Ok(Self {
96 90 instance,

giterated-models/src/repository/operations.rs

View file
@@ -7,7 +7,7 @@ use crate::{
7 7 operation::GiteratedOperation,
8 8 };
9 9
10 use super::{IssueLabel, Repository, RepositoryIssue, RepositoryTreeEntry};
10 use super::{IssueLabel, Repository, RepositoryIssue, RepositoryTreeEntry, RepositoryView};
11 11
12 12 /// A request to get a repository's information.
13 13 ///
@@ -19,6 +19,14 @@ use super::{IssueLabel, Repository, RepositoryIssue, RepositoryTreeEntry};
19 19 /// - User Authorization
20 20 /// - Potential User permissions checks
21 21 #[derive(Clone, Debug, Serialize, Deserialize)]
22 pub struct RepositoryInfoRequest;
23
24 impl GiteratedOperation<Repository> for RepositoryInfoRequest {
25 type Success = RepositoryView;
26 type Failure = RepositoryError;
27 }
28
29 #[derive(Clone, Debug, Serialize, Deserialize)]
22 30 pub struct RepositoryIssuesCountRequest;
23 31
24 32 impl GiteratedOperation<Repository> for RepositoryIssuesCountRequest {
@@ -80,10 +88,14 @@ impl GiteratedOperation<Repository> for RepositoryFileInspectRequest {
80 88 }
81 89
82 90 impl<B: ObjectBackend + std::fmt::Debug> Object<'_, Repository, B> {
83 pub async fn issues_count(&mut self) -> Result<u64, OperationError<RepositoryError>> {
84 self.request::<RepositoryIssuesCountRequest>(RepositoryIssuesCountRequest)
91 pub async fn info(&mut self) -> Result<RepositoryView, OperationError<RepositoryError>> {
92 self.request::<RepositoryInfoRequest>(RepositoryInfoRequest)
85 93 .await
86 94 }
95 // pub async fn issues_count(&mut self) -> Result<u64, OperationError<RepositoryError>> {
96 // self.request::<RepositoryIssuesCountRequest>(RepositoryIssuesCountRequest)
97 // .await
98 // }
87 99
88 100 pub async fn issue_labels(
89 101 &mut self,

giterated-models/src/user/mod.rs

View file
@@ -72,11 +72,8 @@ impl FromStr for User {
72 72 }
73 73
74 74 let mut colon_split = s.split(':');
75 let username = colon_split
76 .next()
77 .ok_or_else(|| UserParseError)?
78 .to_string();
79 let instance = Instance::from_str(colon_split.next().ok_or_else(|| UserParseError)?)
75 let username = colon_split.next().ok_or(UserParseError)?.to_string();
76 let instance = Instance::from_str(colon_split.next().ok_or(UserParseError)?)
80 77 .map_err(|_| UserParseError)?;
81 78
82 79 Ok(Self { username, instance })

giterated-models/src/user/operations.rs

View file
@@ -6,7 +6,7 @@ use crate::{
6 6 object::Object,
7 7 object_backend::ObjectBackend,
8 8 operation::GiteratedOperation,
9 repository::Repository,
9 repository::RepositorySummary,
10 10 };
11 11
12 12 use super::User;
@@ -18,7 +18,7 @@ pub struct UserRepositoriesRequest {
18 18 }
19 19
20 20 impl GiteratedOperation<User> for UserRepositoriesRequest {
21 type Success = Vec<Repository>;
21 type Success = Vec<RepositorySummary>;
22 22 type Failure = UserError;
23 23 }
24 24
@@ -26,7 +26,7 @@ impl<B: ObjectBackend + std::fmt::Debug> Object<'_, User, B> {
26 26 pub async fn repositories(
27 27 &mut self,
28 28 instance: &Instance,
29 ) -> Result<Vec<Repository>, OperationError<UserError>> {
29 ) -> Result<Vec<RepositorySummary>, OperationError<UserError>> {
30 30 self.request::<UserRepositoriesRequest>(UserRepositoriesRequest {
31 31 instance: instance.clone(),
32 32 user: self.inner.clone(),

giterated-models/src/user/values.rs

View file
@@ -1,3 +1,5 @@
1 use std::fmt::Display;
2
1 3 use serde::{Deserialize, Serialize};
2 4
3 5 use crate::value::GiteratedObjectValue;
@@ -18,6 +20,12 @@ impl GiteratedObjectValue for Bio {
18 20 #[derive(Debug, Hash, Clone, PartialEq, Eq, Serialize, Deserialize)]
19 21 pub struct DisplayName(pub String);
20 22
23 impl Display for DisplayName {
24 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
25 f.write_str(&self.0)
26 }
27 }
28
21 29 impl GiteratedObjectValue for DisplayName {
22 30 type Object = User;
23 31