Commit Graph
37 Commits
Author SHA1 Message Date
Bobby HoandTracy Johnson 4245e4e378 feat: expose dynamic client registration in deployment settings (#27480)
Adds the admin-controlled OAuth2 Dynamic Client Registration setting
landed by #27316 (`GET`/`PUT /api/v2/oauth2-provider/settings`) to the
OAuth2 Applications deployment settings page, since it was previously
only reachable via the API or `coder oauth2-provider dcr
enable|disable`.

The page is now tabbed, **Applications** and **Settings**, so DCR has a
home that further OAuth2 settings can share (an Initial Access Token
setting is a likely next one). The active tab is backed by a `tab`
search param, so `?tab=settings` links straight to it, and an
unpermitted deep link falls back to **Applications** rather than
selecting nothing. On the Settings tab, DCR renders as a titled section
with a description, an `Enabled` badge when active, and an
Enable/Disable button.

Enabling opens a confirmation dialog, since it lets any OAuth2 client
self-register against the deployment without prior admin approval (RFC
7591). Disabling is immediate, no confirmation.

The control is a button rather than a switch on design feedback: a
switch reads as an immediate on/off flip, which conflicts with a
confirmation dialog standing in front of it, and it left the only
explanation of the risk inside a dialog that disappears. A button
carries the confirmation step without misrepresenting what a click
costs, the always-visible description explains the setting on the page,
and the `Enabled` badge gives the active state a persistent indicator.
The layout follows Tracy's mockup on `tj/oauth2-apps-pagination`; the
apps-table pagination work that shares that branch is deliberately not
included here.

Visibility and editability are gated on the same
`ResourceDeploymentConfig` RBAC checks the endpoint itself enforces
(`viewDeploymentConfig` / `editDeploymentConfig`), not a separate
hardcoded check. The view takes the settings values as one optional
`settings` prop, absent when the viewer lacks `viewDeploymentConfig`, so
"cannot view" is the shape of the prop rather than a flag the caller
keeps consistent with the values beside it, and the tab is not rendered
at all.

Closes https://github.com/coder/coder/issues/27432

## Where this sits in the request path

```mermaid
sequenceDiagram
    autonumber
    actor Admin
    participant View as OAuth2AppsSettingsPageView<br/>(Tabs + Enable/Disable + Dialog)
    participant Page as OAuth2AppsSettingsPage<br/>(React Query)
    participant S as coderd

    Note over Page: On mount
    Page->>S: GET /api/v2/oauth2-provider/settings
    S-->>Page: { dynamic_client_registration_enabled }
    Page-->>View: settings: { dynamicClientRegistrationEnabled, canEdit, ... }

    Note over Admin,View: Admin opens the Settings tab and enables DCR
    Admin->>View: click "Enable"
    View->>View: open confirmation dialog<br/>(no request sent yet)
    Admin->>View: click Confirm
    View->>Page: settings.onDynamicClientRegistrationChange(true)
    Page->>S: PUT /api/v2/oauth2-provider/settings<br/>{dynamic_client_registration_enabled: true}
    S-->>Page: 200 OK (audited)
    Page->>S: GET /api/v2/oauth2-provider/settings (refetch)
    S-->>Page: { dynamic_client_registration_enabled: true }
    Page-->>View: section shows the "Enabled" badge and a Disable button

    Note over Admin,View: Admin disables DCR
    Admin->>View: click "Disable"
    View->>Page: onDynamicClientRegistrationChange(false)<br/>(no dialog, disable is immediate)
    Page->>S: PUT ... {dynamic_client_registration_enabled: false}
    S-->>Page: 200 OK (audited)
```

## Files changed

All 10 files are hand-written; nothing in this PR is `make gen` output.

| File | What changed |
|---|---|
| `site/src/api/api.ts` | New
`getOAuth2ProviderSettings`/`putOAuth2ProviderSettings` methods, thin
typed wrappers around the two endpoints #27316 added to `main`. |
| `site/src/api/api.test.ts` | Covers both methods against the request
they issue and the error they propagate. |
| `site/src/api/queries/oauth2.ts` | A `getSettings` query and a
`putSettings` mutation that invalidates the settings key on success.
Both the app and settings keys now derive from a shared
`oauth2ProviderKey` constant. |
| `site/src/api/queries/oauth2.test.ts` | 4 tests: the key nesting, both
delegations, and that a successful update invalidates the settings key
without touching app queries. |
| `.../OAuth2AppsSettingsPage.tsx` | Wires query and mutation into the
page and passes the settings values down as one object, or omits it
entirely without `viewDeploymentConfig`. The apps error stays its own
prop, since the view gates the applications empty state on it. |
| `.../OAuth2AppsSettingsPageView.tsx` | `Tabs` splitting Applications
from Settings. The settings tab distinguishes loading, failed, and a
value the server omitted rather than rendering nothing, and the header's
"Add application" action is scoped to the applications tab. |
| `.../OAuth2AppsSettingsPageView.stories.tsx` | 14 stories, covering
the tab wiring, both permission boundaries, the header action's scope,
and the settings tab's loading, fetch-error, update-error, and
value-omitted states. |
| `.../DynamicClientRegistrationSetting.tsx` | The section itself:
heading, description including what disabling does not undo, `Enabled`
badge, a permission explanation when the viewer cannot edit, and one
button that confirms only in the enable direction. |
| `.../DynamicClientRegistrationSetting.stories.tsx` | 11 stories,
including focus surviving an in-flight request and the dialog ignoring a
value that changes underneath it. |
| `docs/admin/integrations/oauth2-provider.md` | Adds the web UI route
to the DCR section, which previously enumerated only the CLI and the
management API. |

## Suggested review order

Follows the direction data actually flows, from the raw HTTP call up to
the rendered section.

1. **`site/src/api/api.ts`**: the two new methods. Confirms they match
the `codersdk.OAuth2ProviderSettings` shape #27316 landed and sit next
to the existing OAuth2 app methods they mirror.
2. **`site/src/api/queries/oauth2.ts`**: the query/mutation pair. The
mutation's `onSuccess` → `invalidateQueries` is the one detail worth
double-checking: it's what makes the on-screen state catch up with what
was just saved, rather than trusting the PUT payload.
3. **`OAuth2AppsSettingsPage.tsx`**: the container. Check the two
separate permission gates (`viewDeploymentConfig` on the query's
`enabled` option, `editDeploymentConfig` on the button's editability)
match the RBAC the backend enforces.
4. **`OAuth2AppsSettingsPageView.tsx`**: the tabs and the settings tab's
four states. The `settings` prop being optional is what hides the tab;
the error inside the tab is deliberately separate from the page-level
`error`, which gates the applications empty state.
5. **`DynamicClientRegistrationSetting.tsx`**: the section. Two things
worth reading closely: the enable path opens the dialog while the
disable path calls straight through, and lacking permission uses the
native `disabled` attribute while an in-flight request uses
`aria-disabled`, so a keyboard user is not blurred mid-flip.
6. **The two story files**: read last, as they exercise everything above
without a real server. The dialog stories query
`canvasElement.ownerDocument.body` rather than `canvasElement`, since
the dialog renders into a portal attached to `<body>`.

## Deliberately not in this PR

- **ENG-3116**: the applications list cannot distinguish self-registered
clients from admin-created ones. Surfacing that needs a new field on
`codersdk.OAuth2ProviderApp`, which is an API addition this PR does not
need.
- **ENG-3118**: reusing the shared `EnabledBadge` and `SettingsHeader`
primitives for this section. Both hinge on what the mockup intends, and
the badge in particular is a visible change either here or on the four
other pages that share it.

## Screenshots

Default (disabled):
<img width="1676" height="497" alt="image"
src="https://github.com/user-attachments/assets/cfa60266-8678-410e-9577-16ef474491e3"
/>



Enabling (confirmation dialog):

<img width="1661" height="558" alt="image"
src="https://github.com/user-attachments/assets/a7d54fdd-f65d-4fec-9ed9-3bfdcfdae5be"
/>



Enabled:

<img width="1666" height="559" alt="image"
src="https://github.com/user-attachments/assets/d39251c2-771c-4608-81c2-dda151b35c3d"
/>

---------

Co-authored-by: Tracy Johnson <tracy@coder.com>
2026-08-03 08:29:35 -07:00
Zach 85984ff142 feat: add enable/disable support for user secrets (#27537)
Users can now disable a secret to stop it from being injected into
workspaces without deleting it, and re-enable it later. Disabled secrets
stay visible and editable everywhere they already appear.

An enabled secret must have at least one injection target; a secret with
no target can be stored only while disabled. Existing target-less secrets
are migrated to disabled to preserve current behavior.

Support spans the REST API, SDK, CLI, dashboard, and audit log.
2026-07-28 09:58:33 -06:00
McKayla はな 00d134ebfd chore: remove classic parameter UI (#25014) 2026-07-27 19:02:28 -06:00
Ehab Younes 6ec45f75c6 chore(site): replace handrolled AI spend types with generated types (#27342)
The groups and group members pages consumed AI spend through local ai_cost_control wrapper types with TODOs to adopt the generated contract. Both spend endpoints are now live, so this switches to the generated types and hardens the fetch path.

- Use OrganizationGroupsAISpend and GroupMembersAISpend from typesGenerated for the org groups and group members spend endpoints
- Fetch identity and spend separately, joining by group_id/user_id at the container so each row gets one enriched object
- Batch spend requests at the backend cap of 100 IDs in the API client and merge the responses, with table-driven tests covering both endpoints
- Treat a null effective_group_id as a budget managed by a group in another org: render an em-dash with an info tooltip and skip the group name lookup instead of firing an empty-ID request

Closes AIGOV-509
2026-07-22 12:17:22 +03:00
Jake Howell b4332443b3 fix: resolve stopWorkspaceIfRunning common path (#25639)
Closes #24333

This was a common setup in `updateWorkspace()` but was not appropriately
ported to `changeWorkspaceVersion()`. Some tests have been added also to
ensure this works 🙂 Simple smooth and easy.
2026-05-27 00:01:10 +10:00
Michael Suchacz ca1f6b19a2 feat: remove legacy chat provider tables (#25416) 2026-05-22 09:50:01 +02:00
Danielle Maywood e27d917135 feat: enable chat sharing (#24987) 2026-05-20 18:45:44 +01:00
dylanhuff-at-coder 441854daa8 feat: add user secrets client utilities (#25370)
Add frontend API methods, mocks, and form helpers for user secrets CRUD. The new client methods cover list, get, create, update, and delete requests, including URL encoding for secret names used in route paths.

Add user secret form utilities for create and update payload construction, required create field checks, and structured API validation error mapping back to form fields. User secret name validation now lives in codersdk with tests, and coderd returns field-level validation errors for create, update, and uniqueness conflicts so the frontend can show backend-owned validation results consistently.
2026-05-19 09:30:31 -07:00
Danielle Maywood aede045549 chore: bump @biomejs/biome from 2.2 to 2.4.10 (#24074) 2026-04-07 12:22:18 +01:00
Kayla はな aa81238cd0 chore: modernize all typescript imports (#23511) 2026-03-26 16:04:24 -06:00
Danielle Maywood ed19a3a08e refactor(site): move experimental endpoints to ExperimentalApiMethods (#23449) 2026-03-23 16:29:07 +00:00
edee917d88 feat: add experimental agents support (#22290)
feat: add AI chat system with agent tools and chat UI

Introduce the chatd subsystem and Agents UI for AI-powered chat
within Coder workspaces.

- Add chatd package with chat loop, message compaction, prompt
  management, and LLM provider integration (OpenAI, Anthropic)
- Add agent tools: create workspace, list/read templates, read/write/
  edit files, execute commands
- Add chat API endpoints with streaming, message editing, and
  durable reconnection
- Add database schema and migrations for chats, chat messages, chat
  providers, and chat model configs
- Add RBAC policies and dbauthz enforcement for chat resources
- Add Agents UI pages with conversation timeline, queued messages
  list, diff viewer, and model configuration panel
- Add comprehensive test coverage including coderd integration tests,
  chatd unit tests, and Storybook stories
- Gate feature behind experiments flag

---------

Co-authored-by: Cian Johnston <cian@coder.com>
Co-authored-by: Danielle Maywood <danielle@themaywoods.com>
Co-authored-by: Jeremy Ruppel <jeremy@coder.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-27 16:50:56 +00:00
ケイラ 98834a7837 chore: continue vitest test migrations (#21639) 2026-01-23 11:28:59 -07:00
ケイラ c627a68e96 chore: migrate some tests from jest to vitest (#20568) 2025-10-31 15:15:30 -06:00
Bruno Quaresma accdcb8b77 chore: upgrade biome to v2 (#19362)
Guide for migration: https://biomejs.dev/guides/upgrade-to-biome-v2/
2025-08-14 18:25:15 -03:00
Cian Johnston 49fcffc266 fix!: stop workspace before update (#18425)
Fixes https://github.com/coder/coder/issues/17840

NOTE: calling this out as a breaking change so that it is highly visible
in the changelog.

* CLI: Modifies `coder update` to stop the workspace if already running.
* UI: Modifies "update" button to always stop the workspace if already
running.
2025-06-23 09:12:37 +01:00
Kayla Washburn-Love 95a7c0c4f0 chore: use tabs for prettier and biome (#14283) 2024-08-15 14:53:53 -06:00
Kayla Washburn-Love d15f16fa2e chore: replace eslint with biome (#14263) 2024-08-15 13:26:29 -06:00
Michael Smith f13b1c9af6 refactor: improve test isolation for Axios API logic (#13125)
* wip: commit progress on code split-up

* wip: commit more progress

* wip: finish initial version of class implementation

* chore: update all import paths to go through client instance

* fix: remove temp comments

* refactor: smoooooooosh the API

* refactor: update import setup for tests
2024-05-12 19:05:22 +00:00
Michael Smith 3f21cb8a2f fix: update API code to use Axios instances (#13029)
* fix: update API code to use Axios instance

* docs: fix typo

* fix: update all global axios imports to use Coder instance

* fix: remove needless import

* fix: update import order

* refactor: rename coderAxiosInstance to axiosInstance

* docs: update variable reference in FE contributing docs
2024-04-24 17:01:23 +00:00
Kayla Washburn-Love 0fe109d517 chore: sort imports in our typescript code (#12417) 2024-03-05 16:31:22 -07:00
Kayla Washburn 988c9af015 chore: format code with semicolons when using prettier (#9555) 2023-09-06 12:59:26 -06:00
Bruno Quaresma 9abfe97dcc Revert "fix(site): Fix update when missing parameters (#7221)" (#7223)
This reverts commit 7d9a7636e9.
2023-04-20 12:40:31 -03:00
Bruno Quaresma 7d9a7636e9 fix(site): Fix update when missing parameters (#7221) 2023-04-20 09:32:20 -05:00
Bruno Quaresma 46f42ea9ac fix(site): Prompting user for missing variables (#7002) 2023-04-04 13:15:35 +00:00
Kyle Carberry ad9c9b468f fix: block updating mutable parameters (#6717) 2023-03-22 11:05:04 -05:00
Kyle Carberry 38d278ac46 fix: use the default value for a rich parameter if unset (#6715)
This fixes an error thrown on the workspace settings page when
a new parameter is added and the workspace hasn't been built yet.
2023-03-22 00:02:55 +00:00
Bruno Quaresma 01a6af98b4 fix(site): Do not require immutable parameters (#6637) 2023-03-17 10:09:10 -03:00
Bruno Quaresma 3cf235c564 feat(site): Ask for parameter values when updating a workspace (#6586) 2023-03-14 13:20:49 -03:00
Ammar Bandukwala 85c679597c site: reduce printWidth to 80 (#4437)
Resolves #4435
2022-10-10 10:33:35 -07:00
Abhineet Jain 0d25e1752f feat: Add filter on Users page (#2653)
This commit adds a new filter feature to the Users page.

- adds a filter to the getUsers API call and users state machine.
- adds filter UI to Users page view.
- addresses error handling in the filter component, users page and machine.
- refactors user table code.
- refactors common code for workspace filter.
- adds and updates unit tests and stories.
2022-06-28 19:12:15 -04:00
Steven MasleyandGarrett dc1de58857 feat: workspace filter query supported in backend (#2232)
* feat: add support for template in workspace filter
* feat: Implement workspace search filter to support names
* Use new query param parser for pagination fields
* Remove excessive calls, use filters on a single query

Co-authored-by: Garrett <garrett@coder.com>
2022-06-14 08:46:33 -05:00
8b03e2b0e1 feat: Workspaces filtering (#1972)
Co-authored-by: G r e y <grey@coder.com>
Co-authored-by: Kira Pilot <kira@coder.com>
2022-06-03 17:20:28 +00:00
G r e y 67333b6186 feat: getWorkspaces filter site api (#1564) 2022-05-19 12:08:55 -04:00
Bruno Quaresma e6168ba238 feat: Add permissions for links (#1407) 2022-05-13 14:25:57 +00:00
Asher 26b04cc96f chore: switch to generated types (#1394)
* Make column renderer use the same type as its key

That way the renderer only takes `string` for example when rendering the
name field instead of `string | number` when the interface has some
fields that are strings and some fields are numbers.

This will be necessary when switching to generated types since some of
the fields are numbers (like the owner count on a template).

* Switch fully to generated types

In some places the organization ID is part of the URL but not part of
the request so I separated out the ID into a separate argument in the
relevant API functions.

Otherwise this was a straightforward replacement where I mostly only
needed to change some of the interface names (User instead of
UserResponse for example) and add a few missing but required properties.

I kind of winged the template form; I am not sure what the difference
between a template and template version is or why the latter comes
before the former so the form just returns all the data required to
create both.

* Delete handwritten types

Except for UserAgent which seems to be purely frontend and
ReconnectingPTYRequest which is not in codersdk so I am just leaving it
for now.

* Remove implemented omitempty as a future idea

This was implemented in 2d3dc436a8.

* Add missing optionalities to generated request interfaces
2022-05-12 10:01:28 -05:00
Kira Pilot f93804a2a0 chore: renaming index files (#1397) 2022-05-11 17:02:28 -04:00