Files
coder/enterprise/coderd/servicebanner.go
2022-12-06 18:38:38 +00:00

110 lines
2.7 KiB
Go

package coderd
import (
"database/sql"
"encoding/hex"
"encoding/json"
"errors"
"fmt"
"net/http"
"golang.org/x/xerrors"
"github.com/coder/coder/coderd/httpapi"
"github.com/coder/coder/coderd/rbac"
"github.com/coder/coder/codersdk"
)
func (api *API) serviceBanner(rw http.ResponseWriter, r *http.Request) {
api.entitlementsMu.RLock()
isEntitled := api.entitlements.Features[codersdk.FeatureServiceBanners].Entitlement == codersdk.EntitlementEntitled
api.entitlementsMu.RUnlock()
ctx := r.Context()
if !isEntitled {
httpapi.Write(ctx, rw, http.StatusOK, codersdk.ServiceBanner{
Enabled: false,
})
return
}
serviceBannerJSON, err := api.Database.GetServiceBanner(r.Context())
if errors.Is(err, sql.ErrNoRows) {
httpapi.Write(ctx, rw, http.StatusOK, codersdk.ServiceBanner{
Enabled: false,
})
return
} else if err != nil {
httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{
Message: fmt.Sprintf("database error: %+v", err),
})
return
}
var serviceBanner codersdk.ServiceBanner
err = json.Unmarshal([]byte(serviceBannerJSON), &serviceBanner)
if err != nil {
httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{
Message: fmt.Sprintf(
"unmarshal json: %+v, raw: %s", err, serviceBannerJSON,
),
})
return
}
httpapi.Write(r.Context(), rw, http.StatusOK, serviceBanner)
}
func validateHexColor(color string) error {
if len(color) != 7 {
return xerrors.New("expected 7 characters")
}
if color[0] != '#' {
return xerrors.New("no # prefix")
}
_, err := hex.DecodeString(color[1:])
return err
}
func (api *API) putServiceBanner(rw http.ResponseWriter, r *http.Request) {
ctx := r.Context()
if !api.Authorize(r, rbac.ActionUpdate, rbac.ResourceDeploymentConfig) {
httpapi.Write(ctx, rw, http.StatusForbidden, codersdk.Response{
Message: "Insufficient permissions to update service banner",
})
return
}
var serviceBanner codersdk.ServiceBanner
if !httpapi.Read(ctx, rw, r, &serviceBanner) {
return
}
if err := validateHexColor(serviceBanner.BackgroundColor); err != nil {
httpapi.Write(ctx, rw, http.StatusBadRequest, codersdk.Response{
Message: fmt.Sprintf("parse color: %+v", err),
})
return
}
serviceBannerJSON, err := json.Marshal(serviceBanner)
if err != nil {
httpapi.Write(ctx, rw, http.StatusBadRequest, codersdk.Response{
Message: fmt.Sprintf("marshal banner: %+v", err),
})
return
}
err = api.Database.InsertOrUpdateServiceBanner(ctx, string(serviceBannerJSON))
if err != nil {
httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{
Message: fmt.Sprintf("database error: %+v", err),
})
return
}
httpapi.Write(r.Context(), rw, http.StatusOK, serviceBanner)
}