ref: move httpapi.Reponse into codersdk (#2954)

This commit is contained in:
Jon Ayers
2022-07-12 19:15:02 -05:00
committed by GitHub
parent dde51f1caa
commit 7e9819f2a8
53 changed files with 524 additions and 486 deletions

View File

@ -134,7 +134,7 @@ func New(options *Options) *API {
r.Route("/api/v2", func(r chi.Router) { r.Route("/api/v2", func(r chi.Router) {
r.NotFound(func(rw http.ResponseWriter, r *http.Request) { r.NotFound(func(rw http.ResponseWriter, r *http.Request) {
httpapi.Write(rw, http.StatusNotFound, httpapi.Response{ httpapi.Write(rw, http.StatusNotFound, codersdk.Response{
Message: "Route not found.", Message: "Route not found.",
}) })
}) })
@ -144,7 +144,7 @@ func New(options *Options) *API {
debugLogRequest(api.Logger), debugLogRequest(api.Logger),
) )
r.Get("/", func(w http.ResponseWriter, r *http.Request) { r.Get("/", func(w http.ResponseWriter, r *http.Request) {
httpapi.Write(w, http.StatusOK, httpapi.Response{ httpapi.Write(w, http.StatusOK, codersdk.Response{
//nolint:gocritic //nolint:gocritic
Message: "👋", Message: "👋",
}) })

View File

@ -5,6 +5,7 @@ import (
"net/http" "net/http"
"github.com/coder/coder/coderd/httpapi" "github.com/coder/coder/coderd/httpapi"
"github.com/coder/coder/codersdk"
"cdr.dev/slog" "cdr.dev/slog"
) )
@ -22,7 +23,7 @@ func (api *API) logReportCSPViolations(rw http.ResponseWriter, r *http.Request)
err := dec.Decode(&v) err := dec.Decode(&v)
if err != nil { if err != nil {
api.Logger.Warn(ctx, "csp violation", slog.Error(err)) api.Logger.Warn(ctx, "csp violation", slog.Error(err))
httpapi.Write(rw, http.StatusBadRequest, httpapi.Response{ httpapi.Write(rw, http.StatusBadRequest, codersdk.Response{
Message: "Failed to read body, invalid json.", Message: "Failed to read body, invalid json.",
Detail: err.Error(), Detail: err.Error(),
}) })

View File

@ -32,7 +32,7 @@ func (api *API) postFile(rw http.ResponseWriter, r *http.Request) {
switch contentType { switch contentType {
case "application/x-tar": case "application/x-tar":
default: default:
httpapi.Write(rw, http.StatusBadRequest, httpapi.Response{ httpapi.Write(rw, http.StatusBadRequest, codersdk.Response{
Message: fmt.Sprintf("Unsupported content type header %q.", contentType), Message: fmt.Sprintf("Unsupported content type header %q.", contentType),
}) })
return return
@ -41,7 +41,7 @@ func (api *API) postFile(rw http.ResponseWriter, r *http.Request) {
r.Body = http.MaxBytesReader(rw, r.Body, 10*(10<<20)) r.Body = http.MaxBytesReader(rw, r.Body, 10*(10<<20))
data, err := io.ReadAll(r.Body) data, err := io.ReadAll(r.Body)
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusBadRequest, httpapi.Response{ httpapi.Write(rw, http.StatusBadRequest, codersdk.Response{
Message: "Failed to read file from request.", Message: "Failed to read file from request.",
Detail: err.Error(), Detail: err.Error(),
}) })
@ -65,7 +65,7 @@ func (api *API) postFile(rw http.ResponseWriter, r *http.Request) {
Data: data, Data: data,
}) })
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error saving file.", Message: "Internal error saving file.",
Detail: err.Error(), Detail: err.Error(),
}) })
@ -80,7 +80,7 @@ func (api *API) postFile(rw http.ResponseWriter, r *http.Request) {
func (api *API) fileByHash(rw http.ResponseWriter, r *http.Request) { func (api *API) fileByHash(rw http.ResponseWriter, r *http.Request) {
hash := chi.URLParam(r, "hash") hash := chi.URLParam(r, "hash")
if hash == "" { if hash == "" {
httpapi.Write(rw, http.StatusBadRequest, httpapi.Response{ httpapi.Write(rw, http.StatusBadRequest, codersdk.Response{
Message: "File hash must be provided in url.", Message: "File hash must be provided in url.",
}) })
return return
@ -91,7 +91,7 @@ func (api *API) fileByHash(rw http.ResponseWriter, r *http.Request) {
return return
} }
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error fetching file.", Message: "Internal error fetching file.",
Detail: err.Error(), Detail: err.Error(),
}) })

View File

@ -21,7 +21,7 @@ func (api *API) regenerateGitSSHKey(rw http.ResponseWriter, r *http.Request) {
privateKey, publicKey, err := gitsshkey.Generate(api.SSHKeygenAlgorithm) privateKey, publicKey, err := gitsshkey.Generate(api.SSHKeygenAlgorithm)
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error generating a new SSH keypair.", Message: "Internal error generating a new SSH keypair.",
Detail: err.Error(), Detail: err.Error(),
}) })
@ -35,7 +35,7 @@ func (api *API) regenerateGitSSHKey(rw http.ResponseWriter, r *http.Request) {
PublicKey: publicKey, PublicKey: publicKey,
}) })
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error updating user's git SSH key.", Message: "Internal error updating user's git SSH key.",
Detail: err.Error(), Detail: err.Error(),
}) })
@ -44,7 +44,7 @@ func (api *API) regenerateGitSSHKey(rw http.ResponseWriter, r *http.Request) {
newKey, err := api.Database.GetGitSSHKey(r.Context(), user.ID) newKey, err := api.Database.GetGitSSHKey(r.Context(), user.ID)
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error fetching user's git SSH key.", Message: "Internal error fetching user's git SSH key.",
Detail: err.Error(), Detail: err.Error(),
}) })
@ -70,7 +70,7 @@ func (api *API) gitSSHKey(rw http.ResponseWriter, r *http.Request) {
gitSSHKey, err := api.Database.GetGitSSHKey(r.Context(), user.ID) gitSSHKey, err := api.Database.GetGitSSHKey(r.Context(), user.ID)
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error fetching user's SSH key.", Message: "Internal error fetching user's SSH key.",
Detail: err.Error(), Detail: err.Error(),
}) })
@ -90,7 +90,7 @@ func (api *API) agentGitSSHKey(rw http.ResponseWriter, r *http.Request) {
agent := httpmw.WorkspaceAgent(r) agent := httpmw.WorkspaceAgent(r)
resource, err := api.Database.GetWorkspaceResourceByID(r.Context(), agent.ResourceID) resource, err := api.Database.GetWorkspaceResourceByID(r.Context(), agent.ResourceID)
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error fetching workspace resource.", Message: "Internal error fetching workspace resource.",
Detail: err.Error(), Detail: err.Error(),
}) })
@ -99,7 +99,7 @@ func (api *API) agentGitSSHKey(rw http.ResponseWriter, r *http.Request) {
job, err := api.Database.GetWorkspaceBuildByJobID(r.Context(), resource.JobID) job, err := api.Database.GetWorkspaceBuildByJobID(r.Context(), resource.JobID)
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error fetching workspace build.", Message: "Internal error fetching workspace build.",
Detail: err.Error(), Detail: err.Error(),
}) })
@ -108,7 +108,7 @@ func (api *API) agentGitSSHKey(rw http.ResponseWriter, r *http.Request) {
workspace, err := api.Database.GetWorkspaceByID(r.Context(), job.WorkspaceID) workspace, err := api.Database.GetWorkspaceByID(r.Context(), job.WorkspaceID)
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error fetching workspace.", Message: "Internal error fetching workspace.",
Detail: err.Error(), Detail: err.Error(),
}) })
@ -117,7 +117,7 @@ func (api *API) agentGitSSHKey(rw http.ResponseWriter, r *http.Request) {
gitSSHKey, err := api.Database.GetGitSSHKey(r.Context(), workspace.OwnerID) gitSSHKey, err := api.Database.GetGitSSHKey(r.Context(), workspace.OwnerID)
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error fetching git SSH key.", Message: "Internal error fetching git SSH key.",
Detail: err.Error(), Detail: err.Error(),
}) })

View File

@ -11,6 +11,8 @@ import (
"strings" "strings"
"github.com/go-playground/validator/v10" "github.com/go-playground/validator/v10"
"github.com/coder/coder/codersdk"
) )
var ( var (
@ -50,42 +52,16 @@ func init() {
} }
} }
// Response represents a generic HTTP response.
type Response struct {
// Message is an actionable message that depicts actions the request took.
// These messages should be fully formed sentences with proper punctuation.
// Examples:
// - "A user has been created."
// - "Failed to create a user."
Message string `json:"message"`
// Detail is a debug message that provides further insight into why the
// action failed. This information can be technical and a regular golang
// err.Error() text.
// - "database: too many open connections"
// - "stat: too many open files"
Detail string `json:"detail,omitempty"`
// Validations are form field-specific friendly error messages. They will be
// shown on a form field in the UI. These can also be used to add additional
// context if there is a set of errors in the primary 'Message'.
Validations []Error `json:"validations,omitempty"`
}
// Error represents a scoped error to a user input.
type Error struct {
Field string `json:"field" validate:"required"`
Detail string `json:"detail" validate:"required"`
}
// ResourceNotFound is intentionally vague. All 404 responses should be identical // ResourceNotFound is intentionally vague. All 404 responses should be identical
// to prevent leaking existence of resources. // to prevent leaking existence of resources.
func ResourceNotFound(rw http.ResponseWriter) { func ResourceNotFound(rw http.ResponseWriter) {
Write(rw, http.StatusNotFound, Response{ Write(rw, http.StatusNotFound, codersdk.Response{
Message: "Resource not found or you do not have access to this resource", Message: "Resource not found or you do not have access to this resource",
}) })
} }
func Forbidden(rw http.ResponseWriter) { func Forbidden(rw http.ResponseWriter) {
Write(rw, http.StatusForbidden, Response{ Write(rw, http.StatusForbidden, codersdk.Response{
Message: "Forbidden.", Message: "Forbidden.",
}) })
} }
@ -114,7 +90,7 @@ func Write(rw http.ResponseWriter, status int, response interface{}) {
func Read(rw http.ResponseWriter, r *http.Request, value interface{}) bool { func Read(rw http.ResponseWriter, r *http.Request, value interface{}) bool {
err := json.NewDecoder(r.Body).Decode(value) err := json.NewDecoder(r.Body).Decode(value)
if err != nil { if err != nil {
Write(rw, http.StatusBadRequest, Response{ Write(rw, http.StatusBadRequest, codersdk.Response{
Message: "Request body must be valid JSON.", Message: "Request body must be valid JSON.",
Detail: err.Error(), Detail: err.Error(),
}) })
@ -123,21 +99,21 @@ func Read(rw http.ResponseWriter, r *http.Request, value interface{}) bool {
err = validate.Struct(value) err = validate.Struct(value)
var validationErrors validator.ValidationErrors var validationErrors validator.ValidationErrors
if errors.As(err, &validationErrors) { if errors.As(err, &validationErrors) {
apiErrors := make([]Error, 0, len(validationErrors)) apiErrors := make([]codersdk.ValidationError, 0, len(validationErrors))
for _, validationError := range validationErrors { for _, validationError := range validationErrors {
apiErrors = append(apiErrors, Error{ apiErrors = append(apiErrors, codersdk.ValidationError{
Field: validationError.Field(), Field: validationError.Field(),
Detail: fmt.Sprintf("Validation failed for tag %q with value: \"%v\"", validationError.Tag(), validationError.Value()), Detail: fmt.Sprintf("Validation failed for tag %q with value: \"%v\"", validationError.Tag(), validationError.Value()),
}) })
} }
Write(rw, http.StatusBadRequest, Response{ Write(rw, http.StatusBadRequest, codersdk.Response{
Message: "Validation failed.", Message: "Validation failed.",
Validations: apiErrors, Validations: apiErrors,
}) })
return false return false
} }
if err != nil { if err != nil {
Write(rw, http.StatusInternalServerError, Response{ Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error validating request body payload.", Message: "Internal error validating request body payload.",
Detail: err.Error(), Detail: err.Error(),
}) })

View File

@ -12,6 +12,7 @@ import (
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
"github.com/coder/coder/coderd/httpapi" "github.com/coder/coder/coderd/httpapi"
"github.com/coder/coder/codersdk"
) )
func TestWrite(t *testing.T) { func TestWrite(t *testing.T) {
@ -19,7 +20,7 @@ func TestWrite(t *testing.T) {
t.Run("NoErrors", func(t *testing.T) { t.Run("NoErrors", func(t *testing.T) {
t.Parallel() t.Parallel()
rw := httptest.NewRecorder() rw := httptest.NewRecorder()
httpapi.Write(rw, http.StatusOK, httpapi.Response{ httpapi.Write(rw, http.StatusOK, codersdk.Response{
Message: "Wow.", Message: "Wow.",
}) })
var m map[string]interface{} var m map[string]interface{}
@ -71,7 +72,7 @@ func TestRead(t *testing.T) {
var validate toValidate var validate toValidate
require.False(t, httpapi.Read(rw, r, &validate)) require.False(t, httpapi.Read(rw, r, &validate))
var v httpapi.Response var v codersdk.Response
err := json.NewDecoder(rw.Body).Decode(&v) err := json.NewDecoder(rw.Body).Decode(&v)
require.NoError(t, err) require.NoError(t, err)
require.Len(t, v.Validations, 1) require.Len(t, v.Validations, 1)

View File

@ -8,6 +8,8 @@ import (
"github.com/google/uuid" "github.com/google/uuid"
"github.com/coder/coder/codersdk"
"golang.org/x/xerrors" "golang.org/x/xerrors"
) )
@ -17,19 +19,19 @@ import (
type QueryParamParser struct { type QueryParamParser struct {
// Errors is the set of errors to return via the API. If the length // Errors is the set of errors to return via the API. If the length
// of this set is 0, there are no errors!. // of this set is 0, there are no errors!.
Errors []Error Errors []codersdk.ValidationError
} }
func NewQueryParamParser() *QueryParamParser { func NewQueryParamParser() *QueryParamParser {
return &QueryParamParser{ return &QueryParamParser{
Errors: []Error{}, Errors: []codersdk.ValidationError{},
} }
} }
func (p *QueryParamParser) Int(vals url.Values, def int, queryParam string) int { func (p *QueryParamParser) Int(vals url.Values, def int, queryParam string) int {
v, err := parseQueryParam(vals, strconv.Atoi, def, queryParam) v, err := parseQueryParam(vals, strconv.Atoi, def, queryParam)
if err != nil { if err != nil {
p.Errors = append(p.Errors, Error{ p.Errors = append(p.Errors, codersdk.ValidationError{
Field: queryParam, Field: queryParam,
Detail: fmt.Sprintf("Query param %q must be a valid integer (%s)", queryParam, err.Error()), Detail: fmt.Sprintf("Query param %q must be a valid integer (%s)", queryParam, err.Error()),
}) })
@ -47,7 +49,7 @@ func (p *QueryParamParser) UUIDorMe(vals url.Values, def uuid.UUID, me uuid.UUID
func (p *QueryParamParser) UUID(vals url.Values, def uuid.UUID, queryParam string) uuid.UUID { func (p *QueryParamParser) UUID(vals url.Values, def uuid.UUID, queryParam string) uuid.UUID {
v, err := parseQueryParam(vals, uuid.Parse, def, queryParam) v, err := parseQueryParam(vals, uuid.Parse, def, queryParam)
if err != nil { if err != nil {
p.Errors = append(p.Errors, Error{ p.Errors = append(p.Errors, codersdk.ValidationError{
Field: queryParam, Field: queryParam,
Detail: fmt.Sprintf("Query param %q must be a valid uuid", queryParam), Detail: fmt.Sprintf("Query param %q must be a valid uuid", queryParam),
}) })
@ -75,7 +77,7 @@ func (p *QueryParamParser) UUIDs(vals url.Values, def []uuid.UUID, queryParam st
return ids, nil return ids, nil
}, def, queryParam) }, def, queryParam)
if err != nil { if err != nil {
p.Errors = append(p.Errors, Error{ p.Errors = append(p.Errors, codersdk.ValidationError{
Field: queryParam, Field: queryParam,
Detail: fmt.Sprintf("Query param %q has invalid uuids: %q", queryParam, err.Error()), Detail: fmt.Sprintf("Query param %q has invalid uuids: %q", queryParam, err.Error()),
}) })
@ -105,7 +107,7 @@ func (*QueryParamParser) Strings(vals url.Values, def []string, queryParam strin
func ParseCustom[T any](parser *QueryParamParser, vals url.Values, def T, queryParam string, parseFunc func(v string) (T, error)) T { func ParseCustom[T any](parser *QueryParamParser, vals url.Values, def T, queryParam string, parseFunc func(v string) (T, error)) T {
v, err := parseQueryParam(vals, parseFunc, def, queryParam) v, err := parseQueryParam(vals, parseFunc, def, queryParam)
if err != nil { if err != nil {
parser.Errors = append(parser.Errors, Error{ parser.Errors = append(parser.Errors, codersdk.ValidationError{
Field: queryParam, Field: queryParam,
Detail: fmt.Sprintf("Query param %q has invalid value: %s", queryParam, err.Error()), Detail: fmt.Sprintf("Query param %q has invalid value: %s", queryParam, err.Error()),
}) })

View File

@ -18,11 +18,9 @@ import (
"github.com/coder/coder/coderd/database" "github.com/coder/coder/coderd/database"
"github.com/coder/coder/coderd/httpapi" "github.com/coder/coder/coderd/httpapi"
"github.com/coder/coder/codersdk"
) )
// SessionTokenKey represents the name of the cookie or query parameter the API key is stored in.
const SessionTokenKey = "session_token"
type apiKeyContextKey struct{} type apiKeyContextKey struct{}
// APIKey returns the API key from the ExtractAPIKey handler. // APIKey returns the API key from the ExtractAPIKey handler.
@ -63,7 +61,7 @@ func ExtractAPIKey(db database.Store, oauth *OAuth2Configs, redirectToLogin bool
// Write wraps writing a response to redirect if the handler // Write wraps writing a response to redirect if the handler
// specified it should. This redirect is used for user-facing // specified it should. This redirect is used for user-facing
// pages like workspace applications. // pages like workspace applications.
write := func(code int, response httpapi.Response) { write := func(code int, response codersdk.Response) {
if redirectToLogin { if redirectToLogin {
q := r.URL.Query() q := r.URL.Query()
q.Add("message", response.Message) q.Add("message", response.Message)
@ -77,23 +75,23 @@ func ExtractAPIKey(db database.Store, oauth *OAuth2Configs, redirectToLogin bool
} }
var cookieValue string var cookieValue string
cookie, err := r.Cookie(SessionTokenKey) cookie, err := r.Cookie(codersdk.SessionTokenKey)
if err != nil { if err != nil {
cookieValue = r.URL.Query().Get(SessionTokenKey) cookieValue = r.URL.Query().Get(codersdk.SessionTokenKey)
} else { } else {
cookieValue = cookie.Value cookieValue = cookie.Value
} }
if cookieValue == "" { if cookieValue == "" {
write(http.StatusUnauthorized, httpapi.Response{ write(http.StatusUnauthorized, codersdk.Response{
Message: fmt.Sprintf("Cookie %q or query parameter must be provided.", SessionTokenKey), Message: fmt.Sprintf("Cookie %q or query parameter must be provided.", codersdk.SessionTokenKey),
}) })
return return
} }
parts := strings.Split(cookieValue, "-") parts := strings.Split(cookieValue, "-")
// APIKeys are formatted: ID-SECRET // APIKeys are formatted: ID-SECRET
if len(parts) != 2 { if len(parts) != 2 {
write(http.StatusUnauthorized, httpapi.Response{ write(http.StatusUnauthorized, codersdk.Response{
Message: fmt.Sprintf("Invalid %q cookie API key format.", SessionTokenKey), Message: fmt.Sprintf("Invalid %q cookie API key format.", codersdk.SessionTokenKey),
}) })
return return
} }
@ -101,26 +99,26 @@ func ExtractAPIKey(db database.Store, oauth *OAuth2Configs, redirectToLogin bool
keySecret := parts[1] keySecret := parts[1]
// Ensuring key lengths are valid. // Ensuring key lengths are valid.
if len(keyID) != 10 { if len(keyID) != 10 {
write(http.StatusUnauthorized, httpapi.Response{ write(http.StatusUnauthorized, codersdk.Response{
Message: fmt.Sprintf("Invalid %q cookie API key id.", SessionTokenKey), Message: fmt.Sprintf("Invalid %q cookie API key id.", codersdk.SessionTokenKey),
}) })
return return
} }
if len(keySecret) != 22 { if len(keySecret) != 22 {
write(http.StatusUnauthorized, httpapi.Response{ write(http.StatusUnauthorized, codersdk.Response{
Message: fmt.Sprintf("Invalid %q cookie API key secret.", SessionTokenKey), Message: fmt.Sprintf("Invalid %q cookie API key secret.", codersdk.SessionTokenKey),
}) })
return return
} }
key, err := db.GetAPIKeyByID(r.Context(), keyID) key, err := db.GetAPIKeyByID(r.Context(), keyID)
if err != nil { if err != nil {
if errors.Is(err, sql.ErrNoRows) { if errors.Is(err, sql.ErrNoRows) {
write(http.StatusUnauthorized, httpapi.Response{ write(http.StatusUnauthorized, codersdk.Response{
Message: "API key is invalid.", Message: "API key is invalid.",
}) })
return return
} }
write(http.StatusInternalServerError, httpapi.Response{ write(http.StatusInternalServerError, codersdk.Response{
Message: "Internal error fetching API key by id.", Message: "Internal error fetching API key by id.",
Detail: err.Error(), Detail: err.Error(),
}) })
@ -130,7 +128,7 @@ func ExtractAPIKey(db database.Store, oauth *OAuth2Configs, redirectToLogin bool
// Checking to see if the secret is valid. // Checking to see if the secret is valid.
if subtle.ConstantTimeCompare(key.HashedSecret, hashed[:]) != 1 { if subtle.ConstantTimeCompare(key.HashedSecret, hashed[:]) != 1 {
write(http.StatusUnauthorized, httpapi.Response{ write(http.StatusUnauthorized, codersdk.Response{
Message: "API key secret is invalid.", Message: "API key secret is invalid.",
}) })
return return
@ -147,7 +145,7 @@ func ExtractAPIKey(db database.Store, oauth *OAuth2Configs, redirectToLogin bool
case database.LoginTypeGithub: case database.LoginTypeGithub:
oauthConfig = oauth.Github oauthConfig = oauth.Github
default: default:
write(http.StatusInternalServerError, httpapi.Response{ write(http.StatusInternalServerError, codersdk.Response{
Message: fmt.Sprintf("Unexpected authentication type %q.", key.LoginType), Message: fmt.Sprintf("Unexpected authentication type %q.", key.LoginType),
}) })
return return
@ -159,7 +157,7 @@ func ExtractAPIKey(db database.Store, oauth *OAuth2Configs, redirectToLogin bool
Expiry: key.OAuthExpiry, Expiry: key.OAuthExpiry,
}).Token() }).Token()
if err != nil { if err != nil {
write(http.StatusUnauthorized, httpapi.Response{ write(http.StatusUnauthorized, codersdk.Response{
Message: "Could not refresh expired Oauth token.", Message: "Could not refresh expired Oauth token.",
Detail: err.Error(), Detail: err.Error(),
}) })
@ -175,7 +173,7 @@ func ExtractAPIKey(db database.Store, oauth *OAuth2Configs, redirectToLogin bool
// Checking if the key is expired. // Checking if the key is expired.
if key.ExpiresAt.Before(now) { if key.ExpiresAt.Before(now) {
write(http.StatusUnauthorized, httpapi.Response{ write(http.StatusUnauthorized, codersdk.Response{
Message: fmt.Sprintf("API key expired at %q.", key.ExpiresAt.String()), Message: fmt.Sprintf("API key expired at %q.", key.ExpiresAt.String()),
}) })
return return
@ -217,7 +215,7 @@ func ExtractAPIKey(db database.Store, oauth *OAuth2Configs, redirectToLogin bool
OAuthExpiry: key.OAuthExpiry, OAuthExpiry: key.OAuthExpiry,
}) })
if err != nil { if err != nil {
write(http.StatusInternalServerError, httpapi.Response{ write(http.StatusInternalServerError, codersdk.Response{
Message: fmt.Sprintf("API key couldn't update: %s.", err.Error()), Message: fmt.Sprintf("API key couldn't update: %s.", err.Error()),
}) })
return return
@ -229,7 +227,7 @@ func ExtractAPIKey(db database.Store, oauth *OAuth2Configs, redirectToLogin bool
// is to block 'suspended' users from accessing the platform. // is to block 'suspended' users from accessing the platform.
roles, err := db.GetAuthorizationUserRoles(r.Context(), key.UserID) roles, err := db.GetAuthorizationUserRoles(r.Context(), key.UserID)
if err != nil { if err != nil {
write(http.StatusUnauthorized, httpapi.Response{ write(http.StatusUnauthorized, codersdk.Response{
Message: "Internal error fetching user's roles.", Message: "Internal error fetching user's roles.",
Detail: err.Error(), Detail: err.Error(),
}) })
@ -237,7 +235,7 @@ func ExtractAPIKey(db database.Store, oauth *OAuth2Configs, redirectToLogin bool
} }
if roles.Status != database.UserStatusActive { if roles.Status != database.UserStatusActive {
write(http.StatusUnauthorized, httpapi.Response{ write(http.StatusUnauthorized, codersdk.Response{
Message: fmt.Sprintf("User is not active (status = %q). Contact an admin to reactivate your account.", roles.Status), Message: fmt.Sprintf("User is not active (status = %q). Contact an admin to reactivate your account.", roles.Status),
}) })
return return

View File

@ -18,6 +18,7 @@ import (
"github.com/coder/coder/coderd/database/databasefake" "github.com/coder/coder/coderd/database/databasefake"
"github.com/coder/coder/coderd/httpapi" "github.com/coder/coder/coderd/httpapi"
"github.com/coder/coder/coderd/httpmw" "github.com/coder/coder/coderd/httpmw"
"github.com/coder/coder/codersdk"
"github.com/coder/coder/cryptorand" "github.com/coder/coder/cryptorand"
) )
@ -32,7 +33,7 @@ func TestAPIKey(t *testing.T) {
successHandler := http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) { successHandler := http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
// Only called if the API key passes through the handler. // Only called if the API key passes through the handler.
httpapi.Write(rw, http.StatusOK, httpapi.Response{ httpapi.Write(rw, http.StatusOK, codersdk.Response{
Message: "It worked!", Message: "It worked!",
}) })
}) })
@ -74,7 +75,7 @@ func TestAPIKey(t *testing.T) {
rw = httptest.NewRecorder() rw = httptest.NewRecorder()
) )
r.AddCookie(&http.Cookie{ r.AddCookie(&http.Cookie{
Name: httpmw.SessionTokenKey, Name: codersdk.SessionTokenKey,
Value: "test-wow-hello", Value: "test-wow-hello",
}) })
@ -92,7 +93,7 @@ func TestAPIKey(t *testing.T) {
rw = httptest.NewRecorder() rw = httptest.NewRecorder()
) )
r.AddCookie(&http.Cookie{ r.AddCookie(&http.Cookie{
Name: httpmw.SessionTokenKey, Name: codersdk.SessionTokenKey,
Value: "test-wow", Value: "test-wow",
}) })
@ -110,7 +111,7 @@ func TestAPIKey(t *testing.T) {
rw = httptest.NewRecorder() rw = httptest.NewRecorder()
) )
r.AddCookie(&http.Cookie{ r.AddCookie(&http.Cookie{
Name: httpmw.SessionTokenKey, Name: codersdk.SessionTokenKey,
Value: "testtestid-wow", Value: "testtestid-wow",
}) })
@ -129,7 +130,7 @@ func TestAPIKey(t *testing.T) {
rw = httptest.NewRecorder() rw = httptest.NewRecorder()
) )
r.AddCookie(&http.Cookie{ r.AddCookie(&http.Cookie{
Name: httpmw.SessionTokenKey, Name: codersdk.SessionTokenKey,
Value: fmt.Sprintf("%s-%s", id, secret), Value: fmt.Sprintf("%s-%s", id, secret),
}) })
@ -149,7 +150,7 @@ func TestAPIKey(t *testing.T) {
user = createUser(r.Context(), t, db) user = createUser(r.Context(), t, db)
) )
r.AddCookie(&http.Cookie{ r.AddCookie(&http.Cookie{
Name: httpmw.SessionTokenKey, Name: codersdk.SessionTokenKey,
Value: fmt.Sprintf("%s-%s", id, secret), Value: fmt.Sprintf("%s-%s", id, secret),
}) })
@ -178,7 +179,7 @@ func TestAPIKey(t *testing.T) {
user = createUser(r.Context(), t, db) user = createUser(r.Context(), t, db)
) )
r.AddCookie(&http.Cookie{ r.AddCookie(&http.Cookie{
Name: httpmw.SessionTokenKey, Name: codersdk.SessionTokenKey,
Value: fmt.Sprintf("%s-%s", id, secret), Value: fmt.Sprintf("%s-%s", id, secret),
}) })
@ -205,7 +206,7 @@ func TestAPIKey(t *testing.T) {
user = createUser(r.Context(), t, db) user = createUser(r.Context(), t, db)
) )
r.AddCookie(&http.Cookie{ r.AddCookie(&http.Cookie{
Name: httpmw.SessionTokenKey, Name: codersdk.SessionTokenKey,
Value: fmt.Sprintf("%s-%s", id, secret), Value: fmt.Sprintf("%s-%s", id, secret),
}) })
@ -219,7 +220,7 @@ func TestAPIKey(t *testing.T) {
httpmw.ExtractAPIKey(db, nil, false)(http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) { httpmw.ExtractAPIKey(db, nil, false)(http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
// Checks that it exists on the context! // Checks that it exists on the context!
_ = httpmw.APIKey(r) _ = httpmw.APIKey(r)
httpapi.Write(rw, http.StatusOK, httpapi.Response{ httpapi.Write(rw, http.StatusOK, codersdk.Response{
Message: "It worked!", Message: "It worked!",
}) })
})).ServeHTTP(rw, r) })).ServeHTTP(rw, r)
@ -244,7 +245,7 @@ func TestAPIKey(t *testing.T) {
user = createUser(r.Context(), t, db) user = createUser(r.Context(), t, db)
) )
q := r.URL.Query() q := r.URL.Query()
q.Add(httpmw.SessionTokenKey, fmt.Sprintf("%s-%s", id, secret)) q.Add(codersdk.SessionTokenKey, fmt.Sprintf("%s-%s", id, secret))
r.URL.RawQuery = q.Encode() r.URL.RawQuery = q.Encode()
_, err := db.InsertAPIKey(r.Context(), database.InsertAPIKeyParams{ _, err := db.InsertAPIKey(r.Context(), database.InsertAPIKeyParams{
@ -257,7 +258,7 @@ func TestAPIKey(t *testing.T) {
httpmw.ExtractAPIKey(db, nil, false)(http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) { httpmw.ExtractAPIKey(db, nil, false)(http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
// Checks that it exists on the context! // Checks that it exists on the context!
_ = httpmw.APIKey(r) _ = httpmw.APIKey(r)
httpapi.Write(rw, http.StatusOK, httpapi.Response{ httpapi.Write(rw, http.StatusOK, codersdk.Response{
Message: "It worked!", Message: "It worked!",
}) })
})).ServeHTTP(rw, r) })).ServeHTTP(rw, r)
@ -277,7 +278,7 @@ func TestAPIKey(t *testing.T) {
user = createUser(r.Context(), t, db) user = createUser(r.Context(), t, db)
) )
r.AddCookie(&http.Cookie{ r.AddCookie(&http.Cookie{
Name: httpmw.SessionTokenKey, Name: codersdk.SessionTokenKey,
Value: fmt.Sprintf("%s-%s", id, secret), Value: fmt.Sprintf("%s-%s", id, secret),
}) })
@ -312,7 +313,7 @@ func TestAPIKey(t *testing.T) {
user = createUser(r.Context(), t, db) user = createUser(r.Context(), t, db)
) )
r.AddCookie(&http.Cookie{ r.AddCookie(&http.Cookie{
Name: httpmw.SessionTokenKey, Name: codersdk.SessionTokenKey,
Value: fmt.Sprintf("%s-%s", id, secret), Value: fmt.Sprintf("%s-%s", id, secret),
}) })
@ -347,7 +348,7 @@ func TestAPIKey(t *testing.T) {
user = createUser(r.Context(), t, db) user = createUser(r.Context(), t, db)
) )
r.AddCookie(&http.Cookie{ r.AddCookie(&http.Cookie{
Name: httpmw.SessionTokenKey, Name: codersdk.SessionTokenKey,
Value: fmt.Sprintf("%s-%s", id, secret), Value: fmt.Sprintf("%s-%s", id, secret),
}) })
@ -383,7 +384,7 @@ func TestAPIKey(t *testing.T) {
user = createUser(r.Context(), t, db) user = createUser(r.Context(), t, db)
) )
r.AddCookie(&http.Cookie{ r.AddCookie(&http.Cookie{
Name: httpmw.SessionTokenKey, Name: codersdk.SessionTokenKey,
Value: fmt.Sprintf("%s-%s", id, secret), Value: fmt.Sprintf("%s-%s", id, secret),
}) })
@ -432,7 +433,7 @@ func TestAPIKey(t *testing.T) {
) )
r.RemoteAddr = "1.1.1.1:3555" r.RemoteAddr = "1.1.1.1:3555"
r.AddCookie(&http.Cookie{ r.AddCookie(&http.Cookie{
Name: httpmw.SessionTokenKey, Name: codersdk.SessionTokenKey,
Value: fmt.Sprintf("%s-%s", id, secret), Value: fmt.Sprintf("%s-%s", id, secret),
}) })

View File

@ -10,6 +10,7 @@ import (
"time" "time"
"github.com/coder/coder/coderd/rbac" "github.com/coder/coder/coderd/rbac"
"github.com/coder/coder/codersdk"
"github.com/google/uuid" "github.com/google/uuid"
@ -93,7 +94,7 @@ func TestExtractUserRoles(t *testing.T) {
req := httptest.NewRequest("GET", "/", nil) req := httptest.NewRequest("GET", "/", nil)
req.AddCookie(&http.Cookie{ req.AddCookie(&http.Cookie{
Name: httpmw.SessionTokenKey, Name: codersdk.SessionTokenKey,
Value: token, Value: token,
}) })

View File

@ -8,13 +8,14 @@ import (
"github.com/google/uuid" "github.com/google/uuid"
"github.com/coder/coder/coderd/httpapi" "github.com/coder/coder/coderd/httpapi"
"github.com/coder/coder/codersdk"
) )
// parseUUID consumes a url parameter and parses it as a UUID. // parseUUID consumes a url parameter and parses it as a UUID.
func parseUUID(rw http.ResponseWriter, r *http.Request, param string) (uuid.UUID, bool) { func parseUUID(rw http.ResponseWriter, r *http.Request, param string) (uuid.UUID, bool) {
rawID := chi.URLParam(r, param) rawID := chi.URLParam(r, param)
if rawID == "" { if rawID == "" {
httpapi.Write(rw, http.StatusBadRequest, httpapi.Response{ httpapi.Write(rw, http.StatusBadRequest, codersdk.Response{
Message: "Missing UUID in URL.", Message: "Missing UUID in URL.",
// Url params mean nothing to a user // Url params mean nothing to a user
Detail: fmt.Sprintf("%q URL param missing", param), Detail: fmt.Sprintf("%q URL param missing", param),
@ -24,7 +25,7 @@ func parseUUID(rw http.ResponseWriter, r *http.Request, param string) (uuid.UUID
parsed, err := uuid.Parse(rawID) parsed, err := uuid.Parse(rawID)
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusBadRequest, httpapi.Response{ httpapi.Write(rw, http.StatusBadRequest, codersdk.Response{
Message: fmt.Sprintf("Invalid UUID %q.", param), Message: fmt.Sprintf("Invalid UUID %q.", param),
Detail: err.Error(), Detail: err.Error(),
}) })

View File

@ -9,6 +9,7 @@ import (
"golang.org/x/oauth2" "golang.org/x/oauth2"
"github.com/coder/coder/coderd/httpapi" "github.com/coder/coder/coderd/httpapi"
"github.com/coder/coder/codersdk"
"github.com/coder/coder/cryptorand" "github.com/coder/coder/cryptorand"
) )
@ -49,7 +50,7 @@ func ExtractOAuth2(config OAuth2Config) func(http.Handler) http.Handler {
return http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) { return http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
// Interfaces can hold a nil value // Interfaces can hold a nil value
if config == nil || reflect.ValueOf(config).IsNil() { if config == nil || reflect.ValueOf(config).IsNil() {
httpapi.Write(rw, http.StatusPreconditionRequired, httpapi.Response{ httpapi.Write(rw, http.StatusPreconditionRequired, codersdk.Response{
Message: "The oauth2 method requested is not configured!", Message: "The oauth2 method requested is not configured!",
}) })
return return
@ -62,7 +63,7 @@ func ExtractOAuth2(config OAuth2Config) func(http.Handler) http.Handler {
// If the code isn't provided, we'll redirect! // If the code isn't provided, we'll redirect!
state, err := cryptorand.String(32) state, err := cryptorand.String(32)
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error generating state string.", Message: "Internal error generating state string.",
Detail: err.Error(), Detail: err.Error(),
}) })
@ -91,7 +92,7 @@ func ExtractOAuth2(config OAuth2Config) func(http.Handler) http.Handler {
} }
if state == "" { if state == "" {
httpapi.Write(rw, http.StatusBadRequest, httpapi.Response{ httpapi.Write(rw, http.StatusBadRequest, codersdk.Response{
Message: "State must be provided.", Message: "State must be provided.",
}) })
return return
@ -99,13 +100,13 @@ func ExtractOAuth2(config OAuth2Config) func(http.Handler) http.Handler {
stateCookie, err := r.Cookie(oauth2StateCookieName) stateCookie, err := r.Cookie(oauth2StateCookieName)
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusUnauthorized, httpapi.Response{ httpapi.Write(rw, http.StatusUnauthorized, codersdk.Response{
Message: fmt.Sprintf("Cookie %q must be provided.", oauth2StateCookieName), Message: fmt.Sprintf("Cookie %q must be provided.", oauth2StateCookieName),
}) })
return return
} }
if stateCookie.Value != state { if stateCookie.Value != state {
httpapi.Write(rw, http.StatusUnauthorized, httpapi.Response{ httpapi.Write(rw, http.StatusUnauthorized, codersdk.Response{
Message: "State mismatched.", Message: "State mismatched.",
}) })
return return
@ -119,7 +120,7 @@ func ExtractOAuth2(config OAuth2Config) func(http.Handler) http.Handler {
oauthToken, err := config.Exchange(r.Context(), code) oauthToken, err := config.Exchange(r.Context(), code)
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error exchanging Oauth code.", Message: "Internal error exchanging Oauth code.",
Detail: err.Error(), Detail: err.Error(),
}) })

View File

@ -8,6 +8,7 @@ import (
"github.com/coder/coder/coderd/database" "github.com/coder/coder/coderd/database"
"github.com/coder/coder/coderd/httpapi" "github.com/coder/coder/coderd/httpapi"
"github.com/coder/coder/codersdk"
) )
type organizationParamContextKey struct{} type organizationParamContextKey struct{}
@ -48,7 +49,7 @@ func ExtractOrganizationParam(db database.Store) func(http.Handler) http.Handler
return return
} }
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error fetching organization.", Message: "Internal error fetching organization.",
Detail: err.Error(), Detail: err.Error(),
}) })
@ -77,7 +78,7 @@ func ExtractOrganizationMemberParam(db database.Store) func(http.Handler) http.H
return return
} }
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error fetching organization member.", Message: "Internal error fetching organization member.",
Detail: err.Error(), Detail: err.Error(),
}) })

View File

@ -16,6 +16,7 @@ import (
"github.com/coder/coder/coderd/database" "github.com/coder/coder/coderd/database"
"github.com/coder/coder/coderd/database/databasefake" "github.com/coder/coder/coderd/database/databasefake"
"github.com/coder/coder/coderd/httpmw" "github.com/coder/coder/coderd/httpmw"
"github.com/coder/coder/codersdk"
"github.com/coder/coder/cryptorand" "github.com/coder/coder/cryptorand"
) )
@ -29,7 +30,7 @@ func TestOrganizationParam(t *testing.T) {
hashed = sha256.Sum256([]byte(secret)) hashed = sha256.Sum256([]byte(secret))
) )
r.AddCookie(&http.Cookie{ r.AddCookie(&http.Cookie{
Name: httpmw.SessionTokenKey, Name: codersdk.SessionTokenKey,
Value: fmt.Sprintf("%s-%s", id, secret), Value: fmt.Sprintf("%s-%s", id, secret),
}) })

View File

@ -8,6 +8,7 @@ import (
"github.com/coder/coder/coderd/database" "github.com/coder/coder/coderd/database"
"github.com/coder/coder/coderd/httpapi" "github.com/coder/coder/coderd/httpapi"
"github.com/coder/coder/codersdk"
) )
// RateLimitPerMinute returns a handler that limits requests per-minute based // RateLimitPerMinute returns a handler that limits requests per-minute based
@ -31,7 +32,7 @@ func RateLimitPerMinute(count int) func(http.Handler) http.Handler {
return httprate.KeyByIP(r) return httprate.KeyByIP(r)
}, httprate.KeyByEndpoint), }, httprate.KeyByEndpoint),
httprate.WithLimitHandler(func(w http.ResponseWriter, r *http.Request) { httprate.WithLimitHandler(func(w http.ResponseWriter, r *http.Request) {
httpapi.Write(w, http.StatusTooManyRequests, httpapi.Response{ httpapi.Write(w, http.StatusTooManyRequests, codersdk.Response{
Message: "You've been rate limited for sending too many requests!", Message: "You've been rate limited for sending too many requests!",
}) })
}), }),

View File

@ -10,6 +10,7 @@ import (
"github.com/coder/coder/coderd/database" "github.com/coder/coder/coderd/database"
"github.com/coder/coder/coderd/httpapi" "github.com/coder/coder/coderd/httpapi"
"github.com/coder/coder/codersdk"
) )
type templateParamContextKey struct{} type templateParamContextKey struct{}
@ -37,7 +38,7 @@ func ExtractTemplateParam(db database.Store) func(http.Handler) http.Handler {
return return
} }
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error fetching template.", Message: "Internal error fetching template.",
Detail: err.Error(), Detail: err.Error(),
}) })

View File

@ -16,6 +16,7 @@ import (
"github.com/coder/coder/coderd/database" "github.com/coder/coder/coderd/database"
"github.com/coder/coder/coderd/database/databasefake" "github.com/coder/coder/coderd/database/databasefake"
"github.com/coder/coder/coderd/httpmw" "github.com/coder/coder/coderd/httpmw"
"github.com/coder/coder/codersdk"
"github.com/coder/coder/cryptorand" "github.com/coder/coder/cryptorand"
) )
@ -29,7 +30,7 @@ func TestTemplateParam(t *testing.T) {
) )
r := httptest.NewRequest("GET", "/", nil) r := httptest.NewRequest("GET", "/", nil)
r.AddCookie(&http.Cookie{ r.AddCookie(&http.Cookie{
Name: httpmw.SessionTokenKey, Name: codersdk.SessionTokenKey,
Value: fmt.Sprintf("%s-%s", id, secret), Value: fmt.Sprintf("%s-%s", id, secret),
}) })

View File

@ -10,6 +10,7 @@ import (
"github.com/coder/coder/coderd/database" "github.com/coder/coder/coderd/database"
"github.com/coder/coder/coderd/httpapi" "github.com/coder/coder/coderd/httpapi"
"github.com/coder/coder/codersdk"
) )
type templateVersionParamContextKey struct{} type templateVersionParamContextKey struct{}
@ -37,7 +38,7 @@ func ExtractTemplateVersionParam(db database.Store) func(http.Handler) http.Hand
return return
} }
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error fetching template version.", Message: "Internal error fetching template version.",
Detail: err.Error(), Detail: err.Error(),
}) })

View File

@ -16,6 +16,7 @@ import (
"github.com/coder/coder/coderd/database" "github.com/coder/coder/coderd/database"
"github.com/coder/coder/coderd/database/databasefake" "github.com/coder/coder/coderd/database/databasefake"
"github.com/coder/coder/coderd/httpmw" "github.com/coder/coder/coderd/httpmw"
"github.com/coder/coder/codersdk"
"github.com/coder/coder/cryptorand" "github.com/coder/coder/cryptorand"
) )
@ -29,7 +30,7 @@ func TestTemplateVersionParam(t *testing.T) {
) )
r := httptest.NewRequest("GET", "/", nil) r := httptest.NewRequest("GET", "/", nil)
r.AddCookie(&http.Cookie{ r.AddCookie(&http.Cookie{
Name: httpmw.SessionTokenKey, Name: codersdk.SessionTokenKey,
Value: fmt.Sprintf("%s-%s", id, secret), Value: fmt.Sprintf("%s-%s", id, secret),
}) })

View File

@ -12,6 +12,7 @@ import (
"github.com/coder/coder/coderd/database" "github.com/coder/coder/coderd/database"
"github.com/coder/coder/coderd/httpapi" "github.com/coder/coder/coderd/httpapi"
"github.com/coder/coder/codersdk"
) )
type userParamContextKey struct{} type userParamContextKey struct{}
@ -42,7 +43,7 @@ func ExtractUserParam(db database.Store) func(http.Handler) http.Handler {
// userQuery is either a uuid, a username, or 'me' // userQuery is either a uuid, a username, or 'me'
userQuery := chi.URLParam(r, "user") userQuery := chi.URLParam(r, "user")
if userQuery == "" { if userQuery == "" {
httpapi.Write(rw, http.StatusBadRequest, httpapi.Response{ httpapi.Write(rw, http.StatusBadRequest, codersdk.Response{
Message: "\"user\" must be provided.", Message: "\"user\" must be provided.",
}) })
return return
@ -55,7 +56,7 @@ func ExtractUserParam(db database.Store) func(http.Handler) http.Handler {
return return
} }
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error fetching user.", Message: "Internal error fetching user.",
Detail: err.Error(), Detail: err.Error(),
}) })
@ -65,7 +66,7 @@ func ExtractUserParam(db database.Store) func(http.Handler) http.Handler {
// If the userQuery is a valid uuid // If the userQuery is a valid uuid
user, err = db.GetUserByID(r.Context(), userID) user, err = db.GetUserByID(r.Context(), userID)
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusBadRequest, httpapi.Response{ httpapi.Write(rw, http.StatusBadRequest, codersdk.Response{
Message: userErrorMessage, Message: userErrorMessage,
}) })
return return
@ -76,7 +77,7 @@ func ExtractUserParam(db database.Store) func(http.Handler) http.Handler {
Username: userQuery, Username: userQuery,
}) })
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusBadRequest, httpapi.Response{ httpapi.Write(rw, http.StatusBadRequest, codersdk.Response{
Message: userErrorMessage, Message: userErrorMessage,
}) })
return return

View File

@ -16,6 +16,7 @@ import (
"github.com/coder/coder/coderd/database" "github.com/coder/coder/coderd/database"
"github.com/coder/coder/coderd/database/databasefake" "github.com/coder/coder/coderd/database/databasefake"
"github.com/coder/coder/coderd/httpmw" "github.com/coder/coder/coderd/httpmw"
"github.com/coder/coder/codersdk"
) )
func TestUserParam(t *testing.T) { func TestUserParam(t *testing.T) {
@ -29,7 +30,7 @@ func TestUserParam(t *testing.T) {
rw = httptest.NewRecorder() rw = httptest.NewRecorder()
) )
r.AddCookie(&http.Cookie{ r.AddCookie(&http.Cookie{
Name: httpmw.SessionTokenKey, Name: codersdk.SessionTokenKey,
Value: fmt.Sprintf("%s-%s", id, secret), Value: fmt.Sprintf("%s-%s", id, secret),
}) })

View File

@ -11,6 +11,7 @@ import (
"github.com/coder/coder/coderd/database" "github.com/coder/coder/coderd/database"
"github.com/coder/coder/coderd/httpapi" "github.com/coder/coder/coderd/httpapi"
"github.com/coder/coder/codersdk"
) )
type workspaceAgentContextKey struct{} type workspaceAgentContextKey struct{}
@ -28,16 +29,16 @@ func WorkspaceAgent(r *http.Request) database.WorkspaceAgent {
func ExtractWorkspaceAgent(db database.Store) func(http.Handler) http.Handler { func ExtractWorkspaceAgent(db database.Store) func(http.Handler) http.Handler {
return func(next http.Handler) http.Handler { return func(next http.Handler) http.Handler {
return http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) { return http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
cookie, err := r.Cookie(SessionTokenKey) cookie, err := r.Cookie(codersdk.SessionTokenKey)
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusUnauthorized, httpapi.Response{ httpapi.Write(rw, http.StatusUnauthorized, codersdk.Response{
Message: fmt.Sprintf("Cookie %q must be provided.", SessionTokenKey), Message: fmt.Sprintf("Cookie %q must be provided.", codersdk.SessionTokenKey),
}) })
return return
} }
token, err := uuid.Parse(cookie.Value) token, err := uuid.Parse(cookie.Value)
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusUnauthorized, httpapi.Response{ httpapi.Write(rw, http.StatusUnauthorized, codersdk.Response{
Message: "Agent token is invalid.", Message: "Agent token is invalid.",
}) })
return return
@ -45,13 +46,13 @@ func ExtractWorkspaceAgent(db database.Store) func(http.Handler) http.Handler {
agent, err := db.GetWorkspaceAgentByAuthToken(r.Context(), token) agent, err := db.GetWorkspaceAgentByAuthToken(r.Context(), token)
if err != nil { if err != nil {
if errors.Is(err, sql.ErrNoRows) { if errors.Is(err, sql.ErrNoRows) {
httpapi.Write(rw, http.StatusUnauthorized, httpapi.Response{ httpapi.Write(rw, http.StatusUnauthorized, codersdk.Response{
Message: "Agent token is invalid.", Message: "Agent token is invalid.",
}) })
return return
} }
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error fetching workspace agent.", Message: "Internal error fetching workspace agent.",
Detail: err.Error(), Detail: err.Error(),
}) })

View File

@ -13,6 +13,7 @@ import (
"github.com/coder/coder/coderd/database" "github.com/coder/coder/coderd/database"
"github.com/coder/coder/coderd/database/databasefake" "github.com/coder/coder/coderd/database/databasefake"
"github.com/coder/coder/coderd/httpmw" "github.com/coder/coder/coderd/httpmw"
"github.com/coder/coder/codersdk"
) )
func TestWorkspaceAgent(t *testing.T) { func TestWorkspaceAgent(t *testing.T) {
@ -22,7 +23,7 @@ func TestWorkspaceAgent(t *testing.T) {
token := uuid.New() token := uuid.New()
r := httptest.NewRequest("GET", "/", nil) r := httptest.NewRequest("GET", "/", nil)
r.AddCookie(&http.Cookie{ r.AddCookie(&http.Cookie{
Name: httpmw.SessionTokenKey, Name: codersdk.SessionTokenKey,
Value: token.String(), Value: token.String(),
}) })
return r, token return r, token

View File

@ -10,6 +10,7 @@ import (
"github.com/coder/coder/coderd/database" "github.com/coder/coder/coderd/database"
"github.com/coder/coder/coderd/httpapi" "github.com/coder/coder/coderd/httpapi"
"github.com/coder/coder/codersdk"
) )
type workspaceAgentParamContextKey struct{} type workspaceAgentParamContextKey struct{}
@ -34,13 +35,13 @@ func ExtractWorkspaceAgentParam(db database.Store) func(http.Handler) http.Handl
agent, err := db.GetWorkspaceAgentByID(r.Context(), agentUUID) agent, err := db.GetWorkspaceAgentByID(r.Context(), agentUUID)
if errors.Is(err, sql.ErrNoRows) { if errors.Is(err, sql.ErrNoRows) {
httpapi.Write(rw, http.StatusNotFound, httpapi.Response{ httpapi.Write(rw, http.StatusNotFound, codersdk.Response{
Message: "Agent doesn't exist with that id.", Message: "Agent doesn't exist with that id.",
}) })
return return
} }
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error fetching workspace agent.", Message: "Internal error fetching workspace agent.",
Detail: err.Error(), Detail: err.Error(),
}) })
@ -49,7 +50,7 @@ func ExtractWorkspaceAgentParam(db database.Store) func(http.Handler) http.Handl
resource, err := db.GetWorkspaceResourceByID(r.Context(), agent.ResourceID) resource, err := db.GetWorkspaceResourceByID(r.Context(), agent.ResourceID)
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error fetching workspace resource.", Message: "Internal error fetching workspace resource.",
Detail: err.Error(), Detail: err.Error(),
}) })
@ -58,21 +59,21 @@ func ExtractWorkspaceAgentParam(db database.Store) func(http.Handler) http.Handl
job, err := db.GetProvisionerJobByID(r.Context(), resource.JobID) job, err := db.GetProvisionerJobByID(r.Context(), resource.JobID)
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error fetching provisioner job.", Message: "Internal error fetching provisioner job.",
Detail: err.Error(), Detail: err.Error(),
}) })
return return
} }
if job.Type != database.ProvisionerJobTypeWorkspaceBuild { if job.Type != database.ProvisionerJobTypeWorkspaceBuild {
httpapi.Write(rw, http.StatusBadRequest, httpapi.Response{ httpapi.Write(rw, http.StatusBadRequest, codersdk.Response{
Message: "Workspace agents can only be fetched for builds.", Message: "Workspace agents can only be fetched for builds.",
}) })
return return
} }
build, err := db.GetWorkspaceBuildByJobID(r.Context(), job.ID) build, err := db.GetWorkspaceBuildByJobID(r.Context(), job.ID)
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error fetching workspace build.", Message: "Internal error fetching workspace build.",
Detail: err.Error(), Detail: err.Error(),
}) })

View File

@ -16,6 +16,7 @@ import (
"github.com/coder/coder/coderd/database" "github.com/coder/coder/coderd/database"
"github.com/coder/coder/coderd/database/databasefake" "github.com/coder/coder/coderd/database/databasefake"
"github.com/coder/coder/coderd/httpmw" "github.com/coder/coder/coderd/httpmw"
"github.com/coder/coder/codersdk"
"github.com/coder/coder/cryptorand" "github.com/coder/coder/cryptorand"
) )
@ -29,7 +30,7 @@ func TestWorkspaceAgentParam(t *testing.T) {
) )
r := httptest.NewRequest("GET", "/", nil) r := httptest.NewRequest("GET", "/", nil)
r.AddCookie(&http.Cookie{ r.AddCookie(&http.Cookie{
Name: httpmw.SessionTokenKey, Name: codersdk.SessionTokenKey,
Value: fmt.Sprintf("%s-%s", id, secret), Value: fmt.Sprintf("%s-%s", id, secret),
}) })

View File

@ -10,6 +10,7 @@ import (
"github.com/coder/coder/coderd/database" "github.com/coder/coder/coderd/database"
"github.com/coder/coder/coderd/httpapi" "github.com/coder/coder/coderd/httpapi"
"github.com/coder/coder/codersdk"
) )
type workspaceBuildParamContextKey struct{} type workspaceBuildParamContextKey struct{}
@ -37,7 +38,7 @@ func ExtractWorkspaceBuildParam(db database.Store) func(http.Handler) http.Handl
return return
} }
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error fetching workspace build.", Message: "Internal error fetching workspace build.",
Detail: err.Error(), Detail: err.Error(),
}) })

View File

@ -16,6 +16,7 @@ import (
"github.com/coder/coder/coderd/database" "github.com/coder/coder/coderd/database"
"github.com/coder/coder/coderd/database/databasefake" "github.com/coder/coder/coderd/database/databasefake"
"github.com/coder/coder/coderd/httpmw" "github.com/coder/coder/coderd/httpmw"
"github.com/coder/coder/codersdk"
"github.com/coder/coder/cryptorand" "github.com/coder/coder/cryptorand"
) )
@ -29,7 +30,7 @@ func TestWorkspaceBuildParam(t *testing.T) {
) )
r := httptest.NewRequest("GET", "/", nil) r := httptest.NewRequest("GET", "/", nil)
r.AddCookie(&http.Cookie{ r.AddCookie(&http.Cookie{
Name: httpmw.SessionTokenKey, Name: codersdk.SessionTokenKey,
Value: fmt.Sprintf("%s-%s", id, secret), Value: fmt.Sprintf("%s-%s", id, secret),
}) })

View File

@ -8,6 +8,7 @@ import (
"github.com/coder/coder/coderd/database" "github.com/coder/coder/coderd/database"
"github.com/coder/coder/coderd/httpapi" "github.com/coder/coder/coderd/httpapi"
"github.com/coder/coder/codersdk"
) )
type workspaceParamContextKey struct{} type workspaceParamContextKey struct{}
@ -35,7 +36,7 @@ func ExtractWorkspaceParam(db database.Store) func(http.Handler) http.Handler {
return return
} }
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error fetching workspace.", Message: "Internal error fetching workspace.",
Detail: err.Error(), Detail: err.Error(),
}) })

View File

@ -16,6 +16,7 @@ import (
"github.com/coder/coder/coderd/database" "github.com/coder/coder/coderd/database"
"github.com/coder/coder/coderd/database/databasefake" "github.com/coder/coder/coderd/database/databasefake"
"github.com/coder/coder/coderd/httpmw" "github.com/coder/coder/coderd/httpmw"
"github.com/coder/coder/codersdk"
"github.com/coder/coder/cryptorand" "github.com/coder/coder/cryptorand"
) )
@ -29,7 +30,7 @@ func TestWorkspaceParam(t *testing.T) {
) )
r := httptest.NewRequest("GET", "/", nil) r := httptest.NewRequest("GET", "/", nil)
r.AddCookie(&http.Cookie{ r.AddCookie(&http.Cookie{
Name: httpmw.SessionTokenKey, Name: codersdk.SessionTokenKey,
Value: fmt.Sprintf("%s-%s", id, secret), Value: fmt.Sprintf("%s-%s", id, secret),
}) })

View File

@ -10,6 +10,7 @@ import (
"github.com/coder/coder/coderd/database" "github.com/coder/coder/coderd/database"
"github.com/coder/coder/coderd/httpapi" "github.com/coder/coder/coderd/httpapi"
"github.com/coder/coder/codersdk"
) )
type workspaceResourceParamContextKey struct{} type workspaceResourceParamContextKey struct{}
@ -33,13 +34,13 @@ func ExtractWorkspaceResourceParam(db database.Store) func(http.Handler) http.Ha
} }
resource, err := db.GetWorkspaceResourceByID(r.Context(), resourceUUID) resource, err := db.GetWorkspaceResourceByID(r.Context(), resourceUUID)
if errors.Is(err, sql.ErrNoRows) { if errors.Is(err, sql.ErrNoRows) {
httpapi.Write(rw, http.StatusNotFound, httpapi.Response{ httpapi.Write(rw, http.StatusNotFound, codersdk.Response{
Message: "Resource doesn't exist with that id.", Message: "Resource doesn't exist with that id.",
}) })
return return
} }
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error fetching provisioner resource.", Message: "Internal error fetching provisioner resource.",
Detail: err.Error(), Detail: err.Error(),
}) })
@ -48,21 +49,21 @@ func ExtractWorkspaceResourceParam(db database.Store) func(http.Handler) http.Ha
job, err := db.GetProvisionerJobByID(r.Context(), resource.JobID) job, err := db.GetProvisionerJobByID(r.Context(), resource.JobID)
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error provisioner job.", Message: "Internal error provisioner job.",
Detail: err.Error(), Detail: err.Error(),
}) })
return return
} }
if job.Type != database.ProvisionerJobTypeWorkspaceBuild { if job.Type != database.ProvisionerJobTypeWorkspaceBuild {
httpapi.Write(rw, http.StatusBadRequest, httpapi.Response{ httpapi.Write(rw, http.StatusBadRequest, codersdk.Response{
Message: "Workspace resources can only be fetched for builds.", Message: "Workspace resources can only be fetched for builds.",
}) })
return return
} }
build, err := db.GetWorkspaceBuildByJobID(r.Context(), job.ID) build, err := db.GetWorkspaceBuildByJobID(r.Context(), job.ID)
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error workspace build.", Message: "Internal error workspace build.",
Detail: err.Error(), Detail: err.Error(),
}) })

View File

@ -23,7 +23,7 @@ func (api *API) putMemberRoles(rw http.ResponseWriter, r *http.Request) {
apiKey := httpmw.APIKey(r) apiKey := httpmw.APIKey(r)
if apiKey.UserID == member.UserID { if apiKey.UserID == member.UserID {
httpapi.Write(rw, http.StatusBadRequest, httpapi.Response{ httpapi.Write(rw, http.StatusBadRequest, codersdk.Response{
Message: "You cannot change your own organization roles.", Message: "You cannot change your own organization roles.",
}) })
return return
@ -58,7 +58,7 @@ func (api *API) putMemberRoles(rw http.ResponseWriter, r *http.Request) {
OrgID: organization.ID, OrgID: organization.ID,
}) })
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusBadRequest, httpapi.Response{ httpapi.Write(rw, http.StatusBadRequest, codersdk.Response{
Message: err.Error(), Message: err.Error(),
}) })
return return

View File

@ -45,13 +45,13 @@ func (api *API) postOrganizations(rw http.ResponseWriter, r *http.Request) {
_, err := api.Database.GetOrganizationByName(r.Context(), req.Name) _, err := api.Database.GetOrganizationByName(r.Context(), req.Name)
if err == nil { if err == nil {
httpapi.Write(rw, http.StatusConflict, httpapi.Response{ httpapi.Write(rw, http.StatusConflict, codersdk.Response{
Message: "Organization already exists with that name.", Message: "Organization already exists with that name.",
}) })
return return
} }
if !errors.Is(err, sql.ErrNoRows) { if !errors.Is(err, sql.ErrNoRows) {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: fmt.Sprintf("Internal error fetching organization %q.", req.Name), Message: fmt.Sprintf("Internal error fetching organization %q.", req.Name),
Detail: err.Error(), Detail: err.Error(),
}) })
@ -84,7 +84,7 @@ func (api *API) postOrganizations(rw http.ResponseWriter, r *http.Request) {
return nil return nil
}) })
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error inserting organization member.", Message: "Internal error inserting organization member.",
Detail: err.Error(), Detail: err.Error(),
}) })

View File

@ -21,7 +21,7 @@ func parsePagination(w http.ResponseWriter, r *http.Request) (p codersdk.Paginat
Offset: parser.Int(queryParams, 0, "offset"), Offset: parser.Int(queryParams, 0, "offset"),
} }
if len(parser.Errors) > 0 { if len(parser.Errors) > 0 {
httpapi.Write(w, http.StatusBadRequest, httpapi.Response{ httpapi.Write(w, http.StatusBadRequest, codersdk.Response{
Message: "Query parameters have invalid values.", Message: "Query parameters have invalid values.",
Validations: parser.Errors, Validations: parser.Errors,
}) })

View File

@ -41,13 +41,13 @@ func (api *API) postParameter(rw http.ResponseWriter, r *http.Request) {
Name: createRequest.Name, Name: createRequest.Name,
}) })
if err == nil { if err == nil {
httpapi.Write(rw, http.StatusConflict, httpapi.Response{ httpapi.Write(rw, http.StatusConflict, codersdk.Response{
Message: fmt.Sprintf("Parameter already exists in scope %q and name %q.", scope, createRequest.Name), Message: fmt.Sprintf("Parameter already exists in scope %q and name %q.", scope, createRequest.Name),
}) })
return return
} }
if !errors.Is(err, sql.ErrNoRows) { if !errors.Is(err, sql.ErrNoRows) {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error fetching parameter.", Message: "Internal error fetching parameter.",
Detail: err.Error(), Detail: err.Error(),
}) })
@ -66,7 +66,7 @@ func (api *API) postParameter(rw http.ResponseWriter, r *http.Request) {
DestinationScheme: database.ParameterDestinationScheme(createRequest.DestinationScheme), DestinationScheme: database.ParameterDestinationScheme(createRequest.DestinationScheme),
}) })
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error inserting parameter.", Message: "Internal error inserting parameter.",
Detail: err.Error(), Detail: err.Error(),
}) })
@ -99,7 +99,7 @@ func (api *API) parameters(rw http.ResponseWriter, r *http.Request) {
err = nil err = nil
} }
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error fetching parameter scope values.", Message: "Internal error fetching parameter scope values.",
Detail: err.Error(), Detail: err.Error(),
}) })
@ -139,7 +139,7 @@ func (api *API) deleteParameter(rw http.ResponseWriter, r *http.Request) {
return return
} }
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error fetching parameter.", Message: "Internal error fetching parameter.",
Detail: err.Error(), Detail: err.Error(),
}) })
@ -147,13 +147,13 @@ func (api *API) deleteParameter(rw http.ResponseWriter, r *http.Request) {
} }
err = api.Database.DeleteParameterValueByID(r.Context(), parameterValue.ID) err = api.Database.DeleteParameterValueByID(r.Context(), parameterValue.ID)
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error deleting parameter.", Message: "Internal error deleting parameter.",
Detail: err.Error(), Detail: err.Error(),
}) })
return return
} }
httpapi.Write(rw, http.StatusOK, httpapi.Response{ httpapi.Write(rw, http.StatusOK, codersdk.Response{
Message: "Parameter deleted.", Message: "Parameter deleted.",
}) })
} }
@ -225,11 +225,11 @@ func (api *API) parameterRBACResource(rw http.ResponseWriter, r *http.Request, s
// Write error payload to rw if we cannot find the resource for the scope // Write error payload to rw if we cannot find the resource for the scope
if err != nil { if err != nil {
if xerrors.Is(err, sql.ErrNoRows) { if xerrors.Is(err, sql.ErrNoRows) {
httpapi.Write(rw, http.StatusNotFound, httpapi.Response{ httpapi.Write(rw, http.StatusNotFound, codersdk.Response{
Message: fmt.Sprintf("Scope %q resource %q not found.", scope, scopeID), Message: fmt.Sprintf("Scope %q resource %q not found.", scope, scopeID),
}) })
} else { } else {
httpapi.Write(rw, http.StatusBadRequest, httpapi.Response{ httpapi.Write(rw, http.StatusBadRequest, codersdk.Response{
Message: err.Error(), Message: err.Error(),
}) })
} }
@ -243,9 +243,9 @@ func readScopeAndID(rw http.ResponseWriter, r *http.Request) (database.Parameter
switch scope { switch scope {
case database.ParameterScopeTemplate, database.ParameterScopeImportJob, database.ParameterScopeWorkspace: case database.ParameterScopeTemplate, database.ParameterScopeImportJob, database.ParameterScopeWorkspace:
default: default:
httpapi.Write(rw, http.StatusBadRequest, httpapi.Response{ httpapi.Write(rw, http.StatusBadRequest, codersdk.Response{
Message: fmt.Sprintf("Invalid scope %q.", scope), Message: fmt.Sprintf("Invalid scope %q.", scope),
Validations: []httpapi.Error{ Validations: []codersdk.ValidationError{
{Field: "scope", Detail: "invalid scope"}, {Field: "scope", Detail: "invalid scope"},
}, },
}) })
@ -255,10 +255,10 @@ func readScopeAndID(rw http.ResponseWriter, r *http.Request) (database.Parameter
id := chi.URLParam(r, "id") id := chi.URLParam(r, "id")
uid, err := uuid.Parse(id) uid, err := uuid.Parse(id)
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusBadRequest, httpapi.Response{ httpapi.Write(rw, http.StatusBadRequest, codersdk.Response{
Message: fmt.Sprintf("Invalid UUID %q.", id), Message: fmt.Sprintf("Invalid UUID %q.", id),
Detail: err.Error(), Detail: err.Error(),
Validations: []httpapi.Error{ Validations: []codersdk.ValidationError{
{Field: "id", Detail: "Invalid UUID"}, {Field: "id", Detail: "Invalid UUID"},
}, },
}) })

View File

@ -28,6 +28,7 @@ import (
"github.com/coder/coder/coderd/parameter" "github.com/coder/coder/coderd/parameter"
"github.com/coder/coder/coderd/rbac" "github.com/coder/coder/coderd/rbac"
"github.com/coder/coder/coderd/telemetry" "github.com/coder/coder/coderd/telemetry"
"github.com/coder/coder/codersdk"
"github.com/coder/coder/peer/peerwg" "github.com/coder/coder/peer/peerwg"
"github.com/coder/coder/provisionerd/proto" "github.com/coder/coder/provisionerd/proto"
"github.com/coder/coder/provisionersdk" "github.com/coder/coder/provisionersdk"
@ -40,7 +41,7 @@ func (api *API) provisionerDaemons(rw http.ResponseWriter, r *http.Request) {
err = nil err = nil
} }
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error fetching provisioner daemons.", Message: "Internal error fetching provisioner daemons.",
Detail: err.Error(), Detail: err.Error(),
}) })

View File

@ -33,7 +33,7 @@ func (api *API) provisionerJobLogs(rw http.ResponseWriter, r *http.Request, job
afterRaw := r.URL.Query().Get("after") afterRaw := r.URL.Query().Get("after")
beforeRaw := r.URL.Query().Get("before") beforeRaw := r.URL.Query().Get("before")
if beforeRaw != "" && follow { if beforeRaw != "" && follow {
httpapi.Write(rw, http.StatusBadRequest, httpapi.Response{ httpapi.Write(rw, http.StatusBadRequest, codersdk.Response{
Message: "Query param \"before\" cannot be used with \"follow\".", Message: "Query param \"before\" cannot be used with \"follow\".",
}) })
return return
@ -46,7 +46,7 @@ func (api *API) provisionerJobLogs(rw http.ResponseWriter, r *http.Request, job
if follow { if follow {
bl, closeFollow, err := api.followLogs(job.ID) bl, closeFollow, err := api.followLogs(job.ID)
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error watching provisioner logs.", Message: "Internal error watching provisioner logs.",
Detail: err.Error(), Detail: err.Error(),
}) })
@ -62,7 +62,7 @@ func (api *API) provisionerJobLogs(rw http.ResponseWriter, r *http.Request, job
// avoid this, but not worth it for one fewer query at this point. // avoid this, but not worth it for one fewer query at this point.
job, err = api.Database.GetProvisionerJobByID(r.Context(), job.ID) job, err = api.Database.GetProvisionerJobByID(r.Context(), job.ID)
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error querying job.", Message: "Internal error querying job.",
Detail: err.Error(), Detail: err.Error(),
}) })
@ -75,9 +75,9 @@ func (api *API) provisionerJobLogs(rw http.ResponseWriter, r *http.Request, job
if afterRaw != "" { if afterRaw != "" {
afterMS, err := strconv.ParseInt(afterRaw, 10, 64) afterMS, err := strconv.ParseInt(afterRaw, 10, 64)
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusBadRequest, httpapi.Response{ httpapi.Write(rw, http.StatusBadRequest, codersdk.Response{
Message: "Query param \"after\" must be an integer.", Message: "Query param \"after\" must be an integer.",
Validations: []httpapi.Error{ Validations: []codersdk.ValidationError{
{Field: "after", Detail: "Must be an integer"}, {Field: "after", Detail: "Must be an integer"},
}, },
}) })
@ -94,9 +94,9 @@ func (api *API) provisionerJobLogs(rw http.ResponseWriter, r *http.Request, job
if beforeRaw != "" { if beforeRaw != "" {
beforeMS, err := strconv.ParseInt(beforeRaw, 10, 64) beforeMS, err := strconv.ParseInt(beforeRaw, 10, 64)
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusBadRequest, httpapi.Response{ httpapi.Write(rw, http.StatusBadRequest, codersdk.Response{
Message: "Query param \"before\" must be an integer.", Message: "Query param \"before\" must be an integer.",
Validations: []httpapi.Error{ Validations: []codersdk.ValidationError{
{Field: "before", Detail: "Must be an integer"}, {Field: "before", Detail: "Must be an integer"},
}, },
}) })
@ -119,7 +119,7 @@ func (api *API) provisionerJobLogs(rw http.ResponseWriter, r *http.Request, job
err = nil err = nil
} }
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error fetching provisioner logs.", Message: "Internal error fetching provisioner logs.",
Detail: err.Error(), Detail: err.Error(),
}) })
@ -141,7 +141,7 @@ func (api *API) provisionerJobLogs(rw http.ResponseWriter, r *http.Request, job
defer api.websocketWaitGroup.Done() defer api.websocketWaitGroup.Done()
conn, err := websocket.Accept(rw, r, nil) conn, err := websocket.Accept(rw, r, nil)
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusBadRequest, httpapi.Response{ httpapi.Write(rw, http.StatusBadRequest, codersdk.Response{
Message: "Failed to accept websocket.", Message: "Failed to accept websocket.",
Detail: err.Error(), Detail: err.Error(),
}) })
@ -195,7 +195,7 @@ func (api *API) provisionerJobLogs(rw http.ResponseWriter, r *http.Request, job
func (api *API) provisionerJobResources(rw http.ResponseWriter, r *http.Request, job database.ProvisionerJob) { func (api *API) provisionerJobResources(rw http.ResponseWriter, r *http.Request, job database.ProvisionerJob) {
if !job.CompletedAt.Valid { if !job.CompletedAt.Valid {
httpapi.Write(rw, http.StatusPreconditionFailed, httpapi.Response{ httpapi.Write(rw, http.StatusPreconditionFailed, codersdk.Response{
Message: "Job hasn't completed!", Message: "Job hasn't completed!",
}) })
return return
@ -205,7 +205,7 @@ func (api *API) provisionerJobResources(rw http.ResponseWriter, r *http.Request,
err = nil err = nil
} }
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error fetching job resources.", Message: "Internal error fetching job resources.",
Detail: err.Error(), Detail: err.Error(),
}) })
@ -220,7 +220,7 @@ func (api *API) provisionerJobResources(rw http.ResponseWriter, r *http.Request,
err = nil err = nil
} }
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error fetching workspace agent.", Message: "Internal error fetching workspace agent.",
Detail: err.Error(), Detail: err.Error(),
}) })
@ -235,7 +235,7 @@ func (api *API) provisionerJobResources(rw http.ResponseWriter, r *http.Request,
err = nil err = nil
} }
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error fetching workspace applications.", Message: "Internal error fetching workspace applications.",
Detail: err.Error(), Detail: err.Error(),
}) })
@ -258,7 +258,7 @@ func (api *API) provisionerJobResources(rw http.ResponseWriter, r *http.Request,
apiAgent, err := convertWorkspaceAgent(agent, convertApps(dbApps), api.AgentInactiveDisconnectTimeout) apiAgent, err := convertWorkspaceAgent(agent, convertApps(dbApps), api.AgentInactiveDisconnectTimeout)
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error reading job agent.", Message: "Internal error reading job agent.",
Detail: err.Error(), Detail: err.Error(),
}) })

View File

@ -63,7 +63,7 @@ func (api *API) checkPermissions(rw http.ResponseWriter, r *http.Request) {
response := make(codersdk.UserAuthorizationResponse) response := make(codersdk.UserAuthorizationResponse)
for k, v := range params.Checks { for k, v := range params.Checks {
if v.Object.ResourceType == "" { if v.Object.ResourceType == "" {
httpapi.Write(rw, http.StatusBadRequest, httpapi.Response{ httpapi.Write(rw, http.StatusBadRequest, codersdk.Response{
Message: fmt.Sprintf("Object's \"resource_type\" field must be defined for key %q.", k), Message: fmt.Sprintf("Object's \"resource_type\" field must be defined for key %q.", k),
}) })
return return

View File

@ -40,7 +40,7 @@ func (api *API) template(rw http.ResponseWriter, r *http.Request) {
err = nil err = nil
} }
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error fetching workspace count.", Message: "Internal error fetching workspace count.",
Detail: err.Error(), Detail: err.Error(),
}) })
@ -59,7 +59,7 @@ func (api *API) template(rw http.ResponseWriter, r *http.Request) {
createdByNameMap, err := getCreatedByNamesByTemplateIDs(r.Context(), api.Database, []database.Template{template}) createdByNameMap, err := getCreatedByNamesByTemplateIDs(r.Context(), api.Database, []database.Template{template})
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error fetching creator name.", Message: "Internal error fetching creator name.",
Detail: err.Error(), Detail: err.Error(),
}) })
@ -83,14 +83,14 @@ func (api *API) deleteTemplate(rw http.ResponseWriter, r *http.Request) {
err = nil err = nil
} }
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error fetching workspaces by template id.", Message: "Internal error fetching workspaces by template id.",
Detail: err.Error(), Detail: err.Error(),
}) })
return return
} }
if len(workspaces) > 0 { if len(workspaces) > 0 {
httpapi.Write(rw, http.StatusPreconditionFailed, httpapi.Response{ httpapi.Write(rw, http.StatusPreconditionFailed, codersdk.Response{
Message: "All workspaces must be deleted before a template can be removed.", Message: "All workspaces must be deleted before a template can be removed.",
}) })
return return
@ -101,13 +101,13 @@ func (api *API) deleteTemplate(rw http.ResponseWriter, r *http.Request) {
UpdatedAt: database.Now(), UpdatedAt: database.Now(),
}) })
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error deleting template.", Message: "Internal error deleting template.",
Detail: err.Error(), Detail: err.Error(),
}) })
return return
} }
httpapi.Write(rw, http.StatusOK, httpapi.Response{ httpapi.Write(rw, http.StatusOK, codersdk.Response{
Message: "Template has been deleted!", Message: "Template has been deleted!",
}) })
} }
@ -130,9 +130,9 @@ func (api *API) postTemplateByOrganization(rw http.ResponseWriter, r *http.Reque
Name: createTemplate.Name, Name: createTemplate.Name,
}) })
if err == nil { if err == nil {
httpapi.Write(rw, http.StatusConflict, httpapi.Response{ httpapi.Write(rw, http.StatusConflict, codersdk.Response{
Message: fmt.Sprintf("Template with name %q already exists.", createTemplate.Name), Message: fmt.Sprintf("Template with name %q already exists.", createTemplate.Name),
Validations: []httpapi.Error{{ Validations: []codersdk.ValidationError{{
Field: "name", Field: "name",
Detail: "This value is already in use and should be unique.", Detail: "This value is already in use and should be unique.",
}}, }},
@ -140,7 +140,7 @@ func (api *API) postTemplateByOrganization(rw http.ResponseWriter, r *http.Reque
return return
} }
if !errors.Is(err, sql.ErrNoRows) { if !errors.Is(err, sql.ErrNoRows) {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error fetching template by name.", Message: "Internal error fetching template by name.",
Detail: err.Error(), Detail: err.Error(),
}) })
@ -148,16 +148,16 @@ func (api *API) postTemplateByOrganization(rw http.ResponseWriter, r *http.Reque
} }
templateVersion, err := api.Database.GetTemplateVersionByID(r.Context(), createTemplate.VersionID) templateVersion, err := api.Database.GetTemplateVersionByID(r.Context(), createTemplate.VersionID)
if errors.Is(err, sql.ErrNoRows) { if errors.Is(err, sql.ErrNoRows) {
httpapi.Write(rw, http.StatusNotFound, httpapi.Response{ httpapi.Write(rw, http.StatusNotFound, codersdk.Response{
Message: fmt.Sprintf("Template version %q does not exist.", createTemplate.VersionID), Message: fmt.Sprintf("Template version %q does not exist.", createTemplate.VersionID),
Validations: []httpapi.Error{ Validations: []codersdk.ValidationError{
{Field: "template_version_id", Detail: "Template version does not exist"}, {Field: "template_version_id", Detail: "Template version does not exist"},
}, },
}) })
return return
} }
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error fetching template version.", Message: "Internal error fetching template version.",
Detail: err.Error(), Detail: err.Error(),
}) })
@ -165,7 +165,7 @@ func (api *API) postTemplateByOrganization(rw http.ResponseWriter, r *http.Reque
} }
importJob, err := api.Database.GetProvisionerJobByID(r.Context(), templateVersion.JobID) importJob, err := api.Database.GetProvisionerJobByID(r.Context(), templateVersion.JobID)
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error fetching provisioner job.", Message: "Internal error fetching provisioner job.",
Detail: err.Error(), Detail: err.Error(),
}) })
@ -240,7 +240,7 @@ func (api *API) postTemplateByOrganization(rw http.ResponseWriter, r *http.Reque
return nil return nil
}) })
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error inserting template.", Message: "Internal error inserting template.",
Detail: err.Error(), Detail: err.Error(),
}) })
@ -264,7 +264,7 @@ func (api *API) templatesByOrganization(rw http.ResponseWriter, r *http.Request)
err = nil err = nil
} }
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error fetching templates in organization.", Message: "Internal error fetching templates in organization.",
Detail: err.Error(), Detail: err.Error(),
}) })
@ -284,7 +284,7 @@ func (api *API) templatesByOrganization(rw http.ResponseWriter, r *http.Request)
err = nil err = nil
} }
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error fetching workspace counts.", Message: "Internal error fetching workspace counts.",
Detail: err.Error(), Detail: err.Error(),
}) })
@ -293,7 +293,7 @@ func (api *API) templatesByOrganization(rw http.ResponseWriter, r *http.Request)
createdByNameMap, err := getCreatedByNamesByTemplateIDs(r.Context(), api.Database, templates) createdByNameMap, err := getCreatedByNamesByTemplateIDs(r.Context(), api.Database, templates)
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error fetching creator names.", Message: "Internal error fetching creator names.",
Detail: err.Error(), Detail: err.Error(),
}) })
@ -316,7 +316,7 @@ func (api *API) templateByOrganizationAndName(rw http.ResponseWriter, r *http.Re
return return
} }
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error fetching template.", Message: "Internal error fetching template.",
Detail: err.Error(), Detail: err.Error(),
}) })
@ -333,7 +333,7 @@ func (api *API) templateByOrganizationAndName(rw http.ResponseWriter, r *http.Re
err = nil err = nil
} }
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error fetching workspace counts.", Message: "Internal error fetching workspace counts.",
Detail: err.Error(), Detail: err.Error(),
}) })
@ -347,7 +347,7 @@ func (api *API) templateByOrganizationAndName(rw http.ResponseWriter, r *http.Re
createdByNameMap, err := getCreatedByNamesByTemplateIDs(r.Context(), api.Database, []database.Template{template}) createdByNameMap, err := getCreatedByNamesByTemplateIDs(r.Context(), api.Database, []database.Template{template})
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error fetching creator name.", Message: "Internal error fetching creator name.",
Detail: err.Error(), Detail: err.Error(),
}) })
@ -369,16 +369,16 @@ func (api *API) patchTemplateMeta(rw http.ResponseWriter, r *http.Request) {
return return
} }
var validErrs []httpapi.Error var validErrs []codersdk.ValidationError
if req.MaxTTLMillis < 0 { if req.MaxTTLMillis < 0 {
validErrs = append(validErrs, httpapi.Error{Field: "max_ttl_ms", Detail: "Must be a positive integer."}) validErrs = append(validErrs, codersdk.ValidationError{Field: "max_ttl_ms", Detail: "Must be a positive integer."})
} }
if req.MinAutostartIntervalMillis < 0 { if req.MinAutostartIntervalMillis < 0 {
validErrs = append(validErrs, httpapi.Error{Field: "min_autostart_interval_ms", Detail: "Must be a positive integer."}) validErrs = append(validErrs, codersdk.ValidationError{Field: "min_autostart_interval_ms", Detail: "Must be a positive integer."})
} }
if len(validErrs) > 0 { if len(validErrs) > 0 {
httpapi.Write(rw, http.StatusBadRequest, httpapi.Response{ httpapi.Write(rw, http.StatusBadRequest, codersdk.Response{
Message: "Invalid request to update template metadata!", Message: "Invalid request to update template metadata!",
Validations: validErrs, Validations: validErrs,
}) })
@ -439,7 +439,7 @@ func (api *API) patchTemplateMeta(rw http.ResponseWriter, r *http.Request) {
return nil return nil
}) })
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error updating template metadata.", Message: "Internal error updating template metadata.",
Detail: err.Error(), Detail: err.Error(),
}) })
@ -453,7 +453,7 @@ func (api *API) patchTemplateMeta(rw http.ResponseWriter, r *http.Request) {
createdByNameMap, err := getCreatedByNamesByTemplateIDs(r.Context(), api.Database, []database.Template{updated}) createdByNameMap, err := getCreatedByNamesByTemplateIDs(r.Context(), api.Database, []database.Template{updated})
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error fetching creator name.", Message: "Internal error fetching creator name.",
Detail: err.Error(), Detail: err.Error(),
}) })

View File

@ -29,7 +29,7 @@ func (api *API) templateVersion(rw http.ResponseWriter, r *http.Request) {
job, err := api.Database.GetProvisionerJobByID(r.Context(), templateVersion.JobID) job, err := api.Database.GetProvisionerJobByID(r.Context(), templateVersion.JobID)
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error fetching provisioner job.", Message: "Internal error fetching provisioner job.",
Detail: err.Error(), Detail: err.Error(),
}) })
@ -48,20 +48,20 @@ func (api *API) patchCancelTemplateVersion(rw http.ResponseWriter, r *http.Reque
job, err := api.Database.GetProvisionerJobByID(r.Context(), templateVersion.JobID) job, err := api.Database.GetProvisionerJobByID(r.Context(), templateVersion.JobID)
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error fetching provisioner job.", Message: "Internal error fetching provisioner job.",
Detail: err.Error(), Detail: err.Error(),
}) })
return return
} }
if job.CompletedAt.Valid { if job.CompletedAt.Valid {
httpapi.Write(rw, http.StatusPreconditionFailed, httpapi.Response{ httpapi.Write(rw, http.StatusPreconditionFailed, codersdk.Response{
Message: "Job has already completed!", Message: "Job has already completed!",
}) })
return return
} }
if job.CanceledAt.Valid { if job.CanceledAt.Valid {
httpapi.Write(rw, http.StatusPreconditionFailed, httpapi.Response{ httpapi.Write(rw, http.StatusPreconditionFailed, codersdk.Response{
Message: "Job has already been marked as canceled!", Message: "Job has already been marked as canceled!",
}) })
return return
@ -74,13 +74,13 @@ func (api *API) patchCancelTemplateVersion(rw http.ResponseWriter, r *http.Reque
}, },
}) })
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error updating provisioner job.", Message: "Internal error updating provisioner job.",
Detail: err.Error(), Detail: err.Error(),
}) })
return return
} }
httpapi.Write(rw, http.StatusOK, httpapi.Response{ httpapi.Write(rw, http.StatusOK, codersdk.Response{
Message: "Job has been marked as canceled...", Message: "Job has been marked as canceled...",
}) })
} }
@ -94,14 +94,14 @@ func (api *API) templateVersionSchema(rw http.ResponseWriter, r *http.Request) {
job, err := api.Database.GetProvisionerJobByID(r.Context(), templateVersion.JobID) job, err := api.Database.GetProvisionerJobByID(r.Context(), templateVersion.JobID)
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error fetching provisioner job.", Message: "Internal error fetching provisioner job.",
Detail: err.Error(), Detail: err.Error(),
}) })
return return
} }
if !job.CompletedAt.Valid { if !job.CompletedAt.Valid {
httpapi.Write(rw, http.StatusPreconditionFailed, httpapi.Response{ httpapi.Write(rw, http.StatusPreconditionFailed, codersdk.Response{
Message: "Template version job hasn't completed!", Message: "Template version job hasn't completed!",
}) })
return return
@ -111,7 +111,7 @@ func (api *API) templateVersionSchema(rw http.ResponseWriter, r *http.Request) {
err = nil err = nil
} }
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error listing parameter schemas.", Message: "Internal error listing parameter schemas.",
Detail: err.Error(), Detail: err.Error(),
}) })
@ -121,7 +121,7 @@ func (api *API) templateVersionSchema(rw http.ResponseWriter, r *http.Request) {
for _, schema := range schemas { for _, schema := range schemas {
apiSchema, err := convertParameterSchema(schema) apiSchema, err := convertParameterSchema(schema)
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: fmt.Sprintf("Internal error converting schema %s.", schema.Name), Message: fmt.Sprintf("Internal error converting schema %s.", schema.Name),
Detail: err.Error(), Detail: err.Error(),
}) })
@ -142,14 +142,14 @@ func (api *API) templateVersionParameters(rw http.ResponseWriter, r *http.Reques
job, err := api.Database.GetProvisionerJobByID(r.Context(), templateVersion.JobID) job, err := api.Database.GetProvisionerJobByID(r.Context(), templateVersion.JobID)
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error fetching provisioner job.", Message: "Internal error fetching provisioner job.",
Detail: err.Error(), Detail: err.Error(),
}) })
return return
} }
if !job.CompletedAt.Valid { if !job.CompletedAt.Valid {
httpapi.Write(rw, http.StatusPreconditionFailed, httpapi.Response{ httpapi.Write(rw, http.StatusPreconditionFailed, codersdk.Response{
Message: "Job hasn't completed!", Message: "Job hasn't completed!",
}) })
return return
@ -163,7 +163,7 @@ func (api *API) templateVersionParameters(rw http.ResponseWriter, r *http.Reques
HideRedisplayValues: true, HideRedisplayValues: true,
}) })
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error computing values.", Message: "Internal error computing values.",
Detail: err.Error(), Detail: err.Error(),
}) })
@ -198,14 +198,14 @@ func (api *API) postTemplateVersionDryRun(rw http.ResponseWriter, r *http.Reques
job, err := api.Database.GetProvisionerJobByID(r.Context(), templateVersion.JobID) job, err := api.Database.GetProvisionerJobByID(r.Context(), templateVersion.JobID)
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error updating provisioner job.", Message: "Internal error updating provisioner job.",
Detail: err.Error(), Detail: err.Error(),
}) })
return return
} }
if !job.CompletedAt.Valid { if !job.CompletedAt.Valid {
httpapi.Write(rw, http.StatusPreconditionFailed, httpapi.Response{ httpapi.Write(rw, http.StatusPreconditionFailed, codersdk.Response{
Message: "Template version import job hasn't completed!", Message: "Template version import job hasn't completed!",
}) })
return return
@ -233,7 +233,7 @@ func (api *API) postTemplateVersionDryRun(rw http.ResponseWriter, r *http.Reques
ParameterValues: parameterValues, ParameterValues: parameterValues,
}) })
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error unmarshalling provisioner job.", Message: "Internal error unmarshalling provisioner job.",
Detail: err.Error(), Detail: err.Error(),
}) })
@ -255,7 +255,7 @@ func (api *API) postTemplateVersionDryRun(rw http.ResponseWriter, r *http.Reques
Input: input, Input: input,
}) })
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error inserting provisioner job.", Message: "Internal error inserting provisioner job.",
Detail: err.Error(), Detail: err.Error(),
}) })
@ -306,13 +306,13 @@ func (api *API) patchTemplateVersionDryRunCancel(rw http.ResponseWriter, r *http
} }
if job.CompletedAt.Valid { if job.CompletedAt.Valid {
httpapi.Write(rw, http.StatusPreconditionFailed, httpapi.Response{ httpapi.Write(rw, http.StatusPreconditionFailed, codersdk.Response{
Message: "Job has already completed.", Message: "Job has already completed.",
}) })
return return
} }
if job.CanceledAt.Valid { if job.CanceledAt.Valid {
httpapi.Write(rw, http.StatusPreconditionFailed, httpapi.Response{ httpapi.Write(rw, http.StatusPreconditionFailed, codersdk.Response{
Message: "Job has already been marked as canceled.", Message: "Job has already been marked as canceled.",
}) })
return return
@ -326,14 +326,14 @@ func (api *API) patchTemplateVersionDryRunCancel(rw http.ResponseWriter, r *http
}, },
}) })
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error updating provisioner job.", Message: "Internal error updating provisioner job.",
Detail: err.Error(), Detail: err.Error(),
}) })
return return
} }
httpapi.Write(rw, http.StatusOK, httpapi.Response{ httpapi.Write(rw, http.StatusOK, codersdk.Response{
Message: "Job has been marked as canceled.", Message: "Job has been marked as canceled.",
}) })
} }
@ -350,7 +350,7 @@ func (api *API) fetchTemplateVersionDryRunJob(rw http.ResponseWriter, r *http.Re
jobUUID, err := uuid.Parse(jobID) jobUUID, err := uuid.Parse(jobID)
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusBadRequest, httpapi.Response{ httpapi.Write(rw, http.StatusBadRequest, codersdk.Response{
Message: fmt.Sprintf("Job ID %q must be a valid UUID.", jobID), Message: fmt.Sprintf("Job ID %q must be a valid UUID.", jobID),
Detail: err.Error(), Detail: err.Error(),
}) })
@ -359,13 +359,13 @@ func (api *API) fetchTemplateVersionDryRunJob(rw http.ResponseWriter, r *http.Re
job, err := api.Database.GetProvisionerJobByID(r.Context(), jobUUID) job, err := api.Database.GetProvisionerJobByID(r.Context(), jobUUID)
if xerrors.Is(err, sql.ErrNoRows) { if xerrors.Is(err, sql.ErrNoRows) {
httpapi.Write(rw, http.StatusNotFound, httpapi.Response{ httpapi.Write(rw, http.StatusNotFound, codersdk.Response{
Message: fmt.Sprintf("Provisioner job %q not found.", jobUUID), Message: fmt.Sprintf("Provisioner job %q not found.", jobUUID),
}) })
return database.ProvisionerJob{}, false return database.ProvisionerJob{}, false
} }
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error fetching provisioner job.", Message: "Internal error fetching provisioner job.",
Detail: err.Error(), Detail: err.Error(),
}) })
@ -386,7 +386,7 @@ func (api *API) fetchTemplateVersionDryRunJob(rw http.ResponseWriter, r *http.Re
var input templateVersionDryRunJob var input templateVersionDryRunJob
err = json.Unmarshal(job.Input, &input) err = json.Unmarshal(job.Input, &input)
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error unmarshaling job metadata.", Message: "Internal error unmarshaling job metadata.",
Detail: err.Error(), Detail: err.Error(),
}) })
@ -420,12 +420,12 @@ func (api *API) templateVersionsByTemplate(rw http.ResponseWriter, r *http.Reque
// query will not work. // query will not work.
_, err := store.GetTemplateVersionByID(r.Context(), paginationParams.AfterID) _, err := store.GetTemplateVersionByID(r.Context(), paginationParams.AfterID)
if err != nil && xerrors.Is(err, sql.ErrNoRows) { if err != nil && xerrors.Is(err, sql.ErrNoRows) {
httpapi.Write(rw, http.StatusBadRequest, httpapi.Response{ httpapi.Write(rw, http.StatusBadRequest, codersdk.Response{
Message: fmt.Sprintf("Record at \"after_id\" (%q) does not exists.", paginationParams.AfterID.String()), Message: fmt.Sprintf("Record at \"after_id\" (%q) does not exists.", paginationParams.AfterID.String()),
}) })
return err return err
} else if err != nil { } else if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error fetching template version at after_id.", Message: "Internal error fetching template version at after_id.",
Detail: err.Error(), Detail: err.Error(),
}) })
@ -444,7 +444,7 @@ func (api *API) templateVersionsByTemplate(rw http.ResponseWriter, r *http.Reque
return err return err
} }
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error fetching template versions.", Message: "Internal error fetching template versions.",
Detail: err.Error(), Detail: err.Error(),
}) })
@ -457,7 +457,7 @@ func (api *API) templateVersionsByTemplate(rw http.ResponseWriter, r *http.Reque
} }
jobs, err := store.GetProvisionerJobsByIDs(r.Context(), jobIDs) jobs, err := store.GetProvisionerJobsByIDs(r.Context(), jobIDs)
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error fetching provisioner job.", Message: "Internal error fetching provisioner job.",
Detail: err.Error(), Detail: err.Error(),
}) })
@ -471,7 +471,7 @@ func (api *API) templateVersionsByTemplate(rw http.ResponseWriter, r *http.Reque
for _, version := range versions { for _, version := range versions {
job, exists := jobByID[version.JobID.String()] job, exists := jobByID[version.JobID.String()]
if !exists { if !exists {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: fmt.Sprintf("Job %q doesn't exist for version %q.", version.JobID, version.ID), Message: fmt.Sprintf("Job %q doesn't exist for version %q.", version.JobID, version.ID),
}) })
return err return err
@ -504,13 +504,13 @@ func (api *API) templateVersionByName(rw http.ResponseWriter, r *http.Request) {
Name: templateVersionName, Name: templateVersionName,
}) })
if errors.Is(err, sql.ErrNoRows) { if errors.Is(err, sql.ErrNoRows) {
httpapi.Write(rw, http.StatusNotFound, httpapi.Response{ httpapi.Write(rw, http.StatusNotFound, codersdk.Response{
Message: fmt.Sprintf("No template version found by name %q.", templateVersionName), Message: fmt.Sprintf("No template version found by name %q.", templateVersionName),
}) })
return return
} }
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error fetching template version.", Message: "Internal error fetching template version.",
Detail: err.Error(), Detail: err.Error(),
}) })
@ -518,7 +518,7 @@ func (api *API) templateVersionByName(rw http.ResponseWriter, r *http.Request) {
} }
job, err := api.Database.GetProvisionerJobByID(r.Context(), templateVersion.JobID) job, err := api.Database.GetProvisionerJobByID(r.Context(), templateVersion.JobID)
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error fetching provisioner job.", Message: "Internal error fetching provisioner job.",
Detail: err.Error(), Detail: err.Error(),
}) })
@ -541,20 +541,20 @@ func (api *API) patchActiveTemplateVersion(rw http.ResponseWriter, r *http.Reque
} }
version, err := api.Database.GetTemplateVersionByID(r.Context(), req.ID) version, err := api.Database.GetTemplateVersionByID(r.Context(), req.ID)
if errors.Is(err, sql.ErrNoRows) { if errors.Is(err, sql.ErrNoRows) {
httpapi.Write(rw, http.StatusNotFound, httpapi.Response{ httpapi.Write(rw, http.StatusNotFound, codersdk.Response{
Message: "Template version not found.", Message: "Template version not found.",
}) })
return return
} }
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error fetching template version.", Message: "Internal error fetching template version.",
Detail: err.Error(), Detail: err.Error(),
}) })
return return
} }
if version.TemplateID.UUID.String() != template.ID.String() { if version.TemplateID.UUID.String() != template.ID.String() {
httpapi.Write(rw, http.StatusUnauthorized, httpapi.Response{ httpapi.Write(rw, http.StatusUnauthorized, codersdk.Response{
Message: "The provided template version doesn't belong to the specified template.", Message: "The provided template version doesn't belong to the specified template.",
}) })
return return
@ -572,13 +572,13 @@ func (api *API) patchActiveTemplateVersion(rw http.ResponseWriter, r *http.Reque
return nil return nil
}) })
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error updating active template version.", Message: "Internal error updating active template version.",
Detail: err.Error(), Detail: err.Error(),
}) })
return return
} }
httpapi.Write(rw, http.StatusOK, httpapi.Response{ httpapi.Write(rw, http.StatusOK, codersdk.Response{
Message: "Updated the active template version!", Message: "Updated the active template version!",
}) })
} }
@ -595,13 +595,13 @@ func (api *API) postTemplateVersionsByOrganization(rw http.ResponseWriter, r *ht
if req.TemplateID != uuid.Nil { if req.TemplateID != uuid.Nil {
_, err := api.Database.GetTemplateByID(r.Context(), req.TemplateID) _, err := api.Database.GetTemplateByID(r.Context(), req.TemplateID)
if errors.Is(err, sql.ErrNoRows) { if errors.Is(err, sql.ErrNoRows) {
httpapi.Write(rw, http.StatusNotFound, httpapi.Response{ httpapi.Write(rw, http.StatusNotFound, codersdk.Response{
Message: "Template does not exist.", Message: "Template does not exist.",
}) })
return return
} }
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error fetching template.", Message: "Internal error fetching template.",
Detail: err.Error(), Detail: err.Error(),
}) })
@ -611,13 +611,13 @@ func (api *API) postTemplateVersionsByOrganization(rw http.ResponseWriter, r *ht
file, err := api.Database.GetFileByHash(r.Context(), req.StorageSource) file, err := api.Database.GetFileByHash(r.Context(), req.StorageSource)
if errors.Is(err, sql.ErrNoRows) { if errors.Is(err, sql.ErrNoRows) {
httpapi.Write(rw, http.StatusNotFound, httpapi.Response{ httpapi.Write(rw, http.StatusNotFound, codersdk.Response{
Message: "File not found.", Message: "File not found.",
}) })
return return
} }
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error fetching file.", Message: "Internal error fetching file.",
Detail: err.Error(), Detail: err.Error(),
}) })
@ -742,7 +742,7 @@ func (api *API) postTemplateVersionsByOrganization(rw http.ResponseWriter, r *ht
return nil return nil
}) })
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: err.Error(), Message: err.Error(),
}) })
return return
@ -765,7 +765,7 @@ func (api *API) templateVersionResources(rw http.ResponseWriter, r *http.Request
job, err := api.Database.GetProvisionerJobByID(r.Context(), templateVersion.JobID) job, err := api.Database.GetProvisionerJobByID(r.Context(), templateVersion.JobID)
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error fetching provisioner job.", Message: "Internal error fetching provisioner job.",
Detail: err.Error(), Detail: err.Error(),
}) })
@ -787,7 +787,7 @@ func (api *API) templateVersionLogs(rw http.ResponseWriter, r *http.Request) {
job, err := api.Database.GetProvisionerJobByID(r.Context(), templateVersion.JobID) job, err := api.Database.GetProvisionerJobByID(r.Context(), templateVersion.JobID)
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error fetching provisioner job.", Message: "Internal error fetching provisioner job.",
Detail: err.Error(), Detail: err.Error(),
}) })

View File

@ -49,7 +49,7 @@ func (api *API) userOAuth2Github(rw http.ResponseWriter, r *http.Request) {
oauthClient := oauth2.NewClient(r.Context(), oauth2.StaticTokenSource(state.Token)) oauthClient := oauth2.NewClient(r.Context(), oauth2.StaticTokenSource(state.Token))
memberships, err := api.GithubOAuth2Config.ListOrganizationMemberships(r.Context(), oauthClient) memberships, err := api.GithubOAuth2Config.ListOrganizationMemberships(r.Context(), oauthClient)
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error fetching authenticated Github user organizations.", Message: "Internal error fetching authenticated Github user organizations.",
Detail: err.Error(), Detail: err.Error(),
}) })
@ -66,7 +66,7 @@ func (api *API) userOAuth2Github(rw http.ResponseWriter, r *http.Request) {
} }
} }
if selectedMembership == nil { if selectedMembership == nil {
httpapi.Write(rw, http.StatusUnauthorized, httpapi.Response{ httpapi.Write(rw, http.StatusUnauthorized, codersdk.Response{
Message: "You aren't a member of the authorized Github organizations!", Message: "You aren't a member of the authorized Github organizations!",
}) })
return return
@ -76,7 +76,7 @@ func (api *API) userOAuth2Github(rw http.ResponseWriter, r *http.Request) {
if len(api.GithubOAuth2Config.AllowTeams) > 0 { if len(api.GithubOAuth2Config.AllowTeams) > 0 {
teams, err := api.GithubOAuth2Config.ListTeams(r.Context(), oauthClient, *selectedMembership.Organization.Login) teams, err := api.GithubOAuth2Config.ListTeams(r.Context(), oauthClient, *selectedMembership.Organization.Login)
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Failed to fetch teams from GitHub.", Message: "Failed to fetch teams from GitHub.",
Detail: err.Error(), Detail: err.Error(),
}) })
@ -100,7 +100,7 @@ func (api *API) userOAuth2Github(rw http.ResponseWriter, r *http.Request) {
} }
if allowedTeam == nil { if allowedTeam == nil {
httpapi.Write(rw, http.StatusUnauthorized, httpapi.Response{ httpapi.Write(rw, http.StatusUnauthorized, codersdk.Response{
Message: fmt.Sprintf("You aren't a member of an authorized team in the %s Github organization!", *selectedMembership.Organization.Login), Message: fmt.Sprintf("You aren't a member of an authorized team in the %s Github organization!", *selectedMembership.Organization.Login),
}) })
return return
@ -109,7 +109,7 @@ func (api *API) userOAuth2Github(rw http.ResponseWriter, r *http.Request) {
emails, err := api.GithubOAuth2Config.ListEmails(r.Context(), oauthClient) emails, err := api.GithubOAuth2Config.ListEmails(r.Context(), oauthClient)
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error fetching personal Github user.", Message: "Internal error fetching personal Github user.",
Detail: err.Error(), Detail: err.Error(),
}) })
@ -130,14 +130,14 @@ func (api *API) userOAuth2Github(rw http.ResponseWriter, r *http.Request) {
continue continue
} }
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: fmt.Sprintf("Internal error fetching user by email %q.", *email.Email), Message: fmt.Sprintf("Internal error fetching user by email %q.", *email.Email),
Detail: err.Error(), Detail: err.Error(),
}) })
return return
} }
if !*email.Verified { if !*email.Verified {
httpapi.Write(rw, http.StatusForbidden, httpapi.Response{ httpapi.Write(rw, http.StatusForbidden, codersdk.Response{
Message: fmt.Sprintf("Verify the %q email address on Github to authenticate!", *email.Email), Message: fmt.Sprintf("Verify the %q email address on Github to authenticate!", *email.Email),
}) })
return return
@ -148,7 +148,7 @@ func (api *API) userOAuth2Github(rw http.ResponseWriter, r *http.Request) {
// If the user doesn't exist, create a new one! // If the user doesn't exist, create a new one!
if user.ID == uuid.Nil { if user.ID == uuid.Nil {
if !api.GithubOAuth2Config.AllowSignups { if !api.GithubOAuth2Config.AllowSignups {
httpapi.Write(rw, http.StatusForbidden, httpapi.Response{ httpapi.Write(rw, http.StatusForbidden, codersdk.Response{
Message: "Signups are disabled for Github authentication!", Message: "Signups are disabled for Github authentication!",
}) })
return return
@ -164,7 +164,7 @@ func (api *API) userOAuth2Github(rw http.ResponseWriter, r *http.Request) {
} }
ghUser, err := api.GithubOAuth2Config.AuthenticatedUser(r.Context(), oauthClient) ghUser, err := api.GithubOAuth2Config.AuthenticatedUser(r.Context(), oauthClient)
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error fetching authenticated Github user.", Message: "Internal error fetching authenticated Github user.",
Detail: err.Error(), Detail: err.Error(),
}) })
@ -179,7 +179,7 @@ func (api *API) userOAuth2Github(rw http.ResponseWriter, r *http.Request) {
break break
} }
if verifiedEmail == nil { if verifiedEmail == nil {
httpapi.Write(rw, http.StatusPreconditionRequired, httpapi.Response{ httpapi.Write(rw, http.StatusPreconditionRequired, codersdk.Response{
Message: "Your primary email must be verified on GitHub!", Message: "Your primary email must be verified on GitHub!",
}) })
return return
@ -190,7 +190,7 @@ func (api *API) userOAuth2Github(rw http.ResponseWriter, r *http.Request) {
OrganizationID: organizationID, OrganizationID: organizationID,
}) })
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error creating user.", Message: "Internal error creating user.",
Detail: err.Error(), Detail: err.Error(),
}) })

View File

@ -33,7 +33,7 @@ import (
func (api *API) firstUser(rw http.ResponseWriter, r *http.Request) { func (api *API) firstUser(rw http.ResponseWriter, r *http.Request) {
userCount, err := api.Database.GetUserCount(r.Context()) userCount, err := api.Database.GetUserCount(r.Context())
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error fetching user count.", Message: "Internal error fetching user count.",
Detail: err.Error(), Detail: err.Error(),
}) })
@ -41,13 +41,13 @@ func (api *API) firstUser(rw http.ResponseWriter, r *http.Request) {
} }
if userCount == 0 { if userCount == 0 {
httpapi.Write(rw, http.StatusNotFound, httpapi.Response{ httpapi.Write(rw, http.StatusNotFound, codersdk.Response{
Message: "The initial user has not been created!", Message: "The initial user has not been created!",
}) })
return return
} }
httpapi.Write(rw, http.StatusOK, httpapi.Response{ httpapi.Write(rw, http.StatusOK, codersdk.Response{
Message: "The initial user has already been created!", Message: "The initial user has already been created!",
}) })
} }
@ -62,7 +62,7 @@ func (api *API) postFirstUser(rw http.ResponseWriter, r *http.Request) {
// This should only function for the first user. // This should only function for the first user.
userCount, err := api.Database.GetUserCount(r.Context()) userCount, err := api.Database.GetUserCount(r.Context())
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error fetching user count.", Message: "Internal error fetching user count.",
Detail: err.Error(), Detail: err.Error(),
}) })
@ -71,7 +71,7 @@ func (api *API) postFirstUser(rw http.ResponseWriter, r *http.Request) {
// If a user already exists, the initial admin user no longer can be created. // If a user already exists, the initial admin user no longer can be created.
if userCount != 0 { if userCount != 0 {
httpapi.Write(rw, http.StatusConflict, httpapi.Response{ httpapi.Write(rw, http.StatusConflict, codersdk.Response{
Message: "The initial user has already been created.", Message: "The initial user has already been created.",
}) })
return return
@ -83,7 +83,7 @@ func (api *API) postFirstUser(rw http.ResponseWriter, r *http.Request) {
Password: createUser.Password, Password: createUser.Password,
}) })
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error creating user.", Message: "Internal error creating user.",
Detail: err.Error(), Detail: err.Error(),
}) })
@ -106,7 +106,7 @@ func (api *API) postFirstUser(rw http.ResponseWriter, r *http.Request) {
ID: user.ID, ID: user.ID,
}) })
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error updating user's roles.", Message: "Internal error updating user's roles.",
Detail: err.Error(), Detail: err.Error(),
}) })
@ -123,7 +123,7 @@ func (api *API) users(rw http.ResponseWriter, r *http.Request) {
query := r.URL.Query().Get("q") query := r.URL.Query().Get("q")
params, errs := userSearchQuery(query) params, errs := userSearchQuery(query)
if len(errs) > 0 { if len(errs) > 0 {
httpapi.Write(rw, http.StatusBadRequest, httpapi.Response{ httpapi.Write(rw, http.StatusBadRequest, codersdk.Response{
Message: "Invalid user search query.", Message: "Invalid user search query.",
Validations: errs, Validations: errs,
}) })
@ -148,7 +148,7 @@ func (api *API) users(rw http.ResponseWriter, r *http.Request) {
return return
} }
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error fetching users.", Message: "Internal error fetching users.",
Detail: err.Error(), Detail: err.Error(),
}) })
@ -165,7 +165,7 @@ func (api *API) users(rw http.ResponseWriter, r *http.Request) {
err = nil err = nil
} }
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error fetching user's organizations.", Message: "Internal error fetching user's organizations.",
Detail: err.Error(), Detail: err.Error(),
}) })
@ -207,13 +207,13 @@ func (api *API) postUser(rw http.ResponseWriter, r *http.Request) {
Email: createUser.Email, Email: createUser.Email,
}) })
if err == nil { if err == nil {
httpapi.Write(rw, http.StatusConflict, httpapi.Response{ httpapi.Write(rw, http.StatusConflict, codersdk.Response{
Message: "User already exists.", Message: "User already exists.",
}) })
return return
} }
if !errors.Is(err, sql.ErrNoRows) { if !errors.Is(err, sql.ErrNoRows) {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error fetching user.", Message: "Internal error fetching user.",
Detail: err.Error(), Detail: err.Error(),
}) })
@ -222,13 +222,13 @@ func (api *API) postUser(rw http.ResponseWriter, r *http.Request) {
_, err = api.Database.GetOrganizationByID(r.Context(), createUser.OrganizationID) _, err = api.Database.GetOrganizationByID(r.Context(), createUser.OrganizationID)
if errors.Is(err, sql.ErrNoRows) { if errors.Is(err, sql.ErrNoRows) {
httpapi.Write(rw, http.StatusNotFound, httpapi.Response{ httpapi.Write(rw, http.StatusNotFound, codersdk.Response{
Message: fmt.Sprintf("Organization does not exist with the provided id %q.", createUser.OrganizationID), Message: fmt.Sprintf("Organization does not exist with the provided id %q.", createUser.OrganizationID),
}) })
return return
} }
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error fetching organization.", Message: "Internal error fetching organization.",
Detail: err.Error(), Detail: err.Error(),
}) })
@ -237,7 +237,7 @@ func (api *API) postUser(rw http.ResponseWriter, r *http.Request) {
user, _, err := api.createUser(r.Context(), createUser) user, _, err := api.createUser(r.Context(), createUser)
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error creating user.", Message: "Internal error creating user.",
Detail: err.Error(), Detail: err.Error(),
}) })
@ -264,7 +264,7 @@ func (api *API) userByName(rw http.ResponseWriter, r *http.Request) {
} }
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error fetching user's organizations.", Message: "Internal error fetching user's organizations.",
Detail: err.Error(), Detail: err.Error(),
}) })
@ -292,21 +292,21 @@ func (api *API) putUserProfile(rw http.ResponseWriter, r *http.Request) {
isDifferentUser := existentUser.ID != user.ID isDifferentUser := existentUser.ID != user.ID
if err == nil && isDifferentUser { if err == nil && isDifferentUser {
responseErrors := []httpapi.Error{} responseErrors := []codersdk.ValidationError{}
if existentUser.Username == params.Username { if existentUser.Username == params.Username {
responseErrors = append(responseErrors, httpapi.Error{ responseErrors = append(responseErrors, codersdk.ValidationError{
Field: "username", Field: "username",
Detail: "this value is already in use and should be unique", Detail: "this value is already in use and should be unique",
}) })
} }
httpapi.Write(rw, http.StatusConflict, httpapi.Response{ httpapi.Write(rw, http.StatusConflict, codersdk.Response{
Message: "User already exists.", Message: "User already exists.",
Validations: responseErrors, Validations: responseErrors,
}) })
return return
} }
if !errors.Is(err, sql.ErrNoRows) && isDifferentUser { if !errors.Is(err, sql.ErrNoRows) && isDifferentUser {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error fetching user.", Message: "Internal error fetching user.",
Detail: err.Error(), Detail: err.Error(),
}) })
@ -321,7 +321,7 @@ func (api *API) putUserProfile(rw http.ResponseWriter, r *http.Request) {
}) })
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error updating user.", Message: "Internal error updating user.",
Detail: err.Error(), Detail: err.Error(),
}) })
@ -330,7 +330,7 @@ func (api *API) putUserProfile(rw http.ResponseWriter, r *http.Request) {
organizationIDs, err := userOrganizationIDs(r.Context(), api, user) organizationIDs, err := userOrganizationIDs(r.Context(), api, user)
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error fetching user's organizations.", Message: "Internal error fetching user's organizations.",
Detail: err.Error(), Detail: err.Error(),
}) })
@ -351,7 +351,7 @@ func (api *API) putUserStatus(status database.UserStatus) func(rw http.ResponseW
} }
if status == database.UserStatusSuspended && user.ID == apiKey.UserID { if status == database.UserStatusSuspended && user.ID == apiKey.UserID {
httpapi.Write(rw, http.StatusBadRequest, httpapi.Response{ httpapi.Write(rw, http.StatusBadRequest, codersdk.Response{
Message: "You cannot suspend yourself.", Message: "You cannot suspend yourself.",
}) })
return return
@ -364,7 +364,7 @@ func (api *API) putUserStatus(status database.UserStatus) func(rw http.ResponseW
}) })
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: fmt.Sprintf("Internal error updating user's status to %q.", status), Message: fmt.Sprintf("Internal error updating user's status to %q.", status),
Detail: err.Error(), Detail: err.Error(),
}) })
@ -373,7 +373,7 @@ func (api *API) putUserStatus(status database.UserStatus) func(rw http.ResponseW
organizations, err := userOrganizationIDs(r.Context(), api, user) organizations, err := userOrganizationIDs(r.Context(), api, user)
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error fetching user's organizations.", Message: "Internal error fetching user's organizations.",
Detail: err.Error(), Detail: err.Error(),
}) })
@ -401,9 +401,9 @@ func (api *API) putUserPassword(rw http.ResponseWriter, r *http.Request) {
err := userpassword.Validate(params.Password) err := userpassword.Validate(params.Password)
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusBadRequest, httpapi.Response{ httpapi.Write(rw, http.StatusBadRequest, codersdk.Response{
Message: "Invalid password.", Message: "Invalid password.",
Validations: []httpapi.Error{ Validations: []codersdk.ValidationError{
{ {
Field: "password", Field: "password",
Detail: err.Error(), Detail: err.Error(),
@ -423,16 +423,16 @@ func (api *API) putUserPassword(rw http.ResponseWriter, r *http.Request) {
// if they send something let's validate it // if they send something let's validate it
ok, err := userpassword.Compare(string(user.HashedPassword), params.OldPassword) ok, err := userpassword.Compare(string(user.HashedPassword), params.OldPassword)
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error with passwords.", Message: "Internal error with passwords.",
Detail: err.Error(), Detail: err.Error(),
}) })
return return
} }
if !ok { if !ok {
httpapi.Write(rw, http.StatusBadRequest, httpapi.Response{ httpapi.Write(rw, http.StatusBadRequest, codersdk.Response{
Message: "Old password is incorrect.", Message: "Old password is incorrect.",
Validations: []httpapi.Error{ Validations: []codersdk.ValidationError{
{ {
Field: "old_password", Field: "old_password",
Detail: "Old password is incorrect.", Detail: "Old password is incorrect.",
@ -445,7 +445,7 @@ func (api *API) putUserPassword(rw http.ResponseWriter, r *http.Request) {
hashedPassword, err := userpassword.Hash(params.Password) hashedPassword, err := userpassword.Hash(params.Password)
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error hashing new password.", Message: "Internal error hashing new password.",
Detail: err.Error(), Detail: err.Error(),
}) })
@ -456,7 +456,7 @@ func (api *API) putUserPassword(rw http.ResponseWriter, r *http.Request) {
HashedPassword: []byte(hashedPassword), HashedPassword: []byte(hashedPassword),
}) })
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error updating user's password.", Message: "Internal error updating user's password.",
Detail: err.Error(), Detail: err.Error(),
}) })
@ -481,7 +481,7 @@ func (api *API) userRoles(rw http.ResponseWriter, r *http.Request) {
memberships, err := api.Database.GetOrganizationMembershipsByUserID(r.Context(), user.ID) memberships, err := api.Database.GetOrganizationMembershipsByUserID(r.Context(), user.ID)
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error fetching user's organization memberships.", Message: "Internal error fetching user's organization memberships.",
Detail: err.Error(), Detail: err.Error(),
}) })
@ -508,7 +508,7 @@ func (api *API) putUserRoles(rw http.ResponseWriter, r *http.Request) {
apiKey := httpmw.APIKey(r) apiKey := httpmw.APIKey(r)
if apiKey.UserID == user.ID { if apiKey.UserID == user.ID {
httpapi.Write(rw, http.StatusBadRequest, httpapi.Response{ httpapi.Write(rw, http.StatusBadRequest, codersdk.Response{
Message: "You cannot change your own roles.", Message: "You cannot change your own roles.",
}) })
return return
@ -547,7 +547,7 @@ func (api *API) putUserRoles(rw http.ResponseWriter, r *http.Request) {
ID: user.ID, ID: user.ID,
}) })
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusBadRequest, httpapi.Response{ httpapi.Write(rw, http.StatusBadRequest, codersdk.Response{
Message: err.Error(), Message: err.Error(),
}) })
return return
@ -555,7 +555,7 @@ func (api *API) putUserRoles(rw http.ResponseWriter, r *http.Request) {
organizationIDs, err := userOrganizationIDs(r.Context(), api, user) organizationIDs, err := userOrganizationIDs(r.Context(), api, user)
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error fetching user's organizations.", Message: "Internal error fetching user's organizations.",
Detail: err.Error(), Detail: err.Error(),
}) })
@ -596,7 +596,7 @@ func (api *API) organizationsByUser(rw http.ResponseWriter, r *http.Request) {
organizations = []database.Organization{} organizations = []database.Organization{}
} }
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error fetching user's organizations.", Message: "Internal error fetching user's organizations.",
Detail: err.Error(), Detail: err.Error(),
}) })
@ -622,7 +622,7 @@ func (api *API) organizationByUserAndName(rw http.ResponseWriter, r *http.Reques
return return
} }
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error fetching organization.", Message: "Internal error fetching organization.",
Detail: err.Error(), Detail: err.Error(),
}) })
@ -651,7 +651,7 @@ func (api *API) postLogin(rw http.ResponseWriter, r *http.Request) {
Email: loginWithPassword.Email, Email: loginWithPassword.Email,
}) })
if err != nil && !xerrors.Is(err, sql.ErrNoRows) { if err != nil && !xerrors.Is(err, sql.ErrNoRows) {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error.", Message: "Internal error.",
}) })
return return
@ -660,7 +660,7 @@ func (api *API) postLogin(rw http.ResponseWriter, r *http.Request) {
// If the user doesn't exist, it will be a default struct. // If the user doesn't exist, it will be a default struct.
equal, err := userpassword.Compare(string(user.HashedPassword), loginWithPassword.Password) equal, err := userpassword.Compare(string(user.HashedPassword), loginWithPassword.Password)
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error.", Message: "Internal error.",
}) })
return return
@ -668,7 +668,7 @@ func (api *API) postLogin(rw http.ResponseWriter, r *http.Request) {
if !equal { if !equal {
// This message is the same as above to remove ease in detecting whether // This message is the same as above to remove ease in detecting whether
// users are registered or not. Attackers still could with a timing attack. // users are registered or not. Attackers still could with a timing attack.
httpapi.Write(rw, http.StatusUnauthorized, httpapi.Response{ httpapi.Write(rw, http.StatusUnauthorized, codersdk.Response{
Message: "Incorrect email or password.", Message: "Incorrect email or password.",
}) })
return return
@ -676,7 +676,7 @@ func (api *API) postLogin(rw http.ResponseWriter, r *http.Request) {
// If the user logged into a suspended account, reject the login request. // If the user logged into a suspended account, reject the login request.
if user.Status != database.UserStatusActive { if user.Status != database.UserStatusActive {
httpapi.Write(rw, http.StatusUnauthorized, httpapi.Response{ httpapi.Write(rw, http.StatusUnauthorized, codersdk.Response{
Message: "Your account is suspended. Contact an admin to reactivate your account.", Message: "Your account is suspended. Contact an admin to reactivate your account.",
}) })
return return
@ -738,7 +738,7 @@ func (api *API) apiKey(rw http.ResponseWriter, r *http.Request) {
return return
} }
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error fetching API key.", Message: "Internal error fetching API key.",
Detail: err.Error(), Detail: err.Error(),
}) })
@ -754,7 +754,7 @@ func (api *API) postLogout(rw http.ResponseWriter, r *http.Request) {
cookie := &http.Cookie{ cookie := &http.Cookie{
// MaxAge < 0 means to delete the cookie now. // MaxAge < 0 means to delete the cookie now.
MaxAge: -1, MaxAge: -1,
Name: httpmw.SessionTokenKey, Name: codersdk.SessionTokenKey,
Path: "/", Path: "/",
} }
@ -764,14 +764,14 @@ func (api *API) postLogout(rw http.ResponseWriter, r *http.Request) {
apiKey := httpmw.APIKey(r) apiKey := httpmw.APIKey(r)
err := api.Database.DeleteAPIKeyByID(r.Context(), apiKey.ID) err := api.Database.DeleteAPIKeyByID(r.Context(), apiKey.ID)
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error deleting API key.", Message: "Internal error deleting API key.",
Detail: err.Error(), Detail: err.Error(),
}) })
return return
} }
httpapi.Write(rw, http.StatusOK, httpapi.Response{ httpapi.Write(rw, http.StatusOK, codersdk.Response{
Message: "Logged out!", Message: "Logged out!",
}) })
} }
@ -794,7 +794,7 @@ func generateAPIKeyIDSecret() (id string, secret string, err error) {
func (api *API) createAPIKey(rw http.ResponseWriter, r *http.Request, params database.InsertAPIKeyParams) (string, bool) { func (api *API) createAPIKey(rw http.ResponseWriter, r *http.Request, params database.InsertAPIKeyParams) (string, bool) {
keyID, keySecret, err := generateAPIKeyIDSecret() keyID, keySecret, err := generateAPIKeyIDSecret()
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error generating API key.", Message: "Internal error generating API key.",
Detail: err.Error(), Detail: err.Error(),
}) })
@ -840,7 +840,7 @@ func (api *API) createAPIKey(rw http.ResponseWriter, r *http.Request, params dat
OAuthExpiry: params.OAuthExpiry, OAuthExpiry: params.OAuthExpiry,
}) })
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error inserting API key.", Message: "Internal error inserting API key.",
Detail: err.Error(), Detail: err.Error(),
}) })
@ -854,7 +854,7 @@ func (api *API) createAPIKey(rw http.ResponseWriter, r *http.Request, params dat
// This format is consumed by the APIKey middleware. // This format is consumed by the APIKey middleware.
sessionToken := fmt.Sprintf("%s-%s", keyID, keySecret) sessionToken := fmt.Sprintf("%s-%s", keyID, keySecret)
http.SetCookie(rw, &http.Cookie{ http.SetCookie(rw, &http.Cookie{
Name: httpmw.SessionTokenKey, Name: codersdk.SessionTokenKey,
Value: sessionToken, Value: sessionToken,
Path: "/", Path: "/",
HttpOnly: true, HttpOnly: true,
@ -985,7 +985,7 @@ func findUser(id uuid.UUID, users []database.User) *database.User {
return nil return nil
} }
func userSearchQuery(query string) (database.GetUsersParams, []httpapi.Error) { func userSearchQuery(query string) (database.GetUsersParams, []codersdk.ValidationError) {
searchParams := make(url.Values) searchParams := make(url.Values)
if query == "" { if query == "" {
// No filter // No filter
@ -1005,7 +1005,7 @@ func userSearchQuery(query string) (database.GetUsersParams, []httpapi.Error) {
case 2: case 2:
searchParams.Set(parts[0], parts[1]) searchParams.Set(parts[0], parts[1])
default: default:
return database.GetUsersParams{}, []httpapi.Error{ return database.GetUsersParams{}, []codersdk.ValidationError{
{Field: "q", Detail: fmt.Sprintf("Query element %q can only contain 1 ':'", element)}, {Field: "q", Detail: fmt.Sprintf("Query element %q can only contain 1 ':'", element)},
} }
} }

View File

@ -13,7 +13,6 @@ import (
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
"github.com/coder/coder/coderd/coderdtest" "github.com/coder/coder/coderd/coderdtest"
"github.com/coder/coder/coderd/httpmw"
"github.com/coder/coder/coderd/rbac" "github.com/coder/coder/coderd/rbac"
"github.com/coder/coder/codersdk" "github.com/coder/coder/codersdk"
) )
@ -183,7 +182,7 @@ func TestPostLogout(t *testing.T) {
cookies := res.Cookies() cookies := res.Cookies()
require.Len(t, cookies, 1, "Exactly one cookie should be returned") require.Len(t, cookies, 1, "Exactly one cookie should be returned")
require.Equal(t, httpmw.SessionTokenKey, cookies[0].Name, "Cookie should be the auth cookie") require.Equal(t, codersdk.SessionTokenKey, cookies[0].Name, "Cookie should be the auth cookie")
require.Equal(t, -1, cookies[0].MaxAge, "Cookie should be set to delete") require.Equal(t, -1, cookies[0].MaxAge, "Cookie should be set to delete")
_, err = client.GetAPIKey(ctx, admin.UserID.String(), keyID) _, err = client.GetAPIKey(ctx, admin.UserID.String(), keyID)

View File

@ -44,7 +44,7 @@ func (api *API) workspaceAgent(rw http.ResponseWriter, r *http.Request) {
} }
dbApps, err := api.Database.GetWorkspaceAppsByAgentID(r.Context(), workspaceAgent.ID) dbApps, err := api.Database.GetWorkspaceAppsByAgentID(r.Context(), workspaceAgent.ID)
if err != nil && !xerrors.Is(err, sql.ErrNoRows) { if err != nil && !xerrors.Is(err, sql.ErrNoRows) {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error fetching workspace agent applications.", Message: "Internal error fetching workspace agent applications.",
Detail: err.Error(), Detail: err.Error(),
}) })
@ -52,7 +52,7 @@ func (api *API) workspaceAgent(rw http.ResponseWriter, r *http.Request) {
} }
apiAgent, err := convertWorkspaceAgent(workspaceAgent, convertApps(dbApps), api.AgentInactiveDisconnectTimeout) apiAgent, err := convertWorkspaceAgent(workspaceAgent, convertApps(dbApps), api.AgentInactiveDisconnectTimeout)
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error reading workspace agent.", Message: "Internal error reading workspace agent.",
Detail: err.Error(), Detail: err.Error(),
}) })
@ -76,14 +76,14 @@ func (api *API) workspaceAgentDial(rw http.ResponseWriter, r *http.Request) {
} }
apiAgent, err := convertWorkspaceAgent(workspaceAgent, nil, api.AgentInactiveDisconnectTimeout) apiAgent, err := convertWorkspaceAgent(workspaceAgent, nil, api.AgentInactiveDisconnectTimeout)
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error reading workspace agent.", Message: "Internal error reading workspace agent.",
Detail: err.Error(), Detail: err.Error(),
}) })
return return
} }
if apiAgent.Status != codersdk.WorkspaceAgentConnected { if apiAgent.Status != codersdk.WorkspaceAgentConnected {
httpapi.Write(rw, http.StatusPreconditionFailed, httpapi.Response{ httpapi.Write(rw, http.StatusPreconditionFailed, codersdk.Response{
Message: fmt.Sprintf("Agent isn't connected! Status: %s.", apiAgent.Status), Message: fmt.Sprintf("Agent isn't connected! Status: %s.", apiAgent.Status),
}) })
return return
@ -91,7 +91,7 @@ func (api *API) workspaceAgentDial(rw http.ResponseWriter, r *http.Request) {
conn, err := websocket.Accept(rw, r, nil) conn, err := websocket.Accept(rw, r, nil)
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusBadRequest, httpapi.Response{ httpapi.Write(rw, http.StatusBadRequest, codersdk.Response{
Message: "Failed to accept websocket.", Message: "Failed to accept websocket.",
Detail: err.Error(), Detail: err.Error(),
}) })
@ -123,7 +123,7 @@ func (api *API) workspaceAgentMetadata(rw http.ResponseWriter, r *http.Request)
workspaceAgent := httpmw.WorkspaceAgent(r) workspaceAgent := httpmw.WorkspaceAgent(r)
apiAgent, err := convertWorkspaceAgent(workspaceAgent, nil, api.AgentInactiveDisconnectTimeout) apiAgent, err := convertWorkspaceAgent(workspaceAgent, nil, api.AgentInactiveDisconnectTimeout)
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error reading workspace agent.", Message: "Internal error reading workspace agent.",
Detail: err.Error(), Detail: err.Error(),
}) })
@ -131,7 +131,7 @@ func (api *API) workspaceAgentMetadata(rw http.ResponseWriter, r *http.Request)
} }
resource, err := api.Database.GetWorkspaceResourceByID(r.Context(), workspaceAgent.ResourceID) resource, err := api.Database.GetWorkspaceResourceByID(r.Context(), workspaceAgent.ResourceID)
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error fetching workspace resources.", Message: "Internal error fetching workspace resources.",
Detail: err.Error(), Detail: err.Error(),
}) })
@ -139,7 +139,7 @@ func (api *API) workspaceAgentMetadata(rw http.ResponseWriter, r *http.Request)
} }
build, err := api.Database.GetWorkspaceBuildByJobID(r.Context(), resource.JobID) build, err := api.Database.GetWorkspaceBuildByJobID(r.Context(), resource.JobID)
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error fetching workspace build.", Message: "Internal error fetching workspace build.",
Detail: err.Error(), Detail: err.Error(),
}) })
@ -147,7 +147,7 @@ func (api *API) workspaceAgentMetadata(rw http.ResponseWriter, r *http.Request)
} }
workspace, err := api.Database.GetWorkspaceByID(r.Context(), build.WorkspaceID) workspace, err := api.Database.GetWorkspaceByID(r.Context(), build.WorkspaceID)
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error fetching workspace.", Message: "Internal error fetching workspace.",
Detail: err.Error(), Detail: err.Error(),
}) })
@ -155,7 +155,7 @@ func (api *API) workspaceAgentMetadata(rw http.ResponseWriter, r *http.Request)
} }
owner, err := api.Database.GetUserByID(r.Context(), workspace.OwnerID) owner, err := api.Database.GetUserByID(r.Context(), workspace.OwnerID)
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error fetching workspace owner.", Message: "Internal error fetching workspace owner.",
Detail: err.Error(), Detail: err.Error(),
}) })
@ -164,7 +164,7 @@ func (api *API) workspaceAgentMetadata(rw http.ResponseWriter, r *http.Request)
ipp, ok := netaddr.FromStdIPNet(&workspaceAgent.WireguardNodeIPv6.IPNet) ipp, ok := netaddr.FromStdIPNet(&workspaceAgent.WireguardNodeIPv6.IPNet)
if !ok { if !ok {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Workspace agent has an invalid ipv6 address.", Message: "Workspace agent has an invalid ipv6 address.",
Detail: workspaceAgent.WireguardNodeIPv6.IPNet.String(), Detail: workspaceAgent.WireguardNodeIPv6.IPNet.String(),
}) })
@ -190,7 +190,7 @@ func (api *API) workspaceAgentListen(rw http.ResponseWriter, r *http.Request) {
workspaceAgent := httpmw.WorkspaceAgent(r) workspaceAgent := httpmw.WorkspaceAgent(r)
resource, err := api.Database.GetWorkspaceResourceByID(r.Context(), workspaceAgent.ResourceID) resource, err := api.Database.GetWorkspaceResourceByID(r.Context(), workspaceAgent.ResourceID)
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusBadRequest, httpapi.Response{ httpapi.Write(rw, http.StatusBadRequest, codersdk.Response{
Message: "Failed to accept websocket.", Message: "Failed to accept websocket.",
Detail: err.Error(), Detail: err.Error(),
}) })
@ -199,7 +199,7 @@ func (api *API) workspaceAgentListen(rw http.ResponseWriter, r *http.Request) {
build, err := api.Database.GetWorkspaceBuildByJobID(r.Context(), resource.JobID) build, err := api.Database.GetWorkspaceBuildByJobID(r.Context(), resource.JobID)
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusBadRequest, httpapi.Response{ httpapi.Write(rw, http.StatusBadRequest, codersdk.Response{
Message: "Internal error fetching workspace build job.", Message: "Internal error fetching workspace build job.",
Detail: err.Error(), Detail: err.Error(),
}) })
@ -224,7 +224,7 @@ func (api *API) workspaceAgentListen(rw http.ResponseWriter, r *http.Request) {
slog.F("resource", resource), slog.F("resource", resource),
slog.F("agent", workspaceAgent), slog.F("agent", workspaceAgent),
) )
httpapi.Write(rw, http.StatusForbidden, httpapi.Response{ httpapi.Write(rw, http.StatusForbidden, codersdk.Response{
Message: "Agent trying to connect from non-latest build.", Message: "Agent trying to connect from non-latest build.",
Detail: err.Error(), Detail: err.Error(),
}) })
@ -235,7 +235,7 @@ func (api *API) workspaceAgentListen(rw http.ResponseWriter, r *http.Request) {
CompressionMode: websocket.CompressionDisabled, CompressionMode: websocket.CompressionDisabled,
}) })
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusBadRequest, httpapi.Response{ httpapi.Write(rw, http.StatusBadRequest, codersdk.Response{
Message: "Failed to accept websocket.", Message: "Failed to accept websocket.",
Detail: err.Error(), Detail: err.Error(),
}) })
@ -350,7 +350,7 @@ func (api *API) workspaceAgentTurn(rw http.ResponseWriter, r *http.Request) {
// By default requests have the remote address and port. // By default requests have the remote address and port.
host, port, err := net.SplitHostPort(r.RemoteAddr) host, port, err := net.SplitHostPort(r.RemoteAddr)
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusBadRequest, httpapi.Response{ httpapi.Write(rw, http.StatusBadRequest, codersdk.Response{
Message: "Invalid remote address.", Message: "Invalid remote address.",
Detail: err.Error(), Detail: err.Error(),
}) })
@ -359,7 +359,7 @@ func (api *API) workspaceAgentTurn(rw http.ResponseWriter, r *http.Request) {
remoteAddress.IP = net.ParseIP(host) remoteAddress.IP = net.ParseIP(host)
remoteAddress.Port, err = strconv.Atoi(port) remoteAddress.Port, err = strconv.Atoi(port)
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusBadRequest, httpapi.Response{ httpapi.Write(rw, http.StatusBadRequest, codersdk.Response{
Message: fmt.Sprintf("Port for remote address %q must be an integer.", r.RemoteAddr), Message: fmt.Sprintf("Port for remote address %q must be an integer.", r.RemoteAddr),
Detail: err.Error(), Detail: err.Error(),
}) })
@ -370,7 +370,7 @@ func (api *API) workspaceAgentTurn(rw http.ResponseWriter, r *http.Request) {
CompressionMode: websocket.CompressionDisabled, CompressionMode: websocket.CompressionDisabled,
}) })
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusBadRequest, httpapi.Response{ httpapi.Write(rw, http.StatusBadRequest, codersdk.Response{
Message: "Failed to accept websocket.", Message: "Failed to accept websocket.",
Detail: err.Error(), Detail: err.Error(),
}) })
@ -404,14 +404,14 @@ func (api *API) workspaceAgentPTY(rw http.ResponseWriter, r *http.Request) {
} }
apiAgent, err := convertWorkspaceAgent(workspaceAgent, nil, api.AgentInactiveDisconnectTimeout) apiAgent, err := convertWorkspaceAgent(workspaceAgent, nil, api.AgentInactiveDisconnectTimeout)
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error reading workspace agent.", Message: "Internal error reading workspace agent.",
Detail: err.Error(), Detail: err.Error(),
}) })
return return
} }
if apiAgent.Status != codersdk.WorkspaceAgentConnected { if apiAgent.Status != codersdk.WorkspaceAgentConnected {
httpapi.Write(rw, http.StatusPreconditionRequired, httpapi.Response{ httpapi.Write(rw, http.StatusPreconditionRequired, codersdk.Response{
Message: fmt.Sprintf("Agent state is %q, it must be in the %q state.", apiAgent.Status, codersdk.WorkspaceAgentConnected), Message: fmt.Sprintf("Agent state is %q, it must be in the %q state.", apiAgent.Status, codersdk.WorkspaceAgentConnected),
}) })
return return
@ -419,9 +419,9 @@ func (api *API) workspaceAgentPTY(rw http.ResponseWriter, r *http.Request) {
reconnect, err := uuid.Parse(r.URL.Query().Get("reconnect")) reconnect, err := uuid.Parse(r.URL.Query().Get("reconnect"))
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusBadRequest, httpapi.Response{ httpapi.Write(rw, http.StatusBadRequest, codersdk.Response{
Message: "Query param 'reconnect' must be a valid UUID.", Message: "Query param 'reconnect' must be a valid UUID.",
Validations: []httpapi.Error{ Validations: []codersdk.ValidationError{
{Field: "reconnect", Detail: "invalid UUID"}, {Field: "reconnect", Detail: "invalid UUID"},
}, },
}) })
@ -440,7 +440,7 @@ func (api *API) workspaceAgentPTY(rw http.ResponseWriter, r *http.Request) {
CompressionMode: websocket.CompressionDisabled, CompressionMode: websocket.CompressionDisabled,
}) })
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusBadRequest, httpapi.Response{ httpapi.Write(rw, http.StatusBadRequest, codersdk.Response{
Message: "Failed to accept websocket.", Message: "Failed to accept websocket.",
Detail: err.Error(), Detail: err.Error(),
}) })
@ -495,7 +495,7 @@ func (api *API) postWorkspaceAgentKeys(rw http.ResponseWriter, r *http.Request)
UpdatedAt: database.Now(), UpdatedAt: database.Now(),
}) })
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error setting agent keys.", Message: "Internal error setting agent keys.",
Detail: err.Error(), Detail: err.Error(),
}) })
@ -522,7 +522,7 @@ func (api *API) postWorkspaceAgentWireguardPeer(rw http.ResponseWriter, r *http.
} }
if req.Recipient != workspaceAgent.ID { if req.Recipient != workspaceAgent.ID {
httpapi.Write(rw, http.StatusBadRequest, httpapi.Response{ httpapi.Write(rw, http.StatusBadRequest, codersdk.Response{
Message: "Invalid recipient.", Message: "Invalid recipient.",
}) })
return return
@ -530,7 +530,7 @@ func (api *API) postWorkspaceAgentWireguardPeer(rw http.ResponseWriter, r *http.
raw, err := req.MarshalText() raw, err := req.MarshalText()
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error marshaling wireguard peer message.", Message: "Internal error marshaling wireguard peer message.",
Detail: err.Error(), Detail: err.Error(),
}) })
@ -539,7 +539,7 @@ func (api *API) postWorkspaceAgentWireguardPeer(rw http.ResponseWriter, r *http.
err = api.Pubsub.Publish("wireguard_peers", raw) err = api.Pubsub.Publish("wireguard_peers", raw)
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error publishing wireguard peer message.", Message: "Internal error publishing wireguard peer message.",
Detail: err.Error(), Detail: err.Error(),
}) })
@ -560,7 +560,7 @@ func (api *API) workspaceAgentWireguardListener(rw http.ResponseWriter, r *http.
conn, err := websocket.Accept(rw, r, nil) conn, err := websocket.Accept(rw, r, nil)
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusBadRequest, httpapi.Response{ httpapi.Write(rw, http.StatusBadRequest, codersdk.Response{
Message: "Failed to accept websocket.", Message: "Failed to accept websocket.",
Detail: err.Error(), Detail: err.Error(),
}) })

View File

@ -16,6 +16,7 @@ import (
"github.com/coder/coder/coderd/httpapi" "github.com/coder/coder/coderd/httpapi"
"github.com/coder/coder/coderd/httpmw" "github.com/coder/coder/coderd/httpmw"
"github.com/coder/coder/coderd/rbac" "github.com/coder/coder/coderd/rbac"
"github.com/coder/coder/codersdk"
"github.com/coder/coder/site" "github.com/coder/coder/site"
) )
@ -36,7 +37,7 @@ func (api *API) workspaceAppsProxyPath(rw http.ResponseWriter, r *http.Request)
return return
} }
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error fetching workspace.", Message: "Internal error fetching workspace.",
Detail: err.Error(), Detail: err.Error(),
}) })
@ -49,7 +50,7 @@ func (api *API) workspaceAppsProxyPath(rw http.ResponseWriter, r *http.Request)
build, err := api.Database.GetLatestWorkspaceBuildByWorkspaceID(r.Context(), workspace.ID) build, err := api.Database.GetLatestWorkspaceBuildByWorkspaceID(r.Context(), workspace.ID)
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error fetching workspace build.", Message: "Internal error fetching workspace build.",
Detail: err.Error(), Detail: err.Error(),
}) })
@ -58,7 +59,7 @@ func (api *API) workspaceAppsProxyPath(rw http.ResponseWriter, r *http.Request)
resources, err := api.Database.GetWorkspaceResourcesByJobID(r.Context(), build.JobID) resources, err := api.Database.GetWorkspaceResourcesByJobID(r.Context(), build.JobID)
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error fetching workspace resources.", Message: "Internal error fetching workspace resources.",
Detail: err.Error(), Detail: err.Error(),
}) })
@ -70,14 +71,14 @@ func (api *API) workspaceAppsProxyPath(rw http.ResponseWriter, r *http.Request)
} }
agents, err := api.Database.GetWorkspaceAgentsByResourceIDs(r.Context(), resourceIDs) agents, err := api.Database.GetWorkspaceAgentsByResourceIDs(r.Context(), resourceIDs)
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error fetching workspace agents.", Message: "Internal error fetching workspace agents.",
Detail: err.Error(), Detail: err.Error(),
}) })
return return
} }
if len(agents) == 0 { if len(agents) == 0 {
httpapi.Write(rw, http.StatusBadRequest, httpapi.Response{ httpapi.Write(rw, http.StatusBadRequest, codersdk.Response{
Message: "No agents exist.", Message: "No agents exist.",
}) })
return return
@ -98,20 +99,20 @@ func (api *API) workspaceAppsProxyPath(rw http.ResponseWriter, r *http.Request)
Name: chi.URLParam(r, "workspaceapp"), Name: chi.URLParam(r, "workspaceapp"),
}) })
if errors.Is(err, sql.ErrNoRows) { if errors.Is(err, sql.ErrNoRows) {
httpapi.Write(rw, http.StatusNotFound, httpapi.Response{ httpapi.Write(rw, http.StatusNotFound, codersdk.Response{
Message: "Application not found.", Message: "Application not found.",
}) })
return return
} }
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error fetching workspace application.", Message: "Internal error fetching workspace application.",
Detail: err.Error(), Detail: err.Error(),
}) })
return return
} }
if !app.Url.Valid { if !app.Url.Valid {
httpapi.Write(rw, http.StatusBadRequest, httpapi.Response{ httpapi.Write(rw, http.StatusBadRequest, codersdk.Response{
Message: fmt.Sprintf("Application %s does not have a url.", app.Name), Message: fmt.Sprintf("Application %s does not have a url.", app.Name),
}) })
return return
@ -119,7 +120,7 @@ func (api *API) workspaceAppsProxyPath(rw http.ResponseWriter, r *http.Request)
appURL, err := url.Parse(app.Url.String) appURL, err := url.Parse(app.Url.String)
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: fmt.Sprintf("App url %q must be a valid url.", app.Url.String), Message: fmt.Sprintf("App url %q must be a valid url.", app.Url.String),
Detail: err.Error(), Detail: err.Error(),
}) })
@ -160,7 +161,7 @@ func (api *API) workspaceAppsProxyPath(rw http.ResponseWriter, r *http.Request)
conn, release, err := api.workspaceAgentCache.Acquire(r, agent.ID) conn, release, err := api.workspaceAgentCache.Acquire(r, agent.ID)
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Failed to dial workspace agent.", Message: "Failed to dial workspace agent.",
Detail: err.Error(), Detail: err.Error(),
}) })

View File

@ -32,7 +32,7 @@ func (api *API) workspaceBuild(rw http.ResponseWriter, r *http.Request) {
job, err := api.Database.GetProvisionerJobByID(r.Context(), workspaceBuild.JobID) job, err := api.Database.GetProvisionerJobByID(r.Context(), workspaceBuild.JobID)
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error fetching provisioner job.", Message: "Internal error fetching provisioner job.",
Detail: err.Error(), Detail: err.Error(),
}) })
@ -41,7 +41,7 @@ func (api *API) workspaceBuild(rw http.ResponseWriter, r *http.Request) {
users, err := api.Database.GetUsersByIDs(r.Context(), []uuid.UUID{workspace.OwnerID, workspaceBuild.InitiatorID}) users, err := api.Database.GetUsersByIDs(r.Context(), []uuid.UUID{workspace.OwnerID, workspaceBuild.InitiatorID})
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error fetching user.", Message: "Internal error fetching user.",
Detail: err.Error(), Detail: err.Error(),
}) })
@ -75,12 +75,12 @@ func (api *API) workspaceBuilds(rw http.ResponseWriter, r *http.Request) {
// query will not work. // query will not work.
_, err := store.GetWorkspaceBuildByID(r.Context(), paginationParams.AfterID) _, err := store.GetWorkspaceBuildByID(r.Context(), paginationParams.AfterID)
if err != nil && xerrors.Is(err, sql.ErrNoRows) { if err != nil && xerrors.Is(err, sql.ErrNoRows) {
httpapi.Write(rw, http.StatusBadRequest, httpapi.Response{ httpapi.Write(rw, http.StatusBadRequest, codersdk.Response{
Message: fmt.Sprintf("Record at \"after_id\" (%q) does not exist.", paginationParams.AfterID.String()), Message: fmt.Sprintf("Record at \"after_id\" (%q) does not exist.", paginationParams.AfterID.String()),
}) })
return err return err
} else if err != nil { } else if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error fetching workspace build at \"after_id\".", Message: "Internal error fetching workspace build at \"after_id\".",
Detail: err.Error(), Detail: err.Error(),
}) })
@ -99,7 +99,7 @@ func (api *API) workspaceBuilds(rw http.ResponseWriter, r *http.Request) {
err = nil err = nil
} }
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error fetching workspace build.", Message: "Internal error fetching workspace build.",
Detail: err.Error(), Detail: err.Error(),
}) })
@ -121,7 +121,7 @@ func (api *API) workspaceBuilds(rw http.ResponseWriter, r *http.Request) {
err = nil err = nil
} }
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error fetching provisioner jobs.", Message: "Internal error fetching provisioner jobs.",
Detail: err.Error(), Detail: err.Error(),
}) })
@ -138,7 +138,7 @@ func (api *API) workspaceBuilds(rw http.ResponseWriter, r *http.Request) {
} }
users, err := api.Database.GetUsersByIDs(r.Context(), userIDs) users, err := api.Database.GetUsersByIDs(r.Context(), userIDs)
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error fetching user.", Message: "Internal error fetching user.",
Detail: err.Error(), Detail: err.Error(),
}) })
@ -149,7 +149,7 @@ func (api *API) workspaceBuilds(rw http.ResponseWriter, r *http.Request) {
for _, build := range builds { for _, build := range builds {
job, exists := jobByID[build.JobID.String()] job, exists := jobByID[build.JobID.String()]
if !exists { if !exists {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: fmt.Sprintf("Job %q doesn't exist for build %q.", build.JobID, build.ID), Message: fmt.Sprintf("Job %q doesn't exist for build %q.", build.JobID, build.ID),
}) })
return return
@ -167,7 +167,7 @@ func (api *API) workspaceBuildByBuildNumber(rw http.ResponseWriter, r *http.Requ
workspaceName := chi.URLParam(r, "workspacename") workspaceName := chi.URLParam(r, "workspacename")
buildNumber, err := strconv.ParseInt(chi.URLParam(r, "buildnumber"), 10, 32) buildNumber, err := strconv.ParseInt(chi.URLParam(r, "buildnumber"), 10, 32)
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusBadRequest, httpapi.Response{ httpapi.Write(rw, http.StatusBadRequest, codersdk.Response{
Message: "Failed to parse build number as integer.", Message: "Failed to parse build number as integer.",
Detail: err.Error(), Detail: err.Error(),
}) })
@ -183,7 +183,7 @@ func (api *API) workspaceBuildByBuildNumber(rw http.ResponseWriter, r *http.Requ
return return
} }
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error fetching workspace by name.", Message: "Internal error fetching workspace by name.",
Detail: err.Error(), Detail: err.Error(),
}) })
@ -200,13 +200,13 @@ func (api *API) workspaceBuildByBuildNumber(rw http.ResponseWriter, r *http.Requ
BuildNumber: int32(buildNumber), BuildNumber: int32(buildNumber),
}) })
if errors.Is(err, sql.ErrNoRows) { if errors.Is(err, sql.ErrNoRows) {
httpapi.Write(rw, http.StatusNotFound, httpapi.Response{ httpapi.Write(rw, http.StatusNotFound, codersdk.Response{
Message: fmt.Sprintf("Workspace %q Build %d does not exist.", workspaceName, buildNumber), Message: fmt.Sprintf("Workspace %q Build %d does not exist.", workspaceName, buildNumber),
}) })
return return
} }
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error fetching workspace build.", Message: "Internal error fetching workspace build.",
Detail: err.Error(), Detail: err.Error(),
}) })
@ -215,7 +215,7 @@ func (api *API) workspaceBuildByBuildNumber(rw http.ResponseWriter, r *http.Requ
job, err := api.Database.GetProvisionerJobByID(r.Context(), workspaceBuild.JobID) job, err := api.Database.GetProvisionerJobByID(r.Context(), workspaceBuild.JobID)
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error fetching provisioner job.", Message: "Internal error fetching provisioner job.",
Detail: err.Error(), Detail: err.Error(),
}) })
@ -224,7 +224,7 @@ func (api *API) workspaceBuildByBuildNumber(rw http.ResponseWriter, r *http.Requ
users, err := api.Database.GetUsersByIDs(r.Context(), []uuid.UUID{workspace.OwnerID, workspaceBuild.InitiatorID}) users, err := api.Database.GetUsersByIDs(r.Context(), []uuid.UUID{workspace.OwnerID, workspaceBuild.InitiatorID})
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error fetching user.", Message: "Internal error fetching user.",
Detail: err.Error(), Detail: err.Error(),
}) })
@ -254,7 +254,7 @@ func (api *API) workspaceBuildByName(rw http.ResponseWriter, r *http.Request) {
return return
} }
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error fetching workspace build by name.", Message: "Internal error fetching workspace build by name.",
Detail: err.Error(), Detail: err.Error(),
}) })
@ -262,7 +262,7 @@ func (api *API) workspaceBuildByName(rw http.ResponseWriter, r *http.Request) {
} }
job, err := api.Database.GetProvisionerJobByID(r.Context(), workspaceBuild.JobID) job, err := api.Database.GetProvisionerJobByID(r.Context(), workspaceBuild.JobID)
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error fetching provisioner job.", Message: "Internal error fetching provisioner job.",
Detail: err.Error(), Detail: err.Error(),
}) })
@ -270,7 +270,7 @@ func (api *API) workspaceBuildByName(rw http.ResponseWriter, r *http.Request) {
} }
users, err := api.Database.GetUsersByIDs(r.Context(), []uuid.UUID{workspace.OwnerID, workspaceBuild.InitiatorID}) users, err := api.Database.GetUsersByIDs(r.Context(), []uuid.UUID{workspace.OwnerID, workspaceBuild.InitiatorID})
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error getting user.", Message: "Internal error getting user.",
Detail: err.Error(), Detail: err.Error(),
}) })
@ -298,7 +298,7 @@ func (api *API) postWorkspaceBuilds(rw http.ResponseWriter, r *http.Request) {
case codersdk.WorkspaceTransitionStart, codersdk.WorkspaceTransitionStop: case codersdk.WorkspaceTransitionStart, codersdk.WorkspaceTransitionStop:
action = rbac.ActionUpdate action = rbac.ActionUpdate
default: default:
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: fmt.Sprintf("Transition %q not supported.", createBuild.Transition), Message: fmt.Sprintf("Transition %q not supported.", createBuild.Transition),
}) })
return return
@ -312,7 +312,7 @@ func (api *API) postWorkspaceBuilds(rw http.ResponseWriter, r *http.Request) {
if createBuild.TemplateVersionID == uuid.Nil { if createBuild.TemplateVersionID == uuid.Nil {
latestBuild, err := api.Database.GetLatestWorkspaceBuildByWorkspaceID(r.Context(), workspace.ID) latestBuild, err := api.Database.GetLatestWorkspaceBuildByWorkspaceID(r.Context(), workspace.ID)
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error fetching the latest workspace build.", Message: "Internal error fetching the latest workspace build.",
Detail: err.Error(), Detail: err.Error(),
}) })
@ -322,9 +322,9 @@ func (api *API) postWorkspaceBuilds(rw http.ResponseWriter, r *http.Request) {
} }
templateVersion, err := api.Database.GetTemplateVersionByID(r.Context(), createBuild.TemplateVersionID) templateVersion, err := api.Database.GetTemplateVersionByID(r.Context(), createBuild.TemplateVersionID)
if errors.Is(err, sql.ErrNoRows) { if errors.Is(err, sql.ErrNoRows) {
httpapi.Write(rw, http.StatusBadRequest, httpapi.Response{ httpapi.Write(rw, http.StatusBadRequest, codersdk.Response{
Message: "Template version not found.", Message: "Template version not found.",
Validations: []httpapi.Error{{ Validations: []codersdk.ValidationError{{
Field: "template_version_id", Field: "template_version_id",
Detail: "template version not found", Detail: "template version not found",
}}, }},
@ -332,7 +332,7 @@ func (api *API) postWorkspaceBuilds(rw http.ResponseWriter, r *http.Request) {
return return
} }
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error fetching template version.", Message: "Internal error fetching template version.",
Detail: err.Error(), Detail: err.Error(),
}) })
@ -340,7 +340,7 @@ func (api *API) postWorkspaceBuilds(rw http.ResponseWriter, r *http.Request) {
} }
templateVersionJob, err := api.Database.GetProvisionerJobByID(r.Context(), templateVersion.JobID) templateVersionJob, err := api.Database.GetProvisionerJobByID(r.Context(), templateVersion.JobID)
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error fetching provisioner job.", Message: "Internal error fetching provisioner job.",
Detail: err.Error(), Detail: err.Error(),
}) })
@ -349,17 +349,17 @@ func (api *API) postWorkspaceBuilds(rw http.ResponseWriter, r *http.Request) {
templateVersionJobStatus := convertProvisionerJob(templateVersionJob).Status templateVersionJobStatus := convertProvisionerJob(templateVersionJob).Status
switch templateVersionJobStatus { switch templateVersionJobStatus {
case codersdk.ProvisionerJobPending, codersdk.ProvisionerJobRunning: case codersdk.ProvisionerJobPending, codersdk.ProvisionerJobRunning:
httpapi.Write(rw, http.StatusNotAcceptable, httpapi.Response{ httpapi.Write(rw, http.StatusNotAcceptable, codersdk.Response{
Message: fmt.Sprintf("The provided template version is %s. Wait for it to complete importing!", templateVersionJobStatus), Message: fmt.Sprintf("The provided template version is %s. Wait for it to complete importing!", templateVersionJobStatus),
}) })
return return
case codersdk.ProvisionerJobFailed: case codersdk.ProvisionerJobFailed:
httpapi.Write(rw, http.StatusPreconditionFailed, httpapi.Response{ httpapi.Write(rw, http.StatusPreconditionFailed, codersdk.Response{
Message: fmt.Sprintf("The provided template version %q has failed to import: %q. You cannot build workspaces with it!", templateVersion.Name, templateVersionJob.Error.String), Message: fmt.Sprintf("The provided template version %q has failed to import: %q. You cannot build workspaces with it!", templateVersion.Name, templateVersionJob.Error.String),
}) })
return return
case codersdk.ProvisionerJobCanceled: case codersdk.ProvisionerJobCanceled:
httpapi.Write(rw, http.StatusPreconditionFailed, httpapi.Response{ httpapi.Write(rw, http.StatusPreconditionFailed, codersdk.Response{
Message: "The provided template version was canceled during import. You cannot builds workspaces with it!", Message: "The provided template version was canceled during import. You cannot builds workspaces with it!",
}) })
return return
@ -367,7 +367,7 @@ func (api *API) postWorkspaceBuilds(rw http.ResponseWriter, r *http.Request) {
template, err := api.Database.GetTemplateByID(r.Context(), templateVersion.TemplateID.UUID) template, err := api.Database.GetTemplateByID(r.Context(), templateVersion.TemplateID.UUID)
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error fetching template job.", Message: "Internal error fetching template job.",
Detail: err.Error(), Detail: err.Error(),
}) })
@ -380,7 +380,7 @@ func (api *API) postWorkspaceBuilds(rw http.ResponseWriter, r *http.Request) {
if err == nil { if err == nil {
priorJob, err := api.Database.GetProvisionerJobByID(r.Context(), priorHistory.JobID) priorJob, err := api.Database.GetProvisionerJobByID(r.Context(), priorHistory.JobID)
if err == nil && convertProvisionerJob(priorJob).Status.Active() { if err == nil && convertProvisionerJob(priorJob).Status.Active() {
httpapi.Write(rw, http.StatusConflict, httpapi.Response{ httpapi.Write(rw, http.StatusConflict, codersdk.Response{
Message: "A workspace build is already active.", Message: "A workspace build is already active.",
}) })
return return
@ -388,7 +388,7 @@ func (api *API) postWorkspaceBuilds(rw http.ResponseWriter, r *http.Request) {
priorBuildNum = priorHistory.BuildNumber priorBuildNum = priorHistory.BuildNumber
} else if !errors.Is(err, sql.ErrNoRows) { } else if !errors.Is(err, sql.ErrNoRows) {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error fetching prior workspace build.", Message: "Internal error fetching prior workspace build.",
Detail: err.Error(), Detail: err.Error(),
}) })
@ -485,7 +485,7 @@ func (api *API) postWorkspaceBuilds(rw http.ResponseWriter, r *http.Request) {
return nil return nil
}) })
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error inserting workspace build.", Message: "Internal error inserting workspace build.",
Detail: err.Error(), Detail: err.Error(),
}) })
@ -497,7 +497,7 @@ func (api *API) postWorkspaceBuilds(rw http.ResponseWriter, r *http.Request) {
workspaceBuild.InitiatorID, workspaceBuild.InitiatorID,
}) })
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error getting user.", Message: "Internal error getting user.",
Detail: err.Error(), Detail: err.Error(),
}) })
@ -513,7 +513,7 @@ func (api *API) patchCancelWorkspaceBuild(rw http.ResponseWriter, r *http.Reques
workspaceBuild := httpmw.WorkspaceBuildParam(r) workspaceBuild := httpmw.WorkspaceBuildParam(r)
workspace, err := api.Database.GetWorkspaceByID(r.Context(), workspaceBuild.WorkspaceID) workspace, err := api.Database.GetWorkspaceByID(r.Context(), workspaceBuild.WorkspaceID)
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "No workspace exists for this job.", Message: "No workspace exists for this job.",
}) })
return return
@ -527,20 +527,20 @@ func (api *API) patchCancelWorkspaceBuild(rw http.ResponseWriter, r *http.Reques
job, err := api.Database.GetProvisionerJobByID(r.Context(), workspaceBuild.JobID) job, err := api.Database.GetProvisionerJobByID(r.Context(), workspaceBuild.JobID)
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error fetching provisioner job.", Message: "Internal error fetching provisioner job.",
Detail: err.Error(), Detail: err.Error(),
}) })
return return
} }
if job.CompletedAt.Valid { if job.CompletedAt.Valid {
httpapi.Write(rw, http.StatusPreconditionFailed, httpapi.Response{ httpapi.Write(rw, http.StatusPreconditionFailed, codersdk.Response{
Message: "Job has already completed!", Message: "Job has already completed!",
}) })
return return
} }
if job.CanceledAt.Valid { if job.CanceledAt.Valid {
httpapi.Write(rw, http.StatusPreconditionFailed, httpapi.Response{ httpapi.Write(rw, http.StatusPreconditionFailed, codersdk.Response{
Message: "Job has already been marked as canceled!", Message: "Job has already been marked as canceled!",
}) })
return return
@ -553,13 +553,13 @@ func (api *API) patchCancelWorkspaceBuild(rw http.ResponseWriter, r *http.Reques
}, },
}) })
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error updating provisioner job.", Message: "Internal error updating provisioner job.",
Detail: err.Error(), Detail: err.Error(),
}) })
return return
} }
httpapi.Write(rw, http.StatusOK, httpapi.Response{ httpapi.Write(rw, http.StatusOK, codersdk.Response{
Message: "Job has been marked as canceled...", Message: "Job has been marked as canceled...",
}) })
} }
@ -568,7 +568,7 @@ func (api *API) workspaceBuildResources(rw http.ResponseWriter, r *http.Request)
workspaceBuild := httpmw.WorkspaceBuildParam(r) workspaceBuild := httpmw.WorkspaceBuildParam(r)
workspace, err := api.Database.GetWorkspaceByID(r.Context(), workspaceBuild.WorkspaceID) workspace, err := api.Database.GetWorkspaceByID(r.Context(), workspaceBuild.WorkspaceID)
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "No workspace exists for this job.", Message: "No workspace exists for this job.",
}) })
return return
@ -582,7 +582,7 @@ func (api *API) workspaceBuildResources(rw http.ResponseWriter, r *http.Request)
job, err := api.Database.GetProvisionerJobByID(r.Context(), workspaceBuild.JobID) job, err := api.Database.GetProvisionerJobByID(r.Context(), workspaceBuild.JobID)
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error fetching provisioner job.", Message: "Internal error fetching provisioner job.",
Detail: err.Error(), Detail: err.Error(),
}) })
@ -595,7 +595,7 @@ func (api *API) workspaceBuildLogs(rw http.ResponseWriter, r *http.Request) {
workspaceBuild := httpmw.WorkspaceBuildParam(r) workspaceBuild := httpmw.WorkspaceBuildParam(r)
workspace, err := api.Database.GetWorkspaceByID(r.Context(), workspaceBuild.WorkspaceID) workspace, err := api.Database.GetWorkspaceByID(r.Context(), workspaceBuild.WorkspaceID)
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "No workspace exists for this job.", Message: "No workspace exists for this job.",
}) })
return return
@ -609,7 +609,7 @@ func (api *API) workspaceBuildLogs(rw http.ResponseWriter, r *http.Request) {
job, err := api.Database.GetProvisionerJobByID(r.Context(), workspaceBuild.JobID) job, err := api.Database.GetProvisionerJobByID(r.Context(), workspaceBuild.JobID)
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error fetching provisioner job.", Message: "Internal error fetching provisioner job.",
Detail: err.Error(), Detail: err.Error(),
}) })
@ -622,7 +622,7 @@ func (api *API) workspaceBuildState(rw http.ResponseWriter, r *http.Request) {
workspaceBuild := httpmw.WorkspaceBuildParam(r) workspaceBuild := httpmw.WorkspaceBuildParam(r)
workspace, err := api.Database.GetWorkspaceByID(r.Context(), workspaceBuild.WorkspaceID) workspace, err := api.Database.GetWorkspaceByID(r.Context(), workspaceBuild.WorkspaceID)
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "No workspace exists for this job.", Message: "No workspace exists for this job.",
}) })
return return

View File

@ -25,7 +25,7 @@ func (api *API) postWorkspaceAuthAzureInstanceIdentity(rw http.ResponseWriter, r
} }
instanceID, err := azureidentity.Validate(r.Context(), req.Signature, api.AzureCertificates) instanceID, err := azureidentity.Validate(r.Context(), req.Signature, api.AzureCertificates)
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusUnauthorized, httpapi.Response{ httpapi.Write(rw, http.StatusUnauthorized, codersdk.Response{
Message: "Invalid Azure identity.", Message: "Invalid Azure identity.",
Detail: err.Error(), Detail: err.Error(),
}) })
@ -44,7 +44,7 @@ func (api *API) postWorkspaceAuthAWSInstanceIdentity(rw http.ResponseWriter, r *
} }
identity, err := awsidentity.Validate(req.Signature, req.Document, api.AWSCertificates) identity, err := awsidentity.Validate(req.Signature, req.Document, api.AWSCertificates)
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusUnauthorized, httpapi.Response{ httpapi.Write(rw, http.StatusUnauthorized, codersdk.Response{
Message: "Invalid AWS identity.", Message: "Invalid AWS identity.",
Detail: err.Error(), Detail: err.Error(),
}) })
@ -65,7 +65,7 @@ func (api *API) postWorkspaceAuthGoogleInstanceIdentity(rw http.ResponseWriter,
// We leave the audience blank. It's not important we validate who made the token. // We leave the audience blank. It's not important we validate who made the token.
payload, err := api.GoogleTokenValidator.Validate(r.Context(), req.JSONWebToken, "") payload, err := api.GoogleTokenValidator.Validate(r.Context(), req.JSONWebToken, "")
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusUnauthorized, httpapi.Response{ httpapi.Write(rw, http.StatusUnauthorized, codersdk.Response{
Message: "Invalid GCP identity.", Message: "Invalid GCP identity.",
Detail: err.Error(), Detail: err.Error(),
}) })
@ -80,7 +80,7 @@ func (api *API) postWorkspaceAuthGoogleInstanceIdentity(rw http.ResponseWriter,
}{} }{}
err = mapstructure.Decode(payload.Claims, &claims) err = mapstructure.Decode(payload.Claims, &claims)
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusBadRequest, httpapi.Response{ httpapi.Write(rw, http.StatusBadRequest, codersdk.Response{
Message: "Error decoding JWT claims.", Message: "Error decoding JWT claims.",
Detail: err.Error(), Detail: err.Error(),
}) })
@ -92,13 +92,13 @@ func (api *API) postWorkspaceAuthGoogleInstanceIdentity(rw http.ResponseWriter,
func (api *API) handleAuthInstanceID(rw http.ResponseWriter, r *http.Request, instanceID string) { func (api *API) handleAuthInstanceID(rw http.ResponseWriter, r *http.Request, instanceID string) {
agent, err := api.Database.GetWorkspaceAgentByInstanceID(r.Context(), instanceID) agent, err := api.Database.GetWorkspaceAgentByInstanceID(r.Context(), instanceID)
if errors.Is(err, sql.ErrNoRows) { if errors.Is(err, sql.ErrNoRows) {
httpapi.Write(rw, http.StatusNotFound, httpapi.Response{ httpapi.Write(rw, http.StatusNotFound, codersdk.Response{
Message: fmt.Sprintf("Instance with id %q not found.", instanceID), Message: fmt.Sprintf("Instance with id %q not found.", instanceID),
}) })
return return
} }
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error fetching provisioner job agent.", Message: "Internal error fetching provisioner job agent.",
Detail: err.Error(), Detail: err.Error(),
}) })
@ -106,7 +106,7 @@ func (api *API) handleAuthInstanceID(rw http.ResponseWriter, r *http.Request, in
} }
resource, err := api.Database.GetWorkspaceResourceByID(r.Context(), agent.ResourceID) resource, err := api.Database.GetWorkspaceResourceByID(r.Context(), agent.ResourceID)
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error fetching provisioner job resource.", Message: "Internal error fetching provisioner job resource.",
Detail: err.Error(), Detail: err.Error(),
}) })
@ -114,14 +114,14 @@ func (api *API) handleAuthInstanceID(rw http.ResponseWriter, r *http.Request, in
} }
job, err := api.Database.GetProvisionerJobByID(r.Context(), resource.JobID) job, err := api.Database.GetProvisionerJobByID(r.Context(), resource.JobID)
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error fetching provisioner job.", Message: "Internal error fetching provisioner job.",
Detail: err.Error(), Detail: err.Error(),
}) })
return return
} }
if job.Type != database.ProvisionerJobTypeWorkspaceBuild { if job.Type != database.ProvisionerJobTypeWorkspaceBuild {
httpapi.Write(rw, http.StatusBadRequest, httpapi.Response{ httpapi.Write(rw, http.StatusBadRequest, codersdk.Response{
Message: fmt.Sprintf("%q jobs cannot be authenticated.", job.Type), Message: fmt.Sprintf("%q jobs cannot be authenticated.", job.Type),
}) })
return return
@ -129,7 +129,7 @@ func (api *API) handleAuthInstanceID(rw http.ResponseWriter, r *http.Request, in
var jobData workspaceProvisionJob var jobData workspaceProvisionJob
err = json.Unmarshal(job.Input, &jobData) err = json.Unmarshal(job.Input, &jobData)
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error extracting job data.", Message: "Internal error extracting job data.",
Detail: err.Error(), Detail: err.Error(),
}) })
@ -137,7 +137,7 @@ func (api *API) handleAuthInstanceID(rw http.ResponseWriter, r *http.Request, in
} }
resourceHistory, err := api.Database.GetWorkspaceBuildByID(r.Context(), jobData.WorkspaceBuildID) resourceHistory, err := api.Database.GetWorkspaceBuildByID(r.Context(), jobData.WorkspaceBuildID)
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error fetching workspace build.", Message: "Internal error fetching workspace build.",
Detail: err.Error(), Detail: err.Error(),
}) })
@ -148,14 +148,14 @@ func (api *API) handleAuthInstanceID(rw http.ResponseWriter, r *http.Request, in
// we'd hate to leak access to a user's workspace. // we'd hate to leak access to a user's workspace.
latestHistory, err := api.Database.GetLatestWorkspaceBuildByWorkspaceID(r.Context(), resourceHistory.WorkspaceID) latestHistory, err := api.Database.GetLatestWorkspaceBuildByWorkspaceID(r.Context(), resourceHistory.WorkspaceID)
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error fetching the latest workspace build.", Message: "Internal error fetching the latest workspace build.",
Detail: err.Error(), Detail: err.Error(),
}) })
return return
} }
if latestHistory.ID != resourceHistory.ID { if latestHistory.ID != resourceHistory.ID {
httpapi.Write(rw, http.StatusBadRequest, httpapi.Response{ httpapi.Write(rw, http.StatusBadRequest, codersdk.Response{
Message: fmt.Sprintf("Resource found for id %q, but isn't registered on the latest history.", instanceID), Message: fmt.Sprintf("Resource found for id %q, but isn't registered on the latest history.", instanceID),
}) })
return return

View File

@ -25,14 +25,14 @@ func (api *API) workspaceResource(rw http.ResponseWriter, r *http.Request) {
job, err := api.Database.GetProvisionerJobByID(r.Context(), workspaceBuild.JobID) job, err := api.Database.GetProvisionerJobByID(r.Context(), workspaceBuild.JobID)
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error fetching provisioner job.", Message: "Internal error fetching provisioner job.",
Detail: err.Error(), Detail: err.Error(),
}) })
return return
} }
if !job.CompletedAt.Valid { if !job.CompletedAt.Valid {
httpapi.Write(rw, http.StatusPreconditionFailed, httpapi.Response{ httpapi.Write(rw, http.StatusPreconditionFailed, codersdk.Response{
Message: "Job hasn't completed!", Message: "Job hasn't completed!",
}) })
return return
@ -42,7 +42,7 @@ func (api *API) workspaceResource(rw http.ResponseWriter, r *http.Request) {
err = nil err = nil
} }
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error fetching provisioner job agents.", Message: "Internal error fetching provisioner job agents.",
Detail: err.Error(), Detail: err.Error(),
}) })
@ -54,7 +54,7 @@ func (api *API) workspaceResource(rw http.ResponseWriter, r *http.Request) {
} }
apps, err := api.Database.GetWorkspaceAppsByAgentIDs(r.Context(), agentIDs) apps, err := api.Database.GetWorkspaceAppsByAgentIDs(r.Context(), agentIDs)
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error fetching workspace agent applications.", Message: "Internal error fetching workspace agent applications.",
Detail: err.Error(), Detail: err.Error(),
}) })
@ -71,7 +71,7 @@ func (api *API) workspaceResource(rw http.ResponseWriter, r *http.Request) {
convertedAgent, err := convertWorkspaceAgent(agent, convertApps(dbApps), api.AgentInactiveDisconnectTimeout) convertedAgent, err := convertWorkspaceAgent(agent, convertApps(dbApps), api.AgentInactiveDisconnectTimeout)
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error reading workspace agent.", Message: "Internal error reading workspace agent.",
Detail: err.Error(), Detail: err.Error(),
}) })

View File

@ -49,9 +49,9 @@ func (api *API) workspace(rw http.ResponseWriter, r *http.Request) {
var err error var err error
showDeleted, err = strconv.ParseBool(deletedStr) showDeleted, err = strconv.ParseBool(deletedStr)
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusBadRequest, httpapi.Response{ httpapi.Write(rw, http.StatusBadRequest, codersdk.Response{
Message: fmt.Sprintf("Invalid boolean value %q for \"include_deleted\" query param.", deletedStr), Message: fmt.Sprintf("Invalid boolean value %q for \"include_deleted\" query param.", deletedStr),
Validations: []httpapi.Error{ Validations: []codersdk.ValidationError{
{Field: "deleted", Detail: "Must be a valid boolean"}, {Field: "deleted", Detail: "Must be a valid boolean"},
}, },
}) })
@ -59,7 +59,7 @@ func (api *API) workspace(rw http.ResponseWriter, r *http.Request) {
} }
} }
if workspace.Deleted && !showDeleted { if workspace.Deleted && !showDeleted {
httpapi.Write(rw, http.StatusGone, httpapi.Response{ httpapi.Write(rw, http.StatusGone, codersdk.Response{
Message: fmt.Sprintf("Workspace %q was deleted, you can view this workspace by specifying '?deleted=true' and trying again.", workspace.ID.String()), Message: fmt.Sprintf("Workspace %q was deleted, you can view this workspace by specifying '?deleted=true' and trying again.", workspace.ID.String()),
}) })
return return
@ -67,7 +67,7 @@ func (api *API) workspace(rw http.ResponseWriter, r *http.Request) {
build, err := api.Database.GetLatestWorkspaceBuildByWorkspaceID(r.Context(), workspace.ID) build, err := api.Database.GetLatestWorkspaceBuildByWorkspaceID(r.Context(), workspace.ID)
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error fetching workspace build.", Message: "Internal error fetching workspace build.",
Detail: err.Error(), Detail: err.Error(),
}) })
@ -93,7 +93,7 @@ func (api *API) workspace(rw http.ResponseWriter, r *http.Request) {
}) })
err = group.Wait() err = group.Wait()
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error fetching resource.", Message: "Internal error fetching resource.",
Detail: err.Error(), Detail: err.Error(),
}) })
@ -112,7 +112,7 @@ func (api *API) workspaces(rw http.ResponseWriter, r *http.Request) {
queryStr := r.URL.Query().Get("q") queryStr := r.URL.Query().Get("q")
filter, errs := workspaceSearchQuery(queryStr) filter, errs := workspaceSearchQuery(queryStr)
if len(errs) > 0 { if len(errs) > 0 {
httpapi.Write(rw, http.StatusBadRequest, httpapi.Response{ httpapi.Write(rw, http.StatusBadRequest, codersdk.Response{
Message: "Invalid workspace search query.", Message: "Invalid workspace search query.",
Validations: errs, Validations: errs,
}) })
@ -126,7 +126,7 @@ func (api *API) workspaces(rw http.ResponseWriter, r *http.Request) {
workspaces, err := api.Database.GetWorkspaces(r.Context(), filter) workspaces, err := api.Database.GetWorkspaces(r.Context(), filter)
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error fetching workspaces.", Message: "Internal error fetching workspaces.",
Detail: err.Error(), Detail: err.Error(),
}) })
@ -138,7 +138,7 @@ func (api *API) workspaces(rw http.ResponseWriter, r *http.Request) {
apiWorkspaces, err := convertWorkspaces(r.Context(), api.Database, workspaces) apiWorkspaces, err := convertWorkspaces(r.Context(), api.Database, workspaces)
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error reading workspace.", Message: "Internal error reading workspace.",
Detail: err.Error(), Detail: err.Error(),
}) })
@ -156,9 +156,9 @@ func (api *API) workspaceByOwnerAndName(rw http.ResponseWriter, r *http.Request)
var err error var err error
includeDeleted, err = strconv.ParseBool(s) includeDeleted, err = strconv.ParseBool(s)
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusBadRequest, httpapi.Response{ httpapi.Write(rw, http.StatusBadRequest, codersdk.Response{
Message: fmt.Sprintf("Invalid boolean value %q for \"include_deleted\" query param.", s), Message: fmt.Sprintf("Invalid boolean value %q for \"include_deleted\" query param.", s),
Validations: []httpapi.Error{ Validations: []codersdk.ValidationError{
{Field: "include_deleted", Detail: "Must be a valid boolean"}, {Field: "include_deleted", Detail: "Must be a valid boolean"},
}, },
}) })
@ -182,7 +182,7 @@ func (api *API) workspaceByOwnerAndName(rw http.ResponseWriter, r *http.Request)
return return
} }
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error fetching workspace by name.", Message: "Internal error fetching workspace by name.",
Detail: err.Error(), Detail: err.Error(),
}) })
@ -195,7 +195,7 @@ func (api *API) workspaceByOwnerAndName(rw http.ResponseWriter, r *http.Request)
build, err := api.Database.GetLatestWorkspaceBuildByWorkspaceID(r.Context(), workspace.ID) build, err := api.Database.GetLatestWorkspaceBuildByWorkspaceID(r.Context(), workspace.ID)
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error fetching workspace build.", Message: "Internal error fetching workspace build.",
Detail: err.Error(), Detail: err.Error(),
}) })
@ -203,7 +203,7 @@ func (api *API) workspaceByOwnerAndName(rw http.ResponseWriter, r *http.Request)
} }
job, err := api.Database.GetProvisionerJobByID(r.Context(), build.JobID) job, err := api.Database.GetProvisionerJobByID(r.Context(), build.JobID)
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error fetching provisioner job.", Message: "Internal error fetching provisioner job.",
Detail: err.Error(), Detail: err.Error(),
}) })
@ -211,7 +211,7 @@ func (api *API) workspaceByOwnerAndName(rw http.ResponseWriter, r *http.Request)
} }
template, err := api.Database.GetTemplateByID(r.Context(), workspace.TemplateID) template, err := api.Database.GetTemplateByID(r.Context(), workspace.TemplateID)
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error fetching template.", Message: "Internal error fetching template.",
Detail: err.Error(), Detail: err.Error(),
}) })
@ -220,7 +220,7 @@ func (api *API) workspaceByOwnerAndName(rw http.ResponseWriter, r *http.Request)
initiator, err := api.Database.GetUserByID(r.Context(), build.InitiatorID) initiator, err := api.Database.GetUserByID(r.Context(), build.InitiatorID)
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error fetching template.", Message: "Internal error fetching template.",
Detail: err.Error(), Detail: err.Error(),
}) })
@ -247,9 +247,9 @@ func (api *API) postWorkspacesByOrganization(rw http.ResponseWriter, r *http.Req
template, err := api.Database.GetTemplateByID(r.Context(), createWorkspace.TemplateID) template, err := api.Database.GetTemplateByID(r.Context(), createWorkspace.TemplateID)
if errors.Is(err, sql.ErrNoRows) { if errors.Is(err, sql.ErrNoRows) {
httpapi.Write(rw, http.StatusBadRequest, httpapi.Response{ httpapi.Write(rw, http.StatusBadRequest, codersdk.Response{
Message: fmt.Sprintf("Template %q doesn't exist.", createWorkspace.TemplateID.String()), Message: fmt.Sprintf("Template %q doesn't exist.", createWorkspace.TemplateID.String()),
Validations: []httpapi.Error{{ Validations: []codersdk.ValidationError{{
Field: "template_id", Field: "template_id",
Detail: "template not found", Detail: "template not found",
}}, }},
@ -257,7 +257,7 @@ func (api *API) postWorkspacesByOrganization(rw http.ResponseWriter, r *http.Req
return return
} }
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error fetching template.", Message: "Internal error fetching template.",
Detail: err.Error(), Detail: err.Error(),
}) })
@ -270,7 +270,7 @@ func (api *API) postWorkspacesByOrganization(rw http.ResponseWriter, r *http.Req
} }
if organization.ID != template.OrganizationID { if organization.ID != template.OrganizationID {
httpapi.Write(rw, http.StatusUnauthorized, httpapi.Response{ httpapi.Write(rw, http.StatusUnauthorized, codersdk.Response{
Message: fmt.Sprintf("Template is not in organization %q.", organization.Name), Message: fmt.Sprintf("Template is not in organization %q.", organization.Name),
}) })
return return
@ -278,18 +278,18 @@ func (api *API) postWorkspacesByOrganization(rw http.ResponseWriter, r *http.Req
dbAutostartSchedule, err := validWorkspaceSchedule(createWorkspace.AutostartSchedule, time.Duration(template.MinAutostartInterval)) dbAutostartSchedule, err := validWorkspaceSchedule(createWorkspace.AutostartSchedule, time.Duration(template.MinAutostartInterval))
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusBadRequest, httpapi.Response{ httpapi.Write(rw, http.StatusBadRequest, codersdk.Response{
Message: "Invalid Autostart Schedule.", Message: "Invalid Autostart Schedule.",
Validations: []httpapi.Error{{Field: "schedule", Detail: err.Error()}}, Validations: []codersdk.ValidationError{{Field: "schedule", Detail: err.Error()}},
}) })
return return
} }
dbTTL, err := validWorkspaceTTLMillis(createWorkspace.TTLMillis, time.Duration(template.MaxTtl)) dbTTL, err := validWorkspaceTTLMillis(createWorkspace.TTLMillis, time.Duration(template.MaxTtl))
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusBadRequest, httpapi.Response{ httpapi.Write(rw, http.StatusBadRequest, codersdk.Response{
Message: "Invalid Workspace TTL.", Message: "Invalid Workspace TTL.",
Validations: []httpapi.Error{{Field: "ttl_ms", Detail: err.Error()}}, Validations: []codersdk.ValidationError{{Field: "ttl_ms", Detail: err.Error()}},
}) })
return return
} }
@ -307,16 +307,16 @@ func (api *API) postWorkspacesByOrganization(rw http.ResponseWriter, r *http.Req
// If the workspace already exists, don't allow creation. // If the workspace already exists, don't allow creation.
template, err := api.Database.GetTemplateByID(r.Context(), workspace.TemplateID) template, err := api.Database.GetTemplateByID(r.Context(), workspace.TemplateID)
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: fmt.Sprintf("Find template for conflicting workspace name %q.", createWorkspace.Name), Message: fmt.Sprintf("Find template for conflicting workspace name %q.", createWorkspace.Name),
Detail: err.Error(), Detail: err.Error(),
}) })
return return
} }
// The template is fetched for clarity to the user on where the conflicting name may be. // The template is fetched for clarity to the user on where the conflicting name may be.
httpapi.Write(rw, http.StatusConflict, httpapi.Response{ httpapi.Write(rw, http.StatusConflict, codersdk.Response{
Message: fmt.Sprintf("Workspace %q already exists in the %q template.", createWorkspace.Name, template.Name), Message: fmt.Sprintf("Workspace %q already exists in the %q template.", createWorkspace.Name, template.Name),
Validations: []httpapi.Error{{ Validations: []codersdk.ValidationError{{
Field: "name", Field: "name",
Detail: "this value is already in use and should be unique", Detail: "this value is already in use and should be unique",
}}, }},
@ -324,7 +324,7 @@ func (api *API) postWorkspacesByOrganization(rw http.ResponseWriter, r *http.Req
return return
} }
if !errors.Is(err, sql.ErrNoRows) { if !errors.Is(err, sql.ErrNoRows) {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: fmt.Sprintf("Internal error fetching workspace by name %q.", createWorkspace.Name), Message: fmt.Sprintf("Internal error fetching workspace by name %q.", createWorkspace.Name),
Detail: err.Error(), Detail: err.Error(),
}) })
@ -333,7 +333,7 @@ func (api *API) postWorkspacesByOrganization(rw http.ResponseWriter, r *http.Req
templateVersion, err := api.Database.GetTemplateVersionByID(r.Context(), template.ActiveVersionID) templateVersion, err := api.Database.GetTemplateVersionByID(r.Context(), template.ActiveVersionID)
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error fetching template version.", Message: "Internal error fetching template version.",
Detail: err.Error(), Detail: err.Error(),
}) })
@ -341,7 +341,7 @@ func (api *API) postWorkspacesByOrganization(rw http.ResponseWriter, r *http.Req
} }
templateVersionJob, err := api.Database.GetProvisionerJobByID(r.Context(), templateVersion.JobID) templateVersionJob, err := api.Database.GetProvisionerJobByID(r.Context(), templateVersion.JobID)
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error fetching template version job.", Message: "Internal error fetching template version job.",
Detail: err.Error(), Detail: err.Error(),
}) })
@ -350,17 +350,17 @@ func (api *API) postWorkspacesByOrganization(rw http.ResponseWriter, r *http.Req
templateVersionJobStatus := convertProvisionerJob(templateVersionJob).Status templateVersionJobStatus := convertProvisionerJob(templateVersionJob).Status
switch templateVersionJobStatus { switch templateVersionJobStatus {
case codersdk.ProvisionerJobPending, codersdk.ProvisionerJobRunning: case codersdk.ProvisionerJobPending, codersdk.ProvisionerJobRunning:
httpapi.Write(rw, http.StatusNotAcceptable, httpapi.Response{ httpapi.Write(rw, http.StatusNotAcceptable, codersdk.Response{
Message: fmt.Sprintf("The provided template version is %s. Wait for it to complete importing!", templateVersionJobStatus), Message: fmt.Sprintf("The provided template version is %s. Wait for it to complete importing!", templateVersionJobStatus),
}) })
return return
case codersdk.ProvisionerJobFailed: case codersdk.ProvisionerJobFailed:
httpapi.Write(rw, http.StatusPreconditionFailed, httpapi.Response{ httpapi.Write(rw, http.StatusPreconditionFailed, codersdk.Response{
Message: fmt.Sprintf("The provided template version %q has failed to import. You cannot create workspaces using it!", templateVersion.Name), Message: fmt.Sprintf("The provided template version %q has failed to import. You cannot create workspaces using it!", templateVersion.Name),
}) })
return return
case codersdk.ProvisionerJobCanceled: case codersdk.ProvisionerJobCanceled:
httpapi.Write(rw, http.StatusPreconditionFailed, httpapi.Response{ httpapi.Write(rw, http.StatusPreconditionFailed, codersdk.Response{
Message: "The provided template version was canceled during import. You cannot create workspaces using it!", Message: "The provided template version was canceled during import. You cannot create workspaces using it!",
}) })
return return
@ -444,7 +444,7 @@ func (api *API) postWorkspacesByOrganization(rw http.ResponseWriter, r *http.Req
return nil return nil
}) })
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error creating workspace.", Message: "Internal error creating workspace.",
Detail: err.Error(), Detail: err.Error(),
}) })
@ -452,7 +452,7 @@ func (api *API) postWorkspacesByOrganization(rw http.ResponseWriter, r *http.Req
} }
users, err := api.Database.GetUsersByIDs(r.Context(), []uuid.UUID{apiKey.UserID, workspaceBuild.InitiatorID}) users, err := api.Database.GetUsersByIDs(r.Context(), []uuid.UUID{apiKey.UserID, workspaceBuild.InitiatorID})
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error fetching user.", Message: "Internal error fetching user.",
Detail: err.Error(), Detail: err.Error(),
}) })
@ -483,7 +483,7 @@ func (api *API) putWorkspaceAutostart(rw http.ResponseWriter, r *http.Request) {
template, err := api.Database.GetTemplateByID(r.Context(), workspace.TemplateID) template, err := api.Database.GetTemplateByID(r.Context(), workspace.TemplateID)
if err != nil { if err != nil {
api.Logger.Error(r.Context(), "fetch workspace template", slog.F("workspace_id", workspace.ID), slog.F("template_id", workspace.TemplateID), slog.Error(err)) api.Logger.Error(r.Context(), "fetch workspace template", slog.F("workspace_id", workspace.ID), slog.F("template_id", workspace.TemplateID), slog.Error(err))
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Error fetching workspace template.", Message: "Error fetching workspace template.",
}) })
return return
@ -491,9 +491,9 @@ func (api *API) putWorkspaceAutostart(rw http.ResponseWriter, r *http.Request) {
dbSched, err := validWorkspaceSchedule(req.Schedule, time.Duration(template.MinAutostartInterval)) dbSched, err := validWorkspaceSchedule(req.Schedule, time.Duration(template.MinAutostartInterval))
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusBadRequest, httpapi.Response{ httpapi.Write(rw, http.StatusBadRequest, codersdk.Response{
Message: "Invalid autostart schedule.", Message: "Invalid autostart schedule.",
Validations: []httpapi.Error{{Field: "schedule", Detail: err.Error()}}, Validations: []codersdk.ValidationError{{Field: "schedule", Detail: err.Error()}},
}) })
return return
} }
@ -503,7 +503,7 @@ func (api *API) putWorkspaceAutostart(rw http.ResponseWriter, r *http.Request) {
AutostartSchedule: dbSched, AutostartSchedule: dbSched,
}) })
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error updating workspace autostart schedule.", Message: "Internal error updating workspace autostart schedule.",
Detail: err.Error(), Detail: err.Error(),
}) })
@ -523,12 +523,12 @@ func (api *API) putWorkspaceTTL(rw http.ResponseWriter, r *http.Request) {
return return
} }
var validErrs []httpapi.Error var validErrs []codersdk.ValidationError
err := api.Database.InTx(func(s database.Store) error { err := api.Database.InTx(func(s database.Store) error {
template, err := s.GetTemplateByID(r.Context(), workspace.TemplateID) template, err := s.GetTemplateByID(r.Context(), workspace.TemplateID)
if err != nil { if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ httpapi.Write(rw, http.StatusInternalServerError, codersdk.Response{
Message: "Error fetching workspace template!", Message: "Error fetching workspace template!",
}) })
return xerrors.Errorf("fetch workspace template: %w", err) return xerrors.Errorf("fetch workspace template: %w", err)
@ -536,7 +536,7 @@ func (api *API) putWorkspaceTTL(rw http.ResponseWriter, r *http.Request) {
dbTTL, err := validWorkspaceTTLMillis(req.TTLMillis, time.Duration(template.MaxTtl)) dbTTL, err := validWorkspaceTTLMillis(req.TTLMillis, time.Duration(template.MaxTtl))
if err != nil { if err != nil {
validErrs = append(validErrs, httpapi.Error{Field: "ttl_ms", Detail: err.Error()}) validErrs = append(validErrs, codersdk.ValidationError{Field: "ttl_ms", Detail: err.Error()})
return err return err
} }
if err := s.UpdateWorkspaceTTL(r.Context(), database.UpdateWorkspaceTTLParams{ if err := s.UpdateWorkspaceTTL(r.Context(), database.UpdateWorkspaceTTLParams{
@ -554,7 +554,7 @@ func (api *API) putWorkspaceTTL(rw http.ResponseWriter, r *http.Request) {
if len(validErrs) > 0 { if len(validErrs) > 0 {
code = http.StatusBadRequest code = http.StatusBadRequest
} }
httpapi.Write(rw, code, httpapi.Response{ httpapi.Write(rw, code, codersdk.Response{
Message: "Error updating workspace time until shutdown!", Message: "Error updating workspace time until shutdown!",
Validations: validErrs, Validations: validErrs,
Detail: err.Error(), Detail: err.Error(),
@ -579,7 +579,7 @@ func (api *API) putExtendWorkspace(rw http.ResponseWriter, r *http.Request) {
} }
code := http.StatusOK code := http.StatusOK
resp := httpapi.Response{} resp := codersdk.Response{}
err := api.Database.InTx(func(s database.Store) error { err := api.Database.InTx(func(s database.Store) error {
template, err := s.GetTemplateByID(r.Context(), workspace.TemplateID) template, err := s.GetTemplateByID(r.Context(), workspace.TemplateID)
@ -625,7 +625,7 @@ func (api *API) putExtendWorkspace(rw http.ResponseWriter, r *http.Request) {
if err := validWorkspaceDeadline(job.CompletedAt.Time, newDeadline, time.Duration(template.MaxTtl)); err != nil { if err := validWorkspaceDeadline(job.CompletedAt.Time, newDeadline, time.Duration(template.MaxTtl)); err != nil {
code = http.StatusBadRequest code = http.StatusBadRequest
resp.Message = "Bad extend workspace request." resp.Message = "Bad extend workspace request."
resp.Validations = append(resp.Validations, httpapi.Error{Field: "deadline", Detail: err.Error()}) resp.Validations = append(resp.Validations, codersdk.ValidationError{Field: "deadline", Detail: err.Error()})
return err return err
} }
@ -698,7 +698,7 @@ func (api *API) watchWorkspace(rw http.ResponseWriter, r *http.Request) {
case <-t.C: case <-t.C:
workspace, err := api.Database.GetWorkspaceByID(r.Context(), workspace.ID) workspace, err := api.Database.GetWorkspaceByID(r.Context(), workspace.ID)
if err != nil { if err != nil {
_ = wsjson.Write(ctx, c, httpapi.Response{ _ = wsjson.Write(ctx, c, codersdk.Response{
Message: "Internal error fetching workspace.", Message: "Internal error fetching workspace.",
Detail: err.Error(), Detail: err.Error(),
}) })
@ -706,7 +706,7 @@ func (api *API) watchWorkspace(rw http.ResponseWriter, r *http.Request) {
} }
build, err := api.Database.GetLatestWorkspaceBuildByWorkspaceID(r.Context(), workspace.ID) build, err := api.Database.GetLatestWorkspaceBuildByWorkspaceID(r.Context(), workspace.ID)
if err != nil { if err != nil {
_ = wsjson.Write(ctx, c, httpapi.Response{ _ = wsjson.Write(ctx, c, codersdk.Response{
Message: "Internal error fetching workspace build.", Message: "Internal error fetching workspace build.",
Detail: err.Error(), Detail: err.Error(),
}) })
@ -732,7 +732,7 @@ func (api *API) watchWorkspace(rw http.ResponseWriter, r *http.Request) {
}) })
err = group.Wait() err = group.Wait()
if err != nil { if err != nil {
_ = wsjson.Write(ctx, c, httpapi.Response{ _ = wsjson.Write(ctx, c, codersdk.Response{
Message: "Internal error fetching resource.", Message: "Internal error fetching resource.",
Detail: err.Error(), Detail: err.Error(),
}) })
@ -953,7 +953,7 @@ func validWorkspaceSchedule(s *string, min time.Duration) (sql.NullString, error
// workspaceSearchQuery takes a query string and returns the workspace filter. // workspaceSearchQuery takes a query string and returns the workspace filter.
// It also can return the list of validation errors to return to the api. // It also can return the list of validation errors to return to the api.
func workspaceSearchQuery(query string) (database.GetWorkspacesParams, []httpapi.Error) { func workspaceSearchQuery(query string) (database.GetWorkspacesParams, []codersdk.ValidationError) {
searchParams := make(url.Values) searchParams := make(url.Values)
if query == "" { if query == "" {
// No filter // No filter
@ -977,14 +977,14 @@ func workspaceSearchQuery(query string) (database.GetWorkspacesParams, []httpapi
searchParams.Set("owner", parts[0]) searchParams.Set("owner", parts[0])
searchParams.Set("name", parts[1]) searchParams.Set("name", parts[1])
default: default:
return database.GetWorkspacesParams{}, []httpapi.Error{ return database.GetWorkspacesParams{}, []codersdk.ValidationError{
{Field: "q", Detail: fmt.Sprintf("Query element %q can only contain 1 '/'", element)}, {Field: "q", Detail: fmt.Sprintf("Query element %q can only contain 1 '/'", element)},
} }
} }
case 2: case 2:
searchParams.Set(parts[0], parts[1]) searchParams.Set(parts[0], parts[1])
default: default:
return database.GetWorkspacesParams{}, []httpapi.Error{ return database.GetWorkspacesParams{}, []codersdk.ValidationError{
{Field: "q", Detail: fmt.Sprintf("Query element %q can only contain 1 ':'", element)}, {Field: "q", Detail: fmt.Sprintf("Query element %q can only contain 1 ':'", element)},
} }
} }

View File

@ -13,11 +13,11 @@ import (
"golang.org/x/xerrors" "golang.org/x/xerrors"
"nhooyr.io/websocket" "nhooyr.io/websocket"
"github.com/coder/coder/coderd/httpapi"
"github.com/coder/coder/coderd/httpmw"
) )
// SessionTokenKey represents the name of the cookie or query parameter the API key is stored in.
const SessionTokenKey = "session_token"
// New creates a Coder client for the provided URL. // New creates a Coder client for the provided URL.
func New(serverURL *url.URL) *Client { func New(serverURL *url.URL) *Client {
return &Client{ return &Client{
@ -64,7 +64,7 @@ func (c *Client) Request(ctx context.Context, method, path string, body interfac
return nil, xerrors.Errorf("create request: %w", err) return nil, xerrors.Errorf("create request: %w", err)
} }
req.AddCookie(&http.Cookie{ req.AddCookie(&http.Cookie{
Name: httpmw.SessionTokenKey, Name: SessionTokenKey,
Value: c.SessionToken, Value: c.SessionToken,
}) })
if body != nil { if body != nil {
@ -99,7 +99,7 @@ func (c *Client) dialWebsocket(ctx context.Context, path string) (*websocket.Con
} }
apiURL.Path = path apiURL.Path = path
q := apiURL.Query() q := apiURL.Query()
q.Add(httpmw.SessionTokenKey, c.SessionToken) q.Add(SessionTokenKey, c.SessionToken)
apiURL.RawQuery = q.Encode() apiURL.RawQuery = q.Encode()
//nolint:bodyclose //nolint:bodyclose
@ -113,7 +113,7 @@ func (c *Client) dialWebsocket(ctx context.Context, path string) (*websocket.Con
return conn, nil return conn, nil
} }
// readBodyAsError reads the response as an httpapi.Message, and // readBodyAsError reads the response as an .Message, and
// wraps it in a codersdk.Error type for easy marshaling. // wraps it in a codersdk.Error type for easy marshaling.
func readBodyAsError(res *http.Response) error { func readBodyAsError(res *http.Response) error {
contentType := res.Header.Get("Content-Type") contentType := res.Header.Get("Content-Type")
@ -140,7 +140,7 @@ func readBodyAsError(res *http.Response) error {
} }
return &Error{ return &Error{
statusCode: res.StatusCode, statusCode: res.StatusCode,
Response: httpapi.Response{ Response: Response{
Message: string(resp), Message: string(resp),
}, },
Helper: helper, Helper: helper,
@ -148,7 +148,7 @@ func readBodyAsError(res *http.Response) error {
} }
//nolint:varnamelen //nolint:varnamelen
var m httpapi.Response var m Response
err := json.NewDecoder(res.Body).Decode(&m) err := json.NewDecoder(res.Body).Decode(&m)
if err != nil { if err != nil {
if errors.Is(err, io.EOF) { if errors.Is(err, io.EOF) {
@ -172,7 +172,7 @@ func readBodyAsError(res *http.Response) error {
// Error represents an unaccepted or invalid request to the API. // Error represents an unaccepted or invalid request to the API.
// @typescript-ignore Error // @typescript-ignore Error
type Error struct { type Error struct {
httpapi.Response Response
statusCode int statusCode int
method string method string

27
codersdk/error.go Normal file
View File

@ -0,0 +1,27 @@
package codersdk
// Response represents a generic HTTP response.
type Response struct {
// Message is an actionable message that depicts actions the request took.
// These messages should be fully formed sentences with proper punctuation.
// Examples:
// - "A user has been created."
// - "Failed to create a user."
Message string `json:"message"`
// Detail is a debug message that provides further insight into why the
// action failed. This information can be technical and a regular golang
// err.Error() text.
// - "database: too many open connections"
// - "stat: too many open files"
Detail string `json:"detail,omitempty"`
// Validations are form field-specific friendly error messages. They will be
// shown on a form field in the UI. These can also be used to add additional
// context if there is a set of errors in the primary 'Message'.
Validations []ValidationError `json:"validations,omitempty"`
}
// ValidationError represents a scoped error to a user input.
type ValidationError struct {
Field string `json:"field" validate:"required"`
Detail string `json:"detail" validate:"required"`
}

View File

@ -14,8 +14,6 @@ import (
"github.com/google/uuid" "github.com/google/uuid"
"golang.org/x/xerrors" "golang.org/x/xerrors"
"nhooyr.io/websocket" "nhooyr.io/websocket"
"github.com/coder/coder/coderd/httpmw"
) )
type LogSource string type LogSource string
@ -120,7 +118,7 @@ func (c *Client) provisionerJobLogsAfter(ctx context.Context, path string, after
return nil, xerrors.Errorf("create cookie jar: %w", err) return nil, xerrors.Errorf("create cookie jar: %w", err)
} }
jar.SetCookies(followURL, []*http.Cookie{{ jar.SetCookies(followURL, []*http.Cookie{{
Name: httpmw.SessionTokenKey, Name: SessionTokenKey,
Value: c.SessionToken, Value: c.SessionToken,
}}) }})
httpClient := &http.Client{ httpClient := &http.Client{

View File

@ -20,7 +20,6 @@ import (
"cdr.dev/slog" "cdr.dev/slog"
"github.com/coder/coder/agent" "github.com/coder/coder/agent"
"github.com/coder/coder/coderd/httpmw"
"github.com/coder/coder/coderd/turnconn" "github.com/coder/coder/coderd/turnconn"
"github.com/coder/coder/peer" "github.com/coder/coder/peer"
"github.com/coder/coder/peer/peerwg" "github.com/coder/coder/peer/peerwg"
@ -189,7 +188,7 @@ func (c *Client) ListenWorkspaceAgent(ctx context.Context, logger slog.Logger) (
return agent.Metadata{}, nil, xerrors.Errorf("create cookie jar: %w", err) return agent.Metadata{}, nil, xerrors.Errorf("create cookie jar: %w", err)
} }
jar.SetCookies(serverURL, []*http.Cookie{{ jar.SetCookies(serverURL, []*http.Cookie{{
Name: httpmw.SessionTokenKey, Name: SessionTokenKey,
Value: c.SessionToken, Value: c.SessionToken,
}}) }})
httpClient := &http.Client{ httpClient := &http.Client{
@ -285,7 +284,7 @@ func (c *Client) WireguardPeerListener(ctx context.Context, logger slog.Logger)
return nil, nil, xerrors.Errorf("create cookie jar: %w", err) return nil, nil, xerrors.Errorf("create cookie jar: %w", err)
} }
jar.SetCookies(serverURL, []*http.Cookie{{ jar.SetCookies(serverURL, []*http.Cookie{{
Name: httpmw.SessionTokenKey, Name: SessionTokenKey,
Value: c.SessionToken, Value: c.SessionToken,
}}) }})
httpClient := &http.Client{ httpClient := &http.Client{
@ -355,7 +354,7 @@ func (c *Client) DialWorkspaceAgent(ctx context.Context, agentID uuid.UUID, opti
return nil, xerrors.Errorf("create cookie jar: %w", err) return nil, xerrors.Errorf("create cookie jar: %w", err)
} }
jar.SetCookies(serverURL, []*http.Cookie{{ jar.SetCookies(serverURL, []*http.Cookie{{
Name: httpmw.SessionTokenKey, Name: SessionTokenKey,
Value: c.SessionToken, Value: c.SessionToken,
}}) }})
httpClient := &http.Client{ httpClient := &http.Client{
@ -443,7 +442,7 @@ func (c *Client) WorkspaceAgentReconnectingPTY(ctx context.Context, agentID, rec
return nil, xerrors.Errorf("create cookie jar: %w", err) return nil, xerrors.Errorf("create cookie jar: %w", err)
} }
jar.SetCookies(serverURL, []*http.Cookie{{ jar.SetCookies(serverURL, []*http.Cookie{{
Name: httpmw.SessionTokenKey, Name: SessionTokenKey,
Value: c.SessionToken, Value: c.SessionToken,
}}) }})
httpClient := &http.Client{ httpClient := &http.Client{

View File

@ -12,7 +12,7 @@ export interface APIKey {
readonly lifetime_seconds: number readonly lifetime_seconds: number
} }
// From codersdk/workspaceagents.go:36:6 // From codersdk/workspaceagents.go:35:6
export interface AWSInstanceIdentityToken { export interface AWSInstanceIdentityToken {
readonly signature: string readonly signature: string
readonly document: string readonly document: string
@ -30,7 +30,7 @@ export interface AuthMethods {
readonly github: boolean readonly github: boolean
} }
// From codersdk/workspaceagents.go:41:6 // From codersdk/workspaceagents.go:40:6
export interface AzureInstanceIdentityToken { export interface AzureInstanceIdentityToken {
readonly signature: string readonly signature: string
readonly encoding: string readonly encoding: string
@ -141,7 +141,7 @@ export interface GitSSHKey {
readonly public_key: string readonly public_key: string
} }
// From codersdk/workspaceagents.go:32:6 // From codersdk/workspaceagents.go:31:6
export interface GoogleInstanceIdentityToken { export interface GoogleInstanceIdentityToken {
readonly json_web_token: string readonly json_web_token: string
} }
@ -214,7 +214,7 @@ export interface ParameterSchema {
readonly validation_contains?: string[] readonly validation_contains?: string[]
} }
// From codersdk/provisionerdaemons.go:38:6 // From codersdk/provisionerdaemons.go:36:6
export interface ProvisionerDaemon { export interface ProvisionerDaemon {
readonly id: string readonly id: string
readonly created_at: string readonly created_at: string
@ -223,7 +223,7 @@ export interface ProvisionerDaemon {
readonly provisioners: ProvisionerType[] readonly provisioners: ProvisionerType[]
} }
// From codersdk/provisionerdaemons.go:67:6 // From codersdk/provisionerdaemons.go:65:6
export interface ProvisionerJob { export interface ProvisionerJob {
readonly id: string readonly id: string
readonly created_at: string readonly created_at: string
@ -235,7 +235,7 @@ export interface ProvisionerJob {
readonly storage_source: string readonly storage_source: string
} }
// From codersdk/provisionerdaemons.go:78:6 // From codersdk/provisionerdaemons.go:76:6
export interface ProvisionerJobLog { export interface ProvisionerJobLog {
readonly id: string readonly id: string
readonly created_at: string readonly created_at: string
@ -250,6 +250,13 @@ export interface PutExtendWorkspaceRequest {
readonly deadline: string readonly deadline: string
} }
// From codersdk/error.go:4:6
export interface Response {
readonly message: string
readonly detail?: string
readonly validations?: ValidationError[]
}
// From codersdk/roles.go:12:6 // From codersdk/roles.go:12:6
export interface Role { export interface Role {
readonly name: string readonly name: string
@ -377,6 +384,12 @@ export interface UsersRequest extends Pagination {
readonly q?: string readonly q?: string
} }
// From codersdk/error.go:24:6
export interface ValidationError {
readonly field: string
readonly detail: string
}
// From codersdk/workspaces.go:19:6 // From codersdk/workspaces.go:19:6
export interface Workspace { export interface Workspace {
readonly id: string readonly id: string
@ -422,7 +435,7 @@ export interface WorkspaceAgent {
readonly ipv6: any readonly ipv6: any
} }
// From codersdk/workspaceagents.go:48:6 // From codersdk/workspaceagents.go:47:6
export interface WorkspaceAgentAuthenticateResponse { export interface WorkspaceAgentAuthenticateResponse {
readonly session_token: string readonly session_token: string
} }
@ -506,10 +519,10 @@ export interface WorkspaceResource {
// From codersdk/workspacebuilds.go:22:6 // From codersdk/workspacebuilds.go:22:6
export type BuildReason = "autostart" | "autostop" | "initiator" export type BuildReason = "autostart" | "autostop" | "initiator"
// From codersdk/provisionerdaemons.go:28:6 // From codersdk/provisionerdaemons.go:26:6
export type LogLevel = "debug" | "error" | "info" | "trace" | "warn" export type LogLevel = "debug" | "error" | "info" | "trace" | "warn"
// From codersdk/provisionerdaemons.go:21:6 // From codersdk/provisionerdaemons.go:19:6
export type LogSource = "provisioner" | "provisioner_daemon" export type LogSource = "provisioner" | "provisioner_daemon"
// From codersdk/users.go:25:6 // From codersdk/users.go:25:6
@ -527,7 +540,7 @@ export type ParameterSourceScheme = "data" | "none"
// From codersdk/parameters.go:37:6 // From codersdk/parameters.go:37:6
export type ParameterTypeSystem = "hcl" | "none" export type ParameterTypeSystem = "hcl" | "none"
// From codersdk/provisionerdaemons.go:47:6 // From codersdk/provisionerdaemons.go:45:6
export type ProvisionerJobStatus = export type ProvisionerJobStatus =
| "canceled" | "canceled"
| "canceling" | "canceling"