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

ambee/giterated

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

Re-expose Operation State in generics.

This is the worst code I have ever written. I hate the way this changes everything. ugh.

Amber - ⁨2⁩ years ago

parent: tbd commit: ⁨90db3e2

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