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

ambee/giterated

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

Add authentication operations

Amber - ⁨2⁩ years ago

parent: tbd commit: ⁨c27b4f3

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