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

ambee/giterated

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

Giterated stack changeover, refactor still incomplete

Amber - ⁨2⁩ years ago

parent: tbd commit: ⁨8d40dfe

⁨giterated-daemon/src/database_backend/mod.rs⁩ - ⁨11686⁩ bytes
Raw
1 pub mod handler;
2
3 use std::sync::Arc;
4
5 use giterated_models::error::OperationError;
6 use giterated_models::instance::Instance;
7 use giterated_models::object::{GiteratedObject, Object, ObjectRequestError};
8 use giterated_models::object_backend::ObjectBackend;
9 use giterated_models::operation::GiteratedOperation;
10 use giterated_models::repository::Repository;
11 use giterated_models::user::User;
12 use giterated_stack::handler::GiteratedBackend;
13 use giterated_stack::OperationHandlers;
14 use std::fmt::Debug;
15 use tokio::sync::Mutex;
16
17 use crate::backend::{RepositoryBackend, UserBackend};
18
19 use self::handler::{
20 repository_commit_before, repository_diff, repository_file_from_id, repository_get_setting,
21 repository_get_value, repository_info, repository_set_setting, user_get_repositories,
22 user_get_setting, user_get_value, user_set_setting,
23 };
24
25 #[derive(Clone, Debug)]
26 pub struct Foobackend {}
27
28 #[async_trait::async_trait]
29 impl ObjectBackend for Foobackend {
30 async fn object_operation<O: GiteratedObject + Debug, D: GiteratedOperation<O> + Debug>(
31 &self,
32 _object: O,
33 _operation: &str,
34 _payload: D,
35 ) -> Result<D::Success, OperationError<D::Failure>> {
36 // We don't handle operations with this backend
37 Err(OperationError::Unhandled)
38 }
39
40 async fn get_object<O: GiteratedObject + Debug>(
41 &self,
42 _object_str: &str,
43 ) -> Result<Object<O, Self>, OperationError<ObjectRequestError>> {
44 Err(OperationError::Unhandled)
45 }
46 }
47
48 /// A backend implementation which attempts to resolve data from the instance's database.
49 #[derive(Clone)]
50 pub struct DatabaseBackend {
51 pub(self) our_instance: Instance,
52 pub(self) user_backend: Arc<Mutex<dyn UserBackend + Send>>,
53 pub(self) repository_backend: Arc<Mutex<dyn RepositoryBackend + Send>>,
54 }
55
56 impl DatabaseBackend {
57 pub fn new(
58 instance: Instance,
59 user_backend: Arc<Mutex<dyn UserBackend + Send>>,
60 repository_backend: Arc<Mutex<dyn RepositoryBackend + Send>>,
61 ) -> Self {
62 Self {
63 our_instance: instance,
64 user_backend,
65 repository_backend,
66 }
67 }
68
69 pub fn into_backend(&self) -> GiteratedBackend<Self> {
70 let mut handlers = OperationHandlers::default();
71
72 handlers
73 .insert(user_get_repositories)
74 .insert(user_get_value)
75 .insert(user_get_setting)
76 .insert(user_set_setting)
77 .insert(repository_info)
78 .insert(repository_file_from_id)
79 .insert(repository_diff)
80 .insert(repository_commit_before)
81 .insert(repository_get_value)
82 .insert(repository_get_setting)
83 .insert(repository_set_setting)
84 .register_object::<Instance>()
85 .register_object::<Repository>()
86 .register_object::<User>();
87
88 GiteratedBackend::new(self.clone(), handlers)
89 }
90 }
91
92 impl Debug for DatabaseBackend {
93 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
94 f.debug_struct("DatabaseBackend").finish()
95 }
96 }
97
98 // TODO: These should be on the stack
99 // These tests verify that the essential handling of the database backend is
100 // functional and correct.
101 #[cfg(test)]
102 mod test {
103 use std::{str::FromStr, sync::Arc};
104
105 use anyhow::Error;
106
107 use giterated_models::authenticated::UserAuthenticationToken;
108
109 use giterated_models::instance::{
110 AuthenticationTokenRequest, Instance, RegisterAccountRequest, RepositoryCreateRequest,
111 };
112
113 use giterated_models::object_backend::ObjectBackend;
114
115 use giterated_models::repository::{
116 Commit, Description, Repository, RepositoryCommitBeforeRequest, RepositoryDiff,
117 RepositoryDiffRequest, RepositoryFile, RepositoryFileFromIdRequest,
118 RepositoryFileInspectRequest, RepositorySummary, RepositoryTreeEntry,
119 };
120 use giterated_models::settings::AnySetting;
121 use giterated_models::user::{DisplayName, User};
122 use giterated_models::value::{AnyValue, GiteratedObjectValue};
123 use giterated_stack::handler::GiteratedBackend;
124 use serde_json::Value;
125 use tokio::sync::Mutex;
126
127 use crate::backend::{git::GitBackendError, AuthBackend, RepositoryBackend, UserBackend};
128
129 use super::DatabaseBackend;
130 pub struct TestUserDatabaseBackend;
131
132 #[async_trait::async_trait]
133 impl UserBackend for TestUserDatabaseBackend {
134 async fn get_value(&mut self, _user: &User, name: &str) -> Result<AnyValue<User>, Error> {
135 assert_eq!(name, DisplayName::value_name());
136
137 Ok(serde_json::from_slice(
138 &serde_json::to_vec(&DisplayName(String::from("test"))).unwrap(),
139 )
140 .unwrap())
141 }
142 async fn get_setting(&mut self, _user: &User, _name: &str) -> Result<AnySetting, Error> {
143 Ok(serde_json::from_slice(
144 &serde_json::to_vec(&DisplayName(String::from("test"))).unwrap(),
145 )
146 .unwrap())
147 }
148 async fn write_setting(
149 &mut self,
150 _user: &User,
151 _name: &str,
152 _setting: &Value,
153 ) -> Result<(), Error> {
154 Ok(())
155 }
156 async fn exists(&mut self, user: &User) -> Result<bool, Error> {
157 Ok(user == &User::from_str("test_user:test.giterated.dev").unwrap())
158 }
159 async fn repositories_for_user(
160 &mut self,
161 _requester: Option<&User>,
162 _user: &User,
163 ) -> Result<Vec<RepositorySummary>, Error> {
164 todo!()
165 }
166 }
167
168 #[async_trait::async_trait]
169 impl AuthBackend for TestUserDatabaseBackend {
170 async fn register(
171 &mut self,
172 _request: RegisterAccountRequest,
173 ) -> Result<UserAuthenticationToken, Error> {
174 todo!()
175 }
176
177 async fn login(
178 &mut self,
179 _source: &Instance,
180 _request: AuthenticationTokenRequest,
181 ) -> Result<UserAuthenticationToken, Error> {
182 todo!()
183 }
184 }
185
186 pub struct TestUserRepositoryBackend;
187
188 #[async_trait::async_trait]
189 impl RepositoryBackend for TestUserRepositoryBackend {
190 async fn create_repository(
191 &mut self,
192 _user: &User,
193 _request: &RepositoryCreateRequest,
194 ) -> Result<Repository, GitBackendError> {
195 todo!()
196 }
197 async fn repository_file_inspect(
198 &mut self,
199 _requester: Option<&User>,
200 _repository: &Repository,
201 _request: &RepositoryFileInspectRequest,
202 ) -> Result<Vec<RepositoryTreeEntry>, Error> {
203 todo!()
204 }
205 async fn repository_file_from_id(
206 &mut self,
207 _requester: Option<&User>,
208 _repository: &Repository,
209 _request: &RepositoryFileFromIdRequest,
210 ) -> Result<RepositoryFile, Error> {
211 todo!()
212 }
213 async fn repository_diff(
214 &mut self,
215 _requester: Option<&User>,
216 _repository: &Repository,
217 _request: &RepositoryDiffRequest,
218 ) -> Result<RepositoryDiff, Error> {
219 todo!()
220 }
221 async fn repository_commit_before(
222 &mut self,
223 _requester: Option<&User>,
224 _repository: &Repository,
225 _request: &RepositoryCommitBeforeRequest,
226 ) -> Result<Commit, Error> {
227 todo!()
228 }
229 async fn get_value(
230 &mut self,
231 _repository: &Repository,
232 _name: &str,
233 ) -> Result<AnyValue<Repository>, Error> {
234 Ok(serde_json::from_slice(
235 &serde_json::to_vec(&Description(String::from("test"))).unwrap(),
236 )
237 .unwrap())
238 }
239 async fn get_setting(
240 &mut self,
241 _repository: &Repository,
242 _name: &str,
243 ) -> Result<AnySetting, Error> {
244 Ok(serde_json::from_slice(
245 &serde_json::to_vec(&Description(String::from("test"))).unwrap(),
246 )
247 .unwrap())
248 }
249 async fn write_setting(
250 &mut self,
251 _repository: &Repository,
252 _name: &str,
253 _setting: &Value,
254 ) -> Result<(), Error> {
255 Ok(())
256 }
257
258 async fn exists(&mut self, repository: &Repository) -> Result<bool, Error> {
259 // Ok(true)
260 Ok(repository
261 == &Repository::from_str(
262 "test_user:test.giterated.dev/[email protected]",
263 )
264 .unwrap())
265 }
266 }
267
268 fn test_backend() -> GiteratedBackend<DatabaseBackend> {
269 DatabaseBackend {
270 our_instance: Instance::from_str("testing.giterated.dev").unwrap(),
271 user_backend: Arc::new(Mutex::new(TestUserDatabaseBackend)) as _,
272 repository_backend: Arc::new(Mutex::new(TestUserRepositoryBackend)) as _,
273 }
274 .into_backend()
275 }
276
277 #[tokio::test]
278 async fn test_user_get() {
279 let backend = test_backend();
280
281 let mut user = backend
282 .get_object::<User>("test_user:test.giterated.dev")
283 .await
284 .expect("object should have been returned");
285
286 user.get::<DisplayName>()
287 .await
288 .expect("object value should have been returned");
289 }
290
291 #[tokio::test]
292 async fn test_user_get_setting() {
293 let backend = test_backend();
294
295 let mut user = backend
296 .get_object::<User>("test_user:test.giterated.dev")
297 .await
298 .expect("object should have been returned");
299
300 user.get_setting::<DisplayName>()
301 .await
302 .expect("object value should have been returned");
303 }
304
305 #[tokio::test]
306 async fn test_user_set_setting() {
307 let backend = test_backend();
308
309 let mut user = backend
310 .get_object::<User>("test_user:test.giterated.dev")
311 .await
312 .expect("object should have been returned");
313
314 user.set_setting::<DisplayName>(DisplayName(String::from("test")))
315 .await
316 .expect("object value should have been returned");
317 }
318
319 #[tokio::test]
320 async fn test_respository_get() {
321 let backend = test_backend();
322
323 let mut repository = backend
324 .get_object::<Repository>("test_user:test.giterated.dev/[email protected]")
325 .await
326 .expect("object should have been returned");
327
328 repository
329 .get::<Description>()
330 .await
331 .expect("object value should have been returned");
332 }
333
334 #[tokio::test]
335 async fn test_repository_get_setting() {
336 let backend = test_backend();
337
338 let mut repository = backend
339 .get_object::<Repository>("test_user:test.giterated.dev/[email protected]")
340 .await
341 .expect("object should have been returned");
342
343 repository
344 .get_setting::<Description>()
345 .await
346 .expect("object value should have been returned");
347 }
348
349 #[tokio::test]
350 async fn test_repository_set_setting() {
351 let backend = test_backend();
352
353 let mut repository = backend
354 .get_object::<Repository>("test_user:test.giterated.dev/[email protected]")
355 .await
356 .expect("object should have been returned");
357
358 repository
359 .set_setting::<Description>(Description(String::from("test")))
360 .await
361 .expect("object value should have been returned");
362 }
363 }
364