Skip to content

Commit 7376104

Browse files
committed
move to enterprise
1 parent 971b2a9 commit 7376104

File tree

6 files changed

+53
-36
lines changed

6 files changed

+53
-36
lines changed

coderd/coderd.go

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -915,16 +915,6 @@ func New(options *Options) *API {
915915
})
916916
})
917917
})
918-
r.Route("/provisionerkeys", func(r chi.Router) {
919-
r.Get("/", api.provisionerKeys)
920-
r.Post("/", api.postProvisionerKey)
921-
r.Route("/{provisionerkey}", func(r chi.Router) {
922-
r.Use(
923-
httpmw.ExtractProvisionerKeyParam(options.Database),
924-
)
925-
r.Delete("/", api.deleteProvisionerKey)
926-
})
927-
})
928918
})
929919
})
930920
r.Route("/templates", func(r chi.Router) {

codersdk/deployment.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ const (
5656
FeatureAccessControl FeatureName = "access_control"
5757
FeatureControlSharedPorts FeatureName = "control_shared_ports"
5858
FeatureCustomRoles FeatureName = "custom_roles"
59+
FeatureMultipleOrganizations FeatureName = "multiple_organizations"
5960
)
6061

6162
// FeatureNames must be kept in-sync with the Feature enum above.
@@ -77,6 +78,7 @@ var FeatureNames = []FeatureName{
7778
FeatureAccessControl,
7879
FeatureControlSharedPorts,
7980
FeatureCustomRoles,
81+
FeatureMultipleOrganizations,
8082
}
8183

8284
// Humanize returns the feature name in a human-readable format.

enterprise/coderd/coderd.go

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -205,7 +205,7 @@ func New(ctx context.Context, options *Options) (_ *API, err error) {
205205
})
206206
r.Route("/workspaceproxies", func(r chi.Router) {
207207
r.Use(
208-
api.moonsEnabledMW,
208+
api.RequireFeatureMW(codersdk.FeatureWorkspaceProxy),
209209
)
210210
r.Group(func(r chi.Router) {
211211
r.Use(
@@ -254,6 +254,21 @@ func New(ctx context.Context, options *Options) (_ *API, err error) {
254254
r.Get("/", api.groupByOrganization)
255255
})
256256
})
257+
r.Route("/organizations/{organization}/provisionerkeys", func(r chi.Router) {
258+
r.Use(
259+
apiKeyMiddleware,
260+
httpmw.ExtractOrganizationParam(api.Database),
261+
api.RequireFeatureMW(codersdk.FeatureMultipleOrganizations),
262+
)
263+
r.Get("/", api.provisionerKeys)
264+
r.Post("/", api.postProvisionerKey)
265+
r.Route("/{provisionerkey}", func(r chi.Router) {
266+
r.Use(
267+
httpmw.ExtractProvisionerKeyParam(options.Database),
268+
)
269+
r.Delete("/", api.deleteProvisionerKey)
270+
})
271+
})
257272
// TODO: provisioner daemons are not scoped to organizations in the database, so placing them
258273
// under an organization route doesn't make sense. In order to allow the /serve endpoint to
259274
// work with a pre-shared key (PSK) without an API key, these routes will simply ignore the
@@ -566,6 +581,7 @@ func (api *API) updateEntitlements(ctx context.Context) error {
566581
codersdk.FeatureUserRoleManagement: true,
567582
codersdk.FeatureAccessControl: true,
568583
codersdk.FeatureControlSharedPorts: true,
584+
codersdk.FeatureMultipleOrganizations: true,
569585
})
570586
if err != nil {
571587
return err
@@ -751,6 +767,11 @@ func (api *API) updateEntitlements(ctx context.Context) error {
751767
api.AGPL.CustomRoleHandler.Store(&handler)
752768
}
753769

770+
if initial, changed, enabled := featureChanged(codersdk.FeatureMultipleOrganizations); shouldUpdate(initial, changed, enabled) {
771+
var handler coderd.CustomRoleHandler = &enterpriseCustomRoleHandler{API: api, Enabled: enabled}
772+
api.AGPL.CustomRoleHandler.Store(&handler)
773+
}
774+
754775
// External token encryption is soft-enforced
755776
featureExternalTokenEncryption := entitlements.Features[codersdk.FeatureExternalTokenEncryption]
756777
featureExternalTokenEncryption.Enabled = len(api.ExternalTokenEncryption) > 0

coderd/provisionerkeys.go renamed to enterprise/coderd/provisionerkeys.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ import (
2020
// @Tags Enterprise
2121
// @Param organization path string true "Organization ID"
2222
// @Success 201 {object} codersdk.CreateProvisionerKeyResponse
23-
// @Router /organizations/{organization}/provisionerkey [post]
23+
// @Router /organizations/{organization}/provisionerkeys [post]
2424
func (api *API) postProvisionerKey(rw http.ResponseWriter, r *http.Request) {
2525
ctx := r.Context()
2626
organization := httpmw.OrganizationParam(r)
@@ -86,7 +86,7 @@ func (api *API) postProvisionerKey(rw http.ResponseWriter, r *http.Request) {
8686
// @Tags Enterprise
8787
// @Param organization path string true "Organization ID"
8888
// @Success 200 {object} []codersdk.ProvisionerKey
89-
// @Router /organizations/{organization}/provisionerkey [get]
89+
// @Router /organizations/{organization}/provisionerkeys [get]
9090
func (api *API) provisionerKeys(rw http.ResponseWriter, r *http.Request) {
9191
ctx := r.Context()
9292
organization := httpmw.OrganizationParam(r)
@@ -108,7 +108,7 @@ func (api *API) provisionerKeys(rw http.ResponseWriter, r *http.Request) {
108108
// @Param organization path string true "Organization ID"
109109
// @Param provisionerkey path string true "Provisioner key name"
110110
// @Success 204
111-
// @Router /organizations/{organization}/provisionerkey/{provisionerkey} [delete]
111+
// @Router /organizations/{organization}/provisionerkeys/{provisionerkey} [delete]
112112
func (api *API) deleteProvisionerKey(rw http.ResponseWriter, r *http.Request) {
113113
ctx := r.Context()
114114
organization := httpmw.OrganizationParam(r)

coderd/provisionerkeys_test.go renamed to enterprise/coderd/provisionerkeys_test.go

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ import (
99
"github.com/coder/coder/v2/coderd/coderdtest"
1010
"github.com/coder/coder/v2/coderd/rbac"
1111
"github.com/coder/coder/v2/codersdk"
12+
"github.com/coder/coder/v2/enterprise/coderd/coderdenttest"
13+
"github.com/coder/coder/v2/enterprise/coderd/license"
1214
"github.com/coder/coder/v2/testutil"
1315
)
1416

@@ -17,18 +19,18 @@ func TestProvisionerKeys(t *testing.T) {
1719

1820
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong*10)
1921
t.Cleanup(cancel)
20-
client := coderdtest.New(t, nil)
21-
owner := coderdtest.CreateFirstUser(t, client)
22+
client, owner := coderdenttest.New(t, &coderdenttest.Options{LicenseOptions: &coderdenttest.LicenseOptions{
23+
Features: license.Features{
24+
codersdk.FeatureMultipleOrganizations: 1,
25+
},
26+
}})
2227
orgAdmin, _ := coderdtest.CreateAnotherUser(t, client, owner.OrganizationID, rbac.ScopedRoleOrgAdmin(owner.OrganizationID))
2328
member, _ := coderdtest.CreateAnotherUser(t, client, owner.OrganizationID)
24-
otherOrg, err := client.CreateOrganization(ctx, codersdk.CreateOrganizationRequest{
25-
Name: "other",
26-
})
27-
require.NoError(t, err, "create org")
29+
otherOrg := coderdtest.CreateOrganization(t, client, coderdtest.CreateOrganizationOptions{})
2830
outsideOrgAdmin, _ := coderdtest.CreateAnotherUser(t, client, otherOrg.ID, rbac.ScopedRoleOrgAdmin(otherOrg.ID))
2931

3032
// member cannot create a provisioner key
31-
_, err = member.CreateProvisionerKey(ctx, otherOrg.ID, codersdk.CreateProvisionerKeyRequest{
33+
_, err := member.CreateProvisionerKey(ctx, otherOrg.ID, codersdk.CreateProvisionerKeyRequest{
3234
Name: "key",
3335
})
3436
require.ErrorContains(t, err, "Resource not found")

enterprise/coderd/templates.go

Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -327,7 +327,7 @@ func convertSDKTemplateRole(role codersdk.TemplateRole) []policy.Action {
327327
return nil
328328
}
329329

330-
// TODO reduce the duplication across all of these.
330+
// TODO move to api.RequireFeatureMW when we are OK with changing the behavior.
331331
func (api *API) templateRBACEnabledMW(next http.Handler) http.Handler {
332332
return http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
333333
api.entitlementsMu.RLock()
@@ -343,19 +343,21 @@ func (api *API) templateRBACEnabledMW(next http.Handler) http.Handler {
343343
})
344344
}
345345

346-
func (api *API) moonsEnabledMW(next http.Handler) http.Handler {
347-
return http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
348-
// Entitlement must be enabled.
349-
api.entitlementsMu.RLock()
350-
proxy := api.entitlements.Features[codersdk.FeatureWorkspaceProxy].Enabled
351-
api.entitlementsMu.RUnlock()
352-
if !proxy {
353-
httpapi.Write(r.Context(), rw, http.StatusForbidden, codersdk.Response{
354-
Message: "External workspace proxies is an Enterprise feature. Contact sales!",
355-
})
356-
return
357-
}
346+
func (api *API) RequireFeatureMW(feat codersdk.FeatureName) func(http.Handler) http.Handler {
347+
return func(next http.Handler) http.Handler {
348+
return http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
349+
// Entitlement must be enabled.
350+
api.entitlementsMu.RLock()
351+
enabled := api.entitlements.Features[feat].Enabled
352+
api.entitlementsMu.RUnlock()
353+
if !enabled {
354+
httpapi.Write(r.Context(), rw, http.StatusForbidden, codersdk.Response{
355+
Message: fmt.Sprintf("%s is an Enterprise feature. Contact sales!", feat.Humanize()),
356+
})
357+
return
358+
}
358359

359-
next.ServeHTTP(rw, r)
360-
})
360+
next.ServeHTTP(rw, r)
361+
})
362+
}
361363
}

0 commit comments

Comments
 (0)