From 94e38e8e1824fbf6d0c937d4fd9f9cf3e3180395 Mon Sep 17 00:00:00 2001 From: Steven Masley Date: Thu, 4 May 2023 15:04:15 -0500 Subject: [PATCH 01/15] chore: Add ability to update workspace proxy fields --- coderd/database/dbauthz/querier.go | 7 ++ coderd/database/dbfake/databasefake.go | 25 ++++++ coderd/database/models.go | 2 +- coderd/database/querier.go | 4 +- coderd/database/queries.sql.go | 58 +++++++++++++- coderd/database/queries/proxies.sql | 38 +++++++-- codersdk/workspaceproxy.go | 53 +++++++++++++ enterprise/cli/workspaceproxy.go | 77 ++++++++++++++++++ enterprise/coderd/coderd.go | 2 + enterprise/coderd/workspaceproxy.go | 105 ++++++++++++++++++++++++- 10 files changed, 355 insertions(+), 16 deletions(-) diff --git a/coderd/database/dbauthz/querier.go b/coderd/database/dbauthz/querier.go index 54207fd39085e..1f3a5b81663b9 100644 --- a/coderd/database/dbauthz/querier.go +++ b/coderd/database/dbauthz/querier.go @@ -1705,6 +1705,13 @@ func (q *querier) InsertWorkspaceProxy(ctx context.Context, arg database.InsertW return insert(q.log, q.auth, rbac.ResourceWorkspaceProxy, q.db.InsertWorkspaceProxy)(ctx, arg) } +func (q *querier) UpdateWorkspaceProxy(ctx context.Context, arg database.UpdateWorkspaceProxyParams) (database.WorkspaceProxy, error) { + fetch := func(ctx context.Context, arg database.UpdateWorkspaceProxyParams) (database.WorkspaceProxy, error) { + return q.db.GetWorkspaceProxyByID(ctx, arg.ID) + } + return updateWithReturn(q.log, q.auth, fetch, q.db.UpdateWorkspaceProxy)(ctx, arg) +} + func (q *querier) RegisterWorkspaceProxy(ctx context.Context, arg database.RegisterWorkspaceProxyParams) (database.WorkspaceProxy, error) { fetch := func(ctx context.Context, arg database.RegisterWorkspaceProxyParams) (database.WorkspaceProxy, error) { return q.db.GetWorkspaceProxyByID(ctx, arg.ID) diff --git a/coderd/database/dbfake/databasefake.go b/coderd/database/dbfake/databasefake.go index 7f80385af2dfb..d5b6589f8b89f 100644 --- a/coderd/database/dbfake/databasefake.go +++ b/coderd/database/dbfake/databasefake.go @@ -5231,6 +5231,31 @@ func (q *fakeQuerier) RegisterWorkspaceProxy(_ context.Context, arg database.Reg return database.WorkspaceProxy{}, sql.ErrNoRows } +func (q *fakeQuerier) UpdateWorkspaceProxy(_ context.Context, arg database.UpdateWorkspaceProxyParams) (database.WorkspaceProxy, error) { + q.mutex.Lock() + defer q.mutex.Unlock() + + for _, p := range q.workspaceProxies { + if p.Name == arg.Name && p.ID != arg.ID { + return database.WorkspaceProxy{}, errDuplicateKey + } + } + + for i, p := range q.workspaceProxies { + if p.ID == arg.ID { + p.Name = arg.Name + p.DisplayName = arg.DisplayName + p.Icon = arg.Icon + if len(p.TokenHashedSecret) > 0 { + p.TokenHashedSecret = arg.TokenHashedSecret + } + q.workspaceProxies[i] = p + return p, nil + } + } + return database.WorkspaceProxy{}, sql.ErrNoRows +} + func (q *fakeQuerier) UpdateWorkspaceProxyDeleted(_ context.Context, arg database.UpdateWorkspaceProxyDeletedParams) error { q.mutex.Lock() defer q.mutex.Unlock() diff --git a/coderd/database/models.go b/coderd/database/models.go index 61d4600ad88d6..f6a74ad6e3343 100644 --- a/coderd/database/models.go +++ b/coderd/database/models.go @@ -1,6 +1,6 @@ // Code generated by sqlc. DO NOT EDIT. // versions: -// sqlc v1.17.2 +// sqlc v1.18.0 package database diff --git a/coderd/database/querier.go b/coderd/database/querier.go index 01b79c0ae1f0f..4a57f2552b812 100644 --- a/coderd/database/querier.go +++ b/coderd/database/querier.go @@ -1,6 +1,6 @@ // Code generated by sqlc. DO NOT EDIT. // versions: -// sqlc v1.17.2 +// sqlc v1.18.0 package database @@ -255,6 +255,8 @@ type sqlcQuerier interface { UpdateWorkspaceBuildCostByID(ctx context.Context, arg UpdateWorkspaceBuildCostByIDParams) (WorkspaceBuild, error) UpdateWorkspaceDeletedByID(ctx context.Context, arg UpdateWorkspaceDeletedByIDParams) error UpdateWorkspaceLastUsedAt(ctx context.Context, arg UpdateWorkspaceLastUsedAtParams) error + // This allows editing the properties of a workspace proxy. + UpdateWorkspaceProxy(ctx context.Context, arg UpdateWorkspaceProxyParams) (WorkspaceProxy, error) UpdateWorkspaceProxyDeleted(ctx context.Context, arg UpdateWorkspaceProxyDeletedParams) error UpdateWorkspaceTTL(ctx context.Context, arg UpdateWorkspaceTTLParams) error UpdateWorkspaceTTLToBeWithinTemplateMax(ctx context.Context, arg UpdateWorkspaceTTLToBeWithinTemplateMaxParams) error diff --git a/coderd/database/queries.sql.go b/coderd/database/queries.sql.go index 0ee1f3bc9a573..c64c7d4ced5d6 100644 --- a/coderd/database/queries.sql.go +++ b/coderd/database/queries.sql.go @@ -1,6 +1,6 @@ // Code generated by sqlc. DO NOT EDIT. // versions: -// sqlc v1.17.2 +// sqlc v1.18.0 package database @@ -2829,7 +2829,7 @@ SELECT FROM workspace_proxies WHERE - deleted = false + deleted = false ` func (q *sqlQuerier) GetWorkspaceProxies(ctx context.Context) ([]WorkspaceProxy, error) { @@ -3077,6 +3077,60 @@ func (q *sqlQuerier) RegisterWorkspaceProxy(ctx context.Context, arg RegisterWor return i, err } +const updateWorkspaceProxy = `-- name: UpdateWorkspaceProxy :one +UPDATE + workspace_proxies +SET + -- These values should always be provided. + name = $1, + display_name = $2, + icon = $3, + -- Only update the token if a new one is provided. + -- So this is an optional field. + token_hashed_secret = CASE + WHEN length($4 :: bytea) > 0 THEN $4 :: bytea + ELSE workspace_proxies.token_hashed_secret + END, + -- Always update this timestamp. + updated_at = Now() +WHERE + id = $5 +RETURNING id, name, display_name, icon, url, wildcard_hostname, created_at, updated_at, deleted, token_hashed_secret +` + +type UpdateWorkspaceProxyParams struct { + Name string `db:"name" json:"name"` + DisplayName string `db:"display_name" json:"display_name"` + Icon string `db:"icon" json:"icon"` + TokenHashedSecret []byte `db:"token_hashed_secret" json:"token_hashed_secret"` + ID uuid.UUID `db:"id" json:"id"` +} + +// This allows editing the properties of a workspace proxy. +func (q *sqlQuerier) UpdateWorkspaceProxy(ctx context.Context, arg UpdateWorkspaceProxyParams) (WorkspaceProxy, error) { + row := q.db.QueryRowContext(ctx, updateWorkspaceProxy, + arg.Name, + arg.DisplayName, + arg.Icon, + arg.TokenHashedSecret, + arg.ID, + ) + var i WorkspaceProxy + err := row.Scan( + &i.ID, + &i.Name, + &i.DisplayName, + &i.Icon, + &i.Url, + &i.WildcardHostname, + &i.CreatedAt, + &i.UpdatedAt, + &i.Deleted, + &i.TokenHashedSecret, + ) + return i, err +} + const updateWorkspaceProxyDeleted = `-- name: UpdateWorkspaceProxyDeleted :exec UPDATE workspace_proxies diff --git a/coderd/database/queries/proxies.sql b/coderd/database/queries/proxies.sql index 722138938f1ae..95e6fd25e0ff1 100644 --- a/coderd/database/queries/proxies.sql +++ b/coderd/database/queries/proxies.sql @@ -36,6 +36,28 @@ SET WHERE id = @id; +-- name: UpdateWorkspaceProxy :one +-- This allows editing the properties of a workspace proxy. +UPDATE + workspace_proxies +SET + -- These values should always be provided. + name = @name, + display_name = @display_name, + icon = @icon, + -- Only update the token if a new one is provided. + -- So this is an optional field. + token_hashed_secret = CASE + WHEN length(@token_hashed_secret :: bytea) > 0 THEN @token_hashed_secret :: bytea + ELSE workspace_proxies.token_hashed_secret + END, + -- Always update this timestamp. + updated_at = Now() +WHERE + id = @id +RETURNING * +; + -- name: GetWorkspaceProxyByID :one SELECT * @@ -57,6 +79,14 @@ WHERE LIMIT 1; +-- name: GetWorkspaceProxies :many +SELECT + * +FROM + workspace_proxies +WHERE + deleted = false; + -- Finds a workspace proxy that has an access URL or app hostname that matches -- the provided hostname. This is to check if a hostname matches any workspace -- proxy. @@ -94,11 +124,3 @@ WHERE ) LIMIT 1; - --- name: GetWorkspaceProxies :many -SELECT - * -FROM - workspace_proxies -WHERE - deleted = false; diff --git a/codersdk/workspaceproxy.go b/codersdk/workspaceproxy.go index 8c8e49e63aebc..00d5a6db2ada8 100644 --- a/codersdk/workspaceproxy.go +++ b/codersdk/workspaceproxy.go @@ -110,6 +110,37 @@ func (c *Client) WorkspaceProxies(ctx context.Context) ([]WorkspaceProxy, error) return proxies, json.NewDecoder(res.Body).Decode(&proxies) } +type PatchWorkspaceProxy struct { + ID uuid.UUID `json:"id" format:"uuid" validate:"required"` + Name string `json:"name" validate:"required"` + DisplayName string `json:"display_name" validate:"required"` + Icon string `json:"icon" validate:"required"` + RegenerateToken bool `json:"regenerate_token"` +} + +type PatchWorkspaceProxyResponse struct { + Proxy WorkspaceProxy `json:"proxy" table:"proxy,recursive"` + // ProxyToken is only returned if 'RegenerateToken' is set. + ProxyToken string `json:"proxy_token" table:"proxy token,default_sort"` +} + +func (c *Client) PatchWorkspaceProxy(ctx context.Context, req PatchWorkspaceProxy) (WorkspaceProxy, error) { + res, err := c.Request(ctx, http.MethodPatch, + fmt.Sprintf("/api/v2/workspaceproxies/%s", req.ID.String()), + nil, + ) + if err != nil { + return WorkspaceProxy{}, xerrors.Errorf("make request: %w", err) + } + defer res.Body.Close() + + if res.StatusCode != http.StatusCreated { + return WorkspaceProxy{}, ReadBodyAsError(res) + } + var resp WorkspaceProxy + return resp, json.NewDecoder(res.Body).Decode(&resp) +} + func (c *Client) DeleteWorkspaceProxyByName(ctx context.Context, name string) error { res, err := c.Request(ctx, http.MethodDelete, fmt.Sprintf("/api/v2/workspaceproxies/%s", name), @@ -131,6 +162,28 @@ func (c *Client) DeleteWorkspaceProxyByID(ctx context.Context, id uuid.UUID) err return c.DeleteWorkspaceProxyByName(ctx, id.String()) } +func (c *Client) WorkspaceProxyByName(ctx context.Context, name string) (WorkspaceProxy, error) { + res, err := c.Request(ctx, http.MethodGet, + fmt.Sprintf("/api/v2/workspaceproxies/%s", name), + nil, + ) + if err != nil { + return WorkspaceProxy{}, xerrors.Errorf("make request: %w", err) + } + defer res.Body.Close() + + if res.StatusCode != http.StatusOK { + return WorkspaceProxy{}, ReadBodyAsError(res) + } + + var resp WorkspaceProxy + return resp, json.NewDecoder(res.Body).Decode(&resp) +} + +func (c *Client) WorkspaceProxyByID(ctx context.Context, id uuid.UUID) (WorkspaceProxy, error) { + return c.WorkspaceProxyByName(ctx, id.String()) +} + type RegionsResponse struct { Regions []Region `json:"regions"` } diff --git a/enterprise/cli/workspaceproxy.go b/enterprise/cli/workspaceproxy.go index 54ecc21928595..8a1f553a98f96 100644 --- a/enterprise/cli/workspaceproxy.go +++ b/enterprise/cli/workspaceproxy.go @@ -32,6 +32,83 @@ func (r *RootCmd) workspaceProxy() *clibase.Cmd { return cmd } +func (r *RootCmd) patchProxy() *clibase.Cmd { + var ( + proxyName string + displayName string + proxyIcon string + formatter = cliui.NewOutputFormatter( + // Text formatter should be human readable. + cliui.ChangeFormatterData(cliui.TextFormat(), func(data any) (any, error) { + response, ok := data.(codersdk.WorkspaceProxy) + if !ok { + return nil, xerrors.Errorf("unexpected type %T", data) + } + return fmt.Sprintf("Workspace Proxy %q updated successfully.", response.Name), nil + }), + cliui.JSONFormat(), + // Table formatter expects a slice, make a slice of one. + cliui.ChangeFormatterData(cliui.TableFormat([]codersdk.WorkspaceProxy{}, []string{"proxy name", "proxy url"}), + func(data any) (any, error) { + response, ok := data.(codersdk.WorkspaceProxy) + if !ok { + return nil, xerrors.Errorf("unexpected type %T", data) + } + return []codersdk.WorkspaceProxy{response}, nil + }), + ) + ) + client := new(codersdk.Client) + cmd := &clibase.Cmd{ + Use: "edit ", + Short: "Edit a workspace proxy", + Middleware: clibase.Chain( + clibase.RequireNArgs(1), + r.InitClient(client), + ), + Handler: func(inv *clibase.Invocation) error { + ctx := inv.Context() + // This is cheeky, but you can also use a uuid string in + // 'DeleteWorkspaceProxyByName' and it will work. + proxy, err := client.WorkspaceProxyByName(ctx, inv.Args[0]) + if err != nil { + return xerrors.Errorf("fetch workspace proxy %q: %w", inv.Args[0], err) + } + + updated, err := client.PatchWorkspaceProxy(ctx, codersdk.PatchWorkspaceProxy{ + ID: proxy.ID, + Name: proxyName, + DisplayName: displayName, + Icon: proxyIcon, + }) + + _, _ = formatter.Format(ctx, updated) + return nil + }, + } + + formatter.AttachOptions(&cmd.Options) + cmd.Options.Add( + clibase.Option{ + Flag: "name", + Description: "(Optional) Name of the proxy. This is used to identify the proxy.", + Value: clibase.StringOf(&proxyName), + }, + clibase.Option{ + Flag: "display-name", + Description: "(Optional) Display of the proxy. If omitted, the name is reused as the display name.", + Value: clibase.StringOf(&displayName), + }, + clibase.Option{ + Flag: "icon", + Description: "(Optional) Display icon of the proxy.", + Value: clibase.StringOf(&proxyIcon), + }, + ) + + return cmd +} + func (r *RootCmd) deleteProxy() *clibase.Cmd { client := new(codersdk.Client) cmd := &clibase.Cmd{ diff --git a/enterprise/coderd/coderd.go b/enterprise/coderd/coderd.go index 3d8ad12edea29..b71cb56e8efa6 100644 --- a/enterprise/coderd/coderd.go +++ b/enterprise/coderd/coderd.go @@ -120,6 +120,8 @@ func New(ctx context.Context, options *Options) (*API, error) { httpmw.ExtractWorkspaceProxyParam(api.Database), ) + r.Get("/", api.getWorkspaceProxy) + r.Patch("/", api.patchWorkspaceProxy) r.Delete("/", api.deleteWorkspaceProxy) }) }) diff --git a/enterprise/coderd/workspaceproxy.go b/enterprise/coderd/workspaceproxy.go index bd4e910838f49..0bad112456504 100644 --- a/enterprise/coderd/workspaceproxy.go +++ b/enterprise/coderd/workspaceproxy.go @@ -90,6 +90,78 @@ func (api *API) regions(rw http.ResponseWriter, r *http.Request) { }) } +// @Summary Update workspace proxy +// @ID update-workspace-proxy +// @Security CoderSessionToken +// @Produce json +// @Tags Enterprise +// @Param workspaceproxy path string true "Proxy ID or name" format(uuid) +// @Param request body codersdk.PatchWorkspaceProxy true "Update workspace proxy request" +// @Success 200 {object} codersdk.WorkspaceProxy +// @Router /workspaceproxies/{workspaceproxy} [patch] +func (api *API) patchWorkspaceProxy(rw http.ResponseWriter, r *http.Request) { + var ( + ctx = r.Context() + proxy = httpmw.WorkspaceProxyParam(r) + auditor = api.AGPL.Auditor.Load() + aReq, commitAudit = audit.InitRequest[database.WorkspaceProxy](rw, &audit.RequestParams{ + Audit: *auditor, + Log: api.Logger, + Request: r, + Action: database.AuditActionWrite, + }) + ) + aReq.Old = proxy + defer commitAudit() + + var req codersdk.PatchWorkspaceProxy + if !httpapi.Read(ctx, rw, r, &req) { + return + } + + var hashedSecret []byte + var fullToken string + if req.RegenerateToken { + var err error + fullToken, hashedSecret, err = generateWorkspaceProxyToken(proxy.ID) + if err != nil { + httpapi.InternalServerError(rw, err) + return + } + } + + updatedProxy, err := api.Database.UpdateWorkspaceProxy(ctx, database.UpdateWorkspaceProxyParams{ + Name: req.Name, + DisplayName: req.DisplayName, + Icon: req.Icon, + ID: proxy.ID, + // If hashedSecret is nil or empty, this will not update the secret. + TokenHashedSecret: hashedSecret, + }) + if httpapi.Is404Error(err) { + httpapi.ResourceNotFound(rw) + return + } + if err != nil { + httpapi.InternalServerError(rw, err) + return + } + + aReq.New = updatedProxy + status, ok := api.ProxyHealth.HealthStatus()[updatedProxy.ID] + if !ok { + // The proxy should have some status, but just in case. + status.Status = proxyhealth.Unknown + } + httpapi.Write(ctx, rw, http.StatusOK, codersdk.PatchWorkspaceProxyResponse{ + Proxy: convertProxy(updatedProxy, status), + ProxyToken: fullToken, + }) + + // Update the proxy cache. + go api.forceWorkspaceProxyHealthUpdate(api.ctx) +} + // @Summary Delete workspace proxy // @ID delete-workspace-proxy // @Security CoderSessionToken @@ -107,7 +179,7 @@ func (api *API) deleteWorkspaceProxy(rw http.ResponseWriter, r *http.Request) { Audit: *auditor, Log: api.Logger, Request: r, - Action: database.AuditActionCreate, + Action: database.AuditActionDelete, }) ) aReq.Old = proxy @@ -135,6 +207,23 @@ func (api *API) deleteWorkspaceProxy(rw http.ResponseWriter, r *http.Request) { go api.forceWorkspaceProxyHealthUpdate(api.ctx) } +// @Summary Get workspace proxy +// @ID get-workspace-proxy +// @Security CoderSessionToken +// @Produce json +// @Tags Enterprise +// @Param workspaceproxy path string true "Proxy ID or name" format(uuid) +// @Success 200 {object} codersdk.WorkspaceProxy +// @Router /workspaceproxies/{workspaceproxy} [get] +func (api *API) getWorkspaceProxy(rw http.ResponseWriter, r *http.Request) { + var ( + ctx = r.Context() + proxy = httpmw.WorkspaceProxyParam(r) + ) + + httpapi.Write(ctx, rw, http.StatusOK, convertProxy(proxy, api.ProxyHealth.HealthStatus()[proxy.ID])) +} + // @Summary Create workspace proxy // @ID create-workspace-proxy // @Security CoderSessionToken @@ -177,13 +266,11 @@ func (api *API) postWorkspaceProxy(rw http.ResponseWriter, r *http.Request) { } id := uuid.New() - secret, err := cryptorand.HexString(64) + fullToken, hashedSecret, err := generateWorkspaceProxyToken(id) if err != nil { httpapi.InternalServerError(rw, err) return } - hashedSecret := sha256.Sum256([]byte(secret)) - fullToken := fmt.Sprintf("%s:%s", id, secret) proxy, err := api.Database.InsertWorkspaceProxy(ctx, database.InsertWorkspaceProxyParams{ ID: id, @@ -467,6 +554,16 @@ func (api *API) reconnectingPTYSignedToken(rw http.ResponseWriter, r *http.Reque }) } +func generateWorkspaceProxyToken(id uuid.UUID) (token string, hashed []byte, err error) { + secret, err := cryptorand.HexString(64) + if err != nil { + return "", nil, xerrors.Errorf("generate token: %w", err) + } + hashedSecret := sha256.Sum256([]byte(secret)) + fullToken := fmt.Sprintf("%s:%s", id, secret) + return fullToken, hashedSecret[:], nil +} + func convertProxies(p []database.WorkspaceProxy, statuses map[uuid.UUID]proxyhealth.ProxyStatus) []codersdk.WorkspaceProxy { resp := make([]codersdk.WorkspaceProxy, 0, len(p)) for _, proxy := range p { From fe66e57d1ee610be58f5ad01b24878e0c9bfe569 Mon Sep 17 00:00:00 2001 From: Steven Masley Date: Thu, 4 May 2023 16:39:05 -0500 Subject: [PATCH 02/15] Add unit test --- codersdk/workspaceproxy.go | 11 +++++---- enterprise/coderd/workspaceproxy.go | 1 + enterprise/coderd/workspaceproxy_test.go | 29 ++++++++++++++++++++---- 3 files changed, 31 insertions(+), 10 deletions(-) diff --git a/codersdk/workspaceproxy.go b/codersdk/workspaceproxy.go index 00d5a6db2ada8..61ba8c3013e94 100644 --- a/codersdk/workspaceproxy.go +++ b/codersdk/workspaceproxy.go @@ -46,9 +46,10 @@ type ProxyHealthReport struct { } type WorkspaceProxy struct { - ID uuid.UUID `json:"id" format:"uuid" table:"id"` - Name string `json:"name" table:"name,default_sort"` - Icon string `json:"icon" table:"icon"` + ID uuid.UUID `json:"id" format:"uuid" table:"id"` + Name string `json:"name" table:"name,default_sort"` + DisplayName string `json:"display_name" table:"display_name""` + Icon string `json:"icon" table:"icon"` // Full url including scheme of the proxy api url: https://us.example.com URL string `json:"url" table:"url"` // WildcardHostname with the wildcard for subdomain based app hosting: *.us.example.com @@ -127,14 +128,14 @@ type PatchWorkspaceProxyResponse struct { func (c *Client) PatchWorkspaceProxy(ctx context.Context, req PatchWorkspaceProxy) (WorkspaceProxy, error) { res, err := c.Request(ctx, http.MethodPatch, fmt.Sprintf("/api/v2/workspaceproxies/%s", req.ID.String()), - nil, + req, ) if err != nil { return WorkspaceProxy{}, xerrors.Errorf("make request: %w", err) } defer res.Body.Close() - if res.StatusCode != http.StatusCreated { + if res.StatusCode != http.StatusOK { return WorkspaceProxy{}, ReadBodyAsError(res) } var resp WorkspaceProxy diff --git a/enterprise/coderd/workspaceproxy.go b/enterprise/coderd/workspaceproxy.go index 0bad112456504..133402fbf2d98 100644 --- a/enterprise/coderd/workspaceproxy.go +++ b/enterprise/coderd/workspaceproxy.go @@ -576,6 +576,7 @@ func convertProxy(p database.WorkspaceProxy, status proxyhealth.ProxyStatus) cod return codersdk.WorkspaceProxy{ ID: p.ID, Name: p.Name, + DisplayName: p.DisplayName, Icon: p.Icon, URL: p.Url, WildcardHostname: p.WildcardHostname, diff --git a/enterprise/coderd/workspaceproxy_test.go b/enterprise/coderd/workspaceproxy_test.go index 4a48a0b7349da..ad00b07d7f9ed 100644 --- a/enterprise/coderd/workspaceproxy_test.go +++ b/enterprise/coderd/workspaceproxy_test.go @@ -177,7 +177,7 @@ func TestRegions(t *testing.T) { func TestWorkspaceProxyCRUD(t *testing.T) { t.Parallel() - t.Run("create", func(t *testing.T) { + t.Run("CreateAndUpdate", func(t *testing.T) { t.Parallel() dv := coderdtest.DeploymentValues(t) @@ -203,14 +203,33 @@ func TestWorkspaceProxyCRUD(t *testing.T) { }) require.NoError(t, err) - proxies, err := client.WorkspaceProxies(ctx) + found, err := client.WorkspaceProxyByID(ctx, proxyRes.Proxy.ID) require.NoError(t, err) - require.Len(t, proxies, 1) - require.Equal(t, proxyRes.Proxy.ID, proxies[0].ID) + // This will be different, so set it to the same + found.Status = proxyRes.Proxy.Status + require.Equal(t, proxyRes.Proxy, found, "expected proxy") require.NotEmpty(t, proxyRes.ProxyToken) + + // Update the proxy + expName := namesgenerator.GetRandomName(1) + expDisplayName := namesgenerator.GetRandomName(1) + expIcon := namesgenerator.GetRandomName(1) + _, err = client.PatchWorkspaceProxy(ctx, codersdk.PatchWorkspaceProxy{ + ID: proxyRes.Proxy.ID, + Name: expName, + DisplayName: expDisplayName, + Icon: expIcon, + }) + require.NoError(t, err, "expected no error updating proxy") + + found, err = client.WorkspaceProxyByID(ctx, proxyRes.Proxy.ID) + require.NoError(t, err) + require.Equal(t, expName, found.Name, "name") + require.Equal(t, expDisplayName, found.DisplayName, "display name") + require.Equal(t, expIcon, found.Icon, "icon") }) - t.Run("delete", func(t *testing.T) { + t.Run("Delete", func(t *testing.T) { t.Parallel() dv := coderdtest.DeploymentValues(t) From 28deaca0f35ed4681d2175879d3bc7f7b1e2dca9 Mon Sep 17 00:00:00 2001 From: Steven Masley Date: Fri, 5 May 2023 09:54:04 -0500 Subject: [PATCH 03/15] Audit log proxy registers --- coderd/database/queries/proxies.sql | 4 ++-- enterprise/cli/workspaceproxy.go | 2 +- enterprise/coderd/workspaceproxy.go | 16 +++++++++++++--- 3 files changed, 16 insertions(+), 6 deletions(-) diff --git a/coderd/database/queries/proxies.sql b/coderd/database/queries/proxies.sql index 95e6fd25e0ff1..c6be3333fb9c6 100644 --- a/coderd/database/queries/proxies.sql +++ b/coderd/database/queries/proxies.sql @@ -51,7 +51,7 @@ SET WHEN length(@token_hashed_secret :: bytea) > 0 THEN @token_hashed_secret :: bytea ELSE workspace_proxies.token_hashed_secret END, - -- Always update this timestamp. + -- Always update this timestamp. updated_at = Now() WHERE id = @id @@ -85,7 +85,7 @@ SELECT FROM workspace_proxies WHERE - deleted = false; + deleted = false; -- Finds a workspace proxy that has an access URL or app hostname that matches -- the provided hostname. This is to check if a hostname matches any workspace diff --git a/enterprise/cli/workspaceproxy.go b/enterprise/cli/workspaceproxy.go index 8a1f553a98f96..a4cc6ed00d81a 100644 --- a/enterprise/cli/workspaceproxy.go +++ b/enterprise/cli/workspaceproxy.go @@ -96,7 +96,7 @@ func (r *RootCmd) patchProxy() *clibase.Cmd { }, clibase.Option{ Flag: "display-name", - Description: "(Optional) Display of the proxy. If omitted, the name is reused as the display name.", + Description: "(Optional) Display of the proxy. A more human friendly name to be displayed.", Value: clibase.StringOf(&displayName), }, clibase.Option{ diff --git a/enterprise/coderd/workspaceproxy.go b/enterprise/coderd/workspaceproxy.go index 133402fbf2d98..df0c9ae2b6e2b 100644 --- a/enterprise/coderd/workspaceproxy.go +++ b/enterprise/coderd/workspaceproxy.go @@ -410,9 +410,18 @@ func (api *API) workspaceProxyIssueSignedAppToken(rw http.ResponseWriter, r *htt // @x-apidocgen {"skip": true} func (api *API) workspaceProxyRegister(rw http.ResponseWriter, r *http.Request) { var ( - ctx = r.Context() - proxy = httpmw.WorkspaceProxy(r) + ctx = r.Context() + proxy = httpmw.WorkspaceProxy(r) + auditor = api.AGPL.Auditor.Load() + aReq, commitAudit = audit.InitRequest[database.WorkspaceProxy](rw, &audit.RequestParams{ + Audit: *auditor, + Log: api.Logger, + Request: r, + Action: database.AuditActionWrite, + }) ) + aReq.Old = proxy + defer commitAudit() var req wsproxysdk.RegisterWorkspaceProxyRequest if !httpapi.Read(ctx, rw, r, &req) { @@ -437,7 +446,7 @@ func (api *API) workspaceProxyRegister(rw http.ResponseWriter, r *http.Request) } } - _, err := api.Database.RegisterWorkspaceProxy(ctx, database.RegisterWorkspaceProxyParams{ + updatedProxy, err := api.Database.RegisterWorkspaceProxy(ctx, database.RegisterWorkspaceProxyParams{ ID: proxy.ID, Url: req.AccessURL, WildcardHostname: req.WildcardHostname, @@ -451,6 +460,7 @@ func (api *API) workspaceProxyRegister(rw http.ResponseWriter, r *http.Request) return } + aReq.New = updatedProxy httpapi.Write(ctx, rw, http.StatusCreated, wsproxysdk.RegisterWorkspaceProxyResponse{ AppSecurityKey: api.AppSecurityKey.String(), }) From ded5685ea00384b3e24e8c47c5590b2cb822c2f7 Mon Sep 17 00:00:00 2001 From: Steven Masley Date: Fri, 5 May 2023 10:07:52 -0500 Subject: [PATCH 04/15] Comment why the audit log does not work --- coderd/database/queries.sql.go | 4 ++-- codersdk/workspaceproxy.go | 2 +- enterprise/coderd/workspaceproxy.go | 9 ++++++--- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/coderd/database/queries.sql.go b/coderd/database/queries.sql.go index c64c7d4ced5d6..780ef48e890b9 100644 --- a/coderd/database/queries.sql.go +++ b/coderd/database/queries.sql.go @@ -2829,7 +2829,7 @@ SELECT FROM workspace_proxies WHERE - deleted = false + deleted = false ` func (q *sqlQuerier) GetWorkspaceProxies(ctx context.Context) ([]WorkspaceProxy, error) { @@ -3091,7 +3091,7 @@ SET WHEN length($4 :: bytea) > 0 THEN $4 :: bytea ELSE workspace_proxies.token_hashed_secret END, - -- Always update this timestamp. + -- Always update this timestamp. updated_at = Now() WHERE id = $5 diff --git a/codersdk/workspaceproxy.go b/codersdk/workspaceproxy.go index 61ba8c3013e94..047906eee2dbe 100644 --- a/codersdk/workspaceproxy.go +++ b/codersdk/workspaceproxy.go @@ -48,7 +48,7 @@ type ProxyHealthReport struct { type WorkspaceProxy struct { ID uuid.UUID `json:"id" format:"uuid" table:"id"` Name string `json:"name" table:"name,default_sort"` - DisplayName string `json:"display_name" table:"display_name""` + DisplayName string `json:"display_name" table:"display_name"` Icon string `json:"icon" table:"icon"` // Full url including scheme of the proxy api url: https://us.example.com URL string `json:"url" table:"url"` diff --git a/enterprise/coderd/workspaceproxy.go b/enterprise/coderd/workspaceproxy.go index df0c9ae2b6e2b..4a745c0cc5496 100644 --- a/enterprise/coderd/workspaceproxy.go +++ b/enterprise/coderd/workspaceproxy.go @@ -410,9 +410,12 @@ func (api *API) workspaceProxyIssueSignedAppToken(rw http.ResponseWriter, r *htt // @x-apidocgen {"skip": true} func (api *API) workspaceProxyRegister(rw http.ResponseWriter, r *http.Request) { var ( - ctx = r.Context() - proxy = httpmw.WorkspaceProxy(r) - auditor = api.AGPL.Auditor.Load() + ctx = r.Context() + proxy = httpmw.WorkspaceProxy(r) + auditor = api.AGPL.Auditor.Load() + // TODO: This audit log does not work because it has no user id + // associated with it. The audit log commitAudit() function ignores + // the audit log if there is no user id. aReq, commitAudit = audit.InitRequest[database.WorkspaceProxy](rw, &audit.RequestParams{ Audit: *auditor, Log: api.Logger, From ae5c41ee8cfcbd3ba08fd194bb06c6a006c151fa Mon Sep 17 00:00:00 2001 From: Steven Masley Date: Fri, 5 May 2023 10:18:52 -0500 Subject: [PATCH 05/15] Add proxy edit cli cmd --- enterprise/cli/workspaceproxy.go | 4 ++++ enterprise/coderd/coderd.go | 2 +- enterprise/coderd/workspaceproxy.go | 2 +- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/enterprise/cli/workspaceproxy.go b/enterprise/cli/workspaceproxy.go index a4cc6ed00d81a..366ddbaa8e942 100644 --- a/enterprise/cli/workspaceproxy.go +++ b/enterprise/cli/workspaceproxy.go @@ -26,6 +26,7 @@ func (r *RootCmd) workspaceProxy() *clibase.Cmd { r.createProxy(), r.deleteProxy(), r.listProxies(), + r.patchProxy(), }, } @@ -81,6 +82,9 @@ func (r *RootCmd) patchProxy() *clibase.Cmd { DisplayName: displayName, Icon: proxyIcon, }) + if err != nil { + return xerrors.Errorf("update workspace proxy %q: %w", inv.Args[0], err) + } _, _ = formatter.Format(ctx, updated) return nil diff --git a/enterprise/coderd/coderd.go b/enterprise/coderd/coderd.go index b71cb56e8efa6..ce3b86339ff12 100644 --- a/enterprise/coderd/coderd.go +++ b/enterprise/coderd/coderd.go @@ -120,7 +120,7 @@ func New(ctx context.Context, options *Options) (*API, error) { httpmw.ExtractWorkspaceProxyParam(api.Database), ) - r.Get("/", api.getWorkspaceProxy) + r.Get("/", api.workspaceProxy) r.Patch("/", api.patchWorkspaceProxy) r.Delete("/", api.deleteWorkspaceProxy) }) diff --git a/enterprise/coderd/workspaceproxy.go b/enterprise/coderd/workspaceproxy.go index 4a745c0cc5496..77c71e6ba5fc3 100644 --- a/enterprise/coderd/workspaceproxy.go +++ b/enterprise/coderd/workspaceproxy.go @@ -215,7 +215,7 @@ func (api *API) deleteWorkspaceProxy(rw http.ResponseWriter, r *http.Request) { // @Param workspaceproxy path string true "Proxy ID or name" format(uuid) // @Success 200 {object} codersdk.WorkspaceProxy // @Router /workspaceproxies/{workspaceproxy} [get] -func (api *API) getWorkspaceProxy(rw http.ResponseWriter, r *http.Request) { +func (api *API) workspaceProxy(rw http.ResponseWriter, r *http.Request) { var ( ctx = r.Context() proxy = httpmw.WorkspaceProxyParam(r) From 011505368cae8cf78d59edf134f59fd13af10624 Mon Sep 17 00:00:00 2001 From: Steven Masley Date: Fri, 5 May 2023 15:20:25 +0000 Subject: [PATCH 06/15] Make gen fmt lint --- coderd/apidoc/docs.go | 105 ++++++++++++++++++++++++++++ coderd/apidoc/swagger.json | 92 ++++++++++++++++++++++++ coderd/database/models.go | 2 +- coderd/database/querier.go | 2 +- coderd/database/queries.sql.go | 2 +- docs/api/enterprise.md | 123 +++++++++++++++++++++++++++++++++ docs/api/schemas.md | 24 +++++++ site/src/api/typesGenerated.ts | 16 +++++ 8 files changed, 363 insertions(+), 3 deletions(-) diff --git a/coderd/apidoc/docs.go b/coderd/apidoc/docs.go index 65642323a2f36..fb25959d53d78 100644 --- a/coderd/apidoc/docs.go +++ b/coderd/apidoc/docs.go @@ -5177,6 +5177,39 @@ const docTemplate = `{ } }, "/workspaceproxies/{workspaceproxy}": { + "get": { + "security": [ + { + "CoderSessionToken": [] + } + ], + "produces": [ + "application/json" + ], + "tags": [ + "Enterprise" + ], + "summary": "Get workspace proxy", + "operationId": "get-workspace-proxy", + "parameters": [ + { + "type": "string", + "format": "uuid", + "description": "Proxy ID or name", + "name": "workspaceproxy", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/codersdk.WorkspaceProxy" + } + } + } + }, "delete": { "security": [ { @@ -5209,6 +5242,48 @@ const docTemplate = `{ } } } + }, + "patch": { + "security": [ + { + "CoderSessionToken": [] + } + ], + "produces": [ + "application/json" + ], + "tags": [ + "Enterprise" + ], + "summary": "Update workspace proxy", + "operationId": "update-workspace-proxy", + "parameters": [ + { + "type": "string", + "format": "uuid", + "description": "Proxy ID or name", + "name": "workspaceproxy", + "in": "path", + "required": true + }, + { + "description": "Update workspace proxy request", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/codersdk.PatchWorkspaceProxy" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/codersdk.WorkspaceProxy" + } + } + } } }, "/workspaces": { @@ -8065,6 +8140,33 @@ const docTemplate = `{ } } }, + "codersdk.PatchWorkspaceProxy": { + "type": "object", + "required": [ + "display_name", + "icon", + "id", + "name" + ], + "properties": { + "display_name": { + "type": "string" + }, + "icon": { + "type": "string" + }, + "id": { + "type": "string", + "format": "uuid" + }, + "name": { + "type": "string" + }, + "regenerate_token": { + "type": "boolean" + } + } + }, "codersdk.PprofConfig": { "type": "object", "properties": { @@ -9840,6 +9942,9 @@ const docTemplate = `{ "deleted": { "type": "boolean" }, + "display_name": { + "type": "string" + }, "icon": { "type": "string" }, diff --git a/coderd/apidoc/swagger.json b/coderd/apidoc/swagger.json index f1d59dfa2cfc9..a862cd47a0761 100644 --- a/coderd/apidoc/swagger.json +++ b/coderd/apidoc/swagger.json @@ -4553,6 +4553,35 @@ } }, "/workspaceproxies/{workspaceproxy}": { + "get": { + "security": [ + { + "CoderSessionToken": [] + } + ], + "produces": ["application/json"], + "tags": ["Enterprise"], + "summary": "Get workspace proxy", + "operationId": "get-workspace-proxy", + "parameters": [ + { + "type": "string", + "format": "uuid", + "description": "Proxy ID or name", + "name": "workspaceproxy", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/codersdk.WorkspaceProxy" + } + } + } + }, "delete": { "security": [ { @@ -4581,6 +4610,44 @@ } } } + }, + "patch": { + "security": [ + { + "CoderSessionToken": [] + } + ], + "produces": ["application/json"], + "tags": ["Enterprise"], + "summary": "Update workspace proxy", + "operationId": "update-workspace-proxy", + "parameters": [ + { + "type": "string", + "format": "uuid", + "description": "Proxy ID or name", + "name": "workspaceproxy", + "in": "path", + "required": true + }, + { + "description": "Update workspace proxy request", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/codersdk.PatchWorkspaceProxy" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/codersdk.WorkspaceProxy" + } + } + } } }, "/workspaces": { @@ -7207,6 +7274,28 @@ } } }, + "codersdk.PatchWorkspaceProxy": { + "type": "object", + "required": ["display_name", "icon", "id", "name"], + "properties": { + "display_name": { + "type": "string" + }, + "icon": { + "type": "string" + }, + "id": { + "type": "string", + "format": "uuid" + }, + "name": { + "type": "string" + }, + "regenerate_token": { + "type": "boolean" + } + } + }, "codersdk.PprofConfig": { "type": "object", "properties": { @@ -8877,6 +8966,9 @@ "deleted": { "type": "boolean" }, + "display_name": { + "type": "string" + }, "icon": { "type": "string" }, diff --git a/coderd/database/models.go b/coderd/database/models.go index f6a74ad6e3343..61d4600ad88d6 100644 --- a/coderd/database/models.go +++ b/coderd/database/models.go @@ -1,6 +1,6 @@ // Code generated by sqlc. DO NOT EDIT. // versions: -// sqlc v1.18.0 +// sqlc v1.17.2 package database diff --git a/coderd/database/querier.go b/coderd/database/querier.go index 4a57f2552b812..e30207c7ba44e 100644 --- a/coderd/database/querier.go +++ b/coderd/database/querier.go @@ -1,6 +1,6 @@ // Code generated by sqlc. DO NOT EDIT. // versions: -// sqlc v1.18.0 +// sqlc v1.17.2 package database diff --git a/coderd/database/queries.sql.go b/coderd/database/queries.sql.go index 780ef48e890b9..adb511f50ea76 100644 --- a/coderd/database/queries.sql.go +++ b/coderd/database/queries.sql.go @@ -1,6 +1,6 @@ // Code generated by sqlc. DO NOT EDIT. // versions: -// sqlc v1.18.0 +// sqlc v1.17.2 package database diff --git a/docs/api/enterprise.md b/docs/api/enterprise.md index fbee85b9970f1..95def717b7f3e 100644 --- a/docs/api/enterprise.md +++ b/docs/api/enterprise.md @@ -1182,6 +1182,7 @@ curl -X GET http://coder-server:8080/api/v2/workspaceproxies \ { "created_at": "2019-08-24T14:15:22Z", "deleted": true, + "display_name": "string", "icon": "string", "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08", "name": "string", @@ -1215,6 +1216,7 @@ Status Code **200** | `[array item]` | array | false | | | | `» created_at` | string(date-time) | false | | | | `» deleted` | boolean | false | | | +| `» display_name` | string | false | | | | `» icon` | string | false | | | | `» id` | string(uuid) | false | | | | `» name` | string | false | | | @@ -1277,6 +1279,7 @@ curl -X POST http://coder-server:8080/api/v2/workspaceproxies \ { "created_at": "2019-08-24T14:15:22Z", "deleted": true, + "display_name": "string", "icon": "string", "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08", "name": "string", @@ -1302,6 +1305,59 @@ curl -X POST http://coder-server:8080/api/v2/workspaceproxies \ To perform this operation, you must be authenticated. [Learn more](authentication.md). +## Get workspace proxy + +### Code samples + +```shell +# Example request using curl +curl -X GET http://coder-server:8080/api/v2/workspaceproxies/{workspaceproxy} \ + -H 'Accept: application/json' \ + -H 'Coder-Session-Token: API_KEY' +``` + +`GET /workspaceproxies/{workspaceproxy}` + +### Parameters + +| Name | In | Type | Required | Description | +| ---------------- | ---- | ------------ | -------- | ---------------- | +| `workspaceproxy` | path | string(uuid) | true | Proxy ID or name | + +### Example responses + +> 200 Response + +```json +{ + "created_at": "2019-08-24T14:15:22Z", + "deleted": true, + "display_name": "string", + "icon": "string", + "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08", + "name": "string", + "status": { + "checked_at": "2019-08-24T14:15:22Z", + "report": { + "errors": ["string"], + "warnings": ["string"] + }, + "status": "reachable" + }, + "updated_at": "2019-08-24T14:15:22Z", + "url": "string", + "wildcard_hostname": "string" +} +``` + +### Responses + +| Status | Meaning | Description | Schema | +| ------ | ------------------------------------------------------- | ----------- | ------------------------------------------------------------ | +| 200 | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK | [codersdk.WorkspaceProxy](schemas.md#codersdkworkspaceproxy) | + +To perform this operation, you must be authenticated. [Learn more](authentication.md). + ## Delete workspace proxy ### Code samples @@ -1345,3 +1401,70 @@ curl -X DELETE http://coder-server:8080/api/v2/workspaceproxies/{workspaceproxy} | 200 | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK | [codersdk.Response](schemas.md#codersdkresponse) | To perform this operation, you must be authenticated. [Learn more](authentication.md). + +## Update workspace proxy + +### Code samples + +```shell +# Example request using curl +curl -X PATCH http://coder-server:8080/api/v2/workspaceproxies/{workspaceproxy} \ + -H 'Content-Type: application/json' \ + -H 'Accept: application/json' \ + -H 'Coder-Session-Token: API_KEY' +``` + +`PATCH /workspaceproxies/{workspaceproxy}` + +> Body parameter + +```json +{ + "display_name": "string", + "icon": "string", + "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08", + "name": "string", + "regenerate_token": true +} +``` + +### Parameters + +| Name | In | Type | Required | Description | +| ---------------- | ---- | ---------------------------------------------------------------------- | -------- | ------------------------------ | +| `workspaceproxy` | path | string(uuid) | true | Proxy ID or name | +| `body` | body | [codersdk.PatchWorkspaceProxy](schemas.md#codersdkpatchworkspaceproxy) | true | Update workspace proxy request | + +### Example responses + +> 200 Response + +```json +{ + "created_at": "2019-08-24T14:15:22Z", + "deleted": true, + "display_name": "string", + "icon": "string", + "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08", + "name": "string", + "status": { + "checked_at": "2019-08-24T14:15:22Z", + "report": { + "errors": ["string"], + "warnings": ["string"] + }, + "status": "reachable" + }, + "updated_at": "2019-08-24T14:15:22Z", + "url": "string", + "wildcard_hostname": "string" +} +``` + +### Responses + +| Status | Meaning | Description | Schema | +| ------ | ------------------------------------------------------- | ----------- | ------------------------------------------------------------ | +| 200 | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK | [codersdk.WorkspaceProxy](schemas.md#codersdkworkspaceproxy) | + +To perform this operation, you must be authenticated. [Learn more](authentication.md). diff --git a/docs/api/schemas.md b/docs/api/schemas.md index 0224980889bce..4e8521635e2a2 100644 --- a/docs/api/schemas.md +++ b/docs/api/schemas.md @@ -3208,6 +3208,28 @@ Parameter represents a set value for the scope. | ------ | ------ | -------- | ------------ | ----------- | | `name` | string | false | | | +## codersdk.PatchWorkspaceProxy + +```json +{ + "display_name": "string", + "icon": "string", + "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08", + "name": "string", + "regenerate_token": true +} +``` + +### Properties + +| Name | Type | Required | Restrictions | Description | +| ------------------ | ------- | -------- | ------------ | ----------- | +| `display_name` | string | true | | | +| `icon` | string | true | | | +| `id` | string | true | | | +| `name` | string | true | | | +| `regenerate_token` | boolean | false | | | + ## codersdk.PprofConfig ```json @@ -5321,6 +5343,7 @@ Parameter represents a set value for the scope. { "created_at": "2019-08-24T14:15:22Z", "deleted": true, + "display_name": "string", "icon": "string", "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08", "name": "string", @@ -5344,6 +5367,7 @@ Parameter represents a set value for the scope. | ------------------- | -------------------------------------------------------------- | -------- | ------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `created_at` | string | false | | | | `deleted` | boolean | false | | | +| `display_name` | string | false | | | | `icon` | string | false | | | | `id` | string | false | | | | `name` | string | false | | | diff --git a/site/src/api/typesGenerated.ts b/site/src/api/typesGenerated.ts index 0577976470c1e..ccad02e3578a1 100644 --- a/site/src/api/typesGenerated.ts +++ b/site/src/api/typesGenerated.ts @@ -630,6 +630,21 @@ export interface PatchTemplateVersionRequest { readonly name: string } +// From codersdk/workspaceproxy.go +export interface PatchWorkspaceProxy { + readonly id: string + readonly name: string + readonly display_name: string + readonly icon: string + readonly regenerate_token: boolean +} + +// From codersdk/workspaceproxy.go +export interface PatchWorkspaceProxyResponse { + readonly proxy: WorkspaceProxy + readonly proxy_token: string +} + // From codersdk/deployment.go export interface PprofConfig { readonly enable: boolean @@ -1258,6 +1273,7 @@ export interface WorkspaceOptions { export interface WorkspaceProxy { readonly id: string readonly name: string + readonly display_name: string readonly icon: string readonly url: string readonly wildcard_hostname: string From c2c12ae0828292361c3b9f6eb4e5a02926831646 Mon Sep 17 00:00:00 2001 From: Steven Masley Date: Fri, 5 May 2023 10:20:41 -0500 Subject: [PATCH 07/15] Comment out audit logs that do nothing --- enterprise/coderd/workspaceproxy.go | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/enterprise/coderd/workspaceproxy.go b/enterprise/coderd/workspaceproxy.go index 77c71e6ba5fc3..2742e552aa21f 100644 --- a/enterprise/coderd/workspaceproxy.go +++ b/enterprise/coderd/workspaceproxy.go @@ -410,21 +410,22 @@ func (api *API) workspaceProxyIssueSignedAppToken(rw http.ResponseWriter, r *htt // @x-apidocgen {"skip": true} func (api *API) workspaceProxyRegister(rw http.ResponseWriter, r *http.Request) { var ( - ctx = r.Context() - proxy = httpmw.WorkspaceProxy(r) - auditor = api.AGPL.Auditor.Load() + ctx = r.Context() + proxy = httpmw.WorkspaceProxy(r) // TODO: This audit log does not work because it has no user id // associated with it. The audit log commitAudit() function ignores - // the audit log if there is no user id. - aReq, commitAudit = audit.InitRequest[database.WorkspaceProxy](rw, &audit.RequestParams{ - Audit: *auditor, - Log: api.Logger, - Request: r, - Action: database.AuditActionWrite, - }) + // the audit log if there is no user id. We should find a solution + // to make sure this event is tracked. + //auditor = api.AGPL.Auditor.Load() + //aReq, commitAudit = audit.InitRequest[database.WorkspaceProxy](rw, &audit.RequestParams{ + // Audit: *auditor, + // Log: api.Logger, + // Request: r, + // Action: database.AuditActionWrite, + //}) ) - aReq.Old = proxy - defer commitAudit() + //aReq.Old = proxy + //defer commitAudit() var req wsproxysdk.RegisterWorkspaceProxyRequest if !httpapi.Read(ctx, rw, r, &req) { @@ -463,7 +464,7 @@ func (api *API) workspaceProxyRegister(rw http.ResponseWriter, r *http.Request) return } - aReq.New = updatedProxy + //aReq.New = updatedProxy httpapi.Write(ctx, rw, http.StatusCreated, wsproxysdk.RegisterWorkspaceProxyResponse{ AppSecurityKey: api.AppSecurityKey.String(), }) From 8f38d5287e25e08a8473ed3c2bb8bf5c2870a09d Mon Sep 17 00:00:00 2001 From: Steven Masley Date: Fri, 5 May 2023 13:15:06 -0500 Subject: [PATCH 08/15] Share formatter for similar commands --- enterprise/cli/workspaceproxy.go | 163 +++++++++++++++++++++------- enterprise/coderd/workspaceproxy.go | 6 +- 2 files changed, 128 insertions(+), 41 deletions(-) diff --git a/enterprise/cli/workspaceproxy.go b/enterprise/cli/workspaceproxy.go index 366ddbaa8e942..e064deecd2522 100644 --- a/enterprise/cli/workspaceproxy.go +++ b/enterprise/cli/workspaceproxy.go @@ -1,6 +1,7 @@ package cli import ( + "context" "fmt" "strings" @@ -33,6 +34,52 @@ func (r *RootCmd) workspaceProxy() *clibase.Cmd { return cmd } +func (r *RootCmd) regenerateProxy() *clibase.Cmd { + var ( + formatter = newUpdateProxyResponseFormatter() + ) + client := new(codersdk.Client) + cmd := &clibase.Cmd{ + Use: "regenerate-token ", + Short: "Regenerate a workspace proxy authentication token", + Middleware: clibase.Chain( + clibase.RequireNArgs(1), + r.InitClient(client), + ), + Handler: func(inv *clibase.Invocation) error { + ctx := inv.Context() + // This is cheeky, but you can also use a uuid string in + // 'DeleteWorkspaceProxyByName' and it will work. + proxy, err := client.WorkspaceProxyByName(ctx, inv.Args[0]) + if err != nil { + return xerrors.Errorf("fetch workspace proxy %q: %w", inv.Args[0], err) + } + + // Only regenerate the token + updated, err := client.PatchWorkspaceProxy(ctx, codersdk.PatchWorkspaceProxy{ + ID: proxy.ID, + Name: proxy.Name, + DisplayName: proxy.DisplayName, + Icon: proxy.Icon, + RegenerateToken: true, + }) + if err != nil { + return xerrors.Errorf("update workspace proxy %q: %w", inv.Args[0], err) + } + + output, err := formatter.Format(ctx, updated) + if err != nil { + return err + } + _, err = fmt.Fprintln(inv.Stdout, output) + return nil + }, + } + formatter.AttachOptions(&cmd.Options) + + return cmd +} + func (r *RootCmd) patchProxy() *clibase.Cmd { var ( proxyName string @@ -69,6 +116,10 @@ func (r *RootCmd) patchProxy() *clibase.Cmd { ), Handler: func(inv *clibase.Invocation) error { ctx := inv.Context() + if proxyIcon == "" && displayName == "" && proxyName == "" { + return xerrors.Errorf("specify at least one field to update") + } + // This is cheeky, but you can also use a uuid string in // 'DeleteWorkspaceProxyByName' and it will work. proxy, err := client.WorkspaceProxyByName(ctx, inv.Args[0]) @@ -76,6 +127,17 @@ func (r *RootCmd) patchProxy() *clibase.Cmd { return xerrors.Errorf("fetch workspace proxy %q: %w", inv.Args[0], err) } + // Use the existing values if the user didn't specify them. + if proxyName == "" { + proxyName = proxy.Name + } + if displayName == "" { + displayName = proxy.DisplayName + } + if proxyIcon == "" { + proxyIcon = proxy.Icon + } + updated, err := client.PatchWorkspaceProxy(ctx, codersdk.PatchWorkspaceProxy{ ID: proxy.ID, Name: proxyName, @@ -86,7 +148,11 @@ func (r *RootCmd) patchProxy() *clibase.Cmd { return xerrors.Errorf("update workspace proxy %q: %w", inv.Args[0], err) } - _, _ = formatter.Format(ctx, updated) + output, err := formatter.Format(ctx, updated.Proxy) + if err != nil { + return xerrors.Errorf("format response: %w", err) + } + _, err = fmt.Fprintln(inv.Stdout, output) return nil }, } @@ -142,28 +208,7 @@ func (r *RootCmd) createProxy() *clibase.Cmd { proxyName string displayName string proxyIcon string - onlyToken bool - formatter = cliui.NewOutputFormatter( - // Text formatter should be human readable. - cliui.ChangeFormatterData(cliui.TextFormat(), func(data any) (any, error) { - response, ok := data.(codersdk.CreateWorkspaceProxyResponse) - if !ok { - return nil, xerrors.Errorf("unexpected type %T", data) - } - return fmt.Sprintf("Workspace Proxy %q created successfully. Save this token, it will not be shown again."+ - "\nToken: %s", response.Proxy.Name, response.ProxyToken), nil - }), - cliui.JSONFormat(), - // Table formatter expects a slice, make a slice of one. - cliui.ChangeFormatterData(cliui.TableFormat([]codersdk.CreateWorkspaceProxyResponse{}, []string{"proxy name", "proxy url", "proxy token"}), - func(data any) (any, error) { - response, ok := data.(codersdk.CreateWorkspaceProxyResponse) - if !ok { - return nil, xerrors.Errorf("unexpected type %T", data) - } - return []codersdk.CreateWorkspaceProxyResponse{response}, nil - }), - ) + formatter = newUpdateProxyResponseFormatter() ) client := new(codersdk.Client) @@ -189,18 +234,12 @@ func (r *RootCmd) createProxy() *clibase.Cmd { return xerrors.Errorf("create workspace proxy: %w", err) } - var output string - if onlyToken { - output = resp.ProxyToken - } else { - output, err = formatter.Format(ctx, resp) - if err != nil { - return err - } + output, err := formatter.Format(ctx, resp) + if err != nil { + return err } - _, err = fmt.Fprintln(inv.Stdout, output) - return err + return nil }, } @@ -221,11 +260,6 @@ func (r *RootCmd) createProxy() *clibase.Cmd { Description: "Display icon of the proxy.", Value: clibase.StringOf(&proxyIcon), }, - clibase.Option{ - Flag: "only-token", - Description: "Only print the token. This is useful for scripting.", - Value: clibase.BoolOf(&onlyToken), - }, ) return cmd } @@ -286,3 +320,56 @@ func (r *RootCmd) listProxies() *clibase.Cmd { formatter.AttachOptions(&cmd.Options) return cmd } + +// updateProxyResponseFormatter is used for both create and regenerate proxy commands. +type updateProxyResponseFormatter struct { + onlyToken bool + formatter *cliui.OutputFormatter +} + +func (f *updateProxyResponseFormatter) Format(ctx context.Context, data codersdk.UpdateWorkspaceProxyResponse) (string, error) { + if f.onlyToken { + return data.ProxyToken, nil + } + return f.formatter.Format(ctx, data) +} + +func (f *updateProxyResponseFormatter) AttachOptions(opts *clibase.OptionSet) { + opts.Add( + clibase.Option{ + Flag: "only-token", + Description: "Only print the token. This is useful for scripting.", + Value: clibase.BoolOf(&f.onlyToken), + }, + ) + f.formatter.AttachOptions(opts) +} + +func newUpdateProxyResponseFormatter() *updateProxyResponseFormatter { + up := &updateProxyResponseFormatter{ + onlyToken: false, + formatter: cliui.NewOutputFormatter( + // Text formatter should be human readable. + cliui.ChangeFormatterData(cliui.TextFormat(), func(data any) (any, error) { + response, ok := data.(codersdk.UpdateWorkspaceProxyResponse) + if !ok { + return nil, xerrors.Errorf("unexpected type %T", data) + } + return fmt.Sprintf("Workspace Proxy %q created successfully. Save this token, it will not be shown again."+ + "\nToken: %s", response.Proxy.Name, response.ProxyToken), nil + }), + cliui.JSONFormat(), + // Table formatter expects a slice, make a slice of one. + cliui.ChangeFormatterData(cliui.TableFormat([]codersdk.UpdateWorkspaceProxyResponse{}, []string{"proxy name", "proxy url", "proxy token"}), + func(data any) (any, error) { + response, ok := data.(codersdk.UpdateWorkspaceProxyResponse) + if !ok { + return nil, xerrors.Errorf("unexpected type %T", data) + } + return []codersdk.UpdateWorkspaceProxyResponse{response}, nil + }), + ), + } + + return up +} diff --git a/enterprise/coderd/workspaceproxy.go b/enterprise/coderd/workspaceproxy.go index 2742e552aa21f..b90c630d5eb8d 100644 --- a/enterprise/coderd/workspaceproxy.go +++ b/enterprise/coderd/workspaceproxy.go @@ -153,7 +153,7 @@ func (api *API) patchWorkspaceProxy(rw http.ResponseWriter, r *http.Request) { // The proxy should have some status, but just in case. status.Status = proxyhealth.Unknown } - httpapi.Write(ctx, rw, http.StatusOK, codersdk.PatchWorkspaceProxyResponse{ + httpapi.Write(ctx, rw, http.StatusOK, codersdk.UpdateWorkspaceProxyResponse{ Proxy: convertProxy(updatedProxy, status), ProxyToken: fullToken, }) @@ -293,7 +293,7 @@ func (api *API) postWorkspaceProxy(rw http.ResponseWriter, r *http.Request) { } aReq.New = proxy - httpapi.Write(ctx, rw, http.StatusCreated, codersdk.CreateWorkspaceProxyResponse{ + httpapi.Write(ctx, rw, http.StatusCreated, codersdk.UpdateWorkspaceProxyResponse{ Proxy: convertProxy(proxy, proxyhealth.ProxyStatus{ Proxy: proxy, CheckedAt: time.Now(), @@ -450,7 +450,7 @@ func (api *API) workspaceProxyRegister(rw http.ResponseWriter, r *http.Request) } } - updatedProxy, err := api.Database.RegisterWorkspaceProxy(ctx, database.RegisterWorkspaceProxyParams{ + _, err := api.Database.RegisterWorkspaceProxy(ctx, database.RegisterWorkspaceProxyParams{ ID: proxy.ID, Url: req.AccessURL, WildcardHostname: req.WildcardHostname, From eaeaae5cb0845d937dd08c6da95c2c12a52dafe1 Mon Sep 17 00:00:00 2001 From: Steven Masley Date: Fri, 5 May 2023 13:18:24 -0500 Subject: [PATCH 09/15] fixup! Share formatter for similar commands --- codersdk/workspaceproxy.go | 24 +++++++++--------------- enterprise/cli/workspaceproxy.go | 3 ++- site/src/api/typesGenerated.ts | 18 ++++++------------ 3 files changed, 17 insertions(+), 28 deletions(-) diff --git a/codersdk/workspaceproxy.go b/codersdk/workspaceproxy.go index 047906eee2dbe..95eea1b3a17a7 100644 --- a/codersdk/workspaceproxy.go +++ b/codersdk/workspaceproxy.go @@ -70,26 +70,26 @@ type CreateWorkspaceProxyRequest struct { Icon string `json:"icon"` } -type CreateWorkspaceProxyResponse struct { +type UpdateWorkspaceProxyResponse struct { Proxy WorkspaceProxy `json:"proxy" table:"proxy,recursive"` // The recursive table sort is not working very well. ProxyToken string `json:"proxy_token" table:"proxy token,default_sort"` } -func (c *Client) CreateWorkspaceProxy(ctx context.Context, req CreateWorkspaceProxyRequest) (CreateWorkspaceProxyResponse, error) { +func (c *Client) CreateWorkspaceProxy(ctx context.Context, req CreateWorkspaceProxyRequest) (UpdateWorkspaceProxyResponse, error) { res, err := c.Request(ctx, http.MethodPost, "/api/v2/workspaceproxies", req, ) if err != nil { - return CreateWorkspaceProxyResponse{}, xerrors.Errorf("make request: %w", err) + return UpdateWorkspaceProxyResponse{}, xerrors.Errorf("make request: %w", err) } defer res.Body.Close() if res.StatusCode != http.StatusCreated { - return CreateWorkspaceProxyResponse{}, ReadBodyAsError(res) + return UpdateWorkspaceProxyResponse{}, ReadBodyAsError(res) } - var resp CreateWorkspaceProxyResponse + var resp UpdateWorkspaceProxyResponse return resp, json.NewDecoder(res.Body).Decode(&resp) } @@ -119,26 +119,20 @@ type PatchWorkspaceProxy struct { RegenerateToken bool `json:"regenerate_token"` } -type PatchWorkspaceProxyResponse struct { - Proxy WorkspaceProxy `json:"proxy" table:"proxy,recursive"` - // ProxyToken is only returned if 'RegenerateToken' is set. - ProxyToken string `json:"proxy_token" table:"proxy token,default_sort"` -} - -func (c *Client) PatchWorkspaceProxy(ctx context.Context, req PatchWorkspaceProxy) (WorkspaceProxy, error) { +func (c *Client) PatchWorkspaceProxy(ctx context.Context, req PatchWorkspaceProxy) (UpdateWorkspaceProxyResponse, error) { res, err := c.Request(ctx, http.MethodPatch, fmt.Sprintf("/api/v2/workspaceproxies/%s", req.ID.String()), req, ) if err != nil { - return WorkspaceProxy{}, xerrors.Errorf("make request: %w", err) + return UpdateWorkspaceProxyResponse{}, xerrors.Errorf("make request: %w", err) } defer res.Body.Close() if res.StatusCode != http.StatusOK { - return WorkspaceProxy{}, ReadBodyAsError(res) + return UpdateWorkspaceProxyResponse{}, ReadBodyAsError(res) } - var resp WorkspaceProxy + var resp UpdateWorkspaceProxyResponse return resp, json.NewDecoder(res.Body).Decode(&resp) } diff --git a/enterprise/cli/workspaceproxy.go b/enterprise/cli/workspaceproxy.go index e064deecd2522..7674e7a2bfbd6 100644 --- a/enterprise/cli/workspaceproxy.go +++ b/enterprise/cli/workspaceproxy.go @@ -28,13 +28,14 @@ func (r *RootCmd) workspaceProxy() *clibase.Cmd { r.deleteProxy(), r.listProxies(), r.patchProxy(), + r.regenerateProxyToken(), }, } return cmd } -func (r *RootCmd) regenerateProxy() *clibase.Cmd { +func (r *RootCmd) regenerateProxyToken() *clibase.Cmd { var ( formatter = newUpdateProxyResponseFormatter() ) diff --git a/site/src/api/typesGenerated.ts b/site/src/api/typesGenerated.ts index ccad02e3578a1..dea32f404f492 100644 --- a/site/src/api/typesGenerated.ts +++ b/site/src/api/typesGenerated.ts @@ -262,12 +262,6 @@ export interface CreateWorkspaceProxyRequest { readonly icon: string } -// From codersdk/workspaceproxy.go -export interface CreateWorkspaceProxyResponse { - readonly proxy: WorkspaceProxy - readonly proxy_token: string -} - // From codersdk/organizations.go export interface CreateWorkspaceRequest { readonly template_id: string @@ -639,12 +633,6 @@ export interface PatchWorkspaceProxy { readonly regenerate_token: boolean } -// From codersdk/workspaceproxy.go -export interface PatchWorkspaceProxyResponse { - readonly proxy: WorkspaceProxy - readonly proxy_token: string -} - // From codersdk/deployment.go export interface PprofConfig { readonly enable: boolean @@ -1043,6 +1031,12 @@ export interface UpdateWorkspaceAutostartRequest { readonly schedule?: string } +// From codersdk/workspaceproxy.go +export interface UpdateWorkspaceProxyResponse { + readonly proxy: WorkspaceProxy + readonly proxy_token: string +} + // From codersdk/workspaces.go export interface UpdateWorkspaceRequest { readonly name?: string From 529d4650fcdc41342ed7e6d3e6ed15f5120cf74b Mon Sep 17 00:00:00 2001 From: Steven Masley Date: Fri, 5 May 2023 13:19:06 -0500 Subject: [PATCH 10/15] Fix text --- enterprise/cli/workspaceproxy.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/enterprise/cli/workspaceproxy.go b/enterprise/cli/workspaceproxy.go index 7674e7a2bfbd6..72f314fcca9cd 100644 --- a/enterprise/cli/workspaceproxy.go +++ b/enterprise/cli/workspaceproxy.go @@ -41,8 +41,9 @@ func (r *RootCmd) regenerateProxyToken() *clibase.Cmd { ) client := new(codersdk.Client) cmd := &clibase.Cmd{ - Use: "regenerate-token ", - Short: "Regenerate a workspace proxy authentication token", + Use: "regenerate-token ", + Short: "Regenerate a workspace proxy authentication token. " + + "This will invalidate the existing authentication token.", Middleware: clibase.Chain( clibase.RequireNArgs(1), r.InitClient(client), From 4865ff8e9da219945933a0f13bfae3a1871b31d2 Mon Sep 17 00:00:00 2001 From: Steven Masley Date: Fri, 5 May 2023 13:34:34 -0500 Subject: [PATCH 11/15] Return the right error --- enterprise/cli/workspaceproxy.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/enterprise/cli/workspaceproxy.go b/enterprise/cli/workspaceproxy.go index 5dc4f00a1a16f..de4f41bbc57ed 100644 --- a/enterprise/cli/workspaceproxy.go +++ b/enterprise/cli/workspaceproxy.go @@ -74,7 +74,7 @@ func (r *RootCmd) regenerateProxyToken() *clibase.Cmd { return err } _, err = fmt.Fprintln(inv.Stdout, output) - return nil + return err }, } formatter.AttachOptions(&cmd.Options) @@ -155,7 +155,7 @@ func (r *RootCmd) patchProxy() *clibase.Cmd { return xerrors.Errorf("format response: %w", err) } _, err = fmt.Fprintln(inv.Stdout, output) - return nil + return err }, } @@ -241,7 +241,7 @@ func (r *RootCmd) createProxy() *clibase.Cmd { return err } _, err = fmt.Fprintln(inv.Stdout, output) - return nil + return err }, } From a63c9039b01777402ba3ef14e7709fd275364237 Mon Sep 17 00:00:00 2001 From: Steven Masley Date: Fri, 5 May 2023 18:35:01 +0000 Subject: [PATCH 12/15] Fmt --- enterprise/cli/workspaceproxy.go | 4 +--- enterprise/coderd/workspaceproxy.go | 8 ++++---- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/enterprise/cli/workspaceproxy.go b/enterprise/cli/workspaceproxy.go index de4f41bbc57ed..fac487dce8021 100644 --- a/enterprise/cli/workspaceproxy.go +++ b/enterprise/cli/workspaceproxy.go @@ -36,9 +36,7 @@ func (r *RootCmd) workspaceProxy() *clibase.Cmd { } func (r *RootCmd) regenerateProxyToken() *clibase.Cmd { - var ( - formatter = newUpdateProxyResponseFormatter() - ) + formatter := newUpdateProxyResponseFormatter() client := new(codersdk.Client) cmd := &clibase.Cmd{ Use: "regenerate-token ", diff --git a/enterprise/coderd/workspaceproxy.go b/enterprise/coderd/workspaceproxy.go index b90c630d5eb8d..1ecc8b4b97908 100644 --- a/enterprise/coderd/workspaceproxy.go +++ b/enterprise/coderd/workspaceproxy.go @@ -416,7 +416,7 @@ func (api *API) workspaceProxyRegister(rw http.ResponseWriter, r *http.Request) // associated with it. The audit log commitAudit() function ignores // the audit log if there is no user id. We should find a solution // to make sure this event is tracked. - //auditor = api.AGPL.Auditor.Load() + // auditor = api.AGPL.Auditor.Load() //aReq, commitAudit = audit.InitRequest[database.WorkspaceProxy](rw, &audit.RequestParams{ // Audit: *auditor, // Log: api.Logger, @@ -424,8 +424,8 @@ func (api *API) workspaceProxyRegister(rw http.ResponseWriter, r *http.Request) // Action: database.AuditActionWrite, //}) ) - //aReq.Old = proxy - //defer commitAudit() + // aReq.Old = proxy + // defer commitAudit() var req wsproxysdk.RegisterWorkspaceProxyRequest if !httpapi.Read(ctx, rw, r, &req) { @@ -464,7 +464,7 @@ func (api *API) workspaceProxyRegister(rw http.ResponseWriter, r *http.Request) return } - //aReq.New = updatedProxy + // aReq.New = updatedProxy httpapi.Write(ctx, rw, http.StatusCreated, wsproxysdk.RegisterWorkspaceProxyResponse{ AppSecurityKey: api.AppSecurityKey.String(), }) From 7ceb7a58cfa12bfc061f07748e2aa7fbf7228375 Mon Sep 17 00:00:00 2001 From: Steven Masley Date: Fri, 5 May 2023 13:41:33 -0500 Subject: [PATCH 13/15] Fix swagger tags --- enterprise/coderd/workspaceproxy.go | 1 + 1 file changed, 1 insertion(+) diff --git a/enterprise/coderd/workspaceproxy.go b/enterprise/coderd/workspaceproxy.go index 1ecc8b4b97908..d696aa2331fc5 100644 --- a/enterprise/coderd/workspaceproxy.go +++ b/enterprise/coderd/workspaceproxy.go @@ -93,6 +93,7 @@ func (api *API) regions(rw http.ResponseWriter, r *http.Request) { // @Summary Update workspace proxy // @ID update-workspace-proxy // @Security CoderSessionToken +// @Accept json // @Produce json // @Tags Enterprise // @Param workspaceproxy path string true "Proxy ID or name" format(uuid) From 41ca95f037d7808342c1fff16f4aa3d2a8303b40 Mon Sep 17 00:00:00 2001 From: Steven Masley Date: Mon, 8 May 2023 13:30:52 +0000 Subject: [PATCH 14/15] Fmt --- enterprise/coderd/workspaceproxy.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/enterprise/coderd/workspaceproxy.go b/enterprise/coderd/workspaceproxy.go index d696aa2331fc5..e8b24bb2c7f48 100644 --- a/enterprise/coderd/workspaceproxy.go +++ b/enterprise/coderd/workspaceproxy.go @@ -418,7 +418,7 @@ func (api *API) workspaceProxyRegister(rw http.ResponseWriter, r *http.Request) // the audit log if there is no user id. We should find a solution // to make sure this event is tracked. // auditor = api.AGPL.Auditor.Load() - //aReq, commitAudit = audit.InitRequest[database.WorkspaceProxy](rw, &audit.RequestParams{ + // aReq, commitAudit = audit.InitRequest[database.WorkspaceProxy](rw, &audit.RequestParams{ // Audit: *auditor, // Log: api.Logger, // Request: r, From c0de34a937a77031bcfc97f78600d0776a455307 Mon Sep 17 00:00:00 2001 From: Steven Masley Date: Mon, 8 May 2023 13:54:44 +0000 Subject: [PATCH 15/15] Make gen --- coderd/apidoc/docs.go | 3 +++ coderd/apidoc/swagger.json | 1 + 2 files changed, 4 insertions(+) diff --git a/coderd/apidoc/docs.go b/coderd/apidoc/docs.go index 89e0b82c69fca..4ebc3112a188d 100644 --- a/coderd/apidoc/docs.go +++ b/coderd/apidoc/docs.go @@ -5249,6 +5249,9 @@ const docTemplate = `{ "CoderSessionToken": [] } ], + "consumes": [ + "application/json" + ], "produces": [ "application/json" ], diff --git a/coderd/apidoc/swagger.json b/coderd/apidoc/swagger.json index 96eb52718d707..cdf0f5972a106 100644 --- a/coderd/apidoc/swagger.json +++ b/coderd/apidoc/swagger.json @@ -4617,6 +4617,7 @@ "CoderSessionToken": [] } ], + "consumes": ["application/json"], "produces": ["application/json"], "tags": ["Enterprise"], "summary": "Update workspace proxy",