mirror of
https://github.com/coder/coder.git
synced 2025-07-09 11:45:56 +00:00
feat: add deployment_id
to the ui and licenses (#13096)
* feat: expose `deployment_id` in the user dropdown * feat: add license deployment_id verification * Ignore wireguard.com from mlc config
This commit is contained in:
@ -147,13 +147,14 @@ func NewWithAPI(t *testing.T, options *Options) (
|
||||
}
|
||||
|
||||
type LicenseOptions struct {
|
||||
AccountType string
|
||||
AccountID string
|
||||
Trial bool
|
||||
AllFeatures bool
|
||||
GraceAt time.Time
|
||||
ExpiresAt time.Time
|
||||
Features license.Features
|
||||
AccountType string
|
||||
AccountID string
|
||||
DeploymentIDs []string
|
||||
Trial bool
|
||||
AllFeatures bool
|
||||
GraceAt time.Time
|
||||
ExpiresAt time.Time
|
||||
Features license.Features
|
||||
}
|
||||
|
||||
// AddFullLicense generates a license with all features enabled.
|
||||
@ -190,6 +191,7 @@ func GenerateLicense(t *testing.T, options LicenseOptions) string {
|
||||
LicenseExpires: jwt.NewNumericDate(options.GraceAt),
|
||||
AccountType: options.AccountType,
|
||||
AccountID: options.AccountID,
|
||||
DeploymentIDs: options.DeploymentIDs,
|
||||
Trial: options.Trial,
|
||||
Version: license.CurrentVersion,
|
||||
AllFeatures: options.AllFeatures,
|
||||
|
@ -257,14 +257,16 @@ type Claims struct {
|
||||
// the end of the grace period (identical to LicenseExpires if there is no grace period).
|
||||
// The reason we use the standard claim for the end of the grace period is that we want JWT
|
||||
// processing libraries to consider the token "valid" until then.
|
||||
LicenseExpires *jwt.NumericDate `json:"license_expires,omitempty"`
|
||||
AccountType string `json:"account_type,omitempty"`
|
||||
AccountID string `json:"account_id,omitempty"`
|
||||
Trial bool `json:"trial"`
|
||||
AllFeatures bool `json:"all_features"`
|
||||
Version uint64 `json:"version"`
|
||||
Features Features `json:"features"`
|
||||
RequireTelemetry bool `json:"require_telemetry,omitempty"`
|
||||
LicenseExpires *jwt.NumericDate `json:"license_expires,omitempty"`
|
||||
AccountType string `json:"account_type,omitempty"`
|
||||
AccountID string `json:"account_id,omitempty"`
|
||||
// DeploymentIDs enforces the license can only be used on a set of deployments.
|
||||
DeploymentIDs []string `json:"deployment_ids,omitempty"`
|
||||
Trial bool `json:"trial"`
|
||||
AllFeatures bool `json:"all_features"`
|
||||
Version uint64 `json:"version"`
|
||||
Features Features `json:"features"`
|
||||
RequireTelemetry bool `json:"require_telemetry,omitempty"`
|
||||
}
|
||||
|
||||
// ParseRaw consumes a license and returns the claims.
|
||||
|
@ -10,6 +10,7 @@ import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"slices"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
@ -120,6 +121,15 @@ func (api *API) postLicense(rw http.ResponseWriter, r *http.Request) {
|
||||
// old licenses with a uuid.
|
||||
id = uuid.New()
|
||||
}
|
||||
if len(claims.DeploymentIDs) > 0 && !slices.Contains(claims.DeploymentIDs, api.AGPL.DeploymentID) {
|
||||
httpapi.Write(ctx, rw, http.StatusBadRequest, codersdk.Response{
|
||||
Message: "License cannot be used on this deployment!",
|
||||
Detail: fmt.Sprintf("The provided license is locked to the following deployments: %q. "+
|
||||
"Your deployment identifier is %q. Please contact sales.", claims.DeploymentIDs, api.AGPL.DeploymentID),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
dl, err := api.Database.InsertLicense(ctx, database.InsertLicenseParams{
|
||||
UploadedAt: dbtime.Now(),
|
||||
JWT: addLicense.License,
|
||||
|
@ -5,6 +5,7 @@ import (
|
||||
"net/http"
|
||||
"testing"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"golang.org/x/xerrors"
|
||||
@ -36,6 +37,22 @@ func TestPostLicense(t *testing.T) {
|
||||
assert.EqualValues(t, 1, features[codersdk.FeatureAuditLog])
|
||||
})
|
||||
|
||||
t.Run("InvalidDeploymentID", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
// The generated deployment will start out with a different deployment ID.
|
||||
client, _ := coderdenttest.New(t, &coderdenttest.Options{DontAddLicense: true})
|
||||
license := coderdenttest.GenerateLicense(t, coderdenttest.LicenseOptions{
|
||||
DeploymentIDs: []string{uuid.NewString()},
|
||||
})
|
||||
_, err := client.AddLicense(context.Background(), codersdk.AddLicenseRequest{
|
||||
License: license,
|
||||
})
|
||||
errResp := &codersdk.Error{}
|
||||
require.ErrorAs(t, err, &errResp)
|
||||
require.Equal(t, http.StatusBadRequest, errResp.StatusCode())
|
||||
require.Contains(t, errResp.Message, "License cannot be used on this deployment!")
|
||||
})
|
||||
|
||||
t.Run("Unauthorized", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
client, _ := coderdenttest.New(t, &coderdenttest.Options{DontAddLicense: true})
|
||||
|
Reference in New Issue
Block a user