mirror of
https://github.com/sourcegraph/sourcegraph.git
synced 2026-02-06 17:31:43 +00:00
feat/enterpriseportal: more list options for subscriptions and licenses (#64114)
Required to build an updated subscriptions management UI. Most of the diff is generated proto for some reason Closes https://linear.app/sourcegraph/issue/CORE-226 ## Test plan Integration tests
This commit is contained in:
parent
14a4d7ce31
commit
0de249daf9
@ -132,9 +132,10 @@ func NewLicensesStore(db *pgxpool.Pool) *LicensesStore {
|
||||
}
|
||||
|
||||
type ListLicensesOpts struct {
|
||||
SubscriptionID string
|
||||
LicenseType subscriptionsv1.EnterpriseSubscriptionLicenseType
|
||||
LicenseKeySubstring string
|
||||
SubscriptionID string
|
||||
LicenseType subscriptionsv1.EnterpriseSubscriptionLicenseType
|
||||
LicenseKeySubstring string
|
||||
SalesforceOpportunityID string
|
||||
// PageSize is the maximum number of licenses to return.
|
||||
PageSize int
|
||||
}
|
||||
@ -151,11 +152,21 @@ func (opts ListLicensesOpts) toQueryConditions() (where, limitClause string, _ p
|
||||
"license_type = @licenseType")
|
||||
namedArgs["licenseType"] = opts.LicenseType.String()
|
||||
}
|
||||
if opts.LicenseKeySubstring != "" {
|
||||
whereConds = append(whereConds,
|
||||
"license_data->>'SignedKey' LIKE '%' || @licenseKeySubstring || '%'")
|
||||
namedArgs["licenseKeySubstring"] = opts.LicenseKeySubstring
|
||||
|
||||
switch opts.LicenseType {
|
||||
case subscriptionsv1.EnterpriseSubscriptionLicenseType_ENTERPRISE_SUBSCRIPTION_LICENSE_TYPE_KEY:
|
||||
if opts.LicenseKeySubstring != "" {
|
||||
whereConds = append(whereConds,
|
||||
"license_data->>'SignedKey' LIKE '%' || @licenseKeySubstring || '%'")
|
||||
namedArgs["licenseKeySubstring"] = opts.LicenseKeySubstring
|
||||
}
|
||||
if opts.SalesforceOpportunityID != "" {
|
||||
whereConds = append(whereConds,
|
||||
"license_data->'Info'->>'sf_opp_id' = @salesforceOpportunityID")
|
||||
namedArgs["salesforceOpportunityID"] = opts.SalesforceOpportunityID
|
||||
}
|
||||
}
|
||||
|
||||
where = strings.Join(whereConds, " AND ")
|
||||
|
||||
if opts.PageSize > 0 {
|
||||
|
||||
@ -124,6 +124,8 @@ func TestLicensesStore(t *testing.T) {
|
||||
Tags: []string{"tag"},
|
||||
CreatedAt: time.Time{}.Add(24 * time.Hour),
|
||||
ExpiresAt: time.Time{}.Add(48 * time.Hour),
|
||||
|
||||
SalesforceOpportunityID: pointers.Ptr("sf_opportunity"),
|
||||
},
|
||||
SignedKey: "asdffdsadf",
|
||||
},
|
||||
@ -136,7 +138,7 @@ func TestLicensesStore(t *testing.T) {
|
||||
testLicense(
|
||||
got,
|
||||
autogold.Expect(valast.Ptr("TestLicensesStore/CreateLicenseKey 2")),
|
||||
autogold.Expect(`{"Info": {"c": "0001-01-02T00:00:00Z", "e": "0001-01-03T00:00:00Z", "t": ["tag"], "u": 0}, "SignedKey": "asdffdsadf"}`),
|
||||
autogold.Expect(`{"Info": {"c": "0001-01-02T00:00:00Z", "e": "0001-01-03T00:00:00Z", "t": ["tag"], "u": 0, "sf_opp_id": "sf_opportunity"}, "SignedKey": "asdffdsadf"}`),
|
||||
)
|
||||
createdLicenses = append(createdLicenses, got)
|
||||
|
||||
@ -229,6 +231,34 @@ func TestLicensesStore(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
require.Len(t, listedLicenses, 1)
|
||||
assert.Equal(t, subscriptionID1, listedLicenses[0].SubscriptionID)
|
||||
|
||||
t.Run("no match", func(t *testing.T) {
|
||||
listedLicenses, err = licenses.List(ctx, subscriptions.ListLicensesOpts{
|
||||
LicenseType: subscriptionsv1.EnterpriseSubscriptionLicenseType_ENTERPRISE_SUBSCRIPTION_LICENSE_TYPE_KEY,
|
||||
LicenseKeySubstring: "no-match",
|
||||
})
|
||||
require.NoError(t, err)
|
||||
assert.Len(t, listedLicenses, 0)
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("List by salesforce opportunity ID", func(t *testing.T) {
|
||||
listedLicenses, err := licenses.List(ctx, subscriptions.ListLicensesOpts{
|
||||
LicenseType: subscriptionsv1.EnterpriseSubscriptionLicenseType_ENTERPRISE_SUBSCRIPTION_LICENSE_TYPE_KEY,
|
||||
SalesforceOpportunityID: "sf_opportunity",
|
||||
})
|
||||
require.NoError(t, err)
|
||||
require.Len(t, listedLicenses, 1)
|
||||
assert.Equal(t, subscriptionID2, listedLicenses[0].SubscriptionID)
|
||||
|
||||
t.Run("no match", func(t *testing.T) {
|
||||
listedLicenses, err := licenses.List(ctx, subscriptions.ListLicensesOpts{
|
||||
LicenseType: subscriptionsv1.EnterpriseSubscriptionLicenseType_ENTERPRISE_SUBSCRIPTION_LICENSE_TYPE_KEY,
|
||||
SalesforceOpportunityID: "no-match",
|
||||
})
|
||||
require.NoError(t, err)
|
||||
assert.Len(t, listedLicenses, 0)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
@ -125,7 +125,13 @@ type ListEnterpriseSubscriptionsOptions struct {
|
||||
InstanceDomains []string
|
||||
// IsArchived indicates whether to only list archived subscriptions, or only
|
||||
// non-archived subscriptions.
|
||||
IsArchived bool
|
||||
IsArchived *bool
|
||||
// DisplayNameSubstring is a substring match on display name.
|
||||
DisplayNameSubstring string
|
||||
// SalesforceSubscriptionIDs are exact matches on the Salesforce subscription
|
||||
// ID.
|
||||
SalesforceSubscriptionIDs []string
|
||||
|
||||
// PageSize is the maximum number of subscriptions to return.
|
||||
PageSize int
|
||||
}
|
||||
@ -141,10 +147,24 @@ func (opts ListEnterpriseSubscriptionsOptions) toQueryConditions() (where, limit
|
||||
whereConds = append(whereConds, "instance_domain = ANY(@instanceDomains)")
|
||||
namedArgs["instanceDomains"] = opts.InstanceDomains
|
||||
}
|
||||
// Future: Uncomment the following block when the archived field is added to the table.
|
||||
// if opts.OnlyArchived {
|
||||
// whereConds = append(whereConds, "archived = TRUE")
|
||||
// }
|
||||
if opts.IsArchived != nil {
|
||||
if *opts.IsArchived {
|
||||
whereConds = append(whereConds, "archived_at IS NOT NULL")
|
||||
} else {
|
||||
whereConds = append(whereConds, "archived IS NUlL")
|
||||
}
|
||||
}
|
||||
if len(opts.DisplayNameSubstring) > 0 {
|
||||
whereConds = append(whereConds,
|
||||
"LOWER(display_name) LIKE '%' || LOWER(@displayName) || '%'")
|
||||
namedArgs["displayName"] = opts.DisplayNameSubstring
|
||||
}
|
||||
if len(opts.SalesforceSubscriptionIDs) > 0 {
|
||||
whereConds = append(whereConds,
|
||||
"salesforce_subscription_id = ANY(@salesforceSubscriptionIDs)")
|
||||
namedArgs["salesforceSubscriptionIDs"] = opts.SalesforceSubscriptionIDs
|
||||
}
|
||||
|
||||
where = strings.Join(whereConds, " AND ")
|
||||
|
||||
if opts.PageSize > 0 {
|
||||
|
||||
@ -59,7 +59,9 @@ func SubscriptionsStoreList(t *testing.T, ctx context.Context, s *subscriptions.
|
||||
ctx,
|
||||
uuid.New().String(),
|
||||
subscriptions.UpsertSubscriptionOptions{
|
||||
InstanceDomain: database.NewNullString("s1.sourcegraph.com"),
|
||||
DisplayName: database.NewNullString("Subscription 1"),
|
||||
InstanceDomain: database.NewNullString("s1.sourcegraph.com"),
|
||||
SalesforceSubscriptionID: pointers.Ptr("sf_sub_id"),
|
||||
},
|
||||
)
|
||||
require.NoError(t, err)
|
||||
@ -67,20 +69,24 @@ func SubscriptionsStoreList(t *testing.T, ctx context.Context, s *subscriptions.
|
||||
ctx,
|
||||
uuid.New().String(),
|
||||
subscriptions.UpsertSubscriptionOptions{
|
||||
DisplayName: database.NewNullString("Subscription 2"),
|
||||
InstanceDomain: database.NewNullString("s2.sourcegraph.com"),
|
||||
},
|
||||
)
|
||||
require.NoError(t, err)
|
||||
_, err = s.Upsert(
|
||||
s3, err := s.Upsert(
|
||||
ctx,
|
||||
uuid.New().String(),
|
||||
subscriptions.UpsertSubscriptionOptions{
|
||||
DisplayName: database.NewNullString("Subscription 3"),
|
||||
InstanceDomain: database.NewNullString("s3.sourcegraph.com"),
|
||||
},
|
||||
)
|
||||
require.NoError(t, err)
|
||||
|
||||
t.Run("list by IDs", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
ss, err := s.List(ctx, subscriptions.ListEnterpriseSubscriptionsOptions{IDs: []string{s1.ID, s2.ID}})
|
||||
require.NoError(t, err)
|
||||
require.Len(t, ss, 2)
|
||||
@ -101,6 +107,8 @@ func SubscriptionsStoreList(t *testing.T, ctx context.Context, s *subscriptions.
|
||||
})
|
||||
|
||||
t.Run("list by instance domains", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
ss, err := s.List(ctx, subscriptions.ListEnterpriseSubscriptionsOptions{
|
||||
InstanceDomains: []string{*s1.InstanceDomain, *s2.InstanceDomain}},
|
||||
)
|
||||
@ -122,7 +130,78 @@ func SubscriptionsStoreList(t *testing.T, ctx context.Context, s *subscriptions.
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("list by display name", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
ss, err := s.List(
|
||||
ctx,
|
||||
subscriptions.ListEnterpriseSubscriptionsOptions{
|
||||
DisplayNameSubstring: "Subscription",
|
||||
},
|
||||
)
|
||||
require.NoError(t, err)
|
||||
assert.Len(t, ss, 3) // all 3 are returned
|
||||
|
||||
t.Run("single match", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
ss, err := s.List(
|
||||
ctx,
|
||||
subscriptions.ListEnterpriseSubscriptionsOptions{
|
||||
DisplayNameSubstring: "tion 3",
|
||||
},
|
||||
)
|
||||
require.NoError(t, err)
|
||||
assert.Len(t, ss, 1)
|
||||
assert.Equal(t, s3.ID, ss[0].ID)
|
||||
})
|
||||
|
||||
t.Run("exact match", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
ss, err := s.List(
|
||||
ctx,
|
||||
subscriptions.ListEnterpriseSubscriptionsOptions{
|
||||
DisplayNameSubstring: "Subscription 2",
|
||||
},
|
||||
)
|
||||
require.NoError(t, err)
|
||||
assert.Len(t, ss, 1)
|
||||
assert.Equal(t, s2.ID, ss[0].ID)
|
||||
})
|
||||
|
||||
t.Run("case-insensitive match", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
ss, err := s.List(
|
||||
ctx,
|
||||
subscriptions.ListEnterpriseSubscriptionsOptions{
|
||||
DisplayNameSubstring: "subscription 2",
|
||||
},
|
||||
)
|
||||
require.NoError(t, err)
|
||||
assert.Len(t, ss, 1)
|
||||
assert.Equal(t, s2.ID, ss[0].ID)
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("list by Salesforce subscription ID", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
ss, err := s.List(
|
||||
ctx,
|
||||
subscriptions.ListEnterpriseSubscriptionsOptions{
|
||||
SalesforceSubscriptionIDs: []string{"sf_sub_id"},
|
||||
},
|
||||
)
|
||||
require.NoError(t, err)
|
||||
assert.Len(t, ss, 1)
|
||||
assert.Equal(t, s1.ID, ss[0].ID)
|
||||
})
|
||||
|
||||
t.Run("list with page size", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
ss, err := s.List(
|
||||
ctx,
|
||||
subscriptions.ListEnterpriseSubscriptionsOptions{
|
||||
|
||||
@ -11,6 +11,7 @@ import (
|
||||
"github.com/sourcegraph/sourcegraph/internal/redislock"
|
||||
"github.com/sourcegraph/sourcegraph/internal/redispool"
|
||||
"github.com/sourcegraph/sourcegraph/internal/slack"
|
||||
"github.com/sourcegraph/sourcegraph/lib/pointers"
|
||||
)
|
||||
|
||||
type Store interface {
|
||||
@ -72,7 +73,7 @@ func (s *storeHandle) TryAcquireJob(ctx context.Context) (acquired bool, release
|
||||
|
||||
func (s *storeHandle) ListSubscriptions(ctx context.Context) ([]*subscriptions.SubscriptionWithConditions, error) {
|
||||
return s.subscriptions.List(ctx, subscriptions.ListEnterpriseSubscriptionsOptions{
|
||||
IsArchived: false,
|
||||
IsArchived: pointers.Ptr(false),
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@ -68,9 +68,9 @@ func convertSubscriptionToProto(subscription *subscriptions.SubscriptionWithCond
|
||||
}
|
||||
}
|
||||
|
||||
var sf *subscriptionsv1.EnterpriseSubscription_SalesforceMetadata
|
||||
var sf *subscriptionsv1.EnterpriseSubscriptionSalesforceMetadata
|
||||
if subscription.SalesforceSubscriptionID != nil {
|
||||
sf = &subscriptionsv1.EnterpriseSubscription_SalesforceMetadata{
|
||||
sf = &subscriptionsv1.EnterpriseSubscriptionSalesforceMetadata{
|
||||
SubscriptionId: pointers.DerefZero(subscription.SalesforceSubscriptionID),
|
||||
}
|
||||
}
|
||||
|
||||
@ -74,8 +74,13 @@ func (s *handlerV1) ListEnterpriseSubscriptions(ctx context.Context, req *connec
|
||||
|
||||
// Validate and process filters.
|
||||
filters := req.Msg.GetFilters()
|
||||
isArchived := false
|
||||
subscriptionIDs := make(collections.Set[string], len(filters))
|
||||
var (
|
||||
isArchived *bool
|
||||
subscriptionIDs = make(collections.Set[string], len(filters))
|
||||
displayNameSubstring string
|
||||
salesforceSubscriptionIDs []string
|
||||
instanceDomains []string
|
||||
)
|
||||
var iamListObjectOptions *iam.ListObjectsOptions
|
||||
for _, filter := range filters {
|
||||
switch f := filter.GetFilter().(type) {
|
||||
@ -89,7 +94,7 @@ func (s *handlerV1) ListEnterpriseSubscriptions(ctx context.Context, req *connec
|
||||
subscriptionIDs.Add(
|
||||
strings.TrimPrefix(f.SubscriptionId, subscriptionsv1.EnterpriseSubscriptionIDPrefix))
|
||||
case *subscriptionsv1.ListEnterpriseSubscriptionsFilter_IsArchived:
|
||||
isArchived = f.IsArchived
|
||||
isArchived = &f.IsArchived
|
||||
case *subscriptionsv1.ListEnterpriseSubscriptionsFilter_Permission:
|
||||
if f.Permission == nil {
|
||||
return nil, connect.NewError(
|
||||
@ -130,6 +135,39 @@ func (s *handlerV1) ListEnterpriseSubscriptions(ctx context.Context, req *connec
|
||||
errors.Wrap(err, `invalid filter: "permission" provided but invalid`),
|
||||
)
|
||||
}
|
||||
case *subscriptionsv1.ListEnterpriseSubscriptionsFilter_DisplayName:
|
||||
if displayNameSubstring != "" {
|
||||
return nil, connect.NewError(
|
||||
connect.CodeInvalidArgument,
|
||||
errors.Newf(`invalid filter: "display_name" provided more than once`),
|
||||
)
|
||||
}
|
||||
const minLength = 3
|
||||
if len(f.DisplayName) < minLength {
|
||||
return nil, connect.NewError(
|
||||
connect.CodeInvalidArgument,
|
||||
errors.Newf(`invalid filter: "display_name" must be longer than %d characters`, minLength),
|
||||
)
|
||||
}
|
||||
displayNameSubstring = f.DisplayName
|
||||
case *subscriptionsv1.ListEnterpriseSubscriptionsFilter_Salesforce:
|
||||
if f.Salesforce.SubscriptionId == "" {
|
||||
return nil, connect.NewError(
|
||||
connect.CodeInvalidArgument,
|
||||
errors.Newf(`invalid filter: "salesforce.subscription_id" is empty`),
|
||||
)
|
||||
}
|
||||
salesforceSubscriptionIDs = append(salesforceSubscriptionIDs,
|
||||
f.Salesforce.SubscriptionId)
|
||||
case *subscriptionsv1.ListEnterpriseSubscriptionsFilter_InstanceDomain:
|
||||
domain, err := subscriptionsv1.NormalizeInstanceDomain(f.InstanceDomain)
|
||||
if err != nil {
|
||||
return nil, connect.NewError(
|
||||
connect.CodeInvalidArgument,
|
||||
errors.Wrap(err, `invalid filter: "domain" provided but invalid`),
|
||||
)
|
||||
}
|
||||
instanceDomains = append(instanceDomains, domain)
|
||||
}
|
||||
}
|
||||
|
||||
@ -165,9 +203,13 @@ func (s *handlerV1) ListEnterpriseSubscriptions(ctx context.Context, req *connec
|
||||
subs, err := s.store.ListEnterpriseSubscriptions(
|
||||
ctx,
|
||||
subscriptions.ListEnterpriseSubscriptionsOptions{
|
||||
IDs: subscriptionIDs.Values(),
|
||||
IsArchived: isArchived,
|
||||
PageSize: int(req.Msg.GetPageSize()),
|
||||
IDs: subscriptionIDs.Values(),
|
||||
IsArchived: isArchived,
|
||||
InstanceDomains: instanceDomains,
|
||||
DisplayNameSubstring: displayNameSubstring,
|
||||
SalesforceSubscriptionIDs: salesforceSubscriptionIDs,
|
||||
|
||||
PageSize: int(req.Msg.GetPageSize()),
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
@ -236,10 +278,11 @@ func (s *handlerV1) ListEnterpriseSubscriptionLicenses(ctx context.Context, req
|
||||
opts.LicenseType = f.Type
|
||||
|
||||
case *subscriptionsv1.ListEnterpriseSubscriptionLicensesFilter_LicenseKeySubstring:
|
||||
if f.LicenseKeySubstring == "" {
|
||||
const minLength = 3
|
||||
if len(f.LicenseKeySubstring) < minLength {
|
||||
return nil, connect.NewError(
|
||||
connect.CodeInvalidArgument,
|
||||
errors.New(`invalid filter: "license_key_substring" is provided but is empty`),
|
||||
errors.Newf(`invalid filter: "license_key_substring" must be longer than %d characters`, minLength),
|
||||
)
|
||||
}
|
||||
if opts.LicenseKeySubstring != "" {
|
||||
@ -264,15 +307,31 @@ func (s *handlerV1) ListEnterpriseSubscriptionLicenses(ctx context.Context, req
|
||||
)
|
||||
}
|
||||
opts.SubscriptionID = f.SubscriptionId
|
||||
|
||||
case *subscriptionsv1.ListEnterpriseSubscriptionLicensesFilter_SalesforceOpportunityId:
|
||||
if f.SalesforceOpportunityId == "" {
|
||||
return nil, connect.NewError(
|
||||
connect.CodeInvalidArgument,
|
||||
errors.New(`invalid filter: "salesforce_opportunity_id" provided but is empty`),
|
||||
)
|
||||
}
|
||||
opts.SalesforceOpportunityID = f.SalesforceOpportunityId
|
||||
}
|
||||
}
|
||||
|
||||
if opts.LicenseType != subscriptionsv1.EnterpriseSubscriptionLicenseType_ENTERPRISE_SUBSCRIPTION_LICENSE_TYPE_KEY &&
|
||||
opts.LicenseKeySubstring != "" {
|
||||
return nil, connect.NewError(
|
||||
connect.CodeInvalidArgument,
|
||||
errors.New(`invalid filters: "license_type" must be 'ENTERPRISE_SUBSCRIPTION_LICENSE_TYPE_KEY' to use the "license_key_substring" filter`),
|
||||
)
|
||||
if opts.LicenseType != subscriptionsv1.EnterpriseSubscriptionLicenseType_ENTERPRISE_SUBSCRIPTION_LICENSE_TYPE_KEY {
|
||||
if opts.LicenseKeySubstring != "" {
|
||||
return nil, connect.NewError(
|
||||
connect.CodeInvalidArgument,
|
||||
errors.New(`invalid filters: "license_type" must be 'ENTERPRISE_SUBSCRIPTION_LICENSE_TYPE_KEY' to use the "license_key_substring" filter`),
|
||||
)
|
||||
}
|
||||
if opts.SalesforceOpportunityID != "" {
|
||||
return nil, connect.NewError(
|
||||
connect.CodeInvalidArgument,
|
||||
errors.New(`invalid filters: "license_type" must be 'ENTERPRISE_SUBSCRIPTION_LICENSE_TYPE_KEY' to use the "salesforce_opportunity_id" filter`),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
licenses, err := s.store.ListEnterpriseSubscriptionLicenses(ctx, opts)
|
||||
|
||||
1366
lib/enterpriseportal/subscriptions/v1/subscriptions.pb.go
generated
1366
lib/enterpriseportal/subscriptions/v1/subscriptions.pb.go
generated
File diff suppressed because it is too large
Load Diff
@ -95,6 +95,11 @@ message EnterpriseSubscriptionCondition {
|
||||
string message = 3;
|
||||
}
|
||||
|
||||
message EnterpriseSubscriptionSalesforceMetadata {
|
||||
// The Salesforce subscription ID associated with this Enterprise subscription.
|
||||
string subscription_id = 1;
|
||||
}
|
||||
|
||||
// EnterpriseSubscription represents a Sourcegraph Enterprise subscription.
|
||||
message EnterpriseSubscription {
|
||||
// ID is the external, prefixed UUID-format identifier for this subscription
|
||||
@ -107,12 +112,8 @@ message EnterpriseSubscription {
|
||||
// The instance domain associated with this subscription, e.g. "acme.sourcegraphcloud.com".
|
||||
string instance_domain = 4;
|
||||
|
||||
message SalesforceMetadata {
|
||||
// The Salesforce subscription ID associated with this Enterprise subscription.
|
||||
string subscription_id = 1;
|
||||
}
|
||||
// Salesforce details associated with this subscription.
|
||||
SalesforceMetadata salesforce = 5;
|
||||
EnterpriseSubscriptionSalesforceMetadata salesforce = 5;
|
||||
}
|
||||
|
||||
// EnterpriseSubscriptionLicenseKey is the classic offline Sourcegraph license
|
||||
@ -208,12 +209,20 @@ enum EnterpriseSubscriptionLicenseType {
|
||||
|
||||
message ListEnterpriseSubscriptionsFilter {
|
||||
oneof filter {
|
||||
// Return only product subscriptions has the given subscription ID.
|
||||
// Filter by exact match on the Enterprise Subscription ID.
|
||||
string subscription_id = 1;
|
||||
// Return only product subscriptions with the given archival status.
|
||||
bool is_archived = 2;
|
||||
// Return only product subscriptions that satisfies the given permission.
|
||||
Permission permission = 3;
|
||||
// Filter by partial match on display name. The query must be at least 3
|
||||
// characters long.
|
||||
string display_name = 4;
|
||||
// Filter by exact match on Salesforce metadata.
|
||||
EnterpriseSubscriptionSalesforceMetadata salesforce = 5;
|
||||
// Filter by partial match on instance domain. The query must be a valid
|
||||
// domain.
|
||||
string instance_domain = 6;
|
||||
}
|
||||
}
|
||||
|
||||
@ -252,9 +261,15 @@ message ListEnterpriseSubscriptionLicensesFilter {
|
||||
EnterpriseSubscriptionLicenseType type = 2;
|
||||
// Return only licenses that are active.
|
||||
bool is_revoked = 3;
|
||||
// Return only product subscriptions whose license key contains this
|
||||
// substring.
|
||||
// Return only licenses where the signed license key contains this substring.
|
||||
// Query must be at least 3 characters.
|
||||
//
|
||||
// MUST be used in conjunction with the type = 'ENTERPRISE_SUBSCRIPTION_LICENSE_TYPE_KEY'
|
||||
// filter.
|
||||
string license_key_substring = 4;
|
||||
// Return only licenses associated with this Salesforce opportunity ID.
|
||||
// MUST be used in conjunction with the 'type' filter.
|
||||
string salesforce_opportunity_id = 5;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user