Skip to content

Commit d11feae

Browse files
author
Admin
committed
Merge branch 'main' of https://github.com/coder/coder
2 parents 82d49db + 2459233 commit d11feae

File tree

79 files changed

+2705
-4432
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

79 files changed

+2705
-4432
lines changed

cli/deployment/config.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -248,6 +248,12 @@ func newConfig() *codersdk.DeploymentConfig {
248248
Flag: "oidc-ignore-email-verified",
249249
Default: false,
250250
},
251+
UsernameField: &codersdk.DeploymentConfigField[string]{
252+
Name: "OIDC Username Field",
253+
Usage: "OIDC claim field to use as the username.",
254+
Flag: "oidc-username-field",
255+
Default: "preferred_username",
256+
},
251257
},
252258

253259
Telemetry: &codersdk.TelemetryConfig{

cli/server.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -526,8 +526,9 @@ func Server(vip *viper.Viper, newAPI func(context.Context, *coderd.Options) (*co
526526
Verifier: oidcProvider.Verifier(&oidc.Config{
527527
ClientID: cfg.OIDC.ClientID.Value,
528528
}),
529-
EmailDomain: cfg.OIDC.EmailDomain.Value,
530-
AllowSignups: cfg.OIDC.AllowSignups.Value,
529+
EmailDomain: cfg.OIDC.EmailDomain.Value,
530+
AllowSignups: cfg.OIDC.AllowSignups.Value,
531+
UsernameField: cfg.OIDC.UsernameField.Value,
531532
}
532533
}
533534

cli/testdata/coder_server_--help.golden

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,9 @@ Flags:
112112
OIDC.
113113
Consumes $CODER_OIDC_SCOPES (default
114114
[openid,profile,email])
115+
--oidc-username-field string OIDC claim field to use as the username.
116+
Consumes $CODER_OIDC_USERNAME_FIELD
117+
(default "preferred_username")
115118
--postgres-url string URL of a PostgreSQL database. If empty,
116119
PostgreSQL binaries will be downloaded
117120
from Maven

coderd/apidoc/docs.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1975,6 +1975,9 @@ const docTemplate = `{
19751975
},
19761976
"scopes": {
19771977
"$ref": "#/definitions/codersdk.DeploymentConfigField-array_string"
1978+
},
1979+
"username_field": {
1980+
"$ref": "#/definitions/codersdk.DeploymentConfigField-string"
19781981
}
19791982
}
19801983
},

coderd/apidoc/swagger.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1795,6 +1795,9 @@
17951795
},
17961796
"scopes": {
17971797
"$ref": "#/definitions/codersdk.DeploymentConfigField-array_string"
1798+
},
1799+
"username_field": {
1800+
"$ref": "#/definitions/codersdk.DeploymentConfigField-string"
17981801
}
17991802
}
18001803
},

coderd/audit/request.go

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,7 @@ func InitRequest[T Auditable](w http.ResponseWriter, p *RequestParams) (*Request
157157
}
158158

159159
ip := parseIP(p.Request.RemoteAddr)
160-
err := p.Audit.Export(ctx, database.AuditLog{
160+
auditLog := database.AuditLog{
161161
ID: uuid.New(),
162162
Time: database.Now(),
163163
UserID: httpmw.APIKey(p.Request).UserID,
@@ -171,9 +171,13 @@ func InitRequest[T Auditable](w http.ResponseWriter, p *RequestParams) (*Request
171171
StatusCode: int32(sw.Status),
172172
RequestID: httpmw.RequestID(p.Request),
173173
AdditionalFields: p.AdditionalFields,
174-
})
174+
}
175+
err := p.Audit.Export(ctx, auditLog)
175176
if err != nil {
176-
p.Log.Error(logCtx, "export audit log", slog.Error(err))
177+
p.Log.Error(logCtx, "export audit log",
178+
slog.F("audit_log", auditLog),
179+
slog.Error(err),
180+
)
177181
return
178182
}
179183
}
@@ -192,7 +196,7 @@ func BuildAudit[T Auditable](ctx context.Context, p *BuildAuditParams[T]) {
192196
p.AdditionalFields = json.RawMessage("{}")
193197
}
194198

195-
err := p.Audit.Export(ctx, database.AuditLog{
199+
auditLog := database.AuditLog{
196200
ID: uuid.New(),
197201
Time: database.Now(),
198202
UserID: p.UserID,
@@ -206,9 +210,13 @@ func BuildAudit[T Auditable](ctx context.Context, p *BuildAuditParams[T]) {
206210
StatusCode: int32(p.Status),
207211
RequestID: p.JobID,
208212
AdditionalFields: p.AdditionalFields,
209-
})
213+
}
214+
err := p.Audit.Export(ctx, auditLog)
210215
if err != nil {
211-
p.Log.Error(ctx, "export audit log", slog.Error(err))
216+
p.Log.Error(ctx, "export audit log",
217+
slog.F("audit_log", auditLog),
218+
slog.Error(err),
219+
)
212220
return
213221
}
214222
}

coderd/coderdtest/coderdtest.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -880,6 +880,7 @@ func (o *OIDCConfig) OIDCConfig() *coderd.OIDCConfig {
880880
}, &oidc.Config{
881881
SkipClientIDCheck: true,
882882
}),
883+
UsernameField: "preferred_username",
883884
}
884885
}
885886

coderd/database/databasefake/databasefake.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,7 @@ type data struct {
123123
derpMeshKey string
124124
lastUpdateCheck []byte
125125
serviceBanner []byte
126+
logoURL string
126127
lastLicenseID int32
127128
}
128129

@@ -3356,6 +3357,25 @@ func (q *fakeQuerier) GetServiceBanner(_ context.Context) (string, error) {
33563357
return string(q.serviceBanner), nil
33573358
}
33583359

3360+
func (q *fakeQuerier) InsertOrUpdateLogoURL(_ context.Context, data string) error {
3361+
q.mutex.RLock()
3362+
defer q.mutex.RUnlock()
3363+
3364+
q.logoURL = data
3365+
return nil
3366+
}
3367+
3368+
func (q *fakeQuerier) GetLogoURL(_ context.Context) (string, error) {
3369+
q.mutex.RLock()
3370+
defer q.mutex.RUnlock()
3371+
3372+
if q.logoURL == "" {
3373+
return "", sql.ErrNoRows
3374+
}
3375+
3376+
return q.logoURL, nil
3377+
}
3378+
33593379
func (q *fakeQuerier) InsertLicense(
33603380
_ context.Context, arg database.InsertLicenseParams,
33613381
) (database.License, error) {

coderd/database/querier.go

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

coderd/database/queries.sql.go

Lines changed: 21 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

coderd/database/queries/siteconfig.sql

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,3 +23,10 @@ ON CONFLICT (key) DO UPDATE SET value = $1 WHERE site_configs.key = 'service_ban
2323

2424
-- name: GetServiceBanner :one
2525
SELECT value FROM site_configs WHERE key = 'service_banner';
26+
27+
-- name: InsertOrUpdateLogoURL :exec
28+
INSERT INTO site_configs (key, value) VALUES ('logo_url', $1)
29+
ON CONFLICT (key) DO UPDATE SET value = $1 WHERE site_configs.key = 'logo_url';
30+
31+
-- name: GetLogoURL :one
32+
SELECT value FROM site_configs WHERE key = 'logo_url';

coderd/userauth.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,9 @@ type OIDCConfig struct {
198198
// IgnoreEmailVerified allows ignoring the email_verified claim
199199
// from an upstream OIDC provider. See #5065 for context.
200200
IgnoreEmailVerified bool
201+
// UsernameField selects the claim field to be used as the created user's
202+
// username.
203+
UsernameField string
201204
}
202205

203206
func (api *API) userOIDC(rw http.ResponseWriter, r *http.Request) {
@@ -236,7 +239,7 @@ func (api *API) userOIDC(rw http.ResponseWriter, r *http.Request) {
236239
})
237240
return
238241
}
239-
usernameRaw, ok := claims["preferred_username"]
242+
usernameRaw, ok := claims[api.OIDCConfig.UsernameField]
240243
var username string
241244
if ok {
242245
username, _ = usernameRaw.(string)

codersdk/appearance.go

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
package codersdk
2+
3+
import (
4+
"context"
5+
"encoding/json"
6+
"net/http"
7+
)
8+
9+
type AppearanceConfig struct {
10+
LogoURL string `json:"logo_url"`
11+
ServiceBanner ServiceBannerConfig `json:"service_banner"`
12+
}
13+
14+
type ServiceBannerConfig struct {
15+
Enabled bool `json:"enabled"`
16+
Message string `json:"message,omitempty"`
17+
BackgroundColor string `json:"background_color,omitempty"`
18+
}
19+
20+
func (c *Client) Appearance(ctx context.Context) (AppearanceConfig, error) {
21+
res, err := c.Request(ctx, http.MethodGet, "/api/v2/appearance", nil)
22+
if err != nil {
23+
return AppearanceConfig{}, err
24+
}
25+
defer res.Body.Close()
26+
if res.StatusCode != http.StatusOK {
27+
return AppearanceConfig{}, readBodyAsError(res)
28+
}
29+
var cfg AppearanceConfig
30+
return cfg, json.NewDecoder(res.Body).Decode(&cfg)
31+
}
32+
33+
func (c *Client) UpdateAppearance(ctx context.Context, appearance AppearanceConfig) error {
34+
res, err := c.Request(ctx, http.MethodPut, "/api/v2/appearance", appearance)
35+
if err != nil {
36+
return err
37+
}
38+
defer res.Body.Close()
39+
if res.StatusCode != http.StatusOK {
40+
return readBodyAsError(res)
41+
}
42+
return nil
43+
}

codersdk/branding.go

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
package codersdk
2+
3+
import (
4+
"context"
5+
"net/http"
6+
)
7+
8+
type UpdateBrandingRequest struct {
9+
LogoURL string `json:"logo_url"`
10+
}
11+
12+
// UpdateBranding applies customization settings available to Enterprise customers.
13+
func (c *Client) UpdateBranding(ctx context.Context, req UpdateBrandingRequest) error {
14+
res, err := c.Request(ctx, http.MethodPut, "/api/v2/branding", req)
15+
if err != nil {
16+
return err
17+
}
18+
defer res.Body.Close()
19+
if res.StatusCode != http.StatusOK {
20+
return readBodyAsError(res)
21+
}
22+
return nil
23+
}

codersdk/deploymentconfig.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@ type OIDCConfig struct {
9999
IssuerURL *DeploymentConfigField[string] `json:"issuer_url" typescript:",notnull"`
100100
Scopes *DeploymentConfigField[[]string] `json:"scopes" typescript:",notnull"`
101101
IgnoreEmailVerified *DeploymentConfigField[bool] `json:"ignore_email_verified" typescript:",notnull"`
102+
UsernameField *DeploymentConfigField[string] `json:"username_field" typescript:",notnull"`
102103
}
103104

104105
type TelemetryConfig struct {

codersdk/features.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ const (
2323
FeatureHighAvailability = "high_availability"
2424
FeatureMultipleGitAuth = "multiple_git_auth"
2525
FeatureExternalProvisionerDaemons = "external_provisioner_daemons"
26-
FeatureServiceBanners = "service_banners"
26+
FeatureAppearance = "appearance"
2727
)
2828

2929
var FeatureNames = []string{
@@ -35,7 +35,7 @@ var FeatureNames = []string{
3535
FeatureHighAvailability,
3636
FeatureMultipleGitAuth,
3737
FeatureExternalProvisionerDaemons,
38-
FeatureServiceBanners,
38+
FeatureAppearance,
3939
}
4040

4141
type Feature struct {

codersdk/servicebanner.go

Lines changed: 0 additions & 38 deletions
This file was deleted.

docs/admin/automation.md

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,9 @@
22

33
We recommend automating Coder deployments through the CLI. Examples include [updating templates via CI/CD pipelines](../templates/change-management.md).
44

5-
## Tokens
5+
## Authentication
66

7-
Long-lived tokens can be generated to perform actions on behalf of your user account:
8-
9-
```console
10-
coder tokens create
11-
```
7+
Coder uses authentication tokens to grant machine users access to the REST API. Follow the [Authentication](../api/authentication.md) page to learn how to generate long-lived tokens.
128

139
## CLI
1410

@@ -23,14 +19,13 @@ coder workspaces ls
2319

2420
## REST API
2521

26-
You can use tokens with the Coder's REST API using the `Coder-Session-Token` HTTP header.
22+
You can review the [API reference](../api/index.md) to find the necessary routes and payload. Alternatively, you can enable the [Swagger](https://swagger.io/) endpoint to read the documentation and do requests against the API:
2723

2824
```console
29-
curl 'https://dev.coder.com/api/v2/workspaces' \
30-
-H 'Coder-Session-Token: *****'
25+
coder server --swagger-enable
3126
```
3227

33-
> At this time, we do not publish an API reference. However, [codersdk](https://github.com/coder/coder/tree/main/codersdk) can be grepped to find the necessary routes and payloads.
28+
By default, the local Swagger endpoint is http://localhost:3000/swagger.
3429

3530
## Golang SDK
3631

0 commit comments

Comments
 (0)