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

ambee/giterated

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

Major refactor to handler traits

Added `IntoGiteratedHandler`, which is the new trait for handler functions. This allows us to finally get rid of the Object and ObjectOperation bounds that resulted in hacks around the newer features of the unified stack. Squashed commit of the following: commit 62e1ecf76ee31cda0bab4602d9d00fa0dc2f9158 Author: Amber <[email protected]> Date: Wed Oct 11 09:31:11 2023 -0500 Update commit dfd2d1b0b5d81ee3bc48f0321c6aceaa677e3b8b Author: Amber <[email protected]> Date: Wed Oct 11 09:31:07 2023 -0500 Major refactor to handler traits Added `IntoGiteratedHandler`, which is the new trait for handler functions. This allows us to finally get rid of the Object and ObjectOperation bounds that resulted in hacks around the newer features of the unified stack. Removed dead and legacy code. I think... commit 57b4b398eff32e69f2f4b9700e42a1277a4d1055 Author: Amber <[email protected]> Date: Sun Oct 1 23:05:10 2023 -0500 New handler trait for giterated stack Refactor the old handler trait so it is more generic and can be used for specific kinds of handlers

Amber - ⁨2⁩ years ago

parent: tbd commit: ⁨90c4780

⁨giterated-stack/src/lib.rs⁩ - ⁨12491⁩ bytes
Raw
1 mod handler;
2 pub use handler::*;
3 mod meta;
4 pub use meta::*;
5 pub mod provider;
6 mod stack;
7 pub use stack::*;
8 mod substack;
9 use serde::{de::DeserializeOwned, Deserialize, Serialize};
10 pub use stack::*;
11 pub use substack::*;
12 pub mod state;
13 pub mod update;
14
15 use std::{any::Any, convert::Infallible, ops::Deref, sync::Arc};
16
17 use core::fmt::Debug;
18 use giterated_models::{
19 error::{ExtractorError, UnauthorizedError},
20 instance::{
21 AuthenticationTokenRequest, Instance, RegisterAccountRequest, RepositoryCreateRequest,
22 },
23 object::GiteratedObject,
24 object_backend::ObjectBackend,
25 operation::GiteratedOperation,
26 repository::{AccessList, Repository},
27 settings::{GetSetting, SetSetting, Setting},
28 user::User,
29 value::{GetValue, GiteratedObjectValue},
30 };
31
32 #[derive(Clone, Debug, Hash, Eq, PartialEq)]
33 pub struct ObjectOperationPair<'a> {
34 pub object_name: &'a str,
35 pub operation_name: &'a str,
36 }
37
38 impl ObjectOperationPair<'static> {
39 #[allow(unused)]
40 pub fn from_types<O: GiteratedObject, D: GiteratedOperation<O>>() -> Self {
41 Self {
42 object_name: O::object_name(),
43 operation_name: D::operation_name(),
44 }
45 }
46 }
47
48 #[derive(Clone, Debug, Hash, Eq, PartialEq)]
49 pub struct ObjectValuePair<'a> {
50 pub object_kind: &'a str,
51 pub value_kind: &'a str,
52 }
53
54 impl ObjectValuePair<'static> {
55 pub fn from_types<O: GiteratedObject, V: GiteratedObjectValue<Object = O>>() -> Self {
56 Self {
57 object_kind: O::object_name(),
58 value_kind: V::value_name(),
59 }
60 }
61 }
62
63 #[derive(Clone, Debug, Hash, Eq, PartialEq)]
64 pub struct ObjectSettingPair<'a> {
65 pub object_kind: &'a str,
66 pub setting_name: &'a str,
67 }
68
69 impl ObjectSettingPair<'static> {
70 pub fn from_types<O: GiteratedObject, S: Setting>() -> Self {
71 Self {
72 object_kind: O::object_name(),
73 setting_name: S::name(),
74 }
75 }
76 }
77
78 #[async_trait::async_trait(?Send)]
79 pub trait FromOperationState<O: GiteratedObject, D: GiteratedOperation<O>>: Sized + Clone {
80 type Error: Into<anyhow::Error>;
81
82 async fn from_state(
83 object: &O,
84 operation: &D,
85 state: &StackOperationState,
86 ) -> Result<Self, ExtractorError<Self::Error>>;
87 }
88
89 #[async_trait::async_trait(?Send)]
90 impl<O: GiteratedObject, D: GiteratedOperation<O>> FromOperationState<O, D>
91 for StackOperationState
92 {
93 type Error = Infallible;
94
95 async fn from_state(
96 _object: &O,
97 _operation: &D,
98 state: &StackOperationState,
99 ) -> Result<StackOperationState, ExtractorError<Infallible>> {
100 Ok(state.clone())
101 }
102 }
103
104 #[derive(Debug, thiserror::Error, Serialize, Deserialize)]
105 #[error("missing value")]
106 pub struct MissingValue;
107
108 #[async_trait::async_trait(?Send)]
109 impl<O: GiteratedObject, D: GiteratedOperation<O> + Send + Sync> FromOperationState<O, D>
110 for AuthenticatedUser
111 {
112 type Error = MissingValue;
113
114 async fn from_state(
115 _object: &O,
116 _operation: &D,
117 state: &StackOperationState,
118 ) -> Result<AuthenticatedUser, ExtractorError<MissingValue>> {
119 state.user.clone().ok_or(ExtractorError(MissingValue))
120 }
121 }
122
123 #[async_trait::async_trait(?Send)]
124 impl<O: GiteratedObject, D: GiteratedOperation<O> + Send + Sync> FromOperationState<O, D>
125 for AuthenticatedInstance
126 {
127 type Error = MissingValue;
128
129 async fn from_state(
130 _object: &O,
131 _operation: &D,
132 state: &StackOperationState,
133 ) -> Result<AuthenticatedInstance, ExtractorError<MissingValue>> {
134 state.instance.clone().ok_or(ExtractorError(MissingValue))
135 }
136 }
137
138 #[async_trait::async_trait(?Send)]
139 impl<
140 T: FromOperationState<O, D> + Send + Sync,
141 O: GiteratedObject + Sync,
142 D: GiteratedOperation<O> + Send + Sync,
143 > FromOperationState<O, D> for Option<T>
144 {
145 type Error = Infallible;
146
147 async fn from_state(
148 object: &O,
149 operation: &D,
150 state: &StackOperationState,
151 ) -> Result<Option<T>, ExtractorError<Infallible>> {
152 Ok(T::from_state(object, operation, state).await.ok())
153 }
154 }
155
156 #[derive(Clone)]
157 pub struct AuthorizedUser(AuthenticatedUser);
158
159 #[derive(Clone)]
160 pub struct AuthorizedInstance(AuthenticatedInstance);
161
162 #[async_trait::async_trait(?Send)]
163 pub trait AuthorizedOperation<O: GiteratedObject>: GiteratedOperation<O> {
164 type Error: Into<anyhow::Error>;
165
166 async fn authorize(
167 &self,
168 authorize_for: &O,
169 state: &StackOperationState,
170 ) -> Result<bool, ExtractorError<Self::Error>>;
171 }
172
173 #[async_trait::async_trait(?Send)]
174 impl<O: GiteratedObject + Send + Sync + Debug + 'static> AuthorizedOperation<O> for GetValue {
175 type Error = anyhow::Error;
176
177 async fn authorize(
178 &self,
179 authorize_for: &O,
180 operation_state: &StackOperationState,
181 ) -> Result<bool, ExtractorError<anyhow::Error>> {
182 Ok(operation_state
183 .runtime
184 .get_object::<O>(&authorize_for.to_string(), operation_state)
185 .await
186 .is_ok())
187 }
188 }
189
190 #[async_trait::async_trait(?Send)]
191 impl AuthorizedOperation<User> for SetSetting {
192 type Error = MissingValue;
193
194 async fn authorize(
195 &self,
196 authorize_for: &User,
197 operation_state: &StackOperationState,
198 ) -> Result<bool, ExtractorError<MissingValue>> {
199 let authenticated_user = operation_state.user.as_ref().ok_or(MissingValue)?;
200
201 Ok(authorize_for == authenticated_user.deref())
202 }
203 }
204
205 #[async_trait::async_trait(?Send)]
206 impl AuthorizedOperation<User> for GetSetting {
207 type Error = MissingValue;
208
209 async fn authorize(
210 &self,
211 authorize_for: &User,
212 operation_state: &StackOperationState,
213 ) -> Result<bool, ExtractorError<MissingValue>> {
214 let authenticated_user = operation_state.user.as_ref().ok_or(MissingValue)?;
215
216 Ok(authorize_for == authenticated_user.deref())
217 }
218 }
219
220 #[async_trait::async_trait(?Send)]
221 impl AuthorizedOperation<Repository> for SetSetting {
222 type Error = anyhow::Error;
223
224 async fn authorize(
225 &self,
226 authorize_for: &Repository,
227 operation_state: &StackOperationState,
228 ) -> Result<bool, ExtractorError<anyhow::Error>> {
229 let authenticated_user = operation_state
230 .user
231 .as_ref()
232 .ok_or_else(|| anyhow::Error::from(MissingValue))?;
233
234 let mut object = operation_state
235 .runtime
236 .get_object::<Repository>(&authorize_for.to_string(), operation_state)
237 .await
238 .map_err(anyhow::Error::from)?;
239
240 let access_list = object
241 .get_setting::<AccessList>(operation_state)
242 .await
243 .map_err(anyhow::Error::from)?;
244
245 if access_list
246 .0
247 .iter()
248 .any(|user| user == authenticated_user.deref())
249 {
250 Ok(true)
251 } else {
252 Ok(false)
253 }
254 }
255 }
256
257 #[async_trait::async_trait(?Send)]
258 impl AuthorizedOperation<Repository> for GetSetting {
259 type Error = anyhow::Error;
260
261 async fn authorize(
262 &self,
263 authorize_for: &Repository,
264 operation_state: &StackOperationState,
265 ) -> Result<bool, ExtractorError<anyhow::Error>> {
266 let authenticated_user = operation_state
267 .user
268 .as_ref()
269 .ok_or_else(|| anyhow::Error::from(MissingValue))?;
270
271 let mut object = operation_state
272 .runtime
273 .get_object::<Repository>(&authorize_for.to_string(), operation_state)
274 .await
275 .map_err(anyhow::Error::from)?;
276
277 let access_list = object
278 .get_setting::<AccessList>(operation_state)
279 .await
280 .map_err(anyhow::Error::from)?;
281
282 if access_list
283 .0
284 .iter()
285 .any(|user| user == authenticated_user.deref())
286 {
287 Ok(true)
288 } else {
289 Ok(false)
290 }
291 }
292 }
293
294 #[async_trait::async_trait(?Send)]
295 impl AuthorizedOperation<Instance> for RegisterAccountRequest {
296 type Error = Infallible;
297
298 async fn authorize(
299 &self,
300 authorize_for: &Instance,
301 state: &StackOperationState,
302 ) -> Result<bool, ExtractorError<Infallible>> {
303 if state.our_instance == *authorize_for {
304 Ok(true)
305 } else {
306 Ok(false)
307 }
308 }
309 }
310
311 #[async_trait::async_trait(?Send)]
312 impl AuthorizedOperation<Instance> for AuthenticationTokenRequest {
313 type Error = Infallible;
314
315 async fn authorize(
316 &self,
317 authorize_for: &Instance,
318 state: &StackOperationState,
319 ) -> Result<bool, ExtractorError<Infallible>> {
320 if state.our_instance == *authorize_for {
321 Ok(true)
322 } else {
323 Ok(false)
324 }
325 }
326 }
327
328 #[async_trait::async_trait(?Send)]
329 impl AuthorizedOperation<Instance> for RepositoryCreateRequest {
330 type Error = Infallible;
331
332 async fn authorize(
333 &self,
334 authorize_for: &Instance,
335 state: &StackOperationState,
336 ) -> Result<bool, ExtractorError<Infallible>> {
337 if state.our_instance == *authorize_for {
338 Ok(true)
339 } else {
340 Ok(false)
341 }
342 }
343 }
344
345 #[async_trait::async_trait(?Send)]
346 impl<A: AuthorizedOperation<User> + Send + Sync> FromOperationState<User, A> for AuthorizedUser {
347 type Error = UnauthorizedError;
348
349 async fn from_state(
350 object: &User,
351 operation: &A,
352 state: &StackOperationState,
353 ) -> Result<AuthorizedUser, ExtractorError<UnauthorizedError>> {
354 // TODO
355 let authenticated = AuthenticatedUser::from_state(object, operation, state)
356 .await
357 .map_err(|_| ExtractorError(UnauthorizedError))?;
358
359 match operation.authorize(object, state).await {
360 Ok(authorized) => {
361 assert!(authorized);
362 }
363 Err(_err) => return Err(ExtractorError(UnauthorizedError)),
364 };
365
366 Ok(AuthorizedUser(authenticated))
367 }
368 }
369
370 #[async_trait::async_trait(?Send)]
371 impl<A: AuthorizedOperation<Instance> + Send + Sync> FromOperationState<Instance, A>
372 for AuthorizedInstance
373 {
374 type Error = UnauthorizedError;
375
376 async fn from_state(
377 object: &Instance,
378 operation: &A,
379 state: &StackOperationState,
380 ) -> Result<AuthorizedInstance, ExtractorError<UnauthorizedError>> {
381 //TODO
382 let authenticated = AuthenticatedInstance::from_state(object, operation, state)
383 .await
384 .map_err(|_| ExtractorError(UnauthorizedError))?;
385
386 match operation.authorize(object, state).await {
387 Ok(authorized) => {
388 assert!(authorized);
389 }
390 Err(_err) => return Err(ExtractorError(UnauthorizedError)),
391 };
392
393 Ok(AuthorizedInstance(authenticated))
394 }
395 }
396
397 #[derive(Clone)]
398 pub struct StackOperationState {
399 pub our_instance: Instance,
400 pub runtime: Arc<GiteratedStack>,
401 pub instance: Option<AuthenticatedInstance>,
402 pub user: Option<AuthenticatedUser>,
403 }
404
405 #[derive(Clone, Debug)]
406 pub struct AuthenticatedInstance(Instance);
407
408 impl AuthenticatedInstance {
409 pub fn new(instance: Instance) -> Self {
410 AuthenticatedInstance(instance)
411 }
412 }
413
414 impl Deref for AuthenticatedInstance {
415 type Target = Instance;
416
417 fn deref(&self) -> &Self::Target {
418 &self.0
419 }
420 }
421
422 #[derive(Clone, Debug)]
423 pub struct AuthenticatedUser(User);
424
425 impl AuthenticatedUser {
426 pub fn new(user: User) -> Self {
427 AuthenticatedUser(user)
428 }
429 }
430
431 impl Deref for AuthenticatedUser {
432 type Target = User;
433
434 fn deref(&self) -> &Self::Target {
435 &self.0
436 }
437 }
438
439 #[derive(Clone, Debug, Serialize, Deserialize)]
440 #[serde(transparent)]
441 #[serde(bound(deserialize = "S: DeserializeOwned"))]
442 pub struct SettingUpdate<S: Setting + Serialize + DeserializeOwned>(pub S);
443
444 impl<O, S> GiteratedOperation<O> for SettingUpdate<S>
445 where
446 O: GiteratedObject,
447 S: Setting + Serialize + DeserializeOwned,
448 {
449 type Success = ();
450
451 type Failure = ();
452 }
453
454 #[derive(Clone)]
455 pub struct AnyObject(pub Arc<dyn Any + Send + Sync>);
456
457 #[derive(Clone)]
458 pub struct AnyOperation(pub Arc<dyn Any + Send>);
459
460 #[derive(Clone)]
461 pub struct AnySuccess(pub Arc<dyn Any + Send>);
462
463 #[derive(Clone)]
464 pub struct AnyFailure(pub Arc<dyn Any + Send>);
465
466 #[derive(Clone)]
467 pub struct AnyValue(pub Arc<dyn Any + Send>);
468
469 #[derive(Clone)]
470 pub struct AnySetting(pub Arc<dyn Any + Send + Sync>);
471