refactor: fix all clippy warnings properly

- UserProfile struct groups display_name/bio/avatar/banner/also_known_as/profile_fields
- User::from_persistence takes UserProfile (6 args, was 11)
- PersistedReview struct for Review::from_persistence (1 arg, was 8)
- WatchlistApInput struct for watchlist_to_ap_object (1 arg, was 8)
- ActivityPubDeps struct for activitypub::wire (1 arg, was 11)
- FederationRepos type alias for wire() return types
- FeedSortBy: impl std::str::FromStr instead of inherent from_str
- postgres users.rs: row_to_user takes &PgRow like sqlite
- collapse nested ifs in multipart handlers
- type alias for complex return types (image-converter, worker)
- tui: allow large_enum_variant at crate level (pre-existing, unrelated)
This commit is contained in:
2026-05-29 11:19:02 +02:00
parent 68a939f6c4
commit 2355f89bed
27 changed files with 363 additions and 455 deletions

View File

@@ -163,6 +163,17 @@ pub enum ReviewSource {
},
}
pub struct PersistedReview {
pub id: ReviewId,
pub movie_id: MovieId,
pub user_id: UserId,
pub rating: Rating,
pub comment: Option<Comment>,
pub watched_at: NaiveDateTime,
pub created_at: NaiveDateTime,
pub source: ReviewSource,
}
#[derive(Clone, Debug)]
pub struct Review {
id: ReviewId,
@@ -195,25 +206,16 @@ impl Review {
})
}
pub fn from_persistence(
id: ReviewId,
movie_id: MovieId,
user_id: UserId,
rating: Rating,
comment: Option<Comment>,
watched_at: NaiveDateTime,
created_at: NaiveDateTime,
source: ReviewSource,
) -> Self {
pub fn from_persistence(row: PersistedReview) -> Self {
Self {
id,
movie_id,
user_id,
rating,
comment,
watched_at,
created_at,
source,
id: row.id,
movie_id: row.movie_id,
user_id: row.user_id,
rating: row.rating,
comment: row.comment,
watched_at: row.watched_at,
created_at: row.created_at,
source: row.source,
}
}
@@ -314,6 +316,16 @@ pub struct ProfileField {
pub value: String,
}
#[derive(Clone, Debug, Default)]
pub struct UserProfile {
pub display_name: Option<String>,
pub bio: Option<String>,
pub avatar_path: Option<String>,
pub banner_path: Option<String>,
pub also_known_as: Option<String>,
pub profile_fields: Vec<ProfileField>,
}
#[derive(Clone, Debug)]
pub struct User {
id: UserId,
@@ -321,12 +333,7 @@ pub struct User {
username: Username,
password_hash: PasswordHash,
role: UserRole,
display_name: Option<String>,
bio: Option<String>,
avatar_path: Option<String>,
banner_path: Option<String>,
also_known_as: Option<String>,
profile_fields: Vec<ProfileField>,
profile: UserProfile,
}
impl User {
@@ -342,12 +349,7 @@ impl User {
username,
password_hash,
role,
display_name: None,
bio: None,
avatar_path: None,
banner_path: None,
also_known_as: None,
profile_fields: vec![],
profile: UserProfile::default(),
}
}
@@ -357,12 +359,7 @@ impl User {
username: Username,
password_hash: PasswordHash,
role: UserRole,
display_name: Option<String>,
bio: Option<String>,
avatar_path: Option<String>,
banner_path: Option<String>,
also_known_as: Option<String>,
profile_fields: Vec<ProfileField>,
profile: UserProfile,
) -> Self {
Self {
id,
@@ -370,12 +367,7 @@ impl User {
username,
password_hash,
role,
display_name,
bio,
avatar_path,
banner_path,
also_known_as,
profile_fields,
profile,
}
}
@@ -383,19 +375,8 @@ impl User {
self.password_hash = new_hash;
}
pub fn update_profile(
&mut self,
display_name: Option<String>,
bio: Option<String>,
avatar_path: Option<String>,
banner_path: Option<String>,
also_known_as: Option<String>,
) {
self.display_name = display_name;
self.bio = bio;
self.avatar_path = avatar_path;
self.banner_path = banner_path;
self.also_known_as = also_known_as;
pub fn update_profile(&mut self, profile: UserProfile) {
self.profile = profile;
}
pub fn email(&self) -> &Email {
@@ -414,26 +395,22 @@ impl User {
&self.role
}
pub fn display_name(&self) -> Option<&str> {
self.display_name.as_deref()
self.profile.display_name.as_deref()
}
pub fn bio(&self) -> Option<&str> {
self.bio.as_deref()
self.profile.bio.as_deref()
}
pub fn avatar_path(&self) -> Option<&str> {
self.avatar_path.as_deref()
self.profile.avatar_path.as_deref()
}
pub fn banner_path(&self) -> Option<&str> {
self.banner_path.as_deref()
self.profile.banner_path.as_deref()
}
pub fn also_known_as(&self) -> Option<&str> {
self.also_known_as.as_deref()
self.profile.also_known_as.as_deref()
}
pub fn profile_fields(&self) -> &[ProfileField] {
&self.profile_fields
&self.profile.profile_fields
}
}

View File

@@ -8,23 +8,18 @@ fn make_user() -> User {
Username::new("alice".to_string()).unwrap(),
PasswordHash::new("hash".to_string()).unwrap(),
UserRole::Standard,
None,
None,
None,
None,
vec![],
UserProfile::default(),
)
}
#[test]
fn update_profile_sets_fields() {
let mut user = make_user();
user.update_profile(
Some("My bio".to_string()),
Some("avatars/abc".to_string()),
None,
None,
);
user.update_profile(UserProfile {
bio: Some("My bio".to_string()),
avatar_path: Some("avatars/abc".to_string()),
..Default::default()
});
assert_eq!(user.bio(), Some("My bio"));
assert_eq!(user.avatar_path(), Some("avatars/abc"));
}
@@ -32,13 +27,12 @@ fn update_profile_sets_fields() {
#[test]
fn update_profile_clears_with_none() {
let mut user = make_user();
user.update_profile(
Some("bio".to_string()),
Some("path".to_string()),
None,
None,
);
user.update_profile(None, None, None, None);
user.update_profile(UserProfile {
bio: Some("bio".to_string()),
avatar_path: Some("path".to_string()),
..Default::default()
});
user.update_profile(UserProfile::default());
assert_eq!(user.bio(), None);
assert_eq!(user.avatar_path(), None);
}

View File

@@ -33,14 +33,15 @@ pub enum FeedSortBy {
RatingAsc,
}
impl FeedSortBy {
pub fn from_str(s: &str) -> Self {
match s {
impl std::str::FromStr for FeedSortBy {
type Err = std::convert::Infallible;
fn from_str(s: &str) -> Result<Self, Self::Err> {
Ok(match s {
"date_asc" => Self::DateAsc,
"rating" => Self::Rating,
"rating_asc" => Self::RatingAsc,
_ => Self::Date,
}
})
}
}
@@ -185,11 +186,7 @@ pub trait UserRepository: Send + Sync {
async fn update_profile(
&self,
user_id: &UserId,
display_name: Option<String>,
bio: Option<String>,
avatar_path: Option<String>,
banner_path: Option<String>,
also_known_as: Option<String>,
profile: &crate::models::UserProfile,
) -> Result<(), DomainError>;
}

View File

@@ -219,10 +219,7 @@ impl UserRepository for InMemoryUserRepository {
async fn update_profile(
&self,
_user_id: &UserId,
_bio: Option<String>,
_avatar_path: Option<String>,
_banner_path: Option<String>,
_also_known_as: Option<String>,
_profile: &crate::models::UserProfile,
) -> Result<(), DomainError> {
Ok(())
}