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

ambee/giterated

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

Fix handling stack

Amber - ⁨2⁩ years ago

parent: tbd commit: ⁨c53b026

Showing ⁨⁨15⁩ changed files⁩ with ⁨⁨182⁩ insertions⁩ and ⁨⁨149⁩ deletions⁩

giterated-daemon/src/backend/git.rs

View file
@@ -5,16 +5,16 @@ use futures_util::StreamExt;
5 5 use giterated_models::instance::{Instance, RepositoryCreateRequest};
6 6
7 7 use giterated_models::repository::{
8 Commit, IssueLabel, Repository, RepositoryDescription, RepositoryFileInspectRequest,
9 RepositoryIssue, RepositoryIssueLabelsRequest, RepositoryIssuesCountRequest,
10 RepositoryIssuesRequest, RepositorySummary, RepositoryTreeEntry, RepositoryVisibility,
11 RepositoryVisibilitySetting, RepositoryObjectType, Description, Visibility, LatestCommit, DefaultBranch,
8 Commit, DefaultBranch, Description, IssueLabel, LatestCommit, Repository,
9 RepositoryFileInspectRequest, RepositoryIssue, RepositoryIssueLabelsRequest,
10 RepositoryIssuesCountRequest, RepositoryIssuesRequest, RepositoryObjectType,
11 RepositoryTreeEntry, RepositoryVisibility, Visibility,
12 12 };
13 13 use giterated_models::settings::{AnySetting, Setting};
14 14 use giterated_models::user::{User, UserParseError};
15 15 use giterated_models::value::{AnyValue, GiteratedObjectValue};
16 16 use serde_json::Value;
17 use sqlx::{Either, PgPool};
17 use sqlx::PgPool;
18 18 use std::{
19 19 path::{Path, PathBuf},
20 20 sync::Arc,
@@ -296,24 +296,13 @@ impl RepositoryBackend for GitBackend {
296 296 ) -> Result<AnyValue<Repository>, Error> {
297 297 Ok(unsafe {
298 298 if name == Description::value_name() {
299 info!("Description");
300 AnyValue::from_raw(
301 self.get_setting(repository, RepositoryDescription::name())
302 .await?
303 .0,
304 )
299 AnyValue::from_raw(self.get_setting(repository, Description::name()).await?.0)
305 300 } else if name == Visibility::value_name() {
306 AnyValue::from_raw(
307 self.get_setting(repository, RepositoryVisibilitySetting::name())
308 .await?
309 .0,
310 )
301 AnyValue::from_raw(self.get_setting(repository, Visibility::name()).await?.0)
311 302 } else if name == DefaultBranch::value_name() {
312 AnyValue::from_raw(
313 self.get_setting(repository, DefaultBranch::name())
314 .await?
315 .0,
316 )
303 AnyValue::from_raw(self.get_setting(repository, DefaultBranch::name()).await?.0)
304 } else if name == LatestCommit::value_name() {
305 AnyValue::from_raw(serde_json::to_value(LatestCommit(None)).unwrap())
317 306 } else {
318 307 return Err(UserParseError.into());
319 308 }
@@ -645,14 +634,6 @@ impl RepositoryBackend for GitBackend {
645 634
646 635 Ok(tree)
647 636 }
648
649 async fn repositories_for_user(
650 &mut self,
651 requester: Option<&User>,
652 user: &User,
653 ) -> Result<Vec<RepositorySummary>, Error> {
654 unimplemented!();
655 }
656 637 }
657 638
658 639 impl IssuesBackend for GitBackend {

giterated-daemon/src/backend/mod.rs

View file
@@ -37,11 +37,6 @@ pub trait RepositoryBackend {
37 37 repository: &Repository,
38 38 request: &RepositoryFileInspectRequest,
39 39 ) -> Result<Vec<RepositoryTreeEntry>, Error>;
40 async fn repositories_for_user(
41 &mut self,
42 requester: Option<&User>,
43 user: &User,
44 ) -> Result<Vec<RepositorySummary>, Error>;
45 40 async fn get_value(
46 41 &mut self,
47 42 user: &Repository,
@@ -100,6 +95,11 @@ pub trait UserBackend: AuthBackend {
100 95 setting: &Value,
101 96 ) -> Result<(), Error>;
102 97 async fn exists(&mut self, user: &User) -> Result<bool, Error>;
98 async fn repositories_for_user(
99 &mut self,
100 requester: Option<&User>,
101 user: &User,
102 ) -> Result<Vec<RepositorySummary>, Error>;
103 103 }
104 104
105 105 #[async_trait::async_trait]

giterated-daemon/src/backend/settings.rs

View file
@@ -49,7 +49,7 @@ impl MetadataBackend for DatabaseSettings {
49 49 let row = sqlx::query_as!(
50 50 RepositorySettingRow,
51 51 "SELECT * FROM repository_settings WHERE repository = $1 AND name = $2",
52 format!("{}/{}", repository.owner, repository.name),
52 repository.to_string(),
53 53 name
54 54 )
55 55 .fetch_one(&self.pg_pool)

giterated-daemon/src/backend/user.rs

View file
@@ -1,10 +1,12 @@
1 1 use anyhow::Error;
2 use futures_util::StreamExt;
2 3 use giterated_models::authenticated::UserAuthenticationToken;
3 4
4 5 use giterated_models::instance::{AuthenticationTokenRequest, Instance, RegisterAccountRequest};
5 6
7 use giterated_models::repository::{Repository, RepositorySummary};
6 8 use giterated_models::settings::{AnySetting, Setting};
7 use giterated_models::user::{User, UserBio, UserDisplayName, UserParseError};
9 use giterated_models::user::{Bio, DisplayName, User, UserParseError};
8 10 use giterated_models::value::AnyValue;
9 11 use std::sync::Arc;
10 12
@@ -20,10 +22,11 @@ use rsa::{
20 22
21 23 use secrecy::ExposeSecret;
22 24 use serde_json::Value;
23 use sqlx::PgPool;
25 use sqlx::{Either, PgPool};
24 26 use tokio::sync::Mutex;
25 27
26 28 use crate::authentication::AuthenticationTokenGranter;
29 use crate::backend::git::GitRepository;
27 30
28 31 use super::{AuthBackend, MetadataBackend, UserBackend};
29 32
@@ -55,11 +58,9 @@ impl UserBackend for UserAuth {
55 58 async fn get_value(&mut self, user: &User, name: &str) -> Result<AnyValue<User>, Error> {
56 59 Ok(match name {
57 60 "display_name" => unsafe {
58 AnyValue::from_raw(self.get_setting(user, UserDisplayName::name()).await?.0)
59 },
60 "bio" => unsafe {
61 AnyValue::from_raw(self.get_setting(user, UserBio::name()).await?.0)
61 AnyValue::from_raw(self.get_setting(user, DisplayName::name()).await?.0)
62 62 },
63 "bio" => unsafe { AnyValue::from_raw(self.get_setting(user, Bio::name()).await?.0) },
63 64 _ => {
64 65 return Err(UserParseError.into());
65 66 }
@@ -94,6 +95,37 @@ impl UserBackend for UserAuth {
94 95 .await
95 96 .is_ok())
96 97 }
98
99 async fn repositories_for_user(
100 &mut self,
101 _requester: Option<&User>,
102 user: &User,
103 ) -> Result<Vec<RepositorySummary>, Error> {
104 let mut repositories = sqlx::query_as!(
105 GitRepository,
106 r#"SELECT owner_user, name, description, visibility as "visibility: _", default_branch FROM repositories WHERE owner_user = $1"#,
107 user.to_string()
108 )
109 .fetch_many(&self.pg_pool);
110
111 let mut return_repositories = vec![];
112
113 while let Some(Ok(Either::Right(repository_row))) = repositories.next().await {
114 return_repositories.push(RepositorySummary {
115 repository: Repository {
116 owner: repository_row.owner_user.clone(),
117 name: repository_row.name,
118 instance: self.this_instance.clone(),
119 },
120 owner: repository_row.owner_user,
121 visibility: repository_row.visibility,
122 description: repository_row.description,
123 last_commit: None,
124 })
125 }
126
127 Ok(return_repositories)
128 }
97 129 }
98 130
99 131 #[async_trait::async_trait]
@@ -183,7 +215,6 @@ impl AuthBackend for UserAuth {
183 215 source: &Instance,
184 216 request: AuthenticationTokenRequest,
185 217 ) -> Result<UserAuthenticationToken, Error> {
186 info!("fetching!");
187 218 let user = sqlx::query_as!(
188 219 UserRow,
189 220 r#"SELECT * FROM users WHERE username = $1"#,
@@ -198,7 +229,6 @@ impl AuthBackend for UserAuth {
198 229 .verify_password(request.password.expose_secret().0.as_bytes(), &hash)
199 230 .is_err()
200 231 {
201 info!("invalid password");
202 232 return Err(Error::from(AuthenticationError::InvalidPassword));
203 233 }
204 234

giterated-daemon/src/cache_backend.rs

View file
@@ -14,8 +14,8 @@ impl ObjectBackend for CacheBackend {
14 14 async fn object_operation<O: GiteratedObject + Debug, D: GiteratedOperation<O> + Debug>(
15 15 &self,
16 16 _object: O,
17 operation: &str,
18 payload: D,
17 _operation: &str,
18 _payload: D,
19 19 ) -> Result<D::Success, OperationError<D::Failure>> {
20 20 // We don't handle operations with this backend
21 21 Err(OperationError::Unhandled)

giterated-daemon/src/connection/wrapper.rs

View file
@@ -6,7 +6,7 @@ use std::{
6 6 use anyhow::Error;
7 7 use futures_util::{SinkExt, StreamExt};
8 8
9 use giterated_models::instance::Instance;
9 use giterated_models::{error::OperationError, instance::Instance};
10 10
11 11 use giterated_models::object_backend::ObjectBackend;
12 12
@@ -87,12 +87,23 @@ pub async fn connection_wrapper(
87 87 .object_operation(message.object, &message.operation, message.payload)
88 88 .await;
89 89
90 // Map result to Vec<u8> on both
91 let result = match result {
92 Ok(result) => Ok(serde_json::to_vec(&result).unwrap()),
93 Err(err) => Err(match err {
94 OperationError::Operation(err) => {
95 OperationError::Operation(serde_json::to_vec(&err).unwrap())
96 }
97 OperationError::Internal(err) => OperationError::Internal(err),
98 OperationError::Unhandled => OperationError::Unhandled,
99 }),
100 };
101
90 102 let mut socket = connection_state.socket.lock().await;
91 103 let _ = socket
92 104 .send(Message::Binary(bincode::serialize(&result).unwrap()))
93 105 .await;
94 106
95 info!("Done!");
96 107 drop(socket);
97 108 }
98 109 _ => {

giterated-daemon/src/database_backend/handler.rs

View file
@@ -1,14 +1,18 @@
1 use std::{collections::HashMap, pin::Pin, sync::Arc};
1 use std::{collections::HashMap, error::Error, pin::Pin, sync::Arc};
2 2
3 3 use futures_util::{future::BoxFuture, Future, FutureExt};
4 4 use giterated_models::{
5 error::{GetValueError, OperationError, UserError, RepositoryError},
5 error::{GetValueError, OperationError, RepositoryError, UserError},
6 6 object::{AnyObject, GiteratedObject},
7 object_backend::ObjectBackend,
7 8 operation::{AnyOperation, GiteratedOperation},
8 repository::{Repository, RepositorySummary, RepositoryInfoRequest, RepositoryView, Description, Visibility, DefaultBranch, LatestCommit, RepositoryFileInspectRequest},
9 repository::{
10 DefaultBranch, Description, LatestCommit, Repository, RepositoryFileInspectRequest,
11 RepositoryInfoRequest, RepositorySummary, RepositoryView, Visibility,
12 },
9 13 settings::{AnySetting, GetSetting, GetSettingError, SetSetting, SetSettingError},
10 14 user::{User, UserRepositoriesRequest},
11 value::{AnyValue, GetValue}, object_backend::ObjectBackend,
15 value::{AnyValue, GetValue},
12 16 };
13 17
14 18 use super::DatabaseBackend;
@@ -122,14 +126,14 @@ impl<S: Send + Sync + Clone + 'static> OperationWrapper<S> {
122 126
123 127 pub fn user_get_repositories(
124 128 object: &User,
125 operation: UserRepositoriesRequest,
129 _operation: UserRepositoriesRequest,
126 130 state: DatabaseBackend,
127 131 ) -> BoxFuture<'static, Result<Vec<RepositorySummary>, OperationError<UserError>>> {
128 132 let object = object.clone();
129 133
130 134 async move {
131 let mut repositories_backend = state.repository_backend.lock().await;
132 let repositories = repositories_backend
135 let mut user_backend = state.user_backend.lock().await;
136 let repositories = user_backend
133 137 .repositories_for_user(None, &object)
134 138 .await
135 139 .map_err(|e| OperationError::Internal(e.to_string()))?;
@@ -199,26 +203,50 @@ pub fn user_set_setting(
199 203 pub fn repository_info(
200 204 object: &Repository,
201 205 operation: RepositoryInfoRequest,
202 state: DatabaseBackend
206 state: DatabaseBackend,
203 207 ) -> BoxFuture<'static, Result<RepositoryView, OperationError<RepositoryError>>> {
204 208 let object = object.clone();
205 209
206 210 async move {
207 let mut object = state.get_object::<Repository>(&object.to_string()).await.unwrap();
211 let mut object = state
212 .get_object::<Repository>(&object.to_string())
213 .await
214 .unwrap();
208 215
209 216 let mut repository_backend = state.repository_backend.lock().await;
210 let tree = repository_backend.repository_file_inspect(None, object.object(), &RepositoryFileInspectRequest {
211 extra_metadata: operation.extra_metadata,
212 path: operation.path,
213 rev: operation.rev.clone(),
214 }).await.map_err(|err| OperationError::Internal(format!("{:?}", err)))?;
215
217 let tree = repository_backend
218 .repository_file_inspect(
219 None,
220 object.object(),
221 &RepositoryFileInspectRequest {
222 extra_metadata: operation.extra_metadata,
223 path: operation.path,
224 rev: operation.rev.clone(),
225 },
226 )
227 .await
228 .map_err(|err| OperationError::Internal(format!("{:?}", err)))?;
229 drop(repository_backend);
230
231 let _visibility = object.get::<Visibility>().await.map_err(|e| {
232 OperationError::Internal(format!("{:?}: {}", e.source(), e.to_string()))
233 })?;
234 let _default_branch = object.get::<DefaultBranch>().await.map_err(|e| {
235 OperationError::Internal(format!("{:?}: {}", e.source(), e.to_string()))
236 })?;
237
216 238 let info = RepositoryView {
217 239 name: object.object().name.clone(),
218 240 owner: object.object().owner.clone(),
219 241 description: object.get::<Description>().await.ok(),
220 visibility: object.get::<Visibility>().await.map_err(|e| OperationError::Internal(e.to_string()))?,
221 default_branch: object.get::<DefaultBranch>().await.map_err(|e| OperationError::Internal(e.to_string()))?,
242 visibility: object
243 .get::<Visibility>()
244 .await
245 .map_err(|e| OperationError::Internal(e.to_string()))?,
246 default_branch: object
247 .get::<DefaultBranch>()
248 .await
249 .map_err(|e| OperationError::Internal(e.to_string()))?,
222 250 // 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.
223 251 latest_commit: object.get::<LatestCommit>().await.ok(),
224 252 tree_rev: operation.rev,
@@ -242,7 +270,9 @@ pub fn repository_get_value(
242 270 let value = repository_backend
243 271 .get_value(&object, &operation.value_name)
244 272 .await
245 .map_err(|e| OperationError::Internal(e.to_string()))?;
273 .map_err(|e| {
274 OperationError::Internal(format!("error getting value: {}", e.to_string()))
275 })?;
246 276
247 277 Ok(value)
248 278 }

giterated-daemon/src/database_backend/mod.rs

View file
@@ -1,15 +1,14 @@
1 1 pub mod handler;
2 2
3 use std::any::type_name;
4 3 use std::{str::FromStr, sync::Arc};
5 4
6 5 use giterated_models::error::OperationError;
7 6 use giterated_models::instance::Instance;
8 7 use giterated_models::object::{
9 AnyObject, GiteratedObject, Object, ObjectRequest, ObjectRequestError, ObjectResponse,
8 AnyObject, GiteratedObject, Object, ObjectRequest, ObjectRequestError,
10 9 };
11 10 use giterated_models::object_backend::ObjectBackend;
12 use giterated_models::operation::{AnyOperation, GiteratedOperation};
11 use giterated_models::operation::GiteratedOperation;
13 12 use giterated_models::repository::Repository;
14 13 use giterated_models::user::User;
15 14 use std::fmt::Debug;
@@ -18,8 +17,8 @@ use tokio::sync::Mutex;
18 17 use crate::backend::{RepositoryBackend, UserBackend};
19 18
20 19 use self::handler::{
21 repository_get_setting, repository_get_value, repository_set_setting, user_get_repositories,
22 user_get_setting, user_get_value, user_set_setting, OperationHandlers, repository_info,
20 repository_get_setting, repository_get_value, repository_info, repository_set_setting,
21 user_get_repositories, user_get_setting, user_get_value, user_set_setting, OperationHandlers,
23 22 };
24 23
25 24 #[derive(Clone, Debug)]
@@ -30,8 +29,8 @@ impl ObjectBackend for Foobackend {
30 29 async fn object_operation<O: GiteratedObject + Debug, D: GiteratedOperation<O> + Debug>(
31 30 &self,
32 31 _object: O,
33 operation: &str,
34 payload: D,
32 _operation: &str,
33 _payload: D,
35 34 ) -> Result<D::Success, OperationError<D::Failure>> {
36 35 // We don't handle operations with this backend
37 36 Err(OperationError::Unhandled)
@@ -102,10 +101,8 @@ impl ObjectBackend for DatabaseBackend {
102 101 )
103 102 .await
104 103 {
105 Ok(result) => Ok(
106 serde_json::from_slice(&serde_json::to_vec(&result).unwrap())
107 .map_err(|e| OperationError::Internal(e.to_string()))?,
108 ),
104 Ok(result) => Ok(serde_json::from_slice(&result)
105 .map_err(|e| OperationError::Internal(e.to_string()))?),
109 106 Err(err) => match err {
110 107 OperationError::Internal(internal) => Err(OperationError::Internal(internal)),
111 108 OperationError::Unhandled => Err(OperationError::Unhandled),
@@ -133,10 +130,8 @@ impl ObjectBackend for DatabaseBackend {
133 130 )
134 131 .await
135 132 {
136 Ok(result) => Ok(
137 serde_json::from_slice(&serde_json::to_vec(&result).unwrap())
138 .map_err(|e| OperationError::Internal(e.to_string()))?,
139 ),
133 Ok(result) => Ok(serde_json::from_slice(&result)
134 .map_err(|e| OperationError::Internal(e.to_string()))?),
140 135 Err(err) => match err {
141 136 OperationError::Internal(internal) => Err(OperationError::Internal(internal)),
142 137 OperationError::Unhandled => Err(OperationError::Unhandled),
@@ -167,10 +162,8 @@ impl ObjectBackend for DatabaseBackend {
167 162 });
168 163
169 164 match result {
170 Ok(result) => Ok(
171 serde_json::from_slice(&serde_json::to_vec(&result).unwrap())
172 .map_err(|e| OperationError::Internal(e.to_string()))?,
173 ),
165 Ok(result) => Ok(serde_json::from_slice(&result)
166 .map_err(|e| OperationError::Internal(e.to_string()))?),
174 167 Err(err) => match err {
175 168 OperationError::Internal(internal) => {
176 169 Err(OperationError::Internal(internal))
@@ -265,7 +258,7 @@ mod test {
265 258 RepositoryTreeEntry,
266 259 };
267 260 use giterated_models::settings::AnySetting;
268 use giterated_models::user::{DisplayName, User, UserDisplayName};
261 use giterated_models::user::{DisplayName, User};
269 262 use giterated_models::value::{AnyValue, GiteratedObjectValue};
270 263 use serde_json::Value;
271 264 use tokio::sync::Mutex;
@@ -302,6 +295,13 @@ mod test {
302 295 async fn exists(&mut self, user: &User) -> Result<bool, Error> {
303 296 Ok(user == &User::from_str("test_user:test.giterated.dev").unwrap())
304 297 }
298 async fn repositories_for_user(
299 &mut self,
300 requester: Option<&User>,
301 user: &User,
302 ) -> Result<Vec<RepositorySummary>, Error> {
303 todo!()
304 }
305 305 }
306 306
307 307 #[async_trait::async_trait]
@@ -341,14 +341,6 @@ mod test {
341 341 ) -> Result<Vec<RepositoryTreeEntry>, Error> {
342 342 todo!()
343 343 }
344 async fn repositories_for_user(
345 &mut self,
346 _requester: Option<&User>,
347 _user: &User,
348 ) -> Result<Vec<RepositorySummary>, Error> {
349 todo!()
350 }
351
352 344 async fn get_value(
353 345 &mut self,
354 346 _repository: &Repository,
@@ -419,7 +411,7 @@ mod test {
419 411 .await
420 412 .expect("object should have been returned");
421 413
422 user.get_setting::<UserDisplayName>()
414 user.get_setting::<DisplayName>()
423 415 .await
424 416 .expect("object value should have been returned");
425 417 }
@@ -433,7 +425,7 @@ mod test {
433 425 .await
434 426 .expect("object should have been returned");
435 427
436 user.set_setting::<UserDisplayName>(UserDisplayName(String::from("test")))
428 user.set_setting::<DisplayName>(DisplayName(String::from("test")))
437 429 .await
438 430 .expect("object value should have been returned");
439 431 }

giterated-models/src/error.rs

View file
@@ -17,7 +17,7 @@ pub enum UserError {}
17 17 #[derive(Debug, thiserror::Error, Serialize, Deserialize)]
18 18 pub enum GetValueError {
19 19 #[error("invalid object")]
20 InvalidObject
20 InvalidObject,
21 21 }
22 22
23 23 #[derive(Serialize, Deserialize, Debug, thiserror::Error)]

giterated-models/src/object.rs

View file
@@ -56,11 +56,14 @@ impl<'b, O: GiteratedObject + Clone + Debug, B: ObjectBackend> Object<'b, O, B>
56 56 pub async fn get<V: GiteratedObjectValue<Object = O> + Send + Debug>(
57 57 &mut self,
58 58 ) -> Result<V, OperationError<GetValueError>> {
59 self.request(GetValue {
60 value_name: V::value_name().to_string(),
61 _marker: PhantomData,
62 })
63 .await
59 let result = self
60 .request(GetValue {
61 value_name: V::value_name().to_string(),
62 _marker: PhantomData,
63 })
64 .await;
65
66 result
64 67 }
65 68
66 69 pub async fn get_setting<S: Setting + Send + Clone + Debug>(

giterated-models/src/operation.rs

View file
@@ -20,7 +20,7 @@ pub trait GiteratedOperation<O: GiteratedObject>: Send + Serialize + Deserialize
20 20 pub struct AnyOperation(pub Value);
21 21
22 22 impl<O: GiteratedObject> GiteratedOperation<O> for AnyOperation {
23 type Success = Vec<u8>;
23 type Success = Value;
24 24
25 type Failure = Vec<u8>;
25 type Failure = Value;
26 26 }

giterated-models/src/repository/operations.rs

View file
@@ -7,7 +7,7 @@ use crate::{
7 7 operation::GiteratedOperation,
8 8 };
9 9
10 use super::{IssueLabel, Repository, RepositoryIssue, RepositoryTreeEntry, RepositoryView, Commit};
10 use super::{IssueLabel, Repository, RepositoryIssue, RepositoryTreeEntry, RepositoryView};
11 11
12 12 /// A request to get a repository's information.
13 13 ///
@@ -97,7 +97,12 @@ impl GiteratedOperation<Repository> for RepositoryFileInspectRequest {
97 97 }
98 98
99 99 impl<B: ObjectBackend + std::fmt::Debug> Object<'_, Repository, B> {
100 pub async fn info(&mut self, extra_metadata: bool, rev: Option<String>, path: Option<String>) -> Result<RepositoryView, OperationError<RepositoryError>> {
100 pub async fn info(
101 &mut self,
102 extra_metadata: bool,
103 rev: Option<String>,
104 path: Option<String>,
105 ) -> Result<RepositoryView, OperationError<RepositoryError>> {
101 106 self.request::<RepositoryInfoRequest>(RepositoryInfoRequest {
102 107 extra_metadata,
103 108 rev,

giterated-models/src/repository/settings.rs

View file
@@ -1,29 +1,9 @@
1 use serde::{Deserialize, Serialize};
2
3 1 use crate::settings::Setting;
4 2
5 3 use super::DefaultBranch;
6 4
7 #[derive(Debug, Serialize, Deserialize)]
8 pub struct RepositoryDescription(pub String);
9
10 impl Setting for RepositoryDescription {
11 fn name() -> &'static str {
12 "Repository Description"
13 }
14 }
15
16 #[derive(Debug, Serialize, Deserialize)]
17 pub struct RepositoryVisibilitySetting(pub String);
18
19 impl Setting for RepositoryVisibilitySetting {
20 fn name() -> &'static str {
21 "Repository Visibility"
22 }
23 }
24
25 5 impl Setting for DefaultBranch {
26 6 fn name() -> &'static str {
27 "Default Branch"
7 "default_branch"
28 8 }
29 }
29 \ No newline at end of file
9 }

giterated-models/src/repository/values.rs

View file
@@ -4,7 +4,7 @@ use serde::{Deserialize, Serialize};
4 4
5 5 use crate::{settings::Setting, value::GiteratedObjectValue};
6 6
7 use super::{Repository, RepositoryVisibility, Commit};
7 use super::{Commit, Repository, RepositoryVisibility};
8 8
9 9 // pub struct RepositorySetting<V: GiteratedObjectValue>(pub V);
10 10
@@ -42,6 +42,8 @@ impl Setting for Description {
42 42 }
43 43
44 44 #[derive(Debug, Hash, Clone, PartialEq, Eq, Serialize, Deserialize)]
45 #[repr(transparent)]
46 #[serde(transparent)]
45 47 pub struct Visibility(pub RepositoryVisibility);
46 48
47 49 impl GiteratedObjectValue for Visibility {
@@ -52,9 +54,23 @@ impl GiteratedObjectValue for Visibility {
52 54 }
53 55 }
54 56
57 impl Setting for Visibility {
58 fn name() -> &'static str {
59 "visibility"
60 }
61 }
62
55 63 #[derive(Debug, Hash, Clone, PartialEq, Eq, Serialize, Deserialize)]
64 #[serde(transparent)]
65 #[repr(transparent)]
56 66 pub struct DefaultBranch(pub String);
57 67
68 impl Display for DefaultBranch {
69 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
70 f.write_str(&self.0)
71 }
72 }
73
58 74 impl GiteratedObjectValue for DefaultBranch {
59 75 type Object = Repository;
60 76
@@ -64,7 +80,7 @@ impl GiteratedObjectValue for DefaultBranch {
64 80 }
65 81
66 82 #[derive(Debug, Hash, Clone, PartialEq, Eq, Serialize, Deserialize)]
67 pub struct LatestCommit(pub Commit);
83 pub struct LatestCommit(pub Option<Commit>);
68 84
69 85 impl GiteratedObjectValue for LatestCommit {
70 86 type Object = Repository;

giterated-models/src/user/settings.rs

View file
@@ -1,30 +1,15 @@
1 use serde::{Deserialize, Serialize};
2
3 1 use crate::settings::Setting;
4 2
5 #[derive(Debug, Serialize, Deserialize, Clone)]
6 pub struct UserBio(pub String);
3 use super::{Bio, DisplayName};
7 4
8 impl Setting for UserBio {
5 impl Setting for Bio {
9 6 fn name() -> &'static str {
10 "Bio"
7 "bio"
11 8 }
12 9 }
13 10
14 #[derive(Debug, Serialize, Deserialize, Clone)]
15 pub struct UserDisplayName(pub String);
16
17 impl Setting for UserDisplayName {
18 fn name() -> &'static str {
19 "Display Name"
20 }
21 }
22
23 #[derive(Debug, Serialize, Deserialize, Clone)]
24 pub struct UserDisplayImage(pub String);
25
26 impl Setting for UserDisplayImage {
11 impl Setting for DisplayName {
27 12 fn name() -> &'static str {
28 "Profile Image"
13 "display_name"
29 14 }
30 15 }