mirror of
https://github.com/coder/coder.git
synced 2026-09-24 15:04:27 +08:00
chore: add templates search query to a filter (#13772)
* chore: add templates search query to a filter
This commit is contained in:
@@ -184,6 +184,52 @@ func Workspaces(query string, page codersdk.Pagination, agentInactiveDisconnectT
|
||||
return filter, parser.Errors
|
||||
}
|
||||
|
||||
func Templates(ctx context.Context, db database.Store, query string) (database.GetTemplatesWithFilterParams, []codersdk.ValidationError) {
|
||||
// Always lowercase for all searches.
|
||||
query = strings.ToLower(query)
|
||||
values, errors := searchTerms(query, func(term string, values url.Values) error {
|
||||
// Default to the template name
|
||||
values.Add("name", term)
|
||||
return nil
|
||||
})
|
||||
if len(errors) > 0 {
|
||||
return database.GetTemplatesWithFilterParams{}, errors
|
||||
}
|
||||
|
||||
parser := httpapi.NewQueryParamParser()
|
||||
filter := database.GetTemplatesWithFilterParams{
|
||||
Deleted: parser.Boolean(values, false, "deleted"),
|
||||
// TODO: Should name be a fuzzy search?
|
||||
ExactName: parser.String(values, "", "name"),
|
||||
IDs: parser.UUIDs(values, []uuid.UUID{}, "ids"),
|
||||
Deprecated: parser.NullableBoolean(values, sql.NullBool{}, "deprecated"),
|
||||
}
|
||||
|
||||
// Convert the "organization" parameter to an organization uuid. This can require
|
||||
// a database lookup.
|
||||
organizationArg := parser.String(values, "", "organization")
|
||||
if organizationArg != "" {
|
||||
organizationID, err := uuid.Parse(organizationArg)
|
||||
if err == nil {
|
||||
filter.OrganizationID = organizationID
|
||||
} else {
|
||||
// Organization could be a name
|
||||
organization, err := db.GetOrganizationByName(ctx, organizationArg)
|
||||
if err != nil {
|
||||
parser.Errors = append(parser.Errors, codersdk.ValidationError{
|
||||
Field: "organization",
|
||||
Detail: fmt.Sprintf("Organization %q either does not exist, or you are unauthorized to view it", organizationArg),
|
||||
})
|
||||
} else {
|
||||
filter.OrganizationID = organization.ID
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
parser.ErrorExcessParams(values)
|
||||
return filter, parser.Errors
|
||||
}
|
||||
|
||||
func searchTerms(query string, defaultKey func(term string, values url.Values) error) (url.Values, []codersdk.ValidationError) {
|
||||
searchValues := make(url.Values)
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
@@ -454,3 +455,45 @@ func TestSearchUsers(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestSearchTemplates(t *testing.T) {
|
||||
t.Parallel()
|
||||
testCases := []struct {
|
||||
Name string
|
||||
Query string
|
||||
Expected database.GetTemplatesWithFilterParams
|
||||
ExpectedErrorContains string
|
||||
}{
|
||||
{
|
||||
Name: "Empty",
|
||||
Query: "",
|
||||
Expected: database.GetTemplatesWithFilterParams{},
|
||||
},
|
||||
}
|
||||
|
||||
for _, c := range testCases {
|
||||
c := c
|
||||
t.Run(c.Name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
// Do not use a real database, this is only used for an
|
||||
// organization lookup.
|
||||
db := dbmem.New()
|
||||
values, errs := searchquery.Templates(context.Background(), db, c.Query)
|
||||
if c.ExpectedErrorContains != "" {
|
||||
require.True(t, len(errs) > 0, "expect some errors")
|
||||
var s strings.Builder
|
||||
for _, err := range errs {
|
||||
_, _ = s.WriteString(fmt.Sprintf("%s: %s\n", err.Field, err.Detail))
|
||||
}
|
||||
require.Contains(t, s.String(), c.ExpectedErrorContains)
|
||||
} else {
|
||||
require.Len(t, errs, 0, "expected no error")
|
||||
if c.Expected.IDs == nil {
|
||||
// Nil and length 0 are the same
|
||||
c.Expected.IDs = []uuid.UUID{}
|
||||
}
|
||||
require.Equal(t, c.Expected, values, "expected values")
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user