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

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