CI: Apply Go linter recommendations to "internal/form" package #5330

Signed-off-by: Michael Mayer <michael@photoprism.app>
This commit is contained in:
Michael Mayer 2025-11-22 12:09:21 +01:00
parent c909c0bd5a
commit 7391066fb0
24 changed files with 93 additions and 34 deletions

View file

@ -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
}

View file

@ -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"))

View file

@ -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)

View file

@ -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)

View file

@ -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)

View file

@ -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)

View file

@ -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"`

View file

@ -1,5 +1,6 @@
package form
// IndexOptions configure index paths and maintenance flags.
type IndexOptions struct {
Path string `json:"path"`
Rescan bool `json:"rescan"`

View file

@ -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:

View file

@ -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:

View file

@ -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()

View file

@ -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}
}

View file

@ -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}
}

View file

@ -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)
}

View file

@ -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}
}

View file

@ -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}
}

View file

@ -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}
}

View file

@ -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}
}

View file

@ -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)
}

View file

@ -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))
}
}

View file

@ -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}
}

View file

@ -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"`

View file

@ -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)

View file

@ -1,5 +1,6 @@
package form
// UploadOptions holds album assignment options for uploads.
type UploadOptions struct {
Albums []string `json:"albums"`
}