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-models/src/instance/operations.rs⁩ - ⁨5994⁩ bytes
Raw
1 use secrecy::Secret;
2 use serde::{Deserialize, Serialize};
3
4 use crate::{
5 authenticated::UserAuthenticationToken,
6 error::{InstanceError, OperationError},
7 object::Object,
8 object_backend::ObjectBackend,
9 operation::GiteratedOperation,
10 repository::{Repository, RepositoryVisibility},
11 user::{Password, User},
12 };
13
14 use super::Instance;
15
16 /// An account registration request.
17 ///
18 /// # Authentication
19 /// - Instance Authentication
20 /// - **ONLY ACCEPTED WHEN SAME-INSTANCE**
21 #[derive(Clone, Debug, Serialize, Deserialize)]
22 pub struct RegisterAccountRequest {
23 pub username: String,
24 pub email: Option<String>,
25 pub password: Secret<Password>,
26 }
27
28 impl GiteratedOperation<Instance> for RegisterAccountRequest {
29 type Success = UserAuthenticationToken;
30 type Failure = InstanceError;
31 }
32
33 #[derive(Clone, Debug, Serialize, Deserialize)]
34 pub struct RegisterAccountResponse {
35 pub token: String,
36 }
37
38 /// An authentication token request.
39 ///
40 /// AKA Login Request
41 ///
42 /// # Authentication
43 /// - Instance Authentication
44 /// - Identifies the Instance to issue the token for
45 /// # Authorization
46 /// - Credentials ([`crate::backend::AuthBackend`]-based)
47 /// - Identifies the User account to issue a token for
48 /// - Decrypts user private key to issue to
49 #[derive(Clone, Debug, Serialize, Deserialize)]
50 pub struct AuthenticationTokenRequest {
51 pub instance: Instance,
52 pub username: String,
53 pub password: Secret<Password>,
54 }
55
56 impl GiteratedOperation<Instance> for AuthenticationTokenRequest {
57 type Success = UserAuthenticationToken;
58 type Failure = InstanceError;
59 }
60
61 /// An authentication token extension request.
62 ///
63 /// # Authentication
64 /// - Instance Authentication
65 /// - Identifies the Instance to issue the token for
66 /// - User Authentication
67 /// - Authenticates the validity of the token
68 /// # Authorization
69 /// - Token-based
70 /// - Validates authorization using token's authenticity
71 #[derive(Clone, Debug, Serialize, Deserialize)]
72 pub struct TokenExtensionRequest {
73 pub token: UserAuthenticationToken,
74 }
75
76 impl GiteratedOperation<Instance> for TokenExtensionRequest {
77 type Success = Option<UserAuthenticationToken>;
78 type Failure = InstanceError;
79 }
80
81 /// A request to create a repository.
82 ///
83 /// # Authentication
84 /// - Instance Authentication
85 /// - Used to validate User token `issued_for`
86 /// - User Authentication
87 /// - Used to source owning user
88 /// - Used to authorize user token against user's instance
89 /// # Authorization
90 /// - Instance Authorization
91 /// - Used to authorize action using User token requiring a correct `issued_for` and valid issuance from user's instance
92 /// - User Authorization
93 /// - Potential User permissions checks
94 #[derive(Clone, Debug, Serialize, Deserialize)]
95 pub struct RepositoryCreateRequest {
96 pub instance: Option<Instance>,
97 pub name: String,
98 pub description: Option<String>,
99 pub visibility: RepositoryVisibility,
100 pub default_branch: String,
101 pub owner: User,
102 }
103
104 impl GiteratedOperation<Instance> for RepositoryCreateRequest {
105 type Success = Repository;
106 type Failure = InstanceError;
107 }
108
109 impl<S: Clone + Send + Sync, B: ObjectBackend<S> + std::fmt::Debug> Object<'_, S, Instance, B> {
110 pub async fn register_account(
111 &mut self,
112 email: Option<&str>,
113 username: &str,
114 password: &Secret<Password>,
115 operation_state: &S,
116 ) -> Result<UserAuthenticationToken, OperationError<InstanceError>> {
117 self.request::<RegisterAccountRequest>(
118 RegisterAccountRequest {
119 username: username.to_string(),
120 email: email.map(|s| s.to_string()),
121 password: password.clone(),
122 },
123 operation_state,
124 )
125 .await
126 }
127
128 pub async fn authentication_token(
129 &mut self,
130 username: &str,
131 password: &Secret<Password>,
132 operation_state: &S,
133 ) -> Result<UserAuthenticationToken, OperationError<InstanceError>> {
134 self.request::<AuthenticationTokenRequest>(
135 AuthenticationTokenRequest {
136 instance: self.inner.clone(),
137 username: username.to_string(),
138 password: password.clone(),
139 },
140 operation_state,
141 )
142 .await
143 }
144
145 pub async fn authentication_token_for(
146 &mut self,
147 instance: &Instance,
148 username: &str,
149 password: &Secret<Password>,
150 operation_state: &S,
151 ) -> Result<UserAuthenticationToken, OperationError<InstanceError>> {
152 self.request::<AuthenticationTokenRequest>(
153 AuthenticationTokenRequest {
154 instance: instance.clone(),
155 username: username.to_string(),
156 password: password.clone(),
157 },
158 operation_state,
159 )
160 .await
161 }
162
163 pub async fn token_extension(
164 &mut self,
165 token: &UserAuthenticationToken,
166 operation_state: &S,
167 ) -> Result<Option<UserAuthenticationToken>, OperationError<InstanceError>> {
168 self.request::<TokenExtensionRequest>(
169 TokenExtensionRequest {
170 token: token.clone(),
171 },
172 operation_state,
173 )
174 .await
175 }
176
177 pub async fn create_repository(
178 &mut self,
179 instance: &Instance,
180 name: &str,
181 visibility: &RepositoryVisibility,
182 default_branch: &str,
183 owner: &User,
184 operation_state: &S,
185 ) -> Result<Repository, OperationError<InstanceError>> {
186 self.request::<RepositoryCreateRequest>(
187 RepositoryCreateRequest {
188 instance: Some(instance.clone()),
189 name: name.to_string(),
190 description: None,
191 visibility: visibility.clone(),
192 default_branch: default_branch.to_string(),
193 owner: owner.clone(),
194 },
195 operation_state,
196 )
197 .await
198 }
199 }
200