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

ambee/giterated

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

Finish unified stack refactor.

Adds support for operation state, which will be used to pass authentication information around. Added generic backend that uses a channel to communicate with a typed backend.

Amber - ⁨2⁩ years ago

parent: tbd commit: ⁨d15581c

⁨giterated-daemon/src/database_backend/handler.rs⁩ - ⁨9266⁩ bytes
Raw
1 use std::error::Error;
2
3 use futures_util::{future::BoxFuture, FutureExt};
4 use giterated_models::{
5 error::{GetValueError, OperationError, RepositoryError, UserError},
6 object_backend::ObjectBackend,
7 repository::{
8 Commit, DefaultBranch, Description, LatestCommit, Repository,
9 RepositoryCommitBeforeRequest, RepositoryDiff, RepositoryDiffRequest, RepositoryFile,
10 RepositoryFileFromIdRequest, RepositoryFileInspectRequest, RepositoryInfoRequest,
11 RepositorySummary, RepositoryView, Visibility,
12 },
13 settings::{AnySetting, GetSetting, GetSettingError, SetSetting, SetSettingError},
14 user::{User, UserRepositoriesRequest},
15 value::{AnyValue, GetValue},
16 };
17 use giterated_stack::{BackendWrapper, StackOperationState};
18
19 use super::DatabaseBackend;
20
21 pub fn user_get_repositories(
22 object: &User,
23 _operation: UserRepositoriesRequest,
24 state: DatabaseBackend,
25 ) -> BoxFuture<'static, Result<Vec<RepositorySummary>, OperationError<UserError>>> {
26 let object = object.clone();
27
28 async move {
29 let mut user_backend = state.user_backend.lock().await;
30 let repositories = user_backend
31 .repositories_for_user(None, &object)
32 .await
33 .map_err(|e| OperationError::Internal(e.to_string()))?;
34
35 Ok(repositories)
36 }
37 .boxed()
38 }
39
40 pub fn user_get_value(
41 object: &User,
42 operation: GetValue<AnyValue<User>>,
43 state: DatabaseBackend,
44 ) -> BoxFuture<'static, Result<AnyValue<User>, OperationError<GetValueError>>> {
45 let object = object.clone();
46
47 async move {
48 let mut user_backend = state.user_backend.lock().await;
49 let value = user_backend
50 .get_value(&object, &operation.value_name)
51 .await
52 .map_err(|e| OperationError::Internal(e.to_string()))?;
53
54 Ok(value)
55 }
56 .boxed()
57 }
58
59 pub fn user_get_setting(
60 object: &User,
61 operation: GetSetting<AnySetting>,
62 state: DatabaseBackend,
63 ) -> BoxFuture<'static, Result<AnySetting, OperationError<GetSettingError>>> {
64 let object = object.clone();
65
66 async move {
67 let mut user_backend = state.user_backend.lock().await;
68 let value = user_backend
69 .get_setting(&object, &operation.setting_name)
70 .await
71 .map_err(|e| OperationError::Internal(e.to_string()))?;
72
73 Ok(value)
74 }
75 .boxed()
76 }
77
78 pub fn user_set_setting(
79 object: &User,
80 operation: SetSetting<AnySetting>,
81 state: DatabaseBackend,
82 ) -> BoxFuture<'static, Result<(), OperationError<SetSettingError>>> {
83 let object = object.clone();
84
85 async move {
86 let mut user_backend = state.user_backend.lock().await;
87 let value = user_backend
88 .write_setting(&object, &operation.setting_name, &operation.value.0)
89 .await
90 .map_err(|e| OperationError::Internal(e.to_string()))?;
91
92 Ok(value)
93 }
94 .boxed()
95 }
96
97 pub fn repository_info(
98 object: &Repository,
99 operation: RepositoryInfoRequest,
100 state: DatabaseBackend,
101 operation_state: StackOperationState,
102 backend: BackendWrapper,
103 ) -> BoxFuture<'static, Result<RepositoryView, OperationError<RepositoryError>>> {
104 let object = object.clone();
105
106 async move {
107 let mut object = backend
108 .get_object::<Repository>(&object.to_string(), &operation_state)
109 .await
110 .unwrap();
111
112 let mut repository_backend = state.repository_backend.lock().await;
113 let tree = repository_backend
114 .repository_file_inspect(
115 None,
116 object.object(),
117 &RepositoryFileInspectRequest {
118 extra_metadata: operation.extra_metadata,
119 path: operation.path,
120 rev: operation.rev.clone(),
121 },
122 )
123 .await
124 .map_err(|err| OperationError::Internal(format!("{:?}", err)))?;
125 drop(repository_backend);
126
127 let info = RepositoryView {
128 name: object.object().name.clone(),
129 owner: object.object().owner.clone(),
130 description: object.get::<Description>(&operation_state).await.ok(),
131 visibility: object
132 .get::<Visibility>(&operation_state)
133 .await
134 .map_err(|e| OperationError::Internal(format!("{:?}: {}", e.source(), e)))?,
135 default_branch: object
136 .get::<DefaultBranch>(&operation_state)
137 .await
138 .map_err(|e| OperationError::Internal(format!("{:?}: {}", e.source(), e)))?,
139 // TODO: Can't be a simple get function, this needs to be returned alongside the tree as this differs depending on the rev and path.
140 latest_commit: object.get::<LatestCommit>(&operation_state).await.ok(),
141 tree_rev: operation.rev,
142 tree,
143 };
144
145 Ok(info)
146 }
147 .boxed()
148 }
149
150 pub fn repository_file_from_id(
151 object: &Repository,
152 operation: RepositoryFileFromIdRequest,
153 state: DatabaseBackend,
154 operation_state: StackOperationState,
155 backend: BackendWrapper,
156 ) -> BoxFuture<'static, Result<RepositoryFile, OperationError<RepositoryError>>> {
157 let object = object.clone();
158
159 async move {
160 let object = backend
161 .get_object::<Repository>(&object.to_string(), &operation_state)
162 .await
163 .unwrap();
164
165 let mut repository_backend = state.repository_backend.lock().await;
166 let file = repository_backend
167 .repository_file_from_id(
168 None,
169 object.object(),
170 &RepositoryFileFromIdRequest(operation.0),
171 )
172 .await
173 .map_err(|err| OperationError::Internal(format!("{:?}", err)))?;
174 drop(repository_backend);
175
176 Ok(file)
177 }
178 .boxed()
179 }
180
181 pub fn repository_diff(
182 object: &Repository,
183 operation: RepositoryDiffRequest,
184 state: DatabaseBackend,
185 operation_state: StackOperationState,
186 backend: BackendWrapper,
187 ) -> BoxFuture<'static, Result<RepositoryDiff, OperationError<RepositoryError>>> {
188 let object = object.clone();
189
190 async move {
191 let object = backend
192 .get_object::<Repository>(&object.to_string(), &operation_state)
193 .await
194 .unwrap();
195
196 let mut repository_backend = state.repository_backend.lock().await;
197 let file = repository_backend
198 .repository_diff(None, object.object(), &operation)
199 .await
200 .map_err(|err| OperationError::Internal(format!("{:?}", err)))?;
201 drop(repository_backend);
202
203 Ok(file)
204 }
205 .boxed()
206 }
207
208 pub fn repository_commit_before(
209 object: &Repository,
210 operation: RepositoryCommitBeforeRequest,
211 state: DatabaseBackend,
212 operation_state: StackOperationState,
213 backend: BackendWrapper,
214 ) -> BoxFuture<'static, Result<Commit, OperationError<RepositoryError>>> {
215 let object = object.clone();
216
217 async move {
218 let object = backend
219 .get_object::<Repository>(&object.to_string(), &operation_state)
220 .await
221 .unwrap();
222
223 let mut repository_backend = state.repository_backend.lock().await;
224 let file = repository_backend
225 .repository_commit_before(None, object.object(), &operation)
226 .await
227 .map_err(|err| OperationError::Internal(format!("{:?}", err)))?;
228 drop(repository_backend);
229
230 Ok(file)
231 }
232 .boxed()
233 }
234
235 pub fn repository_get_value(
236 object: &Repository,
237 operation: GetValue<AnyValue<Repository>>,
238 state: DatabaseBackend,
239 ) -> BoxFuture<'static, Result<AnyValue<Repository>, OperationError<GetValueError>>> {
240 let object = object.clone();
241
242 async move {
243 let mut repository_backend = state.repository_backend.lock().await;
244 let value = repository_backend
245 .get_value(&object, &operation.value_name)
246 .await
247 .map_err(|e| {
248 OperationError::Internal(format!("error getting value: {}", e.to_string()))
249 })?;
250
251 Ok(value)
252 }
253 .boxed()
254 }
255
256 pub fn repository_get_setting(
257 object: &Repository,
258 operation: GetSetting<AnySetting>,
259 state: DatabaseBackend,
260 ) -> BoxFuture<'static, Result<AnySetting, OperationError<GetSettingError>>> {
261 let object = object.clone();
262
263 async move {
264 let mut repository_backend = state.repository_backend.lock().await;
265 let value = repository_backend
266 .get_setting(&object, &operation.setting_name)
267 .await
268 .map_err(|e| OperationError::Internal(e.to_string()))?;
269
270 Ok(value)
271 }
272 .boxed()
273 }
274
275 pub fn repository_set_setting(
276 object: &Repository,
277 operation: SetSetting<AnySetting>,
278 state: DatabaseBackend,
279 ) -> BoxFuture<'static, Result<(), OperationError<SetSettingError>>> {
280 let object = object.clone();
281
282 async move {
283 let mut repository_backend = state.repository_backend.lock().await;
284 let value = repository_backend
285 .write_setting(&object, &operation.setting_name, &operation.value.0)
286 .await
287 .map_err(|e| OperationError::Internal(e.to_string()))?;
288
289 Ok(value)
290 }
291 .boxed()
292 }
293