mirror of
https://github.com/coder/coder.git
synced 2026-10-16 14:48:56 +08:00
feat: distinct NewUser and Product trial sources (#28882)
* [DEVEX-847/distinct-newuser-and-product-trial-sources](https://linear.app/codercom/issue/DEVEX-847/distinct-newuser-and-product-trial-sources) * for premium trial signups with a new user account creation, passes the `NewUser` trial source. * for premium trial signups from the /deployment/premium account page, passes the `Product` trial source
This commit is contained in:
@@ -223,6 +223,7 @@ func (api *API) postFirstUser(rw http.ResponseWriter, r *http.Request) {
|
||||
CompanyName: createUser.TrialInfo.CompanyName,
|
||||
Country: createUser.TrialInfo.Country,
|
||||
Developers: createUser.TrialInfo.Developers,
|
||||
Source: codersdk.LicensorTrialSourceNewUser,
|
||||
})
|
||||
if err != nil {
|
||||
httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{
|
||||
|
||||
@@ -84,12 +84,12 @@ func TestFirstUser(t *testing.T) {
|
||||
|
||||
t.Run("Trial", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
trialGenerated := make(chan struct{})
|
||||
trialGenerated := make(chan codersdk.LicensorTrialRequest, 1)
|
||||
entitlementsRefreshed := make(chan struct{})
|
||||
|
||||
client := coderdtest.New(t, &coderdtest.Options{
|
||||
TrialGenerator: func(context.Context, codersdk.LicensorTrialRequest) error {
|
||||
close(trialGenerated)
|
||||
TrialGenerator: func(_ context.Context, req codersdk.LicensorTrialRequest) error {
|
||||
trialGenerated <- req
|
||||
return nil
|
||||
},
|
||||
RefreshEntitlements: func(context.Context) error {
|
||||
@@ -111,7 +111,9 @@ func TestFirstUser(t *testing.T) {
|
||||
_, err := client.CreateFirstUser(ctx, req)
|
||||
require.NoError(t, err)
|
||||
|
||||
_ = testutil.TryReceive(ctx, t, trialGenerated)
|
||||
trialReq := testutil.TryReceive(ctx, t, trialGenerated)
|
||||
|
||||
require.Equal(t, codersdk.LicensorTrialSourceNewUser, trialReq.Source)
|
||||
_ = testutil.TryReceive(ctx, t, entitlementsRefreshed)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -108,6 +108,14 @@ type GetUsersResponse struct {
|
||||
Count int `json:"count"`
|
||||
}
|
||||
|
||||
// Trial request source origination reported to the licensor.
|
||||
const (
|
||||
// LicensorTrialSourceNewUser is the first user setup flow.
|
||||
LicensorTrialSourceNewUser = "NewUser"
|
||||
// LicensorTrialSourceProduct is a request from within the product in-app trial request
|
||||
LicensorTrialSourceProduct = "Product"
|
||||
)
|
||||
|
||||
// @typescript-ignore LicensorTrialRequest
|
||||
type LicensorTrialRequest struct {
|
||||
DeploymentID string `json:"deployment_id"`
|
||||
|
||||
@@ -173,6 +173,7 @@ func (api *API) postTrialLicense(rw http.ResponseWriter, r *http.Request) {
|
||||
rawLicense, err := api.trialer.Request(ctx, codersdk.LicensorTrialRequest{
|
||||
DeploymentID: api.AGPL.DeploymentID,
|
||||
Email: req.Email,
|
||||
Source: codersdk.LicensorTrialSourceProduct,
|
||||
FirstName: req.FirstName,
|
||||
LastName: req.LastName,
|
||||
PhoneNumber: req.PhoneNumber,
|
||||
|
||||
@@ -23,8 +23,9 @@ import (
|
||||
const LicenseRequestURL = "https://v2-licensor.coder.com/trial"
|
||||
|
||||
const (
|
||||
// licenseRequestSource tells the licensor where a trial request originated.
|
||||
licenseRequestSource = "Product"
|
||||
// defaultLicenseRequestSource tells the licensor where a trial request
|
||||
// originated when the caller does not specify a source.
|
||||
defaultLicenseRequestSource = codersdk.LicensorTrialSourceProduct
|
||||
// licenseRequestTimeout bounds a single request to the licensor.
|
||||
licenseRequestTimeout = 30 * time.Second
|
||||
)
|
||||
@@ -56,7 +57,9 @@ func New(db database.Store, url string, keys map[string]ed25519.PublicKey) *Tria
|
||||
|
||||
// Request returns the raw signed license without storing it.
|
||||
func (t *Trialer) Request(ctx context.Context, body codersdk.LicensorTrialRequest) (string, error) {
|
||||
body.Source = licenseRequestSource
|
||||
if body.Source == "" {
|
||||
body.Source = defaultLicenseRequestSource
|
||||
}
|
||||
data, err := json.Marshal(body)
|
||||
if err != nil {
|
||||
return "", xerrors.Errorf("marshal: %w", err)
|
||||
|
||||
@@ -80,6 +80,7 @@ func TestTrialerRequest(t *testing.T) {
|
||||
req := codersdk.LicensorTrialRequest{
|
||||
DeploymentID: "test-deployment",
|
||||
Email: "coder@coder.com",
|
||||
Source: codersdk.LicensorTrialSourceNewUser,
|
||||
FirstName: "Coder",
|
||||
LastName: "McCoder",
|
||||
PhoneNumber: "+1 555 0100",
|
||||
@@ -135,7 +136,7 @@ func TestTrialerRequest(t *testing.T) {
|
||||
require.Equal(t, "application/json", got.contentType)
|
||||
require.Equal(t, map[string]any{
|
||||
"deployment_id": "test-deployment",
|
||||
"source": "Product",
|
||||
"source": codersdk.LicensorTrialSourceNewUser,
|
||||
"email": req.Email,
|
||||
"first_name": req.FirstName,
|
||||
"last_name": req.LastName,
|
||||
|
||||
Generated
+14
@@ -5926,6 +5926,20 @@ export const LicenseManagedAgentLimitExceededWarningText =
|
||||
export const LicenseTelemetryRequiredErrorText =
|
||||
"License requires telemetry but telemetry is disabled";
|
||||
|
||||
// From codersdk/users.go
|
||||
/**
|
||||
* Trial request source origination reported to the licensor.
|
||||
* LicensorTrialSourceNewUser is the first user setup flow.
|
||||
*/
|
||||
export const LicensorTrialSourceNewUser = "NewUser";
|
||||
|
||||
// From codersdk/users.go
|
||||
/**
|
||||
* Trial request source origination reported to the licensor.
|
||||
* LicensorTrialSourceProduct is a request from within the product in-app trial request
|
||||
*/
|
||||
export const LicensorTrialSourceProduct = "Product";
|
||||
|
||||
// From codersdk/deployment.go
|
||||
export interface LinkConfig {
|
||||
readonly name: string;
|
||||
|
||||
Reference in New Issue
Block a user