mirror of
https://github.com/coder/coder.git
synced 2026-06-02 20:48:20 +00:00
AGPL Entitlements API (#3523)
* AGPL Entitlements API Signed-off-by: Spike Curtis <spike@coder.com> * Generate typesGenerated.ts Signed-off-by: Spike Curtis <spike@coder.com> * AllFeatures -> FeatureNames Signed-off-by: Spike Curtis <spike@coder.com> Signed-off-by: Spike Curtis <spike@coder.com>
This commit is contained in:
@@ -391,6 +391,10 @@ func New(options *Options) *API {
|
||||
r.Get("/resources", api.workspaceBuildResources)
|
||||
r.Get("/state", api.workspaceBuildState)
|
||||
})
|
||||
r.Route("/entitlements", func(r chi.Router) {
|
||||
r.Use(apiKeyMiddleware)
|
||||
r.Get("/", entitlements)
|
||||
})
|
||||
})
|
||||
|
||||
r.NotFound(compressHandler(http.HandlerFunc(api.siteHandler.ServeHTTP)).ServeHTTP)
|
||||
|
||||
@@ -242,6 +242,7 @@ func TestAuthorizeAllEndpoints(t *testing.T) {
|
||||
"POST:/api/v2/users/login": {NoAuthorize: true},
|
||||
"GET:/api/v2/users/authmethods": {NoAuthorize: true},
|
||||
"POST:/api/v2/csp/reports": {NoAuthorize: true},
|
||||
"GET:/api/v2/entitlements": {NoAuthorize: true},
|
||||
|
||||
"GET:/%40{user}/{workspacename}/apps/{application}/*": {
|
||||
AssertAction: rbac.ActionRead,
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
package coderd
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/coder/coder/coderd/httpapi"
|
||||
"github.com/coder/coder/codersdk"
|
||||
)
|
||||
|
||||
func entitlements(rw http.ResponseWriter, _ *http.Request) {
|
||||
features := make(map[string]codersdk.Feature)
|
||||
for _, f := range codersdk.FeatureNames {
|
||||
features[f] = codersdk.Feature{
|
||||
Entitlement: codersdk.EntitlementNotEntitled,
|
||||
Enabled: false,
|
||||
}
|
||||
}
|
||||
httpapi.Write(rw, http.StatusOK, codersdk.Entitlements{
|
||||
Features: features,
|
||||
Warnings: nil,
|
||||
HasLicense: false,
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package coderd
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
|
||||
"github.com/coder/coder/codersdk"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestEntitlements(t *testing.T) {
|
||||
t.Parallel()
|
||||
t.Run("GET", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
r := httptest.NewRequest("GET", "https://example.com/api/v2/entitlements", nil)
|
||||
rw := httptest.NewRecorder()
|
||||
entitlements(rw, r)
|
||||
resp := rw.Result()
|
||||
assert.Equal(t, http.StatusOK, resp.StatusCode)
|
||||
dec := json.NewDecoder(resp.Body)
|
||||
var result codersdk.Entitlements
|
||||
err := dec.Decode(&result)
|
||||
require.NoError(t, err)
|
||||
assert.False(t, result.HasLicense)
|
||||
assert.Empty(t, result.Warnings)
|
||||
for _, f := range codersdk.FeatureNames {
|
||||
require.Contains(t, result.Features, f)
|
||||
fe := result.Features[f]
|
||||
assert.False(t, fe.Enabled)
|
||||
assert.Equal(t, codersdk.EntitlementNotEntitled, fe.Entitlement)
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package codersdk
|
||||
|
||||
type Entitlement string
|
||||
|
||||
const (
|
||||
EntitlementEntitled Entitlement = "entitled"
|
||||
EntitlementGracePeriod Entitlement = "grace_period"
|
||||
EntitlementNotEntitled Entitlement = "not_entitled"
|
||||
)
|
||||
|
||||
const (
|
||||
FeatureUserLimit = "user_limit"
|
||||
FeatureAuditLog = "audit_log"
|
||||
)
|
||||
|
||||
var FeatureNames = []string{FeatureUserLimit, FeatureAuditLog}
|
||||
|
||||
type Feature struct {
|
||||
Entitlement Entitlement `json:"entitlement"`
|
||||
Enabled bool `json:"enabled"`
|
||||
Limit *int64 `json:"limit"`
|
||||
Actual *int64 `json:"actual"`
|
||||
}
|
||||
|
||||
type Entitlements struct {
|
||||
Features map[string]Feature `json:"features"`
|
||||
Warnings []string `json:"warnings"`
|
||||
HasLicense bool `json:"has_license"`
|
||||
}
|
||||
@@ -134,6 +134,21 @@ export interface CreateWorkspaceRequest {
|
||||
readonly parameter_values?: CreateParameterRequest[]
|
||||
}
|
||||
|
||||
// From codersdk/features.go
|
||||
export interface Entitlements {
|
||||
readonly features: Record<string, Feature>
|
||||
readonly warnings: string[]
|
||||
readonly has_license: boolean
|
||||
}
|
||||
|
||||
// From codersdk/features.go
|
||||
export interface Feature {
|
||||
readonly entitlement: Entitlement
|
||||
readonly enabled: boolean
|
||||
readonly limit?: number
|
||||
readonly actual?: number
|
||||
}
|
||||
|
||||
// From codersdk/users.go
|
||||
export interface GenerateAPIKeyResponse {
|
||||
readonly key: string
|
||||
@@ -535,6 +550,9 @@ export interface WorkspaceResourceMetadata {
|
||||
// From codersdk/workspacebuilds.go
|
||||
export type BuildReason = "autostart" | "autostop" | "initiator"
|
||||
|
||||
// From codersdk/features.go
|
||||
export type Entitlement = "entitled" | "grace_period" | "not_entitled"
|
||||
|
||||
// From codersdk/provisionerdaemons.go
|
||||
export type LogLevel = "debug" | "error" | "info" | "trace" | "warn"
|
||||
|
||||
|
||||
Reference in New Issue
Block a user