From 7391066fb01e4e8c71d2f4bfd721220cb57e1fd6 Mon Sep 17 00:00:00 2001 From: Michael Mayer Date: Sat, 22 Nov 2025 12:09:21 +0100 Subject: [PATCH] CI: Apply Go linter recommendations to "internal/form" package #5330 Signed-off-by: Michael Mayer --- internal/form/client.go | 14 +++++++------ internal/form/client_test.go | 4 ++-- internal/form/face.go | 1 + internal/form/feedback.go | 2 ++ internal/form/file.go | 1 + internal/form/folder.go | 1 + internal/form/import_options.go | 1 + internal/form/index_options.go | 1 + internal/form/oauth_create_token.go | 32 ++++++++++++++++------------- internal/form/oauth_revoke_token.go | 16 +++++++++------ internal/form/search.go | 2 ++ internal/form/search_albums.go | 4 ++++ internal/form/search_faces.go | 4 ++++ internal/form/search_folders.go | 3 +++ internal/form/search_labels.go | 4 ++++ internal/form/search_photos.go | 4 ++++ internal/form/search_photos_geo.go | 1 + internal/form/search_subjects.go | 4 ++++ internal/form/search_users.go | 3 +++ internal/form/serialize.go | 18 ++++++++++------ internal/form/service_search.go | 4 ++++ internal/form/service_upload.go | 1 + internal/form/subject.go | 1 + internal/form/upload_options.go | 1 + 24 files changed, 93 insertions(+), 34 deletions(-) diff --git a/internal/form/client.go b/internal/form/client.go index 2299f7dea..498acfe3a 100644 --- a/internal/form/client.go +++ b/internal/form/client.go @@ -192,11 +192,12 @@ func (f Client) Scope() string { // Expires returns the access token expiry time in seconds or 0 if not specified. func (f Client) Expires() int64 { - if f.AuthExpires > unix.Month { + switch { + case f.AuthExpires > unix.Month: return unix.Month - } else if f.AuthExpires > 0 { + case f.AuthExpires > 0: return f.AuthExpires - } else if f.AuthExpires < 0 { + case f.AuthExpires < 0: return unix.Hour } @@ -205,11 +206,12 @@ func (f Client) Expires() int64 { // Tokens returns the access token limit or 0 if not specified. func (f Client) Tokens() int64 { - if f.AuthTokens > 2147483647 { + switch { + case f.AuthTokens > 2147483647: return 2147483647 - } else if f.AuthTokens > 0 { + case f.AuthTokens > 0: return f.AuthTokens - } else if f.AuthTokens < 0 { + case f.AuthTokens < 0: return -1 } diff --git a/internal/form/client_test.go b/internal/form/client_test.go index 6f7b4ab76..edb3e74c5 100644 --- a/internal/form/client_test.go +++ b/internal/form/client_test.go @@ -40,7 +40,7 @@ func TestAddClientFromCli(t *testing.T) { assert.NoError(t, ctx.Set("provider", "client_credentials")) assert.NoError(t, ctx.Set("method", "oauth2")) - //t.Logf("ARGS: %#v", ctx.Args()) + // t.Logf("ARGS: %#v", ctx.Args()) // Check flag values. assert.True(t, ctx.IsSet("name")) @@ -69,7 +69,7 @@ func TestAddClientFromCli(t *testing.T) { assert.NoError(t, ctx.Set("provider", "")) assert.NoError(t, ctx.Set("method", "")) - //t.Logf("ARGS: %#v", ctx.Args()) + // t.Logf("ARGS: %#v", ctx.Args()) // Check flag values. assert.True(t, ctx.IsSet("id")) diff --git a/internal/form/face.go b/internal/form/face.go index 443490a51..267a4d81e 100644 --- a/internal/form/face.go +++ b/internal/form/face.go @@ -8,6 +8,7 @@ type Face struct { SubjUID string `json:"SubjUID"` } +// NewFace copies values from an arbitrary model into a Face form. func NewFace(m interface{}) (f Face, err error) { err = deepcopier.Copy(m).To(&f) diff --git a/internal/form/feedback.go b/internal/form/feedback.go index 15d2cc432..615031348 100644 --- a/internal/form/feedback.go +++ b/internal/form/feedback.go @@ -12,10 +12,12 @@ type Feedback struct { UserLocales string `json:"UserLocales"` } +// Empty reports whether the feedback form lacks required content. func (f Feedback) Empty() bool { return len(f.Category) < 1 || len(f.Message) < 3 || len(f.UserEmail) < 5 } +// NewFeedback copies values from an arbitrary model into a Feedback form. func NewFeedback(m interface{}) (f Feedback, err error) { err = deepcopier.Copy(m).To(&f) diff --git a/internal/form/file.go b/internal/form/file.go index 6cf5880c0..c73274a57 100644 --- a/internal/form/file.go +++ b/internal/form/file.go @@ -16,6 +16,7 @@ func (f *File) Orientation() int { return clean.Orientation(f.FileOrientation) } +// NewFile copies values from an arbitrary model into a File form. func NewFile(m interface{}) (f File, err error) { err = deepcopier.Copy(m).To(&f) diff --git a/internal/form/folder.go b/internal/form/folder.go index 72dda0b76..d0da3edb8 100644 --- a/internal/form/folder.go +++ b/internal/form/folder.go @@ -20,6 +20,7 @@ type Folder struct { FolderWatch bool `json:"Watch"` } +// NewFolder copies values from an arbitrary model into a Folder form. func NewFolder(m interface{}) (f Folder, err error) { err = deepcopier.Copy(m).To(&f) diff --git a/internal/form/import_options.go b/internal/form/import_options.go index d1a5190af..c4a0818fc 100644 --- a/internal/form/import_options.go +++ b/internal/form/import_options.go @@ -1,5 +1,6 @@ package form +// ImportOptions holds import path and album assignment flags. type ImportOptions struct { Albums []string `json:"albums"` Path string `json:"path"` diff --git a/internal/form/index_options.go b/internal/form/index_options.go index d8177015a..c59c75503 100644 --- a/internal/form/index_options.go +++ b/internal/form/index_options.go @@ -1,5 +1,6 @@ package form +// IndexOptions configure index paths and maintenance flags. type IndexOptions struct { Path string `json:"path"` Rescan bool `json:"rescan"` diff --git a/internal/form/oauth_create_token.go b/internal/form/oauth_create_token.go index 8285b957c..1abd0f2b0 100644 --- a/internal/form/oauth_create_token.go +++ b/internal/form/oauth_create_token.go @@ -29,42 +29,46 @@ func (f OAuthCreateToken) Validate() error { switch f.GrantType { case authn.GrantClientCredentials, authn.GrantUndefined: // Validate client id. - if f.ClientID == "" { + switch { + case f.ClientID == "": return authn.ErrClientIDRequired - } else if rnd.InvalidUID(f.ClientID, 'c') { + case rnd.InvalidUID(f.ClientID, 'c'): return authn.ErrInvalidCredentials } // Validate client secret. - if f.ClientSecret == "" { + switch { + case f.ClientSecret == "": return authn.ErrClientSecretRequired - } else if !rnd.IsAlnum(f.ClientSecret) { + case !rnd.IsAlnum(f.ClientSecret): return authn.ErrInvalidCredentials } case authn.GrantSession: // Validate request credentials. - if f.Username == "" { + switch { + case f.Username == "": return authn.ErrUsernameRequired - } else if len(f.Username) > txt.ClipUsername { + case len(f.Username) > txt.ClipUsername: return authn.ErrInvalidCredentials - } else if f.ClientName == "" { + case f.ClientName == "": return authn.ErrNameRequired - } else if f.Scope == "" { + case f.Scope == "": return authn.ErrScopeRequired } case authn.GrantPassword: // Validate request credentials. - if f.Username == "" { + switch { + case f.Username == "": return authn.ErrUsernameRequired - } else if len(f.Username) > txt.ClipUsername { + case len(f.Username) > txt.ClipUsername: return authn.ErrInvalidCredentials - } else if f.Password == "" { + case f.Password == "": return authn.ErrPasswordRequired - } else if len(f.Password) > txt.ClipPassword { + case len(f.Password) > txt.ClipPassword: return authn.ErrInvalidCredentials - } else if f.ClientName == "" { + case f.ClientName == "": return authn.ErrNameRequired - } else if f.Scope == "" { + case f.Scope == "": return authn.ErrScopeRequired } default: diff --git a/internal/form/oauth_revoke_token.go b/internal/form/oauth_revoke_token.go index 0c5467ab6..1d3ebdce5 100644 --- a/internal/form/oauth_revoke_token.go +++ b/internal/form/oauth_revoke_token.go @@ -6,8 +6,11 @@ import ( ) const ( - RefID = "ref_id" - SessionID = "session_id" + // RefID indicates a reference token identifier. + RefID = "ref_id" + // SessionID indicates a session token identifier. + SessionID = "session_id" + // AccessToken indicates a bearer access token identifier. AccessToken = "access_token" ) @@ -43,13 +46,14 @@ func (f *OAuthRevokeToken) Validate() error { switch f.TokenTypeHint { case "": - if !isRefID && !isSessionID && !isAuthAny { + switch { + case !isRefID && !isSessionID && !isAuthAny: return authn.ErrInvalidToken - } else if isRefID { + case isRefID: f.TokenTypeHint = RefID - } else if isSessionID { + case isSessionID: f.TokenTypeHint = SessionID - } else { + default: f.TokenTypeHint = AccessToken } case RefID: diff --git a/internal/form/search.go b/internal/form/search.go index 5628aa29c..9c6ac6751 100644 --- a/internal/form/search.go +++ b/internal/form/search.go @@ -1,10 +1,12 @@ package form +// SearchForm defines the minimal interface for query string parsing. type SearchForm interface { GetQuery() string SetQuery(q string) } +// ParseQueryString populates the search form fields from its query string. func ParseQueryString(f SearchForm) (result error) { q := f.GetQuery() diff --git a/internal/form/search_albums.go b/internal/form/search_albums.go index 8cc558b8b..b2f0e8e1b 100644 --- a/internal/form/search_albums.go +++ b/internal/form/search_albums.go @@ -22,18 +22,22 @@ type SearchAlbums struct { Reverse bool `form:"reverse" serialize:"-"` } +// GetQuery returns the current search query string. func (f *SearchAlbums) GetQuery() string { return f.Query } +// SetQuery stores the raw query string. func (f *SearchAlbums) SetQuery(q string) { f.Query = q } +// ParseQueryString deserializes the query string into form fields. func (f *SearchAlbums) ParseQueryString() error { return ParseQueryString(f) } +// NewAlbumSearch creates a SearchAlbums form with the provided query. func NewAlbumSearch(query string) SearchAlbums { return SearchAlbums{Query: query} } diff --git a/internal/form/search_faces.go b/internal/form/search_faces.go index 620de1e65..de0203740 100644 --- a/internal/form/search_faces.go +++ b/internal/form/search_faces.go @@ -14,18 +14,22 @@ type SearchFaces struct { Reverse bool `form:"reverse" serialize:"-"` } +// GetQuery returns the current search query string. func (f *SearchFaces) GetQuery() string { return f.Query } +// SetQuery stores the raw query string. func (f *SearchFaces) SetQuery(q string) { f.Query = q } +// ParseQueryString deserializes the query string into form fields. func (f *SearchFaces) ParseQueryString() error { return ParseQueryString(f) } +// NewFaceSearch creates a SearchFaces form with the provided query. func NewFaceSearch(query string) SearchFaces { return SearchFaces{Query: query} } diff --git a/internal/form/search_folders.go b/internal/form/search_folders.go index b8b01987c..dbdf7a0e8 100644 --- a/internal/form/search_folders.go +++ b/internal/form/search_folders.go @@ -11,14 +11,17 @@ type SearchFolders struct { Offset int `form:"offset" serialize:"-"` } +// GetQuery returns the current search query string. func (f *SearchFolders) GetQuery() string { return f.Query } +// SetQuery stores the raw query string. func (f *SearchFolders) SetQuery(q string) { f.Query = q } +// ParseQueryString deserializes the query string into form fields. func (f *SearchFolders) ParseQueryString() error { return ParseQueryString(f) } diff --git a/internal/form/search_labels.go b/internal/form/search_labels.go index 02c0f8ba9..bf3f0a88a 100644 --- a/internal/form/search_labels.go +++ b/internal/form/search_labels.go @@ -16,18 +16,22 @@ type SearchLabels struct { Reverse bool `form:"reverse" serialize:"-"` } +// GetQuery returns the current search query string. func (f *SearchLabels) GetQuery() string { return f.Query } +// SetQuery stores the raw query string. func (f *SearchLabels) SetQuery(q string) { f.Query = q } +// ParseQueryString deserializes the query string into form fields. func (f *SearchLabels) ParseQueryString() error { return ParseQueryString(f) } +// NewLabelSearch creates a SearchLabels form with the provided query. func NewLabelSearch(query string) SearchLabels { return SearchLabels{Query: query} } diff --git a/internal/form/search_photos.go b/internal/form/search_photos.go index 90921b689..4eb1a69b0 100644 --- a/internal/form/search_photos.go +++ b/internal/form/search_photos.go @@ -103,14 +103,17 @@ type SearchPhotos struct { Details bool `form:"-" serialize:"-"` // Include additional information from details table } +// GetQuery returns the current search query string. func (f *SearchPhotos) GetQuery() string { return f.Query } +// SetQuery stores the raw query string. func (f *SearchPhotos) SetQuery(q string) { f.Query = q } +// ParseQueryString deserializes the query string into form fields and applies aliases. func (f *SearchPhotos) ParseQueryString() error { if err := ParseQueryString(f); err != nil { return err @@ -180,6 +183,7 @@ func (f *SearchPhotos) FindUidOnly() bool { return f.UID != "" && f.Query == "" && f.Scope == "" && f.Filter == "" && f.Album == "" && f.Albums == "" } +// NewSearchPhotos creates a SearchPhotos form with the provided query. func NewSearchPhotos(query string) SearchPhotos { return SearchPhotos{Query: query} } diff --git a/internal/form/search_photos_geo.go b/internal/form/search_photos_geo.go index 8ac8d7c44..d1e1d5a7a 100644 --- a/internal/form/search_photos_geo.go +++ b/internal/form/search_photos_geo.go @@ -166,6 +166,7 @@ func (f *SearchPhotosGeo) FindUidOnly() bool { return f.UID != "" && f.Query == "" && f.Scope == "" && f.Filter == "" && f.Album == "" && f.Albums == "" } +// NewSearchPhotosGeo creates a SearchPhotosGeo form with the provided query. func NewSearchPhotosGeo(query string) SearchPhotosGeo { return SearchPhotosGeo{Query: query} } diff --git a/internal/form/search_subjects.go b/internal/form/search_subjects.go index d25641503..85b09df3c 100644 --- a/internal/form/search_subjects.go +++ b/internal/form/search_subjects.go @@ -19,18 +19,22 @@ type SearchSubjects struct { Reverse bool `form:"reverse" serialize:"-"` } +// GetQuery returns the current search query string. func (f *SearchSubjects) GetQuery() string { return f.Query } +// SetQuery stores the raw query string. func (f *SearchSubjects) SetQuery(q string) { f.Query = q } +// ParseQueryString deserializes the query string into form fields. func (f *SearchSubjects) ParseQueryString() error { return ParseQueryString(f) } +// NewSubjectSearch creates a SearchSubjects form with the provided query. func NewSubjectSearch(query string) SearchSubjects { return SearchSubjects{Query: query} } diff --git a/internal/form/search_users.go b/internal/form/search_users.go index 83cad6168..127f73fd4 100644 --- a/internal/form/search_users.go +++ b/internal/form/search_users.go @@ -14,14 +14,17 @@ type SearchUsers struct { Reverse bool `form:"reverse" serialize:"-"` } +// GetQuery returns the current search query string. func (f *SearchUsers) GetQuery() string { return f.Query } +// SetQuery stores the raw query string. func (f *SearchUsers) SetQuery(q string) { f.Query = q } +// ParseQueryString deserializes the query string into form fields. func (f *SearchUsers) ParseQueryString() error { return ParseQueryString(f) } diff --git a/internal/form/serialize.go b/internal/form/serialize.go index 4d61d4078..dfc1adcb4 100644 --- a/internal/form/serialize.go +++ b/internal/form/serialize.go @@ -76,6 +76,7 @@ func Serialize(f interface{}, all bool) string { return strings.Join(q, " ") } +// Unserialize parses a query string into the provided SearchForm implementation. func Unserialize(f SearchForm, q string) (result error) { var key, value []rune var escaped, isKeyValue bool @@ -110,7 +111,8 @@ func Unserialize(f SearchForm, q string) (result error) { var queryStrings []string for _, char := range q { - if unicode.IsSpace(char) && !escaped { + switch { + case unicode.IsSpace(char) && !escaped: if isKeyValue { formName := strings.ToLower(string(key)) fieldName := fieldNames[formName] @@ -145,7 +147,11 @@ func Unserialize(f SearchForm, q string) (result error) { if intValue, err := strconv.Atoi(stringValue); err != nil { result = err } else { - field.SetUint(uint64(intValue)) + if intValue < 0 { + result = fmt.Errorf("unsupported negative value for %s", formName) + } else { + field.SetUint(uint64(intValue)) + } } case string: field.SetString(clean.SearchString(stringValue)) @@ -165,13 +171,13 @@ func Unserialize(f SearchForm, q string) (result error) { isKeyValue = false key = key[:0] value = value[:0] - } else if char == ':' && !escaped { + case char == ':' && !escaped: isKeyValue = true - } else if char == '"' { + case char == '"': escaped = !escaped - } else if isKeyValue { + case isKeyValue: value = append(value, char) - } else { + default: key = append(key, unicode.ToLower(char)) } } diff --git a/internal/form/service_search.go b/internal/form/service_search.go index 878b1436a..d9e28d972 100644 --- a/internal/form/service_search.go +++ b/internal/form/service_search.go @@ -11,18 +11,22 @@ type SearchServices struct { Order string `form:"order" serialize:"-"` } +// GetQuery returns the current search query string. func (f *SearchServices) GetQuery() string { return f.Query } +// SetQuery stores the raw query string. func (f *SearchServices) SetQuery(q string) { f.Query = q } +// ParseQueryString deserializes the query string into form fields. func (f *SearchServices) ParseQueryString() error { return ParseQueryString(f) } +// NewSearchServices creates a SearchServices form with the provided query. func NewSearchServices(query string) SearchServices { return SearchServices{Query: query} } diff --git a/internal/form/service_upload.go b/internal/form/service_upload.go index 6eec19616..2a166fdd4 100644 --- a/internal/form/service_upload.go +++ b/internal/form/service_upload.go @@ -1,5 +1,6 @@ package form +// SyncUpload defines payload for syncing uploads to a remote service. type SyncUpload struct { Selection Selection `json:"selection"` Folder string `json:"folder"` diff --git a/internal/form/subject.go b/internal/form/subject.go index 9bd06e6e3..28b65afc4 100644 --- a/internal/form/subject.go +++ b/internal/form/subject.go @@ -17,6 +17,7 @@ type Subject struct { ThumbSrc string `json:"ThumbSrc"` } +// NewSubject copies values from an arbitrary model into a Subject form. func NewSubject(m interface{}) (*Subject, error) { frm := &Subject{} err := deepcopier.Copy(m).To(frm) diff --git a/internal/form/upload_options.go b/internal/form/upload_options.go index 6fc7c011f..518db643a 100644 --- a/internal/form/upload_options.go +++ b/internal/form/upload_options.go @@ -1,5 +1,6 @@ package form +// UploadOptions holds album assignment options for uploads. type UploadOptions struct { Albums []string `json:"albums"` }