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

ambee/giterated

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

Progress on refactor

Amber - ⁨2⁩ years ago

parent: tbd commit: ⁨c9f076f

Showing ⁨⁨20⁩ changed files⁩ with ⁨⁨776⁩ insertions⁩ and ⁨⁨117⁩ deletions⁩

Cargo.lock

View file
@@ -708,7 +708,6 @@ dependencies = [
708 708 "tokio",
709 709 "tokio-tungstenite",
710 710 "toml",
711 "tower",
712 711 "tracing",
713 712 "tracing-subscriber",
714 713 ]
@@ -717,19 +716,14 @@ dependencies = [
717 716 name = "giterated-models"
718 717 version = "0.1.0"
719 718 dependencies = [
720 "aes-gcm",
721 719 "anyhow",
722 "argon2",
723 720 "async-trait",
724 721 "base64 0.21.3",
725 722 "bincode",
726 723 "chrono",
727 "futures-util",
728 724 "git2",
729 725 "jsonwebtoken",
730 "log",
731 726 "rand",
732 "reqwest",
733 727 "rsa",
734 728 "secrecy",
735 729 "semver",
@@ -737,12 +731,8 @@ dependencies = [
737 731 "serde_json",
738 732 "sqlx",
739 733 "thiserror",
740 "tokio",
741 "tokio-tungstenite",
742 734 "toml",
743 "tower",
744 735 "tracing",
745 "tracing-subscriber",
746 736 ]
747 737
748 738 [[package]]
@@ -2401,23 +2391,6 @@ dependencies = [
2401 2391 ]
2402 2392
2403 2393 [[package]]
2404 name = "tower"
2405 version = "0.4.13"
2406 source = "registry+https://github.com/rust-lang/crates.io-index"
2407 checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c"
2408 dependencies = [
2409 "tower-layer",
2410 "tower-service",
2411 "tracing",
2412 ]
2413
2414 [[package]]
2415 name = "tower-layer"
2416 version = "0.3.2"
2417 source = "registry+https://github.com/rust-lang/crates.io-index"
2418 checksum = "c20c8dbed6283a09604c3e69b4b7eeb54e298b8a600d4d5ecb5ad39de609f1d0"
2419
2420 [[package]]
2421 2394 name = "tower-service"
2422 2395 version = "0.3.2"
2423 2396 source = "registry+https://github.com/rust-lang/crates.io-index"

giterated-daemon/Cargo.toml

View file
@@ -22,7 +22,6 @@ reqwest = "*"
22 22 argon2 = "*"
23 23 aes-gcm = "0.10.2"
24 24 semver = {version = "*", features = ["serde"]}
25 tower = "*"
26 25 giterated-models = { path = "../giterated-models" }
27 26 giterated-api = { path = "../../giterated-api" }
28 27 deadpool = "*"

giterated-daemon/src/backend/mod.rs

View file
@@ -16,6 +16,7 @@ use giterated_models::{
16 16 repository::{
17 17 IssueLabel, Repository, RepositoryIssue, RepositorySummary, RepositoryTreeEntry,
18 18 },
19 settings::AnySetting,
19 20 user::User,
20 21 },
21 22 operation::{
@@ -25,10 +26,11 @@ use giterated_models::{
25 26 RepositoryIssuesCountRequest, RepositoryIssuesRequest,
26 27 },
27 28 },
29 values::AnyValue,
28 30 };
29 31
30 32 #[async_trait]
31 pub trait RepositoryBackend: IssuesBackend {
33 pub trait RepositoryBackend {
32 34 async fn create_repository(
33 35 &mut self,
34 36 user: &User,
@@ -81,6 +83,14 @@ pub trait AuthBackend {
81 83
82 84 #[async_trait::async_trait]
83 85 pub trait UserBackend: AuthBackend {
86 async fn get_value(&mut self, user: &User, name: &str) -> Result<AnyValue<User>, Error>;
87 async fn get_setting(&mut self, user: &User, name: &str) -> Result<AnySetting, Error>;
88 async fn write_setting(
89 &mut self,
90 user: &User,
91 name: &str,
92 setting: &Value,
93 ) -> Result<(), Error>;
84 94 async fn exists(&mut self, user: &User) -> Result<bool, Error>;
85 95 }
86 96

giterated-daemon/src/backend/user.rs

View file
@@ -6,8 +6,12 @@ use aes_gcm::{aead::Aead, AeadCore, Aes256Gcm, Key, KeyInit};
6 6 use argon2::{password_hash::SaltString, Argon2, PasswordHash, PasswordHasher, PasswordVerifier};
7 7 use base64::{engine::general_purpose::STANDARD, Engine as _};
8 8 use giterated_models::{
9 model::{authenticated::UserAuthenticationToken, instance::Instance, user::User},
9 model::{
10 authenticated::UserAuthenticationToken, instance::Instance, settings::AnySetting,
11 user::User,
12 },
10 13 operation::instance::{AuthenticationTokenRequest, RegisterAccountRequest},
14 values::AnyValue,
11 15 };
12 16 use rsa::{
13 17 pkcs8::{EncodePrivateKey, EncodePublicKey},
@@ -16,6 +20,7 @@ use rsa::{
16 20 };
17 21
18 22 use secrecy::ExposeSecret;
23 use serde_json::Value;
19 24 use sqlx::PgPool;
20 25 use tokio::sync::Mutex;
21 26
@@ -48,6 +53,20 @@ impl UserAuth {
48 53
49 54 #[async_trait::async_trait]
50 55 impl UserBackend for UserAuth {
56 async fn get_value(&mut self, _user: &User, _name: &str) -> Result<AnyValue<User>, Error> {
57 todo!()
58 }
59 async fn get_setting(&mut self, _user: &User, _name: &str) -> Result<AnySetting, Error> {
60 todo!()
61 }
62 async fn write_setting(
63 &mut self,
64 _user: &User,
65 _name: &str,
66 _setting: &Value,
67 ) -> Result<(), Error> {
68 todo!()
69 }
51 70 async fn exists(&mut self, user: &User) -> Result<bool, Error> {
52 71 Ok(sqlx::query_as!(
53 72 UserRow,

giterated-daemon/src/cache_backend.rs

View file
@@ -0,0 +1,27 @@
1 use giterated_models::{
2 error::OperationError,
3 operation::{GiteratedObject, GiteratedOperation, Object, ObjectBackend, ObjectRequestError},
4 };
5 use std::fmt::Debug;
6
7 #[derive(Clone, Debug)]
8 pub struct CacheBackend;
9
10 #[async_trait::async_trait]
11 impl ObjectBackend for CacheBackend {
12 async fn object_operation<O: GiteratedObject + Debug, D: GiteratedOperation<O> + Debug>(
13 &self,
14 _object: O,
15 _operation: D,
16 ) -> Result<D::Success, OperationError<D::Failure>> {
17 // We don't handle operations with this backend
18 Err(OperationError::Unhandled)
19 }
20
21 async fn get_object<O: GiteratedObject + Debug>(
22 &self,
23 _object_str: &str,
24 ) -> Result<Object<O, Self>, OperationError<ObjectRequestError>> {
25 Err(OperationError::Unhandled)
26 }
27 }

giterated-daemon/src/connection/wrapper.rs

View file
@@ -5,7 +5,10 @@ use std::{
5 5
6 6 use anyhow::Error;
7 7 use futures_util::{SinkExt, StreamExt};
8 use giterated_models::model::instance::Instance;
8 use giterated_models::{
9 model::{authenticated::AuthenticatedPayload, instance::Instance},
10 operation::{AnyObject, AnyOperation, GiteratedMessage, ObjectBackend},
11 };
9 12
10 13 use serde::Serialize;
11 14
@@ -16,6 +19,7 @@ use toml::Table;
16 19 use crate::{
17 20 authentication::AuthenticationTokenGranter,
18 21 backend::{RepositoryBackend, SettingsBackend, UserBackend},
22 database_backend::Foobackend,
19 23 federation::connections::InstanceConnections,
20 24 keys::PublicKeyCache,
21 25 };
@@ -34,7 +38,7 @@ pub async fn connection_wrapper(
34 38 instance_connections: Arc<Mutex<InstanceConnections>>,
35 39 config: Table,
36 40 ) {
37 let _connection_state = ConnectionState {
41 let connection_state = ConnectionState {
38 42 socket: Arc::new(Mutex::new(socket)),
39 43 connections,
40 44 repository_backend,
@@ -51,6 +55,42 @@ pub async fn connection_wrapper(
51 55
52 56 let _handshaked = false;
53 57
58 loop {
59 let mut socket = connection_state.socket.lock().await;
60 let message = socket.next().await;
61 drop(socket);
62
63 match message {
64 Some(Ok(message)) => {
65 let payload = match message {
66 Message::Binary(payload) => payload,
67 Message::Ping(_) => {
68 let mut socket = connection_state.socket.lock().await;
69 let _ = socket.send(Message::Pong(vec![])).await;
70 drop(socket);
71 continue;
72 }
73 Message::Close(_) => return,
74 _ => continue,
75 };
76
77 let message: AuthenticatedPayload = bincode::deserialize(&payload).unwrap();
78
79 let message: GiteratedMessage<AnyObject, AnyOperation> = message.into_message();
80
81 let backend = Foobackend {};
82
83 backend
84 .object_operation(message.object, message.payload)
85 .await
86 .unwrap();
87 }
88 _ => {
89 return;
90 }
91 }
92 }
93
54 94 // loop {
55 95 // let mut socket = connection_state.socket.lock().await;
56 96 // let message = socket.next().await;

giterated-daemon/src/database_backend/handler.rs

View file
@@ -0,0 +1,238 @@
1 use std::{collections::HashMap, pin::Pin, sync::Arc};
2
3 use futures_util::{future::BoxFuture, Future, FutureExt};
4 use giterated_models::{
5 error::{GetValueError, OperationError},
6 model::{repository::Repository, settings::AnySetting, user::User},
7 operation::{AnyObject, AnyOperation, GetValue, GiteratedObject, GiteratedOperation},
8 values::{AnyValue, GetSetting, GetSettingError, SetSetting, SetSettingError},
9 };
10
11 use super::DatabaseBackend;
12
13 #[async_trait::async_trait]
14 pub trait GiteratedOperationHandler<
15 O: GiteratedObject,
16 D: GiteratedOperation<O>,
17 S: Send + Sync + Clone,
18 >
19 {
20 fn operation_name(&self) -> &str;
21 fn object_name(&self) -> &str;
22
23 async fn handle(
24 &self,
25 object: &O,
26 operation: D,
27 state: S,
28 ) -> Result<D::Success, OperationError<D::Failure>>;
29 }
30
31 #[async_trait::async_trait]
32 impl<O, D, F, S> GiteratedOperationHandler<O, D, S> for F
33 where
34 F: FnMut(
35 &O,
36 D,
37 S,
38 ) -> Pin<
39 Box<dyn Future<Output = Result<D::Success, OperationError<D::Failure>>> + Send>,
40 > + Send
41 + Sync
42 + Clone,
43 O: GiteratedObject + Send + Sync,
44 D: GiteratedOperation<O> + 'static,
45 <D as GiteratedOperation<O>>::Failure: Send,
46 S: Send + Sync + Clone + 'static,
47 {
48 fn operation_name(&self) -> &str {
49 D::operation_name()
50 }
51
52 fn object_name(&self) -> &str {
53 O::object_name()
54 }
55
56 async fn handle(
57 &self,
58 object: &O,
59 operation: D,
60 state: S,
61 ) -> Result<D::Success, OperationError<D::Failure>> {
62 self.clone()(object, operation, state).await
63 }
64 }
65
66 pub struct OperationWrapper<S: Send + Sync + Clone>(
67 Box<
68 dyn Fn(
69 AnyObject,
70 AnyOperation,
71 S,
72 )
73 -> Pin<Box<dyn Future<Output = Result<Vec<u8>, OperationError<Vec<u8>>>> + Send>>
74 + Send
75 + Sync,
76 >,
77 );
78
79 impl<S: Send + Sync + Clone + 'static> OperationWrapper<S> {
80 pub fn new<
81 O: GiteratedObject + Send + Sync,
82 D: GiteratedOperation<O> + 'static,
83 F: GiteratedOperationHandler<O, D, S> + Send + Sync + 'static + Clone,
84 >(
85 handler: F,
86 ) -> Self {
87 let handler = Arc::new(Box::pin(handler));
88 Self(Box::new(move |any_object, any_operation, state| {
89 let handler = handler.clone();
90 async move {
91 let handler = handler.clone();
92 let object: O = O::from_object_str(&any_object.0).unwrap();
93 let operation: D = serde_json::from_value(any_operation.0.clone()).unwrap();
94
95 let result = handler.handle(&object, operation, state).await;
96 result
97 .map(|success| serde_json::to_vec(&success).unwrap())
98 .map_err(|err| match err {
99 OperationError::Operation(err) => {
100 OperationError::Operation(serde_json::to_vec(&err).unwrap())
101 }
102 OperationError::Internal(internal) => OperationError::Internal(internal),
103 OperationError::Unhandled => OperationError::Unhandled,
104 })
105 }
106 .boxed()
107 }))
108 }
109
110 async fn handle(
111 &mut self,
112 object: AnyObject,
113 operation: AnyOperation,
114 state: S,
115 ) -> Result<Vec<u8>, OperationError<Vec<u8>>> {
116 self.0(object, operation, state).await
117 }
118 }
119
120 fn test_operation(
121 _object: &User,
122 _operation: SetSetting<AnySetting>,
123 _state: (),
124 ) -> Pin<Box<dyn Future<Output = Result<(), OperationError<SetSettingError>>> + Send + 'static>> {
125 todo!()
126 }
127
128 fn foo() {}
129
130 pub fn user_get_value(
131 object: &User,
132 operation: GetValue<AnyValue<User>>,
133 state: DatabaseBackend,
134 ) -> BoxFuture<'static, Result<AnyValue<User>, OperationError<GetValueError>>> {
135 let object = object.clone();
136
137 async move {
138 let mut user_backend = state.user_backend.lock().await;
139 let value = user_backend
140 .get_value(&object, &operation.value_name)
141 .await
142 .map_err(|e| OperationError::Internal(e.to_string()))?;
143
144 Ok(value)
145 }
146 .boxed()
147 }
148
149 pub fn user_get_setting(
150 _object: &User,
151 _operation: GetSetting<AnySetting>,
152 _state: DatabaseBackend,
153 ) -> BoxFuture<'static, Result<AnySetting, OperationError<GetSettingError>>> {
154 todo!()
155 }
156
157 pub fn user_set_setting(
158 _object: &User,
159 _operation: SetSetting<AnySetting>,
160 _state: DatabaseBackend,
161 ) -> BoxFuture<'static, Result<(), OperationError<SetSettingError>>> {
162 todo!()
163 }
164
165 pub fn repository_get_value(
166 _object: &Repository,
167 _operation: GetValue<AnyValue<Repository>>,
168 _state: DatabaseBackend,
169 ) -> BoxFuture<'static, Result<AnyValue<Repository>, OperationError<GetValueError>>> {
170 todo!()
171 }
172
173 pub fn repository_get_setting(
174 _object: &Repository,
175 _operation: GetSetting<AnySetting>,
176 _state: DatabaseBackend,
177 ) -> BoxFuture<'static, Result<AnySetting, OperationError<GetSettingError>>> {
178 todo!()
179 }
180
181 pub fn repository_set_setting(
182 _object: &Repository,
183 _operation: SetSetting<AnySetting>,
184 _state: DatabaseBackend,
185 ) -> BoxFuture<'static, Result<(), OperationError<SetSettingError>>> {
186 todo!()
187 }
188
189 pub struct OperationHandlers<S: Send + Sync + Clone> {
190 operations: HashMap<String, OperationWrapper<S>>,
191 }
192
193 impl<S: Send + Sync + Clone> Default for OperationHandlers<S> {
194 fn default() -> Self {
195 Self {
196 operations: HashMap::new(),
197 }
198 }
199 }
200
201 impl<S: Send + Sync + Clone + 'static> OperationHandlers<S> {
202 pub fn insert<
203 O: GiteratedObject + Send + Sync,
204 D: GiteratedOperation<O> + 'static,
205 H: GiteratedOperationHandler<O, D, S> + Send + Sync + 'static + Clone,
206 >(
207 &mut self,
208 handler: H,
209 ) -> &mut Self {
210 let operation_name = handler.operation_name().to_string();
211
212 let wrapped = OperationWrapper::new(handler);
213
214 self.operations.insert(operation_name, wrapped);
215
216 self
217 }
218
219 pub async fn handle<O: GiteratedObject>(
220 &mut self,
221 object: &O,
222 operation_name: &str,
223 operation: AnyOperation,
224 state: S,
225 ) -> Result<Vec<u8>, OperationError<Vec<u8>>> {
226 if let Some(handler) = self.operations.get_mut(operation_name) {
227 handler
228 .handle(
229 AnyObject(serde_json::to_string(object).unwrap()),
230 operation,
231 state,
232 )
233 .await
234 } else {
235 panic!()
236 }
237 }
238 }

giterated-daemon/src/database_backend/mod.rs

View file
@@ -1,16 +1,23 @@
1 pub mod handler;
2
1 3 use std::{str::FromStr, sync::Arc};
2 4
5 use futures_util::TryFutureExt;
3 6 use giterated_models::{
4 7 error::OperationError,
5 8 model::{instance::Instance, repository::Repository, user::User},
6 9 operation::{GiteratedObject, GiteratedOperation, Object, ObjectBackend, ObjectRequestError},
7 10 };
8 use sqlx::PgPool;
9 11 use std::fmt::Debug;
10 12 use tokio::sync::Mutex;
11 13
12 14 use crate::backend::{RepositoryBackend, UserBackend};
13 15
16 use self::handler::{
17 repository_get_setting, repository_get_value, repository_set_setting, user_get_setting,
18 user_get_value, user_set_setting, OperationHandlers,
19 };
20
14 21 #[derive(Clone, Debug)]
15 22 pub struct Foobackend {}
16 23
@@ -29,34 +36,78 @@ impl ObjectBackend for Foobackend {
29 36 &self,
30 37 _object_str: &str,
31 38 ) -> Result<Object<O, Self>, OperationError<ObjectRequestError>> {
32 todo!()
39 Err(OperationError::Unhandled)
33 40 }
34 41 }
35 42
36 43 /// A backend implementation which attempts to resolve data from the instance's database.
37 44 #[derive(Clone)]
38 pub struct DatabaseBackend<'b> {
39 our_instance: Object<'b, Instance, Foobackend>,
40 user_backend: Arc<Mutex<dyn UserBackend + Send>>,
41 repository_backend: Arc<Mutex<dyn RepositoryBackend + Send>>,
42 pool: PgPool,
45 pub struct DatabaseBackend {
46 pub(self) our_instance: Instance,
47 pub(self) user_backend: Arc<Mutex<dyn UserBackend + Send>>,
48 pub(self) repository_backend: Arc<Mutex<dyn RepositoryBackend + Send>>,
43 49 }
44 50
45 impl Debug for DatabaseBackend<'_> {
51 impl Debug for DatabaseBackend {
46 52 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
47 53 f.debug_struct("DatabaseBackend").finish()
48 54 }
49 55 }
50 56
51 57 #[async_trait::async_trait]
52 impl<'b> ObjectBackend for DatabaseBackend<'b> {
58 impl ObjectBackend for DatabaseBackend {
53 59 async fn object_operation<O: GiteratedObject + Debug, D: GiteratedOperation<O> + Debug>(
54 60 &self,
55 _object: O,
56 _operation: D,
61 object: O,
62 operation: D,
57 63 ) -> Result<D::Success, OperationError<D::Failure>> {
58 // We don't handle operations with this backend
59 Err(OperationError::Unhandled)
64 let serialized =
65 serde_json::to_value(operation).map_err(|e| OperationError::Internal(e.to_string()))?;
66 let object_name = object.to_string();
67
68 if let Ok(user) = User::from_str(&object_name) {
69 let mut handler = OperationHandlers::default();
70
71 handler
72 .insert(user_get_value)
73 .insert(user_get_setting)
74 .insert(user_set_setting);
75
76 match handler
77 .handle(
78 &user,
79 D::operation_name(),
80 serde_json::from_value(serialized.clone()).unwrap(),
81 self.clone(),
82 )
83 .await
84 {
85 Ok(result) => Ok(serde_json::from_slice(&result)
86 .map_err(|e| OperationError::Internal(e.to_string()))?),
87 Err(err) => match err {
88 OperationError::Internal(internal) => Err(OperationError::Internal(internal)),
89 OperationError::Unhandled => Err(OperationError::Unhandled),
90 OperationError::Operation(err) => Err(OperationError::Operation(
91 serde_json::from_slice(&err)
92 .map_err(|e| OperationError::Internal(e.to_string()))?,
93 )),
94 },
95 }
96 } else if let Ok(_repository) = Repository::from_str(&object_name) {
97 let mut handler = OperationHandlers::default();
98
99 handler
100 .insert(repository_get_value)
101 .insert(repository_get_setting)
102 .insert(repository_set_setting);
103
104 // handler.handle(&repository, D::operation_name(), bincode::deserialize(&serialized).unwrap(), DatabaseBackendState).await;
105 todo!()
106 } else if Instance::from_str(&object_name).is_ok() {
107 Err(OperationError::Unhandled)
108 } else {
109 Err(OperationError::Unhandled)
110 }
60 111 }
61 112
62 113 async fn get_object<O: GiteratedObject + Debug>(
@@ -107,3 +158,129 @@ impl<'b> ObjectBackend for DatabaseBackend<'b> {
107 158 }
108 159 }
109 160 }
161
162 mod test {
163 use std::{str::FromStr, sync::Arc};
164
165 use anyhow::Error;
166 use giterated_models::{
167 model::{
168 authenticated::UserAuthenticationToken,
169 instance::Instance,
170 repository::{Repository, RepositorySummary, RepositoryTreeEntry},
171 settings::AnySetting,
172 user::User,
173 },
174 operation::{
175 instance::{
176 AuthenticationTokenRequest, RegisterAccountRequest, RepositoryCreateRequest,
177 },
178 repository::RepositoryFileInspectRequest,
179 GiteratedObjectValue, ObjectBackend,
180 },
181 values::{user::DisplayName, AnyValue},
182 };
183 use serde_json::Value;
184 use tokio::sync::Mutex;
185
186 use crate::backend::{git::GitBackendError, AuthBackend, RepositoryBackend, UserBackend};
187
188 use super::DatabaseBackend;
189 pub struct TestUserDatabaseBackend;
190
191 #[async_trait::async_trait]
192 impl UserBackend for TestUserDatabaseBackend {
193 async fn get_value(&mut self, _user: &User, name: &str) -> Result<AnyValue<User>, Error> {
194 assert_eq!(name, DisplayName::value_name());
195
196 Ok(serde_json::from_slice(
197 &serde_json::to_vec(&DisplayName(String::from("test"))).unwrap(),
198 )
199 .unwrap())
200 }
201 async fn get_setting(&mut self, _user: &User, _name: &str) -> Result<AnySetting, Error> {
202 todo!()
203 }
204 async fn write_setting(
205 &mut self,
206 _user: &User,
207 _name: &str,
208 _setting: &Value,
209 ) -> Result<(), Error> {
210 todo!()
211 }
212 async fn exists(&mut self, user: &User) -> Result<bool, Error> {
213 Ok(user == &User::from_str("test_user:test.giterated.dev").unwrap())
214 }
215 }
216
217 #[async_trait::async_trait]
218 impl AuthBackend for TestUserDatabaseBackend {
219 async fn register(
220 &mut self,
221 _request: RegisterAccountRequest,
222 ) -> Result<UserAuthenticationToken, Error> {
223 todo!()
224 }
225
226 async fn login(
227 &mut self,
228 _source: &Instance,
229 _request: AuthenticationTokenRequest,
230 ) -> Result<UserAuthenticationToken, Error> {
231 todo!()
232 }
233 }
234
235 pub struct TestUserRepositoryBackend;
236
237 #[async_trait::async_trait]
238 impl RepositoryBackend for TestUserRepositoryBackend {
239 async fn create_repository(
240 &mut self,
241 _user: &User,
242 _request: &RepositoryCreateRequest,
243 ) -> Result<Repository, GitBackendError> {
244 todo!()
245 }
246 async fn repository_file_inspect(
247 &mut self,
248 _requester: Option<&User>,
249 _request: &RepositoryFileInspectRequest,
250 ) -> Result<Vec<RepositoryTreeEntry>, Error> {
251 todo!()
252 }
253 async fn repositories_for_user(
254 &mut self,
255 _requester: Option<&User>,
256 _user: &User,
257 ) -> Result<Vec<RepositorySummary>, Error> {
258 todo!()
259 }
260 async fn exists(&mut self, _repository: &Repository) -> Result<bool, Error> {
261 todo!()
262 }
263 }
264
265 fn test_backend() -> DatabaseBackend {
266 DatabaseBackend {
267 our_instance: Instance::from_str("testing.giterated.dev").unwrap(),
268 user_backend: Arc::new(Mutex::new(TestUserDatabaseBackend)) as _,
269 repository_backend: Arc::new(Mutex::new(TestUserRepositoryBackend)) as _,
270 }
271 }
272
273 #[tokio::test]
274 async fn test_user_get() {
275 let backend = test_backend();
276
277 let mut user = backend
278 .get_object::<User>("test_user:test.giterated.dev")
279 .await
280 .expect("object should have been returned");
281
282 user.get::<DisplayName>()
283 .await
284 .expect("object value should have been returned");
285 }
286 }

giterated-daemon/src/lib.rs

View file
@@ -4,6 +4,7 @@ use semver::{Version, VersionReq};
4 4
5 5 pub mod authentication;
6 6 pub mod backend;
7 pub mod cache_backend;
7 8 pub mod connection;
8 9 pub mod database_backend;
9 10 pub mod federation;

giterated-models/Cargo.toml

View file
@@ -6,35 +6,25 @@ edition = "2021"
6 6 # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
7 7
8 8 [dependencies]
9 tokio-tungstenite = "*"
10 tokio = { version = "1.32.0", features = [ "full" ] }
11 9 tracing = "*"
12 futures-util = "*"
13 10 serde = { version = "1.0.188", features = [ "derive" ]}
14 11 serde_json = "1.0"
15 tracing-subscriber = "0.3"
16 12 base64 = "0.21.3"
17 13 jsonwebtoken = { version = "*", features = ["use_pem"]}
18 log = "*"
19 14 rand = "*"
20 15 rsa = {version = "0.9", features = ["sha2"]}
21 reqwest = "*"
22 argon2 = "*"
23 aes-gcm = "0.10.2"
24 16 semver = {version = "*", features = ["serde"]}
25 tower = "*"
26 17 bincode = "*"
27 18 secrecy = { version = "0.8.0", features = ["serde"] }
28
19 thiserror = "1"
20 anyhow = "1"
29 21 toml = { version = "0.7" }
30
22 # Git backend
23 git2 = "0.17"
31 24 chrono = { version = "0.4", features = [ "serde" ] }
32 25 async-trait = "0.1"
33 26
34 27 # Git backend
35 git2 = "0.17"
36 thiserror = "1"
37 anyhow = "1"
38 sqlx = { version = "0.7", features = [ "runtime-tokio", "tls-native-tls", "postgres", "macros", "migrate", "chrono" ] }
28 sqlx = { version = "0.7", default-features = false, features = [ "macros", "chrono" ] }
39 29
40 30 #uuid = { version = "1.4", features = [ "v4", "serde" ] }

giterated-models/src/model/authenticated.rs

View file
@@ -8,9 +8,12 @@ use rsa::{
8 8 RsaPrivateKey,
9 9 };
10 10 use serde::{Deserialize, Serialize};
11 use serde_json::Value;
11 12 use tracing::info;
12 13
13 use crate::operation::{GiteratedMessage, GiteratedObject, GiteratedOperation};
14 use crate::operation::{
15 AnyObject, AnyOperation, GiteratedMessage, GiteratedObject, GiteratedOperation,
16 };
14 17
15 18 use super::{instance::Instance, user::User, MessageTarget};
16 19
@@ -27,12 +30,24 @@ pub struct Authenticated<O: GiteratedObject, D: GiteratedOperation<O>> {
27 30 pub message: GiteratedMessage<O, D>,
28 31 }
29 32
30 #[derive(Debug, Hash, PartialEq, Eq, Serialize, Deserialize)]
33 #[derive(Debug, Clone, Hash, PartialEq, Eq, Serialize, Deserialize)]
31 34 pub struct AuthenticatedPayload {
32 35 pub source: Vec<AuthenticationSource>,
36 pub object: String,
37 pub operation: String,
33 38 pub payload: Vec<u8>,
34 39 }
35 40
41 impl AuthenticatedPayload {
42 pub fn into_message(self) -> GiteratedMessage<AnyObject, AnyOperation> {
43 GiteratedMessage {
44 object: AnyObject(self.object),
45 operation: self.operation,
46 payload: AnyOperation(serde_json::from_slice::<Value>(&self.payload).unwrap()),
47 }
48 }
49 }
50
36 51 // impl<T: Serialize> From<Authenticated<T>> for AuthenticatedPayload {
37 52 // fn from(mut value: Authenticated<T>) -> Self {
38 53 // let payload = bincode::serialize(&value.message).unwrap();
@@ -103,9 +118,11 @@ impl<O: GiteratedObject, D: GiteratedOperation<O>> Authenticated<O, D> {
103 118 }
104 119
105 120 pub fn into_payload(mut self) -> AuthenticatedPayload {
106 let payload = bincode::serialize(&self.message).unwrap();
121 let payload = bincode::serialize(&self.message.payload).unwrap();
107 122
108 123 AuthenticatedPayload {
124 object: self.message.object.to_string(),
125 operation: self.message.operation,
109 126 source: self
110 127 .source
111 128 .drain(..)

giterated-models/src/model/instance.rs

View file
@@ -33,7 +33,7 @@ pub struct Instance {
33 33 }
34 34
35 35 impl GiteratedObject for Instance {
36 fn object_name(&self) -> &str {
36 fn object_name() -> &'static str {
37 37 "instance"
38 38 }
39 39

giterated-models/src/model/repository.rs

View file
@@ -39,7 +39,7 @@ pub struct Repository {
39 39 }
40 40
41 41 impl GiteratedObject for Repository {
42 fn object_name(&self) -> &str {
42 fn object_name() -> &'static str {
43 43 "repository"
44 44 }
45 45

giterated-models/src/model/settings.rs

View file
@@ -1,9 +1,19 @@
1 use serde::{Deserialize, Serialize};
1 use serde::{de::DeserializeOwned, Deserialize, Serialize};
2 use serde_json::Value;
2 3
3 pub trait Setting: Serialize {
4 pub trait Setting: Serialize + DeserializeOwned {
4 5 fn name() -> &'static str;
5 6 }
6 7
8 #[derive(Debug, Clone, Serialize, Deserialize)]
9 pub struct AnySetting(Value);
10
11 impl Setting for AnySetting {
12 fn name() -> &'static str {
13 "any"
14 }
15 }
16
7 17 #[derive(Debug, Serialize, Deserialize)]
8 18 pub struct UserBio(pub String);
9 19

giterated-models/src/model/user.rs

View file
@@ -35,7 +35,7 @@ pub struct User {
35 35 }
36 36
37 37 impl GiteratedObject for User {
38 fn object_name(&self) -> &str {
38 fn object_name() -> &'static str {
39 39 "user"
40 40 }
41 41

giterated-models/src/operation/instance.rs

View file
@@ -2,7 +2,7 @@ use secrecy::Secret;
2 2 use serde::{Deserialize, Serialize};
3 3
4 4 use crate::{
5 error::InstanceError,
5 error::{InstanceError, OperationError},
6 6 model::{
7 7 authenticated::UserAuthenticationToken,
8 8 instance::Instance,
@@ -112,24 +112,26 @@ impl<B: ObjectBackend + std::fmt::Debug> Object<'_, Instance, B> {
112 112 email: Option<&str>,
113 113 username: &str,
114 114 password: &Secret<Password>,
115 ) -> Result<UserAuthenticationToken, InstanceError> {
115 ) -> Result<UserAuthenticationToken, OperationError<InstanceError>> {
116 116 self.request::<RegisterAccountRequest>(RegisterAccountRequest {
117 117 username: username.to_string(),
118 118 email: email.map(|s| s.to_string()),
119 119 password: password.clone(),
120 120 })
121 .await
121 122 }
122 123
123 124 pub async fn authentication_token(
124 125 &mut self,
125 126 username: &str,
126 127 password: &Secret<Password>,
127 ) -> Result<UserAuthenticationToken, InstanceError> {
128 ) -> Result<UserAuthenticationToken, OperationError<InstanceError>> {
128 129 self.request::<AuthenticationTokenRequest>(AuthenticationTokenRequest {
129 130 instance: self.inner.clone(),
130 131 username: username.to_string(),
131 132 password: password.clone(),
132 133 })
134 .await
133 135 }
134 136
135 137 pub async fn authentication_token_for(
@@ -137,21 +139,23 @@ impl<B: ObjectBackend + std::fmt::Debug> Object<'_, Instance, B> {
137 139 instance: &Instance,
138 140 username: &str,
139 141 password: &Secret<Password>,
140 ) -> Result<UserAuthenticationToken, InstanceError> {
142 ) -> Result<UserAuthenticationToken, OperationError<InstanceError>> {
141 143 self.request::<AuthenticationTokenRequest>(AuthenticationTokenRequest {
142 144 instance: instance.clone(),
143 145 username: username.to_string(),
144 146 password: password.clone(),
145 147 })
148 .await
146 149 }
147 150
148 151 pub async fn token_extension(
149 152 &mut self,
150 153 token: &UserAuthenticationToken,
151 ) -> Result<Option<UserAuthenticationToken>, InstanceError> {
154 ) -> Result<Option<UserAuthenticationToken>, OperationError<InstanceError>> {
152 155 self.request::<TokenExtensionRequest>(TokenExtensionRequest {
153 156 token: token.clone(),
154 157 })
158 .await
155 159 }
156 160
157 161 pub async fn create_repository(
@@ -161,7 +165,7 @@ impl<B: ObjectBackend + std::fmt::Debug> Object<'_, Instance, B> {
161 165 visibility: RepositoryVisibility,
162 166 default_branch: &str,
163 167 owner: &User,
164 ) -> Result<Repository, InstanceError> {
168 ) -> Result<Repository, OperationError<InstanceError>> {
165 169 self.request::<RepositoryCreateRequest>(RepositoryCreateRequest {
166 170 instance: Some(instance.clone()),
167 171 name: name.to_string(),
@@ -170,5 +174,6 @@ impl<B: ObjectBackend + std::fmt::Debug> Object<'_, Instance, B> {
170 174 default_branch: default_branch.to_string(),
171 175 owner: owner.clone(),
172 176 })
177 .await
173 178 }
174 179 }

giterated-models/src/operation/mod.rs

View file
@@ -2,18 +2,20 @@ use std::{any::type_name, fmt::Debug, marker::PhantomData};
2 2
3 3 use anyhow::Error;
4 4 use serde::{de::DeserializeOwned, Deserialize, Serialize};
5 use serde_json::Value;
5 6
6 7 use crate::{
7 8 error::{GetValueError, OperationError},
8 model::{instance::Instance, MessageTarget},
9 model::{instance::Instance, settings::Setting, MessageTarget},
10 values::{GetSetting, GetSettingError, SetSetting, SetSettingError},
9 11 };
10 12
11 13 pub mod instance;
12 14 pub mod repository;
13 15 pub mod user;
14 16
15 pub trait GiteratedObject: Send + Serialize + DeserializeOwned {
16 fn object_name(&self) -> &str;
17 pub trait GiteratedObject: Send + Serialize + DeserializeOwned + ToString {
18 fn object_name() -> &'static str;
17 19
18 20 fn from_object_str(object_str: &str) -> Result<Self, Error>;
19 21 }
@@ -22,7 +24,7 @@ pub trait GiteratedOperation<O: GiteratedObject>: Send + Serialize + Deserialize
22 24 type Success: Serialize + DeserializeOwned + Send;
23 25 type Failure: Serialize + DeserializeOwned + Send;
24 26
25 fn operation_name(&self) -> &'static str {
27 fn operation_name() -> &'static str {
26 28 type_name::<Self>()
27 29 }
28 30 }
@@ -73,43 +75,43 @@ impl<'b, B: ObjectBackend + Send + Sync + Clone, O: GiteratedObject> Object<'b,
73 75 impl<'b, O: GiteratedObject + Clone + Debug, B: ObjectBackend + Debug + Send + Sync + Clone>
74 76 Object<'b, O, B>
75 77 {
76 pub async fn get<V: GiteratedObjectValue<Object = O> + Send>(
77 &self,
78 ) -> Result<V, OperationError<ObjectRequestError>> {
79 let operation: GetValue<V> = GetValue {
80 value_name: V::value_name().to_string(),
81 _marker: PhantomData,
82 };
83
84 let _message: GiteratedMessage<O, _> = GiteratedMessage {
85 object: self.inner.clone(),
86 operation: operation.operation_name().to_string(),
87 payload: operation,
88 };
89
90 todo!()
91 }
92
93 pub fn request<R: GiteratedOperation<O> + Debug>(
94 &mut self,
95 request: R,
96 ) -> Result<R::Success, R::Failure> {
97 self.backend.object_operation(self.inner.clone(), request);
98
99 todo!()
100 }
78 // pub async fn get<V: GiteratedObjectValue<Object = O> + Send>(
79 // &self,
80 // ) -> Result<V, OperationError<ObjectRequestError>> {
81 // let operation: GetValue<V> = GetValue {
82 // value_name: V::value_name().to_string(),
83 // _marker: PhantomData,
84 // };
85
86 // let _message: GiteratedMessage<O, _> = GiteratedMessage {
87 // object: self.inner.clone(),
88 // operation: operation.operation_name().to_string(),
89 // payload: operation,
90 // };
91
92 // todo!()
93 // }
94
95 // pub fn request<R: GiteratedOperation<O> + Debug>(
96 // &mut self,
97 // request: R,
98 // ) -> Result<R::Success, R::Failure> {
99 // self.backend.object_operation(self.inner.clone(), request);
100
101 // todo!()
102 // }
101 103 }
102 104
103 #[derive(Serialize, Deserialize)]
105 #[derive(Serialize, Deserialize, Debug, Clone)]
104 106 pub struct GetValue<V: GiteratedObjectValue> {
105 value_name: String,
107 pub value_name: String,
106 108 _marker: PhantomData<V>,
107 109 }
108 110
109 111 impl<O: GiteratedObject + Send, V: GiteratedObjectValue<Object = O> + Send> GiteratedOperation<O>
110 112 for GetValue<V>
111 113 {
112 fn operation_name(&self) -> &'static str {
114 fn operation_name() -> &'static str {
113 115 "get_value"
114 116 }
115 117 type Success = V;
@@ -124,6 +126,21 @@ pub struct GiteratedMessage<O: GiteratedObject, V: GiteratedOperation<O>> {
124 126 pub payload: V,
125 127 }
126 128
129 impl GiteratedMessage<AnyObject, AnyOperation> {
130 pub fn try_into<O: GiteratedObject, V: GiteratedOperation<O>>(
131 &self,
132 ) -> Result<GiteratedMessage<O, V>, ()> {
133 let object = O::from_object_str(&self.object.0).map_err(|_| ())?;
134 let payload = serde_json::from_value::<V>(self.payload.0.clone()).map_err(|_| ())?;
135
136 Ok(GiteratedMessage {
137 object,
138 operation: self.operation.clone(),
139 payload,
140 })
141 }
142 }
143
127 144 impl<O: GiteratedObject, V: GiteratedOperation<O>> MessageTarget for GiteratedMessage<O, V> {}
128 145
129 146 impl<V: GiteratedOperation<O> + Debug, O: GiteratedObject + Debug> Debug
@@ -157,23 +174,74 @@ pub enum ObjectRequestError {
157 174 }
158 175
159 176 #[derive(Clone, Debug, Serialize, Deserialize)]
160 pub struct AnyObject(Vec<u8>);
177 #[repr(transparent)]
178 pub struct AnyObject(pub String);
161 179
162 180 impl GiteratedObject for AnyObject {
163 fn object_name(&self) -> &str {
181 fn object_name() -> &'static str {
164 182 "any"
165 183 }
166 184
167 185 fn from_object_str(object_str: &str) -> Result<Self, Error> {
168 Ok(Self(Vec::from(object_str.as_bytes())))
186 Ok(Self(object_str.to_string()))
187 }
188 }
189
190 impl ToString for AnyObject {
191 fn to_string(&self) -> String {
192 self.0.to_string()
169 193 }
170 194 }
171 195
172 196 #[derive(Clone, Debug, Serialize, Deserialize)]
173 pub struct AnyOperation(Vec<u8>);
197 #[serde(transparent)]
198 #[repr(transparent)]
199 pub struct AnyOperation(pub Value);
174 200
175 201 impl<O: GiteratedObject> GiteratedOperation<O> for AnyOperation {
176 202 type Success = Vec<u8>;
177 203
178 204 type Failure = Vec<u8>;
179 205 }
206
207 impl<'b, O: GiteratedObject + Clone + Debug, B: ObjectBackend> Object<'b, O, B> {
208 pub async fn get<V: GiteratedObjectValue<Object = O> + Send + Debug>(
209 &mut self,
210 ) -> Result<V, OperationError<GetValueError>> {
211 self.request(GetValue {
212 value_name: V::value_name().to_string(),
213 _marker: PhantomData,
214 })
215 .await
216 }
217
218 pub async fn get_setting<S: Setting + Send + Clone + Debug>(
219 &mut self,
220 ) -> Result<S, OperationError<GetSettingError>> {
221 self.request(GetSetting {
222 setting_name: S::name().to_string(),
223 _marker: PhantomData,
224 })
225 .await
226 }
227
228 pub async fn set_setting<S: Setting + Send + Clone + Debug>(
229 &mut self,
230 setting: S,
231 ) -> Result<(), OperationError<SetSettingError>> {
232 self.request(SetSetting {
233 setting_name: S::name().to_string(),
234 value: setting,
235 })
236 .await
237 }
238
239 pub async fn request<R: GiteratedOperation<O> + Debug>(
240 &mut self,
241 request: R,
242 ) -> Result<R::Success, OperationError<R::Failure>> {
243 self.backend
244 .object_operation(self.inner.clone(), request)
245 .await
246 }
247 }

giterated-models/src/operation/repository.rs

View file
@@ -1,7 +1,7 @@
1 1 use serde::{Deserialize, Serialize};
2 2
3 3 use crate::{
4 error::RepositoryError,
4 error::{OperationError, RepositoryError},
5 5 model::repository::{IssueLabel, Repository, RepositoryIssue, RepositoryTreeEntry},
6 6 };
7 7
@@ -78,24 +78,32 @@ impl GiteratedOperation<Repository> for RepositoryFileInspectRequest {
78 78 }
79 79
80 80 impl<B: ObjectBackend + std::fmt::Debug> Object<'_, Repository, B> {
81 pub async fn issues_count(&mut self) -> Result<u64, RepositoryError> {
81 pub async fn issues_count(&mut self) -> Result<u64, OperationError<RepositoryError>> {
82 82 self.request::<RepositoryIssuesCountRequest>(RepositoryIssuesCountRequest)
83 .await
83 84 }
84 85
85 pub async fn issue_labels(&mut self) -> Result<Vec<IssueLabel>, RepositoryError> {
86 pub async fn issue_labels(
87 &mut self,
88 ) -> Result<Vec<IssueLabel>, OperationError<RepositoryError>> {
86 89 self.request::<RepositoryIssueLabelsRequest>(RepositoryIssueLabelsRequest)
90 .await
87 91 }
88 92
89 pub async fn issues(&mut self) -> Result<Vec<RepositoryIssue>, RepositoryError> {
93 pub async fn issues(
94 &mut self,
95 ) -> Result<Vec<RepositoryIssue>, OperationError<RepositoryError>> {
90 96 self.request::<RepositoryIssuesRequest>(RepositoryIssuesRequest)
97 .await
91 98 }
92 99
93 100 pub async fn inspect_files(
94 101 &mut self,
95 102 entry: &RepositoryTreeEntry,
96 ) -> Result<Vec<RepositoryTreeEntry>, RepositoryError> {
103 ) -> Result<Vec<RepositoryTreeEntry>, OperationError<RepositoryError>> {
97 104 self.request::<RepositoryFileInspectRequest>(RepositoryFileInspectRequest {
98 105 path: entry.clone(),
99 106 })
107 .await
100 108 }
101 109 }

giterated-models/src/operation/user.rs

View file
@@ -1,7 +1,7 @@
1 1 use serde::{Deserialize, Serialize};
2 2
3 3 use crate::{
4 error::UserError,
4 error::{OperationError, UserError},
5 5 model::{instance::Instance, repository::Repository, user::User},
6 6 };
7 7
@@ -22,10 +22,11 @@ impl<B: ObjectBackend + std::fmt::Debug> Object<'_, User, B> {
22 22 pub async fn repositories(
23 23 &mut self,
24 24 instance: &Instance,
25 ) -> Result<Vec<Repository>, UserError> {
25 ) -> Result<Vec<Repository>, OperationError<UserError>> {
26 26 self.request::<UserRepositoriesRequest>(UserRepositoriesRequest {
27 27 instance: instance.clone(),
28 28 user: self.inner.clone(),
29 29 })
30 .await
30 31 }
31 32 }

giterated-models/src/values/mod.rs

View file
@@ -1,3 +1,79 @@
1 use std::{fmt::Debug, marker::PhantomData};
2
3 use serde::{de::DeserializeOwned, Deserialize, Serialize};
4 use serde_json::Value;
5 use thiserror::Error;
6
7 use crate::{
8 model::settings::Setting,
9 operation::{GiteratedObject, GiteratedObjectValue, GiteratedOperation},
10 };
11
1 12 pub mod instance;
2 13 pub mod repository;
3 14 pub mod user;
15
16 // #[derive(Serialize, Deserialize)]
17 // pub struct GetRequest<V: GiteratedObjectValue> {
18 // value_name: String,
19 // _marker: PhantomData<V>,
20 // }
21
22 // impl<O: GiteratedObject, V: GiteratedObjectValue<Object = O> + Send> GiteratedOperation<O>
23 // for GetRequest<V>
24 // {
25 // type Success = V;
26
27 // type Failure = GetValueError;
28 // }
29
30 // #[derive(Error, Debug, Serialize, Deserialize)]
31 // pub enum GetValueError {}
32
33 #[derive(Serialize, Deserialize, Debug, Clone)]
34 pub struct GetSetting<S: Setting + std::fmt::Debug + Clone> {
35 pub setting_name: String,
36 pub _marker: PhantomData<S>,
37 }
38
39 impl<O: GiteratedObject, S: Setting + Send + DeserializeOwned + Debug + Clone> GiteratedOperation<O>
40 for GetSetting<S>
41 {
42 type Success = S;
43
44 type Failure = GetSettingError;
45 }
46
47 #[derive(Error, Debug, Serialize, Deserialize)]
48 pub enum GetSettingError {}
49 #[derive(Serialize, Deserialize, Debug, Clone)]
50 #[serde(bound(deserialize = "S: Setting"))]
51 pub struct SetSetting<S: Setting> {
52 pub setting_name: String,
53 pub value: S,
54 }
55
56 impl<O: GiteratedObject, S: Setting + Send> GiteratedOperation<O> for SetSetting<S> {
57 type Success = ();
58
59 type Failure = SetSettingError;
60 }
61
62 #[derive(Error, Debug, Serialize, Deserialize)]
63 pub enum SetSettingError {}
64
65 #[derive(Debug, Clone, Deserialize, Serialize)]
66 #[serde(transparent)]
67 pub struct AnyValue<O> {
68 value: Value,
69 #[serde(skip)]
70 _marker: PhantomData<O>,
71 }
72
73 impl<O: GiteratedObject> GiteratedObjectValue for AnyValue<O> {
74 type Object = O;
75
76 fn value_name() -> &'static str {
77 todo!()
78 }
79 }