feat: Enable custom support links (#6313)

* backend: support links

* frontend: Support links

* fmt

* test: CODER_SUPPORT_LINKS_0_NAME

* Go tests

* Use UpdateAppearanceConfig

* ui: UpdateAppearanceConfig

* fix: fmt

* Fix: site

* Fix: site tests

* fix: fmt

* fix

* test: check default support links
This commit is contained in:
Marcin Tojek
2023-02-27 09:25:04 +01:00
committed by GitHub
parent 16364db483
commit 2e53fb55da
20 changed files with 641 additions and 90 deletions
+30 -4
View File
@@ -15,6 +15,24 @@ import (
"github.com/coder/coder/codersdk"
)
var DefaultSupportLinks = []codersdk.LinkConfig{
{
Name: "Documentation",
Target: "https://coder.com/docs/coder-oss",
Icon: "docs",
},
{
Name: "Report a bug",
Target: "https://github.com/coder/coder/issues/new?labels=needs+grooming&body={CODER_BUILD_INFO}",
Icon: "bug",
},
{
Name: "Join the Coder Discord",
Target: "https://coder.com/chat?utm_source=coder&utm_medium=coder&utm_campaign=server-footer",
Icon: "chat",
},
}
// @Summary Get appearance
// @ID get-appearance
// @Security CoderSessionToken
@@ -30,7 +48,9 @@ func (api *API) appearance(rw http.ResponseWriter, r *http.Request) {
ctx := r.Context()
if !isEntitled {
httpapi.Write(ctx, rw, http.StatusOK, codersdk.AppearanceConfig{})
httpapi.Write(ctx, rw, http.StatusOK, codersdk.AppearanceConfig{
SupportLinks: DefaultSupportLinks,
})
return
}
@@ -67,6 +87,12 @@ func (api *API) appearance(rw http.ResponseWriter, r *http.Request) {
}
}
if len(api.DeploymentConfig.Support.Links.Value) == 0 {
cfg.SupportLinks = DefaultSupportLinks
} else {
cfg.SupportLinks = api.DeploymentConfig.Support.Links.Value
}
httpapi.Write(r.Context(), rw, http.StatusOK, cfg)
}
@@ -87,8 +113,8 @@ func validateHexColor(color string) error {
// @Accept json
// @Produce json
// @Tags Enterprise
// @Param request body codersdk.AppearanceConfig true "Update appearance request"
// @Success 200 {object} codersdk.AppearanceConfig
// @Param request body codersdk.UpdateAppearanceConfig true "Update appearance request"
// @Success 200 {object} codersdk.UpdateAppearanceConfig
// @Router /appearance [put]
func (api *API) putAppearance(rw http.ResponseWriter, r *http.Request) {
ctx := r.Context()
@@ -100,7 +126,7 @@ func (api *API) putAppearance(rw http.ResponseWriter, r *http.Request) {
return
}
var appearance codersdk.AppearanceConfig
var appearance codersdk.UpdateAppearanceConfig
if !httpapi.Read(ctx, rw, r, &appearance) {
return
}
+66 -4
View File
@@ -10,6 +10,7 @@ import (
"github.com/coder/coder/coderd/coderdtest"
"github.com/coder/coder/codersdk"
"github.com/coder/coder/enterprise/coderd"
"github.com/coder/coder/enterprise/coderd/coderdenttest"
"github.com/coder/coder/enterprise/coderd/license"
"github.com/coder/coder/testutil"
@@ -43,16 +44,20 @@ func TestServiceBanners(t *testing.T) {
basicUserClient, _ := coderdtest.CreateAnotherUser(t, adminClient, adminUser.OrganizationID)
uac := codersdk.UpdateAppearanceConfig{
ServiceBanner: sb.ServiceBanner,
}
// Regular user should be unable to set the banner
sb.ServiceBanner.Enabled = true
err = basicUserClient.UpdateAppearance(ctx, sb)
uac.ServiceBanner.Enabled = true
err = basicUserClient.UpdateAppearance(ctx, uac)
require.Error(t, err)
var sdkError *codersdk.Error
require.True(t, errors.As(err, &sdkError))
require.Equal(t, http.StatusForbidden, sdkError.StatusCode())
// But an admin can
wantBanner := sb
wantBanner := uac
wantBanner.ServiceBanner.Enabled = true
wantBanner.ServiceBanner.Message = "Hey"
wantBanner.ServiceBanner.BackgroundColor = "#00FF00"
@@ -60,10 +65,67 @@ func TestServiceBanners(t *testing.T) {
require.NoError(t, err)
gotBanner, err := adminClient.Appearance(ctx)
require.NoError(t, err)
require.Equal(t, wantBanner, gotBanner)
gotBanner.SupportLinks = nil // clean "support links" before comparison
require.Equal(t, wantBanner.ServiceBanner, gotBanner.ServiceBanner)
// But even an admin can't give a bad color
wantBanner.ServiceBanner.BackgroundColor = "#bad color"
err = adminClient.UpdateAppearance(ctx, wantBanner)
require.Error(t, err)
}
func TestCustomSupportLinks(t *testing.T) {
t.Parallel()
supportLinks := []codersdk.LinkConfig{
{
Name: "First link",
Target: "http://first-link-1",
Icon: "chat",
},
{
Name: "Second link",
Target: "http://second-link-2",
Icon: "bug",
},
}
cfg := coderdtest.DeploymentConfig(t)
cfg.Support = new(codersdk.SupportConfig)
cfg.Support.Links = &codersdk.DeploymentConfigField[[]codersdk.LinkConfig]{
Value: supportLinks,
}
client := coderdenttest.New(t, &coderdenttest.Options{
Options: &coderdtest.Options{
DeploymentConfig: cfg,
},
})
coderdtest.CreateFirstUser(t, client)
coderdenttest.AddLicense(t, client, coderdenttest.LicenseOptions{
Features: license.Features{
codersdk.FeatureAppearance: 1,
},
})
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitMedium)
defer cancel()
appearance, err := client.Appearance(ctx)
require.NoError(t, err)
require.Equal(t, supportLinks, appearance.SupportLinks)
}
func TestDefaultSupportLinks(t *testing.T) {
t.Parallel()
client := coderdenttest.New(t, nil)
coderdtest.CreateFirstUser(t, client)
// Don't need to set the license, as default links are passed without it.
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitMedium)
defer cancel()
appearance, err := client.Appearance(ctx)
require.NoError(t, err)
require.Equal(t, coderd.DefaultSupportLinks, appearance.SupportLinks)
}