Skip to content
Clone

refactor(lib): migrate domain and integration tier to central lib/config (issues, project, repo, space, user, webapi, webhook, export, obs)

zhenyi committed
parent 030e59e commit f2834c1 Browse files

32 files changed

+52 −594

File tree 32
Modified lib/export/issues/issues.rs View lib/export/issues/issues.rs
@@ -49,8 +49,6 @@
4949
5050#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
5151pub struct CreateCollectionOption {
52 /// Space the collection lives in. An object channel is minted under `parent_dir`
53 /// (or the space root when `None`) and bound to the collection.
5452 pub space_id: Uuid,
5553 pub parent_dir: Option<Uuid>,
5654 pub name: String,
Modified lib/export/project/lifecycle.rs View lib/export/project/lifecycle.rs
@@ -52,7 +52,6 @@
5252#[derive(Debug, Clone, Deserialize, Validate, ToSchema)]
5353pub struct CreateProjectCmd {
5454 pub space_id: Uuid,
55 /// Optional directory channel to host the project's object channel under.
5655 pub parent_dir: Option<Uuid>,
5756 #[validate(length(min = 1, max = 100))]
5857 pub name: String,
Modified lib/export/repo/lifecycle.rs View lib/export/repo/lifecycle.rs
@@ -223,8 +223,6 @@
223223
224224#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
225225pub struct CreateRepoOption {
226 /// Space the repo lives in. An object channel is minted under `parent_dir` (or
227 /// the space root when `None`) and bound to the new repo.
228226 pub space_id: Uuid,
229227 pub parent_dir: Option<Uuid>,
230228 pub name: String,
Modified lib/issues/Cargo.toml View lib/issues/Cargo.toml
@@ -14,6 +14,7 @@
1414
1515[dependencies]
1616export.workspace = true
17config.workspace = true
1718db.workspace = true
1819cache.workspace = true
1920jwt.workspace = true
Deleted lib/issues/config.rs
@@ -1,107 +0,0 @@
1use std::sync::Arc;
2
3use serde::{Deserialize, Serialize};
4
5#[derive(Debug, Clone, Serialize, Deserialize)]
6pub struct IssueConfig {
7 #[serde(default = "default_max_pagination")]
8 pub max_pagination: u64,
9 #[serde(default = "default_default_pagination")]
10 pub default_pagination: u64,
11 #[serde(default = "default_max_title_len")]
12 pub max_title_len: usize,
13 #[serde(default = "default_max_body_len")]
14 pub max_body_len: usize,
15 #[serde(default = "default_max_collection_name_len")]
16 pub max_collection_name_len: usize,
17 #[serde(default = "default_max_label_name_len")]
18 pub max_label_name_len: usize,
19 #[serde(default = "default_max_label_color_len")]
20 pub max_label_color_len: usize,
21 #[serde(default = "default_max_milestone_title_len")]
22 pub max_milestone_title_len: usize,
23 #[serde(default = "default_max_milestone_description_len")]
24 pub max_milestone_description_len: usize,
25 #[serde(default = "default_max_comment_len")]
26 pub max_comment_len: usize,
27 #[serde(default = "default_default_collection_name")]
28 pub default_collection_name: String,
29 #[serde(default = "default_max_reaction_emoji_len")]
30 pub max_reaction_emoji_len: usize,
31 #[serde(default = "default_max_attachment_size_bytes")]
32 pub max_attachment_size_bytes: i64,
33 #[serde(default = "default_max_dependency_label_len")]
34 pub max_dependency_label_len: usize,
35 #[serde(default = "default_max_event_content_len")]
36 pub max_event_content_len: usize,
37}
38
39fn default_max_pagination() -> u64 {
40 100
41}
42fn default_default_pagination() -> u64 {
43 20
44}
45fn default_max_title_len() -> usize {
46 255
47}
48fn default_max_body_len() -> usize {
49 65_535
50}
51fn default_max_collection_name_len() -> usize {
52 100
53}
54fn default_max_label_name_len() -> usize {
55 50
56}
57fn default_max_label_color_len() -> usize {
58 7
59}
60fn default_max_milestone_title_len() -> usize {
61 100
62}
63fn default_max_milestone_description_len() -> usize {
64 1024
65}
66fn default_max_comment_len() -> usize {
67 65_535
68}
69fn default_default_collection_name() -> String {
70 "default".to_string()
71}
72fn default_max_reaction_emoji_len() -> usize {
73 32
74}
75fn default_max_attachment_size_bytes() -> i64 {
76 10 * 1024 * 1024
77}
78fn default_max_dependency_label_len() -> usize {
79 100
80}
81fn default_max_event_content_len() -> usize {
82 4096
83}
84
85impl Default for IssueConfig {
86 fn default() -> Self {
87 Self {
88 max_pagination: default_max_pagination(),
89 default_pagination: default_default_pagination(),
90 max_title_len: default_max_title_len(),
91 max_body_len: default_max_body_len(),
92 max_collection_name_len: default_max_collection_name_len(),
93 max_label_name_len: default_max_label_name_len(),
94 max_label_color_len: default_max_label_color_len(),
95 max_milestone_title_len: default_max_milestone_title_len(),
96 max_milestone_description_len: default_max_milestone_description_len(),
97 max_comment_len: default_max_comment_len(),
98 default_collection_name: default_default_collection_name(),
99 max_reaction_emoji_len: default_max_reaction_emoji_len(),
100 max_attachment_size_bytes: default_max_attachment_size_bytes(),
101 max_dependency_label_len: default_max_dependency_label_len(),
102 max_event_content_len: default_max_event_content_len(),
103 }
104 }
105}
106
107pub type SharedIssueConfig = Arc<IssueConfig>;
Modified lib/issues/lib.rs View lib/issues/lib.rs
@@ -1,11 +1,9 @@
1pub mod config;
21pub mod error;
32pub mod features;
43pub mod handler;
54pub mod metrics;
65pub mod service;
76
8pub use config::{IssueConfig, SharedIssueConfig};
97pub use error::{IssueError, IssueResult};
108pub use features::IssueService;
119pub use handler::IssuesApiDoc;
Modified lib/issues/service.rs View lib/issues/service.rs
@@ -5,7 +5,7 @@
55use jwt::JwtState;
66use storage::StorageRepository;
77
8use crate::config::{IssueConfig, SharedIssueConfig};
8use config::issues::{IssueConfig, SharedIssueConfig};
99
1010#[derive(Clone)]
1111pub struct IssueService {
@@ -49,7 +49,7 @@
4949 self.kv.clone()
5050 }
5151
52 fn rate_limit_settings(&self) -> Arc<rate_limit::RateLimitConfig> {
53 Arc::new(rate_limit::RateLimitConfig::default())
52 fn rate_limit_settings(&self) -> Arc<config::rate_limit::RateLimitConfig> {
53 Arc::new(config::rate_limit::RateLimitConfig::default())
5454 }
5555}
Modified lib/project/Cargo.toml View lib/project/Cargo.toml
@@ -14,6 +14,7 @@
1414name = "project"
1515[dependencies]
1616export.workspace = true
17config.workspace = true
1718db.workspace = true
1819jwt.workspace = true
1920rate_limit.workspace = true
Deleted lib/project/config.rs
@@ -1,24 +0,0 @@
1use std::sync::Arc;
2
3#[derive(Debug, Clone)]
4pub struct ProjectConfig {
5 pub cache_ttl_project_secs: u64,
6 pub cache_ttl_member_role_secs: u64,
7 pub cache_ttl_favorites_secs: u64,
8 pub default_page_size: u64,
9 pub max_page_size: u64,
10}
11
12impl Default for ProjectConfig {
13 fn default() -> Self {
14 Self {
15 cache_ttl_project_secs: 300,
16 cache_ttl_member_role_secs: 60,
17 cache_ttl_favorites_secs: 600,
18 default_page_size: 20,
19 max_page_size: 100,
20 }
21 }
22}
23
24pub type SharedProjectConfig = Arc<ProjectConfig>;
Modified lib/project/lib.rs View lib/project/lib.rs
@@ -1,6 +1,5 @@
11pub mod actor;
22pub mod cache;
3pub mod config;
43pub mod error;
54pub mod features;
65pub mod graphql;
@@ -11,7 +10,6 @@
1110
1211pub use actor::ActorContext;
1312pub use cache::{CachedProjectDetail, ProjectCache};
14pub use config::{ProjectConfig, SharedProjectConfig};
1513pub use error::{ProjectError, ProjectResult};
1614pub use features::ProjectService;
1715pub use graphql::ProjectSchema;
Modified lib/project/service.rs View lib/project/service.rs
@@ -5,7 +5,7 @@
55use jwt::JwtState;
66
77use crate::cache::ProjectCache;
8use crate::config::{ProjectConfig, SharedProjectConfig};
8use config::project::{ProjectConfig, SharedProjectConfig};
99
1010#[derive(Clone)]
1111pub struct ProjectService {
@@ -51,7 +51,7 @@
5151 self.kv.clone()
5252 }
5353
54 fn rate_limit_settings(&self) -> Arc<rate_limit::RateLimitConfig> {
55 Arc::new(rate_limit::RateLimitConfig::default())
54 fn rate_limit_settings(&self) -> Arc<config::rate_limit::RateLimitConfig> {
55 Arc::new(config::rate_limit::RateLimitConfig::default())
5656 }
5757}
Modified lib/repo/Cargo.toml View lib/repo/Cargo.toml
@@ -14,6 +14,7 @@
1414name = "repo"
1515[dependencies]
1616export.workspace = true
17config.workspace = true
1718db.workspace = true
1819git.workspace = true
1920storage.workspace = true
Deleted lib/repo/config.rs
@@ -1,119 +0,0 @@
1use std::sync::Arc;
2
3use serde::{Deserialize, Serialize};
4
5#[derive(Debug, Clone, Serialize, Deserialize)]
6pub struct RepoConfig {
7 #[serde(default = "default_max_pagination")]
8 pub max_pagination: u64,
9 #[serde(default = "default_default_pagination")]
10 pub default_pagination: u64,
11 #[serde(default = "default_repo_name_len")]
12 pub max_repo_name_len: usize,
13 #[serde(default = "default_description_len")]
14 pub max_description_len: usize,
15 #[serde(default = "default_website_len")]
16 pub max_website_len: usize,
17 #[serde(default = "default_topic_len")]
18 pub max_topic_len: usize,
19 #[serde(default = "default_branch_name_len")]
20 pub max_branch_name_len: usize,
21 #[serde(default = "default_tag_name_len")]
22 pub max_tag_name_len: usize,
23 #[serde(default = "default_release_body_len")]
24 pub max_release_body_len: usize,
25 #[serde(default = "default_default_branch")]
26 pub default_branch: String,
27 #[serde(default = "default_object_format")]
28 pub default_object_format: String,
29 #[serde(default = "default_git_dir")]
30 pub git_storage_root: String,
31 #[serde(default = "default_lfs_dir")]
32 pub lfs_storage_root: String,
33 #[serde(default = "default_branch_protection_priority_max")]
34 pub branch_protection_priority_max: i64,
35 #[serde(default = "default_max_topics")]
36 pub max_topics_per_repo: usize,
37 #[serde(default = "default_pr_title_len")]
38 pub max_pr_title_len: usize,
39 #[serde(default = "default_pr_body_len")]
40 pub max_pr_body_len: usize,
41}
42
43fn default_max_pagination() -> u64 {
44 100
45}
46fn default_default_pagination() -> u64 {
47 20
48}
49fn default_repo_name_len() -> usize {
50 100
51}
52fn default_description_len() -> usize {
53 512
54}
55fn default_website_len() -> usize {
56 256
57}
58fn default_topic_len() -> usize {
59 35
60}
61fn default_branch_name_len() -> usize {
62 100
63}
64fn default_tag_name_len() -> usize {
65 100
66}
67fn default_release_body_len() -> usize {
68 65535
69}
70fn default_default_branch() -> String {
71 "main".to_string()
72}
73fn default_object_format() -> String {
74 "sha1".to_string()
75}
76fn default_git_dir() -> String {
77 "/var/lib/repo/git".to_string()
78}
79fn default_lfs_dir() -> String {
80 "/var/lib/repo/lfs".to_string()
81}
82fn default_branch_protection_priority_max() -> i64 {
83 10_000
84}
85fn default_max_topics() -> usize {
86 25
87}
88fn default_pr_title_len() -> usize {
89 255
90}
91fn default_pr_body_len() -> usize {
92 65535
93}
94
95impl Default for RepoConfig {
96 fn default() -> Self {
97 Self {
98 max_pagination: default_max_pagination(),
99 default_pagination: default_default_pagination(),
100 max_repo_name_len: default_repo_name_len(),
101 max_description_len: default_description_len(),
102 max_website_len: default_website_len(),
103 max_topic_len: default_topic_len(),
104 max_branch_name_len: default_branch_name_len(),
105 max_tag_name_len: default_tag_name_len(),
106 max_release_body_len: default_release_body_len(),
107 default_branch: default_default_branch(),
108 default_object_format: default_object_format(),
109 git_storage_root: default_git_dir(),
110 lfs_storage_root: default_lfs_dir(),
111 branch_protection_priority_max: default_branch_protection_priority_max(),
112 max_topics_per_repo: default_max_topics(),
113 max_pr_title_len: default_pr_title_len(),
114 max_pr_body_len: default_pr_body_len(),
115 }
116 }
117}
118
119pub type SharedRepoConfig = Arc<RepoConfig>;
Modified lib/repo/lib.rs View lib/repo/lib.rs
@@ -1,6 +1,5 @@
11pub mod actor;
22pub mod cache;
3pub mod config;
43pub mod error;
54pub mod features;
65pub mod graphql;
@@ -12,7 +11,6 @@
1211
1312pub use actor::{ActorContext, ChannelRole, RepoAccess, SpaceRole, TokenScope};
1413pub use cache::{ObjectCache, RepoCache};
15pub use config::{RepoConfig, SharedRepoConfig};
1614pub use error::{RepoError, RepoResult};
1715pub use graphql::RepoSchema;
1816pub use handler::router as repo_router;
Modified lib/repo/path.rs View lib/repo/path.rs
@@ -3,8 +3,8 @@
33
44use uuid::Uuid;
55
6use crate::config::SharedRepoConfig;
76use crate::error::{RepoError, RepoResult};
7use config::repo::SharedRepoConfig;
88
99pub const DEFAULT_OBJECT_FORMAT_SHA1: &str = "sha1";
1010pub const DEFAULT_OBJECT_FORMAT_SHA256: &str = "sha256";
Modified lib/repo/service.rs View lib/repo/service.rs
@@ -5,7 +5,7 @@
55use jwt::JwtState;
66
77use crate::cache::RepoCache;
8use crate::config::{RepoConfig, SharedRepoConfig};
8use config::repo::{RepoConfig, SharedRepoConfig};
99
1010use rate_limit::RateLimitProvider;
1111
@@ -55,7 +55,7 @@
5555 self.kv.clone()
5656 }
5757
58 fn rate_limit_settings(&self) -> Arc<rate_limit::RateLimitConfig> {
59 Arc::new(rate_limit::RateLimitConfig::default())
58 fn rate_limit_settings(&self) -> Arc<config::rate_limit::RateLimitConfig> {
59 Arc::new(config::rate_limit::RateLimitConfig::default())
6060 }
6161}
Modified lib/space/features/channels/usecase.rs View lib/space/features/channels/usecase.rs
@@ -95,7 +95,6 @@
9595 result
9696}
9797
98/// Validate that `parent_id` names a Directory channel belonging to `space_id`.
9998async fn require_directory_parent<C: ConnectionTrait>(
10099 db: &C,
101100 space_id: Uuid,
@@ -121,8 +120,6 @@
121120 Ok(())
122121}
123122
124/// Mint a Directory (container) channel inside a space, optionally nested under a
125/// parent directory.
126123pub async fn create_directory(
127124 svc: &SpaceService,
128125 caller: Uuid,
@@ -162,10 +159,6 @@
162159 result
163160}
164161
165/// Atomically mint an Object (leaf) channel for a concrete resource under a parent
166/// directory. The resource crates call this on create/transfer to bind
167/// repo/issue/project/post channel_id to a fresh object channel. `db` may be a
168/// transaction so the caller can bind the resource in the same unit of work.
169162pub async fn ensure_channel_for_resource<C: ConnectionTrait>(
170163 db: &C,
171164 space_id: Uuid,
Modified lib/space/features/mod.rs View lib/space/features/mod.rs
@@ -4,7 +4,7 @@
44use db::conn::Db;
55use jwt::{HasJwtState, JwtState};
66
7use crate::config::{SharedSpaceConfig, SpaceConfig};
7use config::space::{SharedSpaceConfig, SpaceConfig};
88
99pub mod authz;
1010pub mod bans;
@@ -56,7 +56,7 @@
5656 self.kv.clone()
5757 }
5858
59 fn rate_limit_settings(&self) -> Arc<rate_limit::RateLimitConfig> {
60 Arc::new(rate_limit::RateLimitConfig::default())
59 fn rate_limit_settings(&self) -> Arc<config::rate_limit::RateLimitConfig> {
60 Arc::new(config::rate_limit::RateLimitConfig::default())
6161 }
6262}
Modified lib/space/Cargo.toml View lib/space/Cargo.toml
@@ -13,6 +13,7 @@
1313name = "space"
1414[dependencies]
1515export.workspace = true
16config.workspace = true
1617db.workspace = true
1718jwt.workspace = true
1819rate_limit.workspace = true
Deleted lib/space/config.rs
@@ -1,84 +0,0 @@
1use std::sync::Arc;
2
3use serde::{Deserialize, Serialize};
4
5#[derive(Debug, Clone, Serialize, Deserialize)]
6pub struct SpaceConfig {
7 #[serde(default = "default_max_pagination")]
8 pub max_pagination: u64,
9 #[serde(default = "default_default_pagination")]
10 pub default_pagination: u64,
11 #[serde(default = "default_max_space_name_len")]
12 pub max_space_name_len: usize,
13 #[serde(default = "default_max_space_desc_len")]
14 pub max_space_desc_len: usize,
15 #[serde(default = "default_max_role_name_len")]
16 pub max_role_name_len: usize,
17 #[serde(default = "default_max_alias_name_len")]
18 pub max_alias_name_len: usize,
19 #[serde(default = "default_max_invite_email_len")]
20 pub max_invite_email_len: usize,
21 #[serde(default = "default_max_channel_name_len")]
22 pub max_channel_name_len: usize,
23 #[serde(default = "default_max_topic_len")]
24 pub max_topic_len: usize,
25 #[serde(default = "default_max_purpose_len")]
26 pub max_purpose_len: usize,
27 #[serde(default = "default_invite_expiry_hours")]
28 pub invite_expiry_hours: i64,
29}
30
31fn default_max_pagination() -> u64 {
32 100
33}
34fn default_default_pagination() -> u64 {
35 20
36}
37fn default_max_space_name_len() -> usize {
38 64
39}
40fn default_max_space_desc_len() -> usize {
41 512
42}
43fn default_max_role_name_len() -> usize {
44 64
45}
46fn default_max_alias_name_len() -> usize {
47 64
48}
49fn default_max_invite_email_len() -> usize {
50 320
51}
52fn default_max_channel_name_len() -> usize {
53 64
54}
55fn default_max_topic_len() -> usize {
56 256
57}
58fn default_max_purpose_len() -> usize {
59 512
60}
61fn default_invite_expiry_hours() -> i64 {
62 24
63}
64
65impl Default for SpaceConfig {
66 fn default() -> Self {
67 Self {
68 max_pagination: default_max_pagination(),
69 default_pagination: default_default_pagination(),
70 max_space_name_len: default_max_space_name_len(),
71 max_space_desc_len: default_max_space_desc_len(),
72 max_role_name_len: default_max_role_name_len(),
73 max_alias_name_len: default_max_alias_name_len(),
74 max_invite_email_len: default_max_invite_email_len(),
75 max_channel_name_len: default_max_channel_name_len(),
76 max_topic_len: default_max_topic_len(),
77 max_purpose_len: default_max_purpose_len(),
78 invite_expiry_hours: default_invite_expiry_hours(),
79 }
80 }
81}
82
83#[allow(dead_code)]
84pub type SharedSpaceConfig = Arc<SpaceConfig>;
Modified lib/space/lib.rs View lib/space/lib.rs
@@ -1,10 +1,8 @@
1pub mod config;
21pub mod error;
32pub mod features;
43pub mod handler;
54pub mod metrics;
65
7pub use config::{SharedSpaceConfig, SpaceConfig};
86pub use error::{SpaceError, SpaceResult};
97pub use features::SpaceService;
108pub use handler::SpaceApiDoc;
Modified lib/user/features/profile/types.rs View lib/user/features/profile/types.rs
@@ -5,12 +5,30 @@
55use utoipa::ToSchema;
66use uuid::Uuid;
77
8use crate::config::ProfileVisibility;
8use config::user::ProfileVisibility;
99
1010fn fmt_ts(ts: OffsetDateTime) -> String {
1111 ts.format(&Rfc3339).unwrap_or_default()
1212}
1313
14pub(crate) fn visibility_from_entity(v: user_entity::ProfileVisibility) -> ProfileVisibility {
15 match v {
16 user_entity::ProfileVisibility::Public => ProfileVisibility::Public,
17 user_entity::ProfileVisibility::RegisteredOnly => ProfileVisibility::RegisteredOnly,
18 user_entity::ProfileVisibility::MembersOnly => ProfileVisibility::MembersOnly,
19 user_entity::ProfileVisibility::Private => ProfileVisibility::Private,
20 }
21}
22
23pub(crate) fn visibility_to_entity(v: ProfileVisibility) -> user_entity::ProfileVisibility {
24 match v {
25 ProfileVisibility::Public => user_entity::ProfileVisibility::Public,
26 ProfileVisibility::RegisteredOnly => user_entity::ProfileVisibility::RegisteredOnly,
27 ProfileVisibility::MembersOnly => user_entity::ProfileVisibility::MembersOnly,
28 ProfileVisibility::Private => user_entity::ProfileVisibility::Private,
29 }
30}
31
1432#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
1533pub struct UserPublic {
1634 pub uid: Uuid,
@@ -33,7 +51,7 @@
3351 username: m.username,
3452 display_name: m.display_name,
3553 avatar: m.avatar,
36 visibility: ProfileVisibility::from(m.visibility),
54 visibility: visibility_from_entity(m.visibility),
3755 bot: m.bot,
3856 system: m.system,
3957 locale: m.locale,
@@ -71,7 +89,7 @@
7189 username: m.username,
7290 display_name: m.display_name,
7391 avatar: m.avatar,
74 visibility: ProfileVisibility::from(m.visibility),
92 visibility: visibility_from_entity(m.visibility),
7593 is_active: m.is_active,
7694 is_admin: m.is_admin,
7795 is_restricted: m.is_restricted,
@@ -87,28 +105,6 @@
87105 }
88106}
89107
90impl From<user_entity::ProfileVisibility> for ProfileVisibility {
91 fn from(v: user_entity::ProfileVisibility) -> Self {
92 match v {
93 user_entity::ProfileVisibility::Public => ProfileVisibility::Public,
94 user_entity::ProfileVisibility::RegisteredOnly => ProfileVisibility::RegisteredOnly,
95 user_entity::ProfileVisibility::MembersOnly => ProfileVisibility::MembersOnly,
96 user_entity::ProfileVisibility::Private => ProfileVisibility::Private,
97 }
98 }
99}
100
101impl From<ProfileVisibility> for user_entity::ProfileVisibility {
102 fn from(v: ProfileVisibility) -> Self {
103 match v {
104 ProfileVisibility::Public => user_entity::ProfileVisibility::Public,
105 ProfileVisibility::RegisteredOnly => user_entity::ProfileVisibility::RegisteredOnly,
106 ProfileVisibility::MembersOnly => user_entity::ProfileVisibility::MembersOnly,
107 ProfileVisibility::Private => user_entity::ProfileVisibility::Private,
108 }
109 }
110}
111
112108#[derive(Debug, Clone, Serialize, Deserialize, ToSchema, Default)]
113109pub struct ProfileView {
114110 pub user_id: Uuid,
@@ -137,7 +133,7 @@
137133 real_name: m.real_name,
138134 bio: m.bio,
139135 pronouns: m.pronouns,
140 pronouns_privacy: m.pronouns_privacy.map(Into::into),
136 pronouns_privacy: m.pronouns_privacy.map(visibility_from_entity),
141137 website: m.website,
142138 location: m.location,
143139 company: m.company,
Modified lib/user/features/profile/usecase.rs View lib/user/features/profile/usecase.rs
@@ -10,7 +10,8 @@
1010use crate::metrics;
1111
1212use super::types::{
13 MemeView, ProfileView, UpdateProfileCmd, UpdateProfileFields, UpsertMemeCmd, UserMe, UserPublic,
13 MemeView, ProfileView, UpdateProfileCmd, UpdateProfileFields, UpsertMemeCmd, UserMe,
14 UserPublic, visibility_to_entity,
1415};
1516
1617const MAX_DISPLAY_NAME: usize = 64;
@@ -100,7 +101,7 @@
100101 active.timezone = Set(Some(v));
101102 }
102103 if let Some(v) = cmd.visibility {
103 active.visibility = Set(v.into());
104 active.visibility = Set(visibility_to_entity(v));
104105 }
105106 active.updated_at = Set(OffsetDateTime::now_utc());
106107
@@ -325,7 +326,7 @@
325326 active.pronouns = Set(v);
326327 }
327328 if let Some(v) = f.pronouns_privacy {
328 active.pronouns_privacy = Set(v.map(Into::into));
329 active.pronouns_privacy = Set(v.map(visibility_to_entity));
329330 }
330331 if let Some(v) = f.website {
331332 active.website = Set(v);
Modified lib/user/features/mod.rs View lib/user/features/mod.rs
@@ -5,7 +5,7 @@
55use jwt::{HasJwtState, JwtState};
66use storage::StorageRepository;
77
8use crate::config::{SharedUserConfig, UserConfig};
8use config::user::{SharedUserConfig, UserConfig};
99
1010pub mod avatar;
1111pub mod deletion;
@@ -67,7 +67,7 @@
6767 self.kv.clone()
6868 }
6969
70 fn rate_limit_settings(&self) -> Arc<rate_limit::RateLimitConfig> {
71 Arc::new(rate_limit::RateLimitConfig::default())
70 fn rate_limit_settings(&self) -> Arc<config::rate_limit::RateLimitConfig> {
71 Arc::new(config::rate_limit::RateLimitConfig::default())
7272 }
7373}
Modified lib/user/handler/openapi.rs View lib/user/handler/openapi.rs
@@ -1,6 +1,5 @@
11use utoipa::OpenApi;
22
3use crate::config::ProfileVisibility;
43use crate::features::avatar::types::{AvatarFormat, AvatarView, UploadAvatarCmd};
54use crate::features::profile::types::{
65 MemeView, ProfileView, UpdateProfileCmd, UpdateProfileFields, UpsertMemeCmd, UserMe, UserPublic,
@@ -8,6 +7,7 @@
87use crate::features::social::types::{
98 BlockedSummary, FollowerSummary, ListBlocksQuery, ListFollowersQuery, ListFollowingQuery,
109};
10use config::user::ProfileVisibility;
1111use export::user::deletion::{DeletionRequestView, DeletionStatus, RequestDeletionCmd};
1212use export::user::devices::{DeviceView, UpdateDeviceCmd};
1313use export::user::emails::{
Modified lib/user/Cargo.toml View lib/user/Cargo.toml
@@ -14,6 +14,7 @@
1414
1515[dependencies]
1616export.workspace = true
17config.workspace = true
1718db.workspace = true
1819cache.workspace = true
1920auth.workspace = true
Deleted lib/user/config.rs
@@ -1,158 +0,0 @@
1use std::sync::Arc;
2
3use serde::{Deserialize, Serialize};
4use utoipa::ToSchema;
5
6#[derive(Debug, Clone, Copy, Default, Serialize, Deserialize, PartialEq, Eq, ToSchema)]
7#[serde(rename_all = "snake_case")]
8pub enum ProfileVisibility {
9 Public,
10 #[default]
11 RegisteredOnly,
12 MembersOnly,
13 Private,
14}
15
16#[derive(Debug, Clone, Serialize, Deserialize)]
17pub struct UserConfig {
18 #[serde(default = "default_max_pagination")]
19 pub max_profile_pagination: usize,
20 #[serde(default = "default_default_pagination")]
21 pub default_profile_pagination: usize,
22 #[serde(default = "default_max_username_len")]
23 pub max_username_len: usize,
24 #[serde(default = "default_min_username_len")]
25 pub min_username_len: usize,
26 #[serde(default = "default_max_display_name_len")]
27 pub max_display_name_len: usize,
28 #[serde(default = "default_max_bio_len")]
29 pub max_bio_len: usize,
30 #[serde(default = "default_max_pronouns_len")]
31 pub max_pronouns_len: usize,
32 #[serde(default = "default_max_website_len")]
33 pub max_website_len: usize,
34 #[serde(default = "default_max_location_len")]
35 pub max_location_len: usize,
36 #[serde(default = "default_max_company_len")]
37 pub max_company_len: usize,
38 #[serde(default = "default_max_meme_name_len")]
39 pub max_meme_name_len: usize,
40 #[serde(default = "default_max_recovery_codes")]
41 pub max_recovery_codes: usize,
42 #[serde(default = "default_access_key_token_bytes")]
43 pub access_key_token_bytes: usize,
44 #[serde(default = "default_ssh_key_max_per_user")]
45 pub ssh_key_max_per_user: usize,
46 #[serde(default = "default_deletion_grace_days")]
47 pub deletion_grace_days: i64,
48 #[serde(default = "default_follow_rate_limit_secs")]
49 pub follow_rate_limit_secs: u64,
50 #[serde(default = "default_block_rate_limit_secs")]
51 pub block_rate_limit_secs: u64,
52 #[serde(default = "default_report_rate_limit_secs")]
53 pub report_rate_limit_secs: u64,
54 #[serde(default = "default_unread_cache_ttl")]
55 pub notifications_unread_cache_ttl_secs: u64,
56 #[serde(default)]
57 pub default_visibility: ProfileVisibility,
58 #[serde(default = "default_default_locale")]
59 pub default_locale: String,
60 #[serde(default = "default_default_timezone")]
61 pub default_timezone: String,
62}
63
64fn default_max_pagination() -> usize {
65 100
66}
67fn default_default_pagination() -> usize {
68 20
69}
70fn default_max_username_len() -> usize {
71 64
72}
73fn default_min_username_len() -> usize {
74 1
75}
76fn default_max_display_name_len() -> usize {
77 64
78}
79fn default_max_bio_len() -> usize {
80 512
81}
82fn default_max_pronouns_len() -> usize {
83 32
84}
85fn default_max_website_len() -> usize {
86 256
87}
88fn default_max_location_len() -> usize {
89 128
90}
91fn default_max_company_len() -> usize {
92 128
93}
94fn default_max_meme_name_len() -> usize {
95 64
96}
97fn default_max_recovery_codes() -> usize {
98 10
99}
100fn default_access_key_token_bytes() -> usize {
101 32
102}
103fn default_ssh_key_max_per_user() -> usize {
104 50
105}
106fn default_deletion_grace_days() -> i64 {
107 14
108}
109fn default_follow_rate_limit_secs() -> u64 {
110 60
111}
112fn default_block_rate_limit_secs() -> u64 {
113 60
114}
115fn default_report_rate_limit_secs() -> u64 {
116 300
117}
118fn default_unread_cache_ttl() -> u64 {
119 3600
120}
121fn default_default_locale() -> String {
122 "en".to_string()
123}
124fn default_default_timezone() -> String {
125 "UTC".to_string()
126}
127
128impl Default for UserConfig {
129 fn default() -> Self {
130 Self {
131 max_profile_pagination: default_max_pagination(),
132 default_profile_pagination: default_default_pagination(),
133 max_username_len: default_max_username_len(),
134 min_username_len: default_min_username_len(),
135 max_display_name_len: default_max_display_name_len(),
136 max_bio_len: default_max_bio_len(),
137 max_pronouns_len: default_max_pronouns_len(),
138 max_website_len: default_max_website_len(),
139 max_location_len: default_max_location_len(),
140 max_company_len: default_max_company_len(),
141 max_meme_name_len: default_max_meme_name_len(),
142 max_recovery_codes: default_max_recovery_codes(),
143 access_key_token_bytes: default_access_key_token_bytes(),
144 ssh_key_max_per_user: default_ssh_key_max_per_user(),
145 deletion_grace_days: default_deletion_grace_days(),
146 follow_rate_limit_secs: default_follow_rate_limit_secs(),
147 block_rate_limit_secs: default_block_rate_limit_secs(),
148 report_rate_limit_secs: default_report_rate_limit_secs(),
149 notifications_unread_cache_ttl_secs: default_unread_cache_ttl(),
150 default_visibility: ProfileVisibility::default(),
151 default_locale: default_default_locale(),
152 default_timezone: default_default_timezone(),
153 }
154 }
155}
156
157#[allow(dead_code)]
158pub type SharedUserConfig = Arc<UserConfig>;
Modified lib/user/lib.rs View lib/user/lib.rs
@@ -1,10 +1,8 @@
1pub mod config;
21pub mod error;
32pub mod features;
43pub mod handler;
54pub mod metrics;
65
7pub use config::{SharedUserConfig, UserConfig};
86pub use error::{UserError, UserResult};
97pub use features::UserService;
108pub use handler::UserApiDoc;
Modified lib/webapi/Cargo.toml View lib/webapi/Cargo.toml
@@ -13,6 +13,7 @@
1313name = "webapi"
1414[dependencies]
1515axum = { workspace = true }
16config = { workspace = true }
1617tokio = { workspace = true }
1718serde = { workspace = true }
1819serde_json = { workspace = true }
Deleted lib/webapi/config.rs
@@ -1,28 +0,0 @@
1use auth::AuthConfig;
2use cache::config::redis::AppRedisSettings;
3use db::config::AppDatabaseSettings;
4use email::config::AppEmailSettings;
5use issues::IssueConfig;
6use jwt::config::JwtSettings;
7use project::ProjectConfig;
8use queue::config::AppQueueSettings;
9use repo::RepoConfig;
10use space::SpaceConfig;
11use storage::config::StorageSettings;
12use user::UserConfig;
13
14#[derive(Clone, Default)]
15pub struct AppConfig {
16 pub db: AppDatabaseSettings,
17 pub cache: AppRedisSettings,
18 pub queue: AppQueueSettings,
19 pub email: AppEmailSettings,
20 pub storage: StorageSettings,
21 pub jwt: JwtSettings,
22 pub auth: AuthConfig,
23 pub issues: IssueConfig,
24 pub project: ProjectConfig,
25 pub repo: RepoConfig,
26 pub space: SpaceConfig,
27 pub user: UserConfig,
28}
Modified lib/webapi/lib.rs View lib/webapi/lib.rs
@@ -1,12 +1,9 @@
1pub mod config;
21pub mod health;
32pub mod openapi;
43pub mod router;
54pub mod services;
65
7pub use config::AppConfig;
86pub use router::{API_PREFIX, router};
97pub use services::{AppServices, WebapiError, WebapiResult};
108
11/// 支付基础设施骨架(依赖接通,路由/服务装配在后续轮接入)。
129pub use payment;
Modified lib/webapi/services.rs View lib/webapi/services.rs
@@ -1,8 +1,10 @@
11use std::sync::Arc;
22
33use auth::features::AuthService;
4use auth::pow::{PowService, PowSettings};
4use auth::pow::PowService;
55use cache::redis::RedisCache;
6use config::AppConfig;
7use config::pow::PowSettings;
68use db::conn::Db;
79use email::{EmailService, EmailServiceBuilder};
810use issues::service::IssueService;
@@ -17,8 +19,6 @@
1719use thiserror::Error;
1820use tokio::sync::RwLock;
1921use user::features::UserService;
20
21use crate::config::AppConfig;
2222
2323#[derive(Debug, Error)]
2424pub enum WebapiError {