mirror of
https://github.com/coder/coder.git
synced 2026-09-24 15:04:27 +08:00
feat: add oauth2 token exchange (#12196)
Co-authored-by: Steven Masley <stevenmasley@gmail.com>
This commit is contained in:
@@ -23,16 +23,16 @@ type QueryParamParser struct {
|
||||
// Parsed is a map of all query params that were parsed. This is useful
|
||||
// for checking if extra query params were passed in.
|
||||
Parsed map[string]bool
|
||||
// RequiredParams is a map of all query params that are required. This is useful
|
||||
// RequiredNotEmptyParams is a map of all query params that are required. This is useful
|
||||
// for forcing a value to be provided.
|
||||
RequiredParams map[string]bool
|
||||
RequiredNotEmptyParams map[string]bool
|
||||
}
|
||||
|
||||
func NewQueryParamParser() *QueryParamParser {
|
||||
return &QueryParamParser{
|
||||
Errors: []codersdk.ValidationError{},
|
||||
Parsed: map[string]bool{},
|
||||
RequiredParams: map[string]bool{},
|
||||
Errors: []codersdk.ValidationError{},
|
||||
Parsed: map[string]bool{},
|
||||
RequiredNotEmptyParams: map[string]bool{},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -90,8 +90,10 @@ func (p *QueryParamParser) Boolean(vals url.Values, def bool, queryParam string)
|
||||
return v
|
||||
}
|
||||
|
||||
func (p *QueryParamParser) Required(queryParam string) *QueryParamParser {
|
||||
p.RequiredParams[queryParam] = true
|
||||
func (p *QueryParamParser) RequiredNotEmpty(queryParam ...string) *QueryParamParser {
|
||||
for _, q := range queryParam {
|
||||
p.RequiredNotEmptyParams[q] = true
|
||||
}
|
||||
return p
|
||||
}
|
||||
|
||||
@@ -121,6 +123,27 @@ func (p *QueryParamParser) UUIDs(vals url.Values, def []uuid.UUID, queryParam st
|
||||
})
|
||||
}
|
||||
|
||||
func (p *QueryParamParser) RedirectURL(vals url.Values, base *url.URL, queryParam string) *url.URL {
|
||||
v, err := parseQueryParam(p, vals, url.Parse, base, queryParam)
|
||||
if err != nil {
|
||||
p.Errors = append(p.Errors, codersdk.ValidationError{
|
||||
Field: queryParam,
|
||||
Detail: fmt.Sprintf("Query param %q must be a valid url: %s", queryParam, err.Error()),
|
||||
})
|
||||
}
|
||||
|
||||
// It can be a sub-directory but not a sub-domain, as we have apps on
|
||||
// sub-domains and that seems too dangerous.
|
||||
if v.Host != base.Host || !strings.HasPrefix(v.Path, base.Path) {
|
||||
p.Errors = append(p.Errors, codersdk.ValidationError{
|
||||
Field: queryParam,
|
||||
Detail: fmt.Sprintf("Query param %q must be a subset of %s", queryParam, base),
|
||||
})
|
||||
}
|
||||
|
||||
return v
|
||||
}
|
||||
|
||||
func (p *QueryParamParser) Time(vals url.Values, def time.Time, queryParam, layout string) time.Time {
|
||||
return p.timeWithMutate(vals, def, queryParam, layout, nil)
|
||||
}
|
||||
@@ -233,10 +256,10 @@ func ParseCustomList[T any](parser *QueryParamParser, vals url.Values, def []T,
|
||||
func parseQueryParam[T any](parser *QueryParamParser, vals url.Values, parse func(v string) (T, error), def T, queryParam string) (T, error) {
|
||||
parser.addParsed(queryParam)
|
||||
// If the query param is required and not present, return an error.
|
||||
if parser.RequiredParams[queryParam] && (!vals.Has(queryParam)) {
|
||||
if parser.RequiredNotEmptyParams[queryParam] && (!vals.Has(queryParam) || vals.Get(queryParam) == "") {
|
||||
parser.Errors = append(parser.Errors, codersdk.ValidationError{
|
||||
Field: queryParam,
|
||||
Detail: fmt.Sprintf("Query param %q is required", queryParam),
|
||||
Detail: fmt.Sprintf("Query param %q is required and cannot be empty", queryParam),
|
||||
})
|
||||
return def, nil
|
||||
}
|
||||
|
||||
@@ -320,9 +320,14 @@ func TestParseQueryParams(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
parser := httpapi.NewQueryParamParser()
|
||||
parser.Required("test_value")
|
||||
parser.RequiredNotEmpty("test_value")
|
||||
parser.UUID(url.Values{}, uuid.New(), "test_value")
|
||||
require.Len(t, parser.Errors, 1)
|
||||
|
||||
parser = httpapi.NewQueryParamParser()
|
||||
parser.RequiredNotEmpty("test_value")
|
||||
parser.String(url.Values{"test_value": {""}}, "", "test_value")
|
||||
require.Len(t, parser.Errors, 1)
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user