From fa7d5bc616f6b6fe34a534e2eaf62fde6de66cd6 Mon Sep 17 00:00:00 2001 From: Robert Lin Date: Fri, 19 Jul 2024 14:03:30 -0700 Subject: [PATCH] feat/enterpriseportal: all subscriptions APIs use enterprise portal DB --- .../internal/database/codyaccess/BUILD.bazel | 2 +- .../database/codyaccess/codygateway_test.go | 2 +- .../internal/database/importer/BUILD.bazel | 2 +- .../internal/database/importer/importer.go | 6 +- .../database/subscriptions/BUILD.bazel | 4 +- .../subscriptions/license_conditions.go | 2 +- .../database/subscriptions/licenses.go | 5 +- .../database/subscriptions/licenses_test.go | 2 +- .../database/subscriptions/subscriptions.go | 18 +- .../subscriptions/subscriptions_conditions.go | 2 +- .../subscriptions/subscriptions_test.go | 2 +- .../internal/database/types.go | 10 + .../{internal => }/utctime/BUILD.bazel | 2 +- .../{internal => }/utctime/utctime.go | 0 .../internal/subscriptionsservice/BUILD.bazel | 3 + .../internal/subscriptionsservice/adapters.go | 4 +- .../subscriptionsservice/mocks_test.go | 435 +++++++++++++++- .../internal/subscriptionsservice/v1.go | 321 +++++++++++- .../internal/subscriptionsservice/v1_store.go | 55 +- .../internal/subscriptionsservice/v1_test.go | 11 +- .../subscriptions/v1/subscriptions.pb.go | 489 +++++++++--------- .../subscriptions/v1/subscriptions.proto | 8 + 22 files changed, 1092 insertions(+), 293 deletions(-) rename cmd/enterprise-portal/internal/database/{internal => }/utctime/BUILD.bazel (86%) rename cmd/enterprise-portal/internal/database/{internal => }/utctime/utctime.go (100%) diff --git a/cmd/enterprise-portal/internal/database/codyaccess/BUILD.bazel b/cmd/enterprise-portal/internal/database/codyaccess/BUILD.bazel index b8511da53c84b..b2229b8e37c3f 100644 --- a/cmd/enterprise-portal/internal/database/codyaccess/BUILD.bazel +++ b/cmd/enterprise-portal/internal/database/codyaccess/BUILD.bazel @@ -33,8 +33,8 @@ go_test( "//cmd/enterprise-portal/internal/database", "//cmd/enterprise-portal/internal/database/databasetest", "//cmd/enterprise-portal/internal/database/internal/tables", - "//cmd/enterprise-portal/internal/database/internal/utctime", "//cmd/enterprise-portal/internal/database/subscriptions", + "//cmd/enterprise-portal/internal/database/utctime", "//internal/license", "//lib/pointers", "@com_github_google_uuid//:uuid", diff --git a/cmd/enterprise-portal/internal/database/codyaccess/codygateway_test.go b/cmd/enterprise-portal/internal/database/codyaccess/codygateway_test.go index 0d7e3d85b7359..830c66a1a2fab 100644 --- a/cmd/enterprise-portal/internal/database/codyaccess/codygateway_test.go +++ b/cmd/enterprise-portal/internal/database/codyaccess/codygateway_test.go @@ -15,8 +15,8 @@ import ( "github.com/sourcegraph/sourcegraph/cmd/enterprise-portal/internal/database/codyaccess" "github.com/sourcegraph/sourcegraph/cmd/enterprise-portal/internal/database/databasetest" "github.com/sourcegraph/sourcegraph/cmd/enterprise-portal/internal/database/internal/tables" - "github.com/sourcegraph/sourcegraph/cmd/enterprise-portal/internal/database/internal/utctime" "github.com/sourcegraph/sourcegraph/cmd/enterprise-portal/internal/database/subscriptions" + "github.com/sourcegraph/sourcegraph/cmd/enterprise-portal/internal/database/utctime" "github.com/sourcegraph/sourcegraph/internal/license" "github.com/sourcegraph/sourcegraph/lib/pointers" ) diff --git a/cmd/enterprise-portal/internal/database/importer/BUILD.bazel b/cmd/enterprise-portal/internal/database/importer/BUILD.bazel index 3875fa8a318d1..09904cc1473d0 100644 --- a/cmd/enterprise-portal/internal/database/importer/BUILD.bazel +++ b/cmd/enterprise-portal/internal/database/importer/BUILD.bazel @@ -8,8 +8,8 @@ go_library( deps = [ "//cmd/enterprise-portal/internal/database", "//cmd/enterprise-portal/internal/database/codyaccess", - "//cmd/enterprise-portal/internal/database/internal/utctime", "//cmd/enterprise-portal/internal/database/subscriptions", + "//cmd/enterprise-portal/internal/database/utctime", "//cmd/enterprise-portal/internal/dotcomdb", "//internal/goroutine", "//internal/license", diff --git a/cmd/enterprise-portal/internal/database/importer/importer.go b/cmd/enterprise-portal/internal/database/importer/importer.go index 66713e6b01618..72ba617f84ebe 100644 --- a/cmd/enterprise-portal/internal/database/importer/importer.go +++ b/cmd/enterprise-portal/internal/database/importer/importer.go @@ -13,8 +13,8 @@ import ( "github.com/sourcegraph/sourcegraph/cmd/enterprise-portal/internal/database" "github.com/sourcegraph/sourcegraph/cmd/enterprise-portal/internal/database/codyaccess" - "github.com/sourcegraph/sourcegraph/cmd/enterprise-portal/internal/database/internal/utctime" "github.com/sourcegraph/sourcegraph/cmd/enterprise-portal/internal/database/subscriptions" + "github.com/sourcegraph/sourcegraph/cmd/enterprise-portal/internal/database/utctime" "github.com/sourcegraph/sourcegraph/cmd/enterprise-portal/internal/dotcomdb" "github.com/sourcegraph/sourcegraph/internal/goroutine" "github.com/sourcegraph/sourcegraph/internal/license" @@ -198,8 +198,8 @@ func (i *Importer) importSubscription(ctx context.Context, dotcomSub *dotcomdb.S } return pointers.Ptr(utctime.FromTime(*dotcomSub.ArchivedAt)) }(), - SalesforceSubscriptionID: activeLicense.SalesforceSubscriptionID, - SalesforceOpportunityID: activeLicense.SalesforceOpportunityID, + SalesforceSubscriptionID: pointers.Ptr(database.NewNullStringPtr(activeLicense.SalesforceSubscriptionID)), + SalesforceOpportunityID: pointers.Ptr(database.NewNullStringPtr(activeLicense.SalesforceOpportunityID)), }, conditions..., ); err != nil { diff --git a/cmd/enterprise-portal/internal/database/subscriptions/BUILD.bazel b/cmd/enterprise-portal/internal/database/subscriptions/BUILD.bazel index a8c66f47dee7b..f42bdd428058c 100644 --- a/cmd/enterprise-portal/internal/database/subscriptions/BUILD.bazel +++ b/cmd/enterprise-portal/internal/database/subscriptions/BUILD.bazel @@ -15,7 +15,7 @@ go_library( deps = [ "//cmd/enterprise-portal/internal/database/internal/pgxerrors", "//cmd/enterprise-portal/internal/database/internal/upsert", - "//cmd/enterprise-portal/internal/database/internal/utctime", + "//cmd/enterprise-portal/internal/database/utctime", "//internal/license", "//lib/enterpriseportal/subscriptions/v1:subscriptions", "//lib/errors", @@ -42,7 +42,7 @@ go_test( "//cmd/enterprise-portal/internal/database", "//cmd/enterprise-portal/internal/database/databasetest", "//cmd/enterprise-portal/internal/database/internal/tables", - "//cmd/enterprise-portal/internal/database/internal/utctime", + "//cmd/enterprise-portal/internal/database/utctime", "//internal/license", "//lib/enterpriseportal/subscriptions/v1:subscriptions", "//lib/pointers", diff --git a/cmd/enterprise-portal/internal/database/subscriptions/license_conditions.go b/cmd/enterprise-portal/internal/database/subscriptions/license_conditions.go index 720cf905d8263..e7fb162c9377c 100644 --- a/cmd/enterprise-portal/internal/database/subscriptions/license_conditions.go +++ b/cmd/enterprise-portal/internal/database/subscriptions/license_conditions.go @@ -6,7 +6,7 @@ import ( "github.com/jackc/pgx/v5" "gorm.io/gorm" - "github.com/sourcegraph/sourcegraph/cmd/enterprise-portal/internal/database/internal/utctime" + "github.com/sourcegraph/sourcegraph/cmd/enterprise-portal/internal/database/utctime" subscriptionsv1 "github.com/sourcegraph/sourcegraph/lib/enterpriseportal/subscriptions/v1" "github.com/sourcegraph/sourcegraph/lib/errors" "github.com/sourcegraph/sourcegraph/lib/pointers" diff --git a/cmd/enterprise-portal/internal/database/subscriptions/licenses.go b/cmd/enterprise-portal/internal/database/subscriptions/licenses.go index 901141559a915..67b472a1853b7 100644 --- a/cmd/enterprise-portal/internal/database/subscriptions/licenses.go +++ b/cmd/enterprise-portal/internal/database/subscriptions/licenses.go @@ -13,7 +13,7 @@ import ( "gorm.io/gorm" "github.com/sourcegraph/sourcegraph/cmd/enterprise-portal/internal/database/internal/pgxerrors" - "github.com/sourcegraph/sourcegraph/cmd/enterprise-portal/internal/database/internal/utctime" + "github.com/sourcegraph/sourcegraph/cmd/enterprise-portal/internal/database/utctime" internallicense "github.com/sourcegraph/sourcegraph/internal/license" subscriptionsv1 "github.com/sourcegraph/sourcegraph/lib/enterpriseportal/subscriptions/v1" "github.com/sourcegraph/sourcegraph/lib/pointers" @@ -399,6 +399,9 @@ WHERE id = @licenseID "revokedAt": opts.Time, "licenseID": licenseID, }); err != nil { + if errors.Is(err, pgx.ErrNoRows) { + return nil, ErrSubscriptionLicenseNotFound + } return nil, errors.Wrap(err, "revoke license") } diff --git a/cmd/enterprise-portal/internal/database/subscriptions/licenses_test.go b/cmd/enterprise-portal/internal/database/subscriptions/licenses_test.go index 0b6f0f7c0d4e0..e88c5e00243cb 100644 --- a/cmd/enterprise-portal/internal/database/subscriptions/licenses_test.go +++ b/cmd/enterprise-portal/internal/database/subscriptions/licenses_test.go @@ -15,8 +15,8 @@ import ( "github.com/sourcegraph/sourcegraph/cmd/enterprise-portal/internal/database" "github.com/sourcegraph/sourcegraph/cmd/enterprise-portal/internal/database/databasetest" "github.com/sourcegraph/sourcegraph/cmd/enterprise-portal/internal/database/internal/tables" - "github.com/sourcegraph/sourcegraph/cmd/enterprise-portal/internal/database/internal/utctime" "github.com/sourcegraph/sourcegraph/cmd/enterprise-portal/internal/database/subscriptions" + "github.com/sourcegraph/sourcegraph/cmd/enterprise-portal/internal/database/utctime" "github.com/sourcegraph/sourcegraph/internal/license" "github.com/sourcegraph/sourcegraph/lib/pointers" ) diff --git a/cmd/enterprise-portal/internal/database/subscriptions/subscriptions.go b/cmd/enterprise-portal/internal/database/subscriptions/subscriptions.go index 701f14a5f8086..5a81190da7b49 100644 --- a/cmd/enterprise-portal/internal/database/subscriptions/subscriptions.go +++ b/cmd/enterprise-portal/internal/database/subscriptions/subscriptions.go @@ -12,7 +12,7 @@ import ( "github.com/sourcegraph/sourcegraph/cmd/enterprise-portal/internal/database/internal/pgxerrors" "github.com/sourcegraph/sourcegraph/cmd/enterprise-portal/internal/database/internal/upsert" - "github.com/sourcegraph/sourcegraph/cmd/enterprise-portal/internal/database/internal/utctime" + "github.com/sourcegraph/sourcegraph/cmd/enterprise-portal/internal/database/utctime" "github.com/sourcegraph/sourcegraph/lib/errors" ) @@ -205,8 +205,8 @@ type UpsertSubscriptionOptions struct { CreatedAt utctime.Time ArchivedAt *utctime.Time - SalesforceSubscriptionID *string - SalesforceOpportunityID *string + SalesforceSubscriptionID *sql.NullString + SalesforceOpportunityID *sql.NullString // ForceUpdate indicates whether to force update all fields of the subscription // record. @@ -235,9 +235,14 @@ func (opts UpsertSubscriptionOptions) apply(ctx context.Context, db upsert.Exece return b.Exec(ctx, db) } +var ErrInvalidArgument = errors.New("invalid argument") + // Upsert upserts a subscription record based on the given options. If the // operation has additional application meaning, conditions can be provided // for insert as well. +// +// Constraint errors are returned as a human-friendly error that wraps +// ErrInvalidArgument. func (s *Store) Upsert( ctx context.Context, subscriptionID string, @@ -267,7 +272,12 @@ func (s *Store) Upsert( if err := opts.apply(ctx, tx, subscriptionID); err != nil { if pgxerrors.IsContraintError(err, "idx_enterprise_portal_subscriptions_display_name") { return nil, errors.WithSafeDetails( - errors.Newf("display_name %q is already in use", opts.DisplayName.String), + errors.Wrapf(ErrInvalidArgument, "display_name %q is already in use", opts.DisplayName.String), + "%+v", err) + } + if pgxerrors.IsContraintError(err, "idx_enterprise_portal_subscriptions_instance_domain") { + return nil, errors.WithSafeDetails( + errors.Wrapf(ErrInvalidArgument, "instance_domain %q is assigned to another subscription", opts.DisplayName.String), "%+v", err) } return nil, errors.Wrap(err, "upsert") diff --git a/cmd/enterprise-portal/internal/database/subscriptions/subscriptions_conditions.go b/cmd/enterprise-portal/internal/database/subscriptions/subscriptions_conditions.go index 3d4a35a560bb9..927296be1ea92 100644 --- a/cmd/enterprise-portal/internal/database/subscriptions/subscriptions_conditions.go +++ b/cmd/enterprise-portal/internal/database/subscriptions/subscriptions_conditions.go @@ -6,7 +6,7 @@ import ( "github.com/jackc/pgx/v5" "gorm.io/gorm" - "github.com/sourcegraph/sourcegraph/cmd/enterprise-portal/internal/database/internal/utctime" + "github.com/sourcegraph/sourcegraph/cmd/enterprise-portal/internal/database/utctime" subscriptionsv1 "github.com/sourcegraph/sourcegraph/lib/enterpriseportal/subscriptions/v1" "github.com/sourcegraph/sourcegraph/lib/errors" "github.com/sourcegraph/sourcegraph/lib/pointers" diff --git a/cmd/enterprise-portal/internal/database/subscriptions/subscriptions_test.go b/cmd/enterprise-portal/internal/database/subscriptions/subscriptions_test.go index 867663de1f9ca..22be2a76d9d75 100644 --- a/cmd/enterprise-portal/internal/database/subscriptions/subscriptions_test.go +++ b/cmd/enterprise-portal/internal/database/subscriptions/subscriptions_test.go @@ -12,8 +12,8 @@ import ( "github.com/sourcegraph/sourcegraph/cmd/enterprise-portal/internal/database" "github.com/sourcegraph/sourcegraph/cmd/enterprise-portal/internal/database/databasetest" "github.com/sourcegraph/sourcegraph/cmd/enterprise-portal/internal/database/internal/tables" - "github.com/sourcegraph/sourcegraph/cmd/enterprise-portal/internal/database/internal/utctime" "github.com/sourcegraph/sourcegraph/cmd/enterprise-portal/internal/database/subscriptions" + "github.com/sourcegraph/sourcegraph/cmd/enterprise-portal/internal/database/utctime" subscriptionsv1 "github.com/sourcegraph/sourcegraph/lib/enterpriseportal/subscriptions/v1" "github.com/sourcegraph/sourcegraph/lib/pointers" ) diff --git a/cmd/enterprise-portal/internal/database/types.go b/cmd/enterprise-portal/internal/database/types.go index 366ed5e5481b6..0a3ee6d1c360a 100644 --- a/cmd/enterprise-portal/internal/database/types.go +++ b/cmd/enterprise-portal/internal/database/types.go @@ -8,3 +8,13 @@ func NewNullString(v string) sql.NullString { Valid: v != "", } } + +func NewNullStringPtr(v *string) sql.NullString { + if v == nil { + return sql.NullString{} + } + return sql.NullString{ + String: *v, + Valid: *v != "", + } +} diff --git a/cmd/enterprise-portal/internal/database/internal/utctime/BUILD.bazel b/cmd/enterprise-portal/internal/database/utctime/BUILD.bazel similarity index 86% rename from cmd/enterprise-portal/internal/database/internal/utctime/BUILD.bazel rename to cmd/enterprise-portal/internal/database/utctime/BUILD.bazel index 8e3be7b56e31e..0737791739283 100644 --- a/cmd/enterprise-portal/internal/database/internal/utctime/BUILD.bazel +++ b/cmd/enterprise-portal/internal/database/utctime/BUILD.bazel @@ -3,7 +3,7 @@ load("@io_bazel_rules_go//go:def.bzl", "go_library") go_library( name = "utctime", srcs = ["utctime.go"], - importpath = "github.com/sourcegraph/sourcegraph/cmd/enterprise-portal/internal/database/internal/utctime", + importpath = "github.com/sourcegraph/sourcegraph/cmd/enterprise-portal/internal/database/utctime", visibility = ["//cmd/enterprise-portal:__subpackages__"], deps = [ "//lib/errors", diff --git a/cmd/enterprise-portal/internal/database/internal/utctime/utctime.go b/cmd/enterprise-portal/internal/database/utctime/utctime.go similarity index 100% rename from cmd/enterprise-portal/internal/database/internal/utctime/utctime.go rename to cmd/enterprise-portal/internal/database/utctime/utctime.go diff --git a/cmd/enterprise-portal/internal/subscriptionsservice/BUILD.bazel b/cmd/enterprise-portal/internal/subscriptionsservice/BUILD.bazel index d547fc7be1df7..b84f2a6e2e66e 100644 --- a/cmd/enterprise-portal/internal/subscriptionsservice/BUILD.bazel +++ b/cmd/enterprise-portal/internal/subscriptionsservice/BUILD.bazel @@ -16,9 +16,11 @@ go_library( "//cmd/enterprise-portal/internal/connectutil", "//cmd/enterprise-portal/internal/database", "//cmd/enterprise-portal/internal/database/subscriptions", + "//cmd/enterprise-portal/internal/database/utctime", "//cmd/enterprise-portal/internal/dotcomdb", "//cmd/enterprise-portal/internal/samsm2m", "//internal/collections", + "//internal/license", "//internal/trace", "//lib/enterpriseportal/subscriptions/v1:subscriptions", "//lib/enterpriseportal/subscriptions/v1/v1connect", @@ -26,6 +28,7 @@ go_library( "//lib/managedservicesplatform/iam", "//lib/pointers", "@com_connectrpc_connect//:connect", + "@com_github_google_uuid//:uuid", "@com_github_sourcegraph_log//:log", "@com_github_sourcegraph_sourcegraph_accounts_sdk_go//:sourcegraph-accounts-sdk-go", "@com_github_sourcegraph_sourcegraph_accounts_sdk_go//clients/v1:clients", diff --git a/cmd/enterprise-portal/internal/subscriptionsservice/adapters.go b/cmd/enterprise-portal/internal/subscriptionsservice/adapters.go index a84afaf1d0a62..3203f5a9280ee 100644 --- a/cmd/enterprise-portal/internal/subscriptionsservice/adapters.go +++ b/cmd/enterprise-portal/internal/subscriptionsservice/adapters.go @@ -2,6 +2,7 @@ package subscriptionsservice import ( "encoding/json" + "strings" "google.golang.org/protobuf/types/known/timestamppb" @@ -107,7 +108,8 @@ func convertProtoToIAMTupleRelation(action subscriptionsv1.PermissionRelation) i func convertProtoRoleToIAMTupleObject(role subscriptionsv1.Role, subscriptionID string) iam.TupleObject { switch role { case subscriptionsv1.Role_ROLE_SUBSCRIPTION_CUSTOMER_ADMIN: - return iam.ToTupleObject(iam.TupleTypeCustomerAdmin, subscriptionID) + return iam.ToTupleObject(iam.TupleTypeCustomerAdmin, + strings.TrimPrefix(subscriptionID, subscriptionsv1.EnterpriseSubscriptionIDPrefix)) default: return "" } diff --git a/cmd/enterprise-portal/internal/subscriptionsservice/mocks_test.go b/cmd/enterprise-portal/internal/subscriptionsservice/mocks_test.go index 8121dfa547208..9272c83b1fc1d 100644 --- a/cmd/enterprise-portal/internal/subscriptionsservice/mocks_test.go +++ b/cmd/enterprise-portal/internal/subscriptionsservice/mocks_test.go @@ -21,6 +21,14 @@ import ( // github.com/sourcegraph/sourcegraph/cmd/enterprise-portal/internal/subscriptionsservice) // used for unit testing. type MockStoreV1 struct { + // CreateEnterpriseSubscriptionLicenseKeyFunc is an instance of a mock + // function object controlling the behavior of the method + // CreateEnterpriseSubscriptionLicenseKey. + CreateEnterpriseSubscriptionLicenseKeyFunc *StoreV1CreateEnterpriseSubscriptionLicenseKeyFunc + // GetEnterpriseSubscriptionFunc is an instance of a mock function + // object controlling the behavior of the method + // GetEnterpriseSubscription. + GetEnterpriseSubscriptionFunc *StoreV1GetEnterpriseSubscriptionFunc // GetSAMSUserByIDFunc is an instance of a mock function object // controlling the behavior of the method GetSAMSUserByID. GetSAMSUserByIDFunc *StoreV1GetSAMSUserByIDFunc @@ -44,6 +52,10 @@ type MockStoreV1 struct { // object controlling the behavior of the method // ListEnterpriseSubscriptions. ListEnterpriseSubscriptionsFunc *StoreV1ListEnterpriseSubscriptionsFunc + // RevokeEnterpriseSubscriptionLicenseFunc is an instance of a mock + // function object controlling the behavior of the method + // RevokeEnterpriseSubscriptionLicense. + RevokeEnterpriseSubscriptionLicenseFunc *StoreV1RevokeEnterpriseSubscriptionLicenseFunc // UpsertEnterpriseSubscriptionFunc is an instance of a mock function // object controlling the behavior of the method // UpsertEnterpriseSubscription. @@ -54,6 +66,16 @@ type MockStoreV1 struct { // return zero values for all results, unless overwritten. func NewMockStoreV1() *MockStoreV1 { return &MockStoreV1{ + CreateEnterpriseSubscriptionLicenseKeyFunc: &StoreV1CreateEnterpriseSubscriptionLicenseKeyFunc{ + defaultHook: func(context.Context, string, *subscriptions.DataLicenseKey, subscriptions.CreateLicenseOpts) (r0 *subscriptions.LicenseWithConditions, r1 error) { + return + }, + }, + GetEnterpriseSubscriptionFunc: &StoreV1GetEnterpriseSubscriptionFunc{ + defaultHook: func(context.Context, string) (r0 *subscriptions.SubscriptionWithConditions, r1 error) { + return + }, + }, GetSAMSUserByIDFunc: &StoreV1GetSAMSUserByIDFunc{ defaultHook: func(context.Context, string) (r0 *v1.User, r1 error) { return @@ -89,8 +111,13 @@ func NewMockStoreV1() *MockStoreV1 { return }, }, + RevokeEnterpriseSubscriptionLicenseFunc: &StoreV1RevokeEnterpriseSubscriptionLicenseFunc{ + defaultHook: func(context.Context, string, subscriptions.RevokeLicenseOpts) (r0 *subscriptions.LicenseWithConditions, r1 error) { + return + }, + }, UpsertEnterpriseSubscriptionFunc: &StoreV1UpsertEnterpriseSubscriptionFunc{ - defaultHook: func(context.Context, string, subscriptions.UpsertSubscriptionOptions) (r0 *subscriptions.SubscriptionWithConditions, r1 error) { + defaultHook: func(context.Context, string, subscriptions.UpsertSubscriptionOptions, ...subscriptions.CreateSubscriptionConditionOptions) (r0 *subscriptions.SubscriptionWithConditions, r1 error) { return }, }, @@ -101,6 +128,16 @@ func NewMockStoreV1() *MockStoreV1 { // methods panic on invocation, unless overwritten. func NewStrictMockStoreV1() *MockStoreV1 { return &MockStoreV1{ + CreateEnterpriseSubscriptionLicenseKeyFunc: &StoreV1CreateEnterpriseSubscriptionLicenseKeyFunc{ + defaultHook: func(context.Context, string, *subscriptions.DataLicenseKey, subscriptions.CreateLicenseOpts) (*subscriptions.LicenseWithConditions, error) { + panic("unexpected invocation of MockStoreV1.CreateEnterpriseSubscriptionLicenseKey") + }, + }, + GetEnterpriseSubscriptionFunc: &StoreV1GetEnterpriseSubscriptionFunc{ + defaultHook: func(context.Context, string) (*subscriptions.SubscriptionWithConditions, error) { + panic("unexpected invocation of MockStoreV1.GetEnterpriseSubscription") + }, + }, GetSAMSUserByIDFunc: &StoreV1GetSAMSUserByIDFunc{ defaultHook: func(context.Context, string) (*v1.User, error) { panic("unexpected invocation of MockStoreV1.GetSAMSUserByID") @@ -136,8 +173,13 @@ func NewStrictMockStoreV1() *MockStoreV1 { panic("unexpected invocation of MockStoreV1.ListEnterpriseSubscriptions") }, }, + RevokeEnterpriseSubscriptionLicenseFunc: &StoreV1RevokeEnterpriseSubscriptionLicenseFunc{ + defaultHook: func(context.Context, string, subscriptions.RevokeLicenseOpts) (*subscriptions.LicenseWithConditions, error) { + panic("unexpected invocation of MockStoreV1.RevokeEnterpriseSubscriptionLicense") + }, + }, UpsertEnterpriseSubscriptionFunc: &StoreV1UpsertEnterpriseSubscriptionFunc{ - defaultHook: func(context.Context, string, subscriptions.UpsertSubscriptionOptions) (*subscriptions.SubscriptionWithConditions, error) { + defaultHook: func(context.Context, string, subscriptions.UpsertSubscriptionOptions, ...subscriptions.CreateSubscriptionConditionOptions) (*subscriptions.SubscriptionWithConditions, error) { panic("unexpected invocation of MockStoreV1.UpsertEnterpriseSubscription") }, }, @@ -148,6 +190,12 @@ func NewStrictMockStoreV1() *MockStoreV1 { // methods delegate to the given implementation, unless overwritten. func NewMockStoreV1From(i StoreV1) *MockStoreV1 { return &MockStoreV1{ + CreateEnterpriseSubscriptionLicenseKeyFunc: &StoreV1CreateEnterpriseSubscriptionLicenseKeyFunc{ + defaultHook: i.CreateEnterpriseSubscriptionLicenseKey, + }, + GetEnterpriseSubscriptionFunc: &StoreV1GetEnterpriseSubscriptionFunc{ + defaultHook: i.GetEnterpriseSubscription, + }, GetSAMSUserByIDFunc: &StoreV1GetSAMSUserByIDFunc{ defaultHook: i.GetSAMSUserByID, }, @@ -169,12 +217,245 @@ func NewMockStoreV1From(i StoreV1) *MockStoreV1 { ListEnterpriseSubscriptionsFunc: &StoreV1ListEnterpriseSubscriptionsFunc{ defaultHook: i.ListEnterpriseSubscriptions, }, + RevokeEnterpriseSubscriptionLicenseFunc: &StoreV1RevokeEnterpriseSubscriptionLicenseFunc{ + defaultHook: i.RevokeEnterpriseSubscriptionLicense, + }, UpsertEnterpriseSubscriptionFunc: &StoreV1UpsertEnterpriseSubscriptionFunc{ defaultHook: i.UpsertEnterpriseSubscription, }, } } +// StoreV1CreateEnterpriseSubscriptionLicenseKeyFunc describes the behavior +// when the CreateEnterpriseSubscriptionLicenseKey method of the parent +// MockStoreV1 instance is invoked. +type StoreV1CreateEnterpriseSubscriptionLicenseKeyFunc struct { + defaultHook func(context.Context, string, *subscriptions.DataLicenseKey, subscriptions.CreateLicenseOpts) (*subscriptions.LicenseWithConditions, error) + hooks []func(context.Context, string, *subscriptions.DataLicenseKey, subscriptions.CreateLicenseOpts) (*subscriptions.LicenseWithConditions, error) + history []StoreV1CreateEnterpriseSubscriptionLicenseKeyFuncCall + mutex sync.Mutex +} + +// CreateEnterpriseSubscriptionLicenseKey delegates to the next hook +// function in the queue and stores the parameter and result values of this +// invocation. +func (m *MockStoreV1) CreateEnterpriseSubscriptionLicenseKey(v0 context.Context, v1 string, v2 *subscriptions.DataLicenseKey, v3 subscriptions.CreateLicenseOpts) (*subscriptions.LicenseWithConditions, error) { + r0, r1 := m.CreateEnterpriseSubscriptionLicenseKeyFunc.nextHook()(v0, v1, v2, v3) + m.CreateEnterpriseSubscriptionLicenseKeyFunc.appendCall(StoreV1CreateEnterpriseSubscriptionLicenseKeyFuncCall{v0, v1, v2, v3, r0, r1}) + return r0, r1 +} + +// SetDefaultHook sets function that is called when the +// CreateEnterpriseSubscriptionLicenseKey method of the parent MockStoreV1 +// instance is invoked and the hook queue is empty. +func (f *StoreV1CreateEnterpriseSubscriptionLicenseKeyFunc) SetDefaultHook(hook func(context.Context, string, *subscriptions.DataLicenseKey, subscriptions.CreateLicenseOpts) (*subscriptions.LicenseWithConditions, error)) { + f.defaultHook = hook +} + +// PushHook adds a function to the end of hook queue. Each invocation of the +// CreateEnterpriseSubscriptionLicenseKey method of the parent MockStoreV1 +// instance invokes the hook at the front of the queue and discards it. +// After the queue is empty, the default hook function is invoked for any +// future action. +func (f *StoreV1CreateEnterpriseSubscriptionLicenseKeyFunc) PushHook(hook func(context.Context, string, *subscriptions.DataLicenseKey, subscriptions.CreateLicenseOpts) (*subscriptions.LicenseWithConditions, error)) { + f.mutex.Lock() + f.hooks = append(f.hooks, hook) + f.mutex.Unlock() +} + +// SetDefaultReturn calls SetDefaultHook with a function that returns the +// given values. +func (f *StoreV1CreateEnterpriseSubscriptionLicenseKeyFunc) SetDefaultReturn(r0 *subscriptions.LicenseWithConditions, r1 error) { + f.SetDefaultHook(func(context.Context, string, *subscriptions.DataLicenseKey, subscriptions.CreateLicenseOpts) (*subscriptions.LicenseWithConditions, error) { + return r0, r1 + }) +} + +// PushReturn calls PushHook with a function that returns the given values. +func (f *StoreV1CreateEnterpriseSubscriptionLicenseKeyFunc) PushReturn(r0 *subscriptions.LicenseWithConditions, r1 error) { + f.PushHook(func(context.Context, string, *subscriptions.DataLicenseKey, subscriptions.CreateLicenseOpts) (*subscriptions.LicenseWithConditions, error) { + return r0, r1 + }) +} + +func (f *StoreV1CreateEnterpriseSubscriptionLicenseKeyFunc) nextHook() func(context.Context, string, *subscriptions.DataLicenseKey, subscriptions.CreateLicenseOpts) (*subscriptions.LicenseWithConditions, error) { + f.mutex.Lock() + defer f.mutex.Unlock() + + if len(f.hooks) == 0 { + return f.defaultHook + } + + hook := f.hooks[0] + f.hooks = f.hooks[1:] + return hook +} + +func (f *StoreV1CreateEnterpriseSubscriptionLicenseKeyFunc) appendCall(r0 StoreV1CreateEnterpriseSubscriptionLicenseKeyFuncCall) { + f.mutex.Lock() + f.history = append(f.history, r0) + f.mutex.Unlock() +} + +// History returns a sequence of +// StoreV1CreateEnterpriseSubscriptionLicenseKeyFuncCall objects describing +// the invocations of this function. +func (f *StoreV1CreateEnterpriseSubscriptionLicenseKeyFunc) History() []StoreV1CreateEnterpriseSubscriptionLicenseKeyFuncCall { + f.mutex.Lock() + history := make([]StoreV1CreateEnterpriseSubscriptionLicenseKeyFuncCall, len(f.history)) + copy(history, f.history) + f.mutex.Unlock() + + return history +} + +// StoreV1CreateEnterpriseSubscriptionLicenseKeyFuncCall is an object that +// describes an invocation of method CreateEnterpriseSubscriptionLicenseKey +// on an instance of MockStoreV1. +type StoreV1CreateEnterpriseSubscriptionLicenseKeyFuncCall struct { + // Arg0 is the value of the 1st argument passed to this method + // invocation. + Arg0 context.Context + // Arg1 is the value of the 2nd argument passed to this method + // invocation. + Arg1 string + // Arg2 is the value of the 3rd argument passed to this method + // invocation. + Arg2 *subscriptions.DataLicenseKey + // Arg3 is the value of the 4th argument passed to this method + // invocation. + Arg3 subscriptions.CreateLicenseOpts + // Result0 is the value of the 1st result returned from this method + // invocation. + Result0 *subscriptions.LicenseWithConditions + // Result1 is the value of the 2nd result returned from this method + // invocation. + Result1 error +} + +// Args returns an interface slice containing the arguments of this +// invocation. +func (c StoreV1CreateEnterpriseSubscriptionLicenseKeyFuncCall) Args() []interface{} { + return []interface{}{c.Arg0, c.Arg1, c.Arg2, c.Arg3} +} + +// Results returns an interface slice containing the results of this +// invocation. +func (c StoreV1CreateEnterpriseSubscriptionLicenseKeyFuncCall) Results() []interface{} { + return []interface{}{c.Result0, c.Result1} +} + +// StoreV1GetEnterpriseSubscriptionFunc describes the behavior when the +// GetEnterpriseSubscription method of the parent MockStoreV1 instance is +// invoked. +type StoreV1GetEnterpriseSubscriptionFunc struct { + defaultHook func(context.Context, string) (*subscriptions.SubscriptionWithConditions, error) + hooks []func(context.Context, string) (*subscriptions.SubscriptionWithConditions, error) + history []StoreV1GetEnterpriseSubscriptionFuncCall + mutex sync.Mutex +} + +// GetEnterpriseSubscription delegates to the next hook function in the +// queue and stores the parameter and result values of this invocation. +func (m *MockStoreV1) GetEnterpriseSubscription(v0 context.Context, v1 string) (*subscriptions.SubscriptionWithConditions, error) { + r0, r1 := m.GetEnterpriseSubscriptionFunc.nextHook()(v0, v1) + m.GetEnterpriseSubscriptionFunc.appendCall(StoreV1GetEnterpriseSubscriptionFuncCall{v0, v1, r0, r1}) + return r0, r1 +} + +// SetDefaultHook sets function that is called when the +// GetEnterpriseSubscription method of the parent MockStoreV1 instance is +// invoked and the hook queue is empty. +func (f *StoreV1GetEnterpriseSubscriptionFunc) SetDefaultHook(hook func(context.Context, string) (*subscriptions.SubscriptionWithConditions, error)) { + f.defaultHook = hook +} + +// PushHook adds a function to the end of hook queue. Each invocation of the +// GetEnterpriseSubscription method of the parent MockStoreV1 instance +// invokes the hook at the front of the queue and discards it. After the +// queue is empty, the default hook function is invoked for any future +// action. +func (f *StoreV1GetEnterpriseSubscriptionFunc) PushHook(hook func(context.Context, string) (*subscriptions.SubscriptionWithConditions, error)) { + f.mutex.Lock() + f.hooks = append(f.hooks, hook) + f.mutex.Unlock() +} + +// SetDefaultReturn calls SetDefaultHook with a function that returns the +// given values. +func (f *StoreV1GetEnterpriseSubscriptionFunc) SetDefaultReturn(r0 *subscriptions.SubscriptionWithConditions, r1 error) { + f.SetDefaultHook(func(context.Context, string) (*subscriptions.SubscriptionWithConditions, error) { + return r0, r1 + }) +} + +// PushReturn calls PushHook with a function that returns the given values. +func (f *StoreV1GetEnterpriseSubscriptionFunc) PushReturn(r0 *subscriptions.SubscriptionWithConditions, r1 error) { + f.PushHook(func(context.Context, string) (*subscriptions.SubscriptionWithConditions, error) { + return r0, r1 + }) +} + +func (f *StoreV1GetEnterpriseSubscriptionFunc) nextHook() func(context.Context, string) (*subscriptions.SubscriptionWithConditions, error) { + f.mutex.Lock() + defer f.mutex.Unlock() + + if len(f.hooks) == 0 { + return f.defaultHook + } + + hook := f.hooks[0] + f.hooks = f.hooks[1:] + return hook +} + +func (f *StoreV1GetEnterpriseSubscriptionFunc) appendCall(r0 StoreV1GetEnterpriseSubscriptionFuncCall) { + f.mutex.Lock() + f.history = append(f.history, r0) + f.mutex.Unlock() +} + +// History returns a sequence of StoreV1GetEnterpriseSubscriptionFuncCall +// objects describing the invocations of this function. +func (f *StoreV1GetEnterpriseSubscriptionFunc) History() []StoreV1GetEnterpriseSubscriptionFuncCall { + f.mutex.Lock() + history := make([]StoreV1GetEnterpriseSubscriptionFuncCall, len(f.history)) + copy(history, f.history) + f.mutex.Unlock() + + return history +} + +// StoreV1GetEnterpriseSubscriptionFuncCall is an object that describes an +// invocation of method GetEnterpriseSubscription on an instance of +// MockStoreV1. +type StoreV1GetEnterpriseSubscriptionFuncCall struct { + // Arg0 is the value of the 1st argument passed to this method + // invocation. + Arg0 context.Context + // Arg1 is the value of the 2nd argument passed to this method + // invocation. + Arg1 string + // Result0 is the value of the 1st result returned from this method + // invocation. + Result0 *subscriptions.SubscriptionWithConditions + // Result1 is the value of the 2nd result returned from this method + // invocation. + Result1 error +} + +// Args returns an interface slice containing the arguments of this +// invocation. +func (c StoreV1GetEnterpriseSubscriptionFuncCall) Args() []interface{} { + return []interface{}{c.Arg0, c.Arg1} +} + +// Results returns an interface slice containing the results of this +// invocation. +func (c StoreV1GetEnterpriseSubscriptionFuncCall) Results() []interface{} { + return []interface{}{c.Result0, c.Result1} +} + // StoreV1GetSAMSUserByIDFunc describes the behavior when the // GetSAMSUserByID method of the parent MockStoreV1 instance is invoked. type StoreV1GetSAMSUserByIDFunc struct { @@ -933,28 +1214,144 @@ func (c StoreV1ListEnterpriseSubscriptionsFuncCall) Results() []interface{} { return []interface{}{c.Result0, c.Result1} } +// StoreV1RevokeEnterpriseSubscriptionLicenseFunc describes the behavior +// when the RevokeEnterpriseSubscriptionLicense method of the parent +// MockStoreV1 instance is invoked. +type StoreV1RevokeEnterpriseSubscriptionLicenseFunc struct { + defaultHook func(context.Context, string, subscriptions.RevokeLicenseOpts) (*subscriptions.LicenseWithConditions, error) + hooks []func(context.Context, string, subscriptions.RevokeLicenseOpts) (*subscriptions.LicenseWithConditions, error) + history []StoreV1RevokeEnterpriseSubscriptionLicenseFuncCall + mutex sync.Mutex +} + +// RevokeEnterpriseSubscriptionLicense delegates to the next hook function +// in the queue and stores the parameter and result values of this +// invocation. +func (m *MockStoreV1) RevokeEnterpriseSubscriptionLicense(v0 context.Context, v1 string, v2 subscriptions.RevokeLicenseOpts) (*subscriptions.LicenseWithConditions, error) { + r0, r1 := m.RevokeEnterpriseSubscriptionLicenseFunc.nextHook()(v0, v1, v2) + m.RevokeEnterpriseSubscriptionLicenseFunc.appendCall(StoreV1RevokeEnterpriseSubscriptionLicenseFuncCall{v0, v1, v2, r0, r1}) + return r0, r1 +} + +// SetDefaultHook sets function that is called when the +// RevokeEnterpriseSubscriptionLicense method of the parent MockStoreV1 +// instance is invoked and the hook queue is empty. +func (f *StoreV1RevokeEnterpriseSubscriptionLicenseFunc) SetDefaultHook(hook func(context.Context, string, subscriptions.RevokeLicenseOpts) (*subscriptions.LicenseWithConditions, error)) { + f.defaultHook = hook +} + +// PushHook adds a function to the end of hook queue. Each invocation of the +// RevokeEnterpriseSubscriptionLicense method of the parent MockStoreV1 +// instance invokes the hook at the front of the queue and discards it. +// After the queue is empty, the default hook function is invoked for any +// future action. +func (f *StoreV1RevokeEnterpriseSubscriptionLicenseFunc) PushHook(hook func(context.Context, string, subscriptions.RevokeLicenseOpts) (*subscriptions.LicenseWithConditions, error)) { + f.mutex.Lock() + f.hooks = append(f.hooks, hook) + f.mutex.Unlock() +} + +// SetDefaultReturn calls SetDefaultHook with a function that returns the +// given values. +func (f *StoreV1RevokeEnterpriseSubscriptionLicenseFunc) SetDefaultReturn(r0 *subscriptions.LicenseWithConditions, r1 error) { + f.SetDefaultHook(func(context.Context, string, subscriptions.RevokeLicenseOpts) (*subscriptions.LicenseWithConditions, error) { + return r0, r1 + }) +} + +// PushReturn calls PushHook with a function that returns the given values. +func (f *StoreV1RevokeEnterpriseSubscriptionLicenseFunc) PushReturn(r0 *subscriptions.LicenseWithConditions, r1 error) { + f.PushHook(func(context.Context, string, subscriptions.RevokeLicenseOpts) (*subscriptions.LicenseWithConditions, error) { + return r0, r1 + }) +} + +func (f *StoreV1RevokeEnterpriseSubscriptionLicenseFunc) nextHook() func(context.Context, string, subscriptions.RevokeLicenseOpts) (*subscriptions.LicenseWithConditions, error) { + f.mutex.Lock() + defer f.mutex.Unlock() + + if len(f.hooks) == 0 { + return f.defaultHook + } + + hook := f.hooks[0] + f.hooks = f.hooks[1:] + return hook +} + +func (f *StoreV1RevokeEnterpriseSubscriptionLicenseFunc) appendCall(r0 StoreV1RevokeEnterpriseSubscriptionLicenseFuncCall) { + f.mutex.Lock() + f.history = append(f.history, r0) + f.mutex.Unlock() +} + +// History returns a sequence of +// StoreV1RevokeEnterpriseSubscriptionLicenseFuncCall objects describing the +// invocations of this function. +func (f *StoreV1RevokeEnterpriseSubscriptionLicenseFunc) History() []StoreV1RevokeEnterpriseSubscriptionLicenseFuncCall { + f.mutex.Lock() + history := make([]StoreV1RevokeEnterpriseSubscriptionLicenseFuncCall, len(f.history)) + copy(history, f.history) + f.mutex.Unlock() + + return history +} + +// StoreV1RevokeEnterpriseSubscriptionLicenseFuncCall is an object that +// describes an invocation of method RevokeEnterpriseSubscriptionLicense on +// an instance of MockStoreV1. +type StoreV1RevokeEnterpriseSubscriptionLicenseFuncCall struct { + // Arg0 is the value of the 1st argument passed to this method + // invocation. + Arg0 context.Context + // Arg1 is the value of the 2nd argument passed to this method + // invocation. + Arg1 string + // Arg2 is the value of the 3rd argument passed to this method + // invocation. + Arg2 subscriptions.RevokeLicenseOpts + // Result0 is the value of the 1st result returned from this method + // invocation. + Result0 *subscriptions.LicenseWithConditions + // Result1 is the value of the 2nd result returned from this method + // invocation. + Result1 error +} + +// Args returns an interface slice containing the arguments of this +// invocation. +func (c StoreV1RevokeEnterpriseSubscriptionLicenseFuncCall) Args() []interface{} { + return []interface{}{c.Arg0, c.Arg1, c.Arg2} +} + +// Results returns an interface slice containing the results of this +// invocation. +func (c StoreV1RevokeEnterpriseSubscriptionLicenseFuncCall) Results() []interface{} { + return []interface{}{c.Result0, c.Result1} +} + // StoreV1UpsertEnterpriseSubscriptionFunc describes the behavior when the // UpsertEnterpriseSubscription method of the parent MockStoreV1 instance is // invoked. type StoreV1UpsertEnterpriseSubscriptionFunc struct { - defaultHook func(context.Context, string, subscriptions.UpsertSubscriptionOptions) (*subscriptions.SubscriptionWithConditions, error) - hooks []func(context.Context, string, subscriptions.UpsertSubscriptionOptions) (*subscriptions.SubscriptionWithConditions, error) + defaultHook func(context.Context, string, subscriptions.UpsertSubscriptionOptions, ...subscriptions.CreateSubscriptionConditionOptions) (*subscriptions.SubscriptionWithConditions, error) + hooks []func(context.Context, string, subscriptions.UpsertSubscriptionOptions, ...subscriptions.CreateSubscriptionConditionOptions) (*subscriptions.SubscriptionWithConditions, error) history []StoreV1UpsertEnterpriseSubscriptionFuncCall mutex sync.Mutex } // UpsertEnterpriseSubscription delegates to the next hook function in the // queue and stores the parameter and result values of this invocation. -func (m *MockStoreV1) UpsertEnterpriseSubscription(v0 context.Context, v1 string, v2 subscriptions.UpsertSubscriptionOptions) (*subscriptions.SubscriptionWithConditions, error) { - r0, r1 := m.UpsertEnterpriseSubscriptionFunc.nextHook()(v0, v1, v2) - m.UpsertEnterpriseSubscriptionFunc.appendCall(StoreV1UpsertEnterpriseSubscriptionFuncCall{v0, v1, v2, r0, r1}) +func (m *MockStoreV1) UpsertEnterpriseSubscription(v0 context.Context, v1 string, v2 subscriptions.UpsertSubscriptionOptions, v3 ...subscriptions.CreateSubscriptionConditionOptions) (*subscriptions.SubscriptionWithConditions, error) { + r0, r1 := m.UpsertEnterpriseSubscriptionFunc.nextHook()(v0, v1, v2, v3...) + m.UpsertEnterpriseSubscriptionFunc.appendCall(StoreV1UpsertEnterpriseSubscriptionFuncCall{v0, v1, v2, v3, r0, r1}) return r0, r1 } // SetDefaultHook sets function that is called when the // UpsertEnterpriseSubscription method of the parent MockStoreV1 instance is // invoked and the hook queue is empty. -func (f *StoreV1UpsertEnterpriseSubscriptionFunc) SetDefaultHook(hook func(context.Context, string, subscriptions.UpsertSubscriptionOptions) (*subscriptions.SubscriptionWithConditions, error)) { +func (f *StoreV1UpsertEnterpriseSubscriptionFunc) SetDefaultHook(hook func(context.Context, string, subscriptions.UpsertSubscriptionOptions, ...subscriptions.CreateSubscriptionConditionOptions) (*subscriptions.SubscriptionWithConditions, error)) { f.defaultHook = hook } @@ -963,7 +1360,7 @@ func (f *StoreV1UpsertEnterpriseSubscriptionFunc) SetDefaultHook(hook func(conte // invokes the hook at the front of the queue and discards it. After the // queue is empty, the default hook function is invoked for any future // action. -func (f *StoreV1UpsertEnterpriseSubscriptionFunc) PushHook(hook func(context.Context, string, subscriptions.UpsertSubscriptionOptions) (*subscriptions.SubscriptionWithConditions, error)) { +func (f *StoreV1UpsertEnterpriseSubscriptionFunc) PushHook(hook func(context.Context, string, subscriptions.UpsertSubscriptionOptions, ...subscriptions.CreateSubscriptionConditionOptions) (*subscriptions.SubscriptionWithConditions, error)) { f.mutex.Lock() f.hooks = append(f.hooks, hook) f.mutex.Unlock() @@ -972,19 +1369,19 @@ func (f *StoreV1UpsertEnterpriseSubscriptionFunc) PushHook(hook func(context.Con // SetDefaultReturn calls SetDefaultHook with a function that returns the // given values. func (f *StoreV1UpsertEnterpriseSubscriptionFunc) SetDefaultReturn(r0 *subscriptions.SubscriptionWithConditions, r1 error) { - f.SetDefaultHook(func(context.Context, string, subscriptions.UpsertSubscriptionOptions) (*subscriptions.SubscriptionWithConditions, error) { + f.SetDefaultHook(func(context.Context, string, subscriptions.UpsertSubscriptionOptions, ...subscriptions.CreateSubscriptionConditionOptions) (*subscriptions.SubscriptionWithConditions, error) { return r0, r1 }) } // PushReturn calls PushHook with a function that returns the given values. func (f *StoreV1UpsertEnterpriseSubscriptionFunc) PushReturn(r0 *subscriptions.SubscriptionWithConditions, r1 error) { - f.PushHook(func(context.Context, string, subscriptions.UpsertSubscriptionOptions) (*subscriptions.SubscriptionWithConditions, error) { + f.PushHook(func(context.Context, string, subscriptions.UpsertSubscriptionOptions, ...subscriptions.CreateSubscriptionConditionOptions) (*subscriptions.SubscriptionWithConditions, error) { return r0, r1 }) } -func (f *StoreV1UpsertEnterpriseSubscriptionFunc) nextHook() func(context.Context, string, subscriptions.UpsertSubscriptionOptions) (*subscriptions.SubscriptionWithConditions, error) { +func (f *StoreV1UpsertEnterpriseSubscriptionFunc) nextHook() func(context.Context, string, subscriptions.UpsertSubscriptionOptions, ...subscriptions.CreateSubscriptionConditionOptions) (*subscriptions.SubscriptionWithConditions, error) { f.mutex.Lock() defer f.mutex.Unlock() @@ -1027,6 +1424,9 @@ type StoreV1UpsertEnterpriseSubscriptionFuncCall struct { // Arg2 is the value of the 3rd argument passed to this method // invocation. Arg2 subscriptions.UpsertSubscriptionOptions + // Arg3 is a slice containing the values of the variadic arguments + // passed to this method invocation. + Arg3 []subscriptions.CreateSubscriptionConditionOptions // Result0 is the value of the 1st result returned from this method // invocation. Result0 *subscriptions.SubscriptionWithConditions @@ -1036,9 +1436,16 @@ type StoreV1UpsertEnterpriseSubscriptionFuncCall struct { } // Args returns an interface slice containing the arguments of this -// invocation. +// invocation. The variadic slice argument is flattened in this array such +// that one positional argument and three variadic arguments would result in +// a slice of four, not two. func (c StoreV1UpsertEnterpriseSubscriptionFuncCall) Args() []interface{} { - return []interface{}{c.Arg0, c.Arg1, c.Arg2} + trailing := []interface{}{} + for _, val := range c.Arg3 { + trailing = append(trailing, val) + } + + return append([]interface{}{c.Arg0, c.Arg1, c.Arg2}, trailing...) } // Results returns an interface slice containing the results of this diff --git a/cmd/enterprise-portal/internal/subscriptionsservice/v1.go b/cmd/enterprise-portal/internal/subscriptionsservice/v1.go index 93a4fb8bd2ffc..3fc72e33ff37d 100644 --- a/cmd/enterprise-portal/internal/subscriptionsservice/v1.go +++ b/cmd/enterprise-portal/internal/subscriptionsservice/v1.go @@ -4,8 +4,10 @@ import ( "context" "net/http" "strings" + "time" "connectrpc.com/connect" + "github.com/google/uuid" "github.com/sourcegraph/log" "golang.org/x/exp/maps" @@ -21,9 +23,11 @@ import ( "github.com/sourcegraph/sourcegraph/cmd/enterprise-portal/internal/connectutil" "github.com/sourcegraph/sourcegraph/cmd/enterprise-portal/internal/database" "github.com/sourcegraph/sourcegraph/cmd/enterprise-portal/internal/database/subscriptions" + "github.com/sourcegraph/sourcegraph/cmd/enterprise-portal/internal/database/utctime" "github.com/sourcegraph/sourcegraph/cmd/enterprise-portal/internal/dotcomdb" "github.com/sourcegraph/sourcegraph/cmd/enterprise-portal/internal/samsm2m" "github.com/sourcegraph/sourcegraph/internal/collections" + "github.com/sourcegraph/sourcegraph/internal/license" "github.com/sourcegraph/sourcegraph/internal/trace" ) @@ -47,14 +51,44 @@ func RegisterV1( } type handlerV1 struct { - subscriptionsv1connect.UnimplementedSubscriptionsServiceHandler - logger log.Logger store StoreV1 } var _ subscriptionsv1connect.SubscriptionsServiceHandler = (*handlerV1)(nil) +func (s *handlerV1) GetEnterpriseSubscription(ctx context.Context, req *connect.Request[subscriptionsv1.GetEnterpriseSubscriptionRequest]) (*connect.Response[subscriptionsv1.GetEnterpriseSubscriptionResponse], error) { + logger := trace.Logger(ctx, s.logger) + + // 🚨 SECURITY: Require appropriate M2M scope. + requiredScope := samsm2m.EnterprisePortalScope("subscription", scopes.ActionRead) + clientAttrs, err := samsm2m.RequireScope(ctx, logger, s.store, requiredScope, req) + if err != nil { + return nil, err + } + logger = logger.With(clientAttrs...) + + subscriptionID := req.Msg.GetId() + if subscriptionID == "" { + return nil, connect.NewError(connect.CodeInvalidArgument, errors.New("subscription_id is required")) + } + + sub, err := s.store.GetEnterpriseSubscription(ctx, subscriptionID) + if err != nil { + if errors.Is(err, subscriptions.ErrSubscriptionNotFound) { + return nil, connect.NewError(connect.CodeNotFound, err) + } + return nil, connectutil.InternalError(ctx, logger, err, "failed to find subscription") + } + + proto := convertSubscriptionToProto(sub) + logger.Scoped("audit").Info("GetEnterpriseSubscription", + log.String("subscription", proto.Id)) + return connect.NewResponse(&subscriptionsv1.GetEnterpriseSubscriptionResponse{ + Subscription: proto, + }), nil +} + func (s *handlerV1) ListEnterpriseSubscriptions(ctx context.Context, req *connect.Request[subscriptionsv1.ListEnterpriseSubscriptionsRequest]) (*connect.Response[subscriptionsv1.ListEnterpriseSubscriptionsResponse], error) { logger := trace.Logger(ctx, s.logger) @@ -76,7 +110,7 @@ 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)) + internalSubscriptionIDs := make(collections.Set[string], len(filters)) var iamListObjectOptions *iam.ListObjectsOptions for _, filter := range filters { switch f := filter.GetFilter().(type) { @@ -87,7 +121,7 @@ func (s *handlerV1) ListEnterpriseSubscriptions(ctx context.Context, req *connec errors.New(`invalid filter: "subscription_id" provided but is empty`), ) } - subscriptionIDs.Add( + internalSubscriptionIDs.Add( strings.TrimPrefix(f.SubscriptionId, subscriptionsv1.EnterpriseSubscriptionIDPrefix)) case *subscriptionsv1.ListEnterpriseSubscriptionsFilter_IsArchived: isArchived = f.IsArchived @@ -147,18 +181,18 @@ func (s *handlerV1) ListEnterpriseSubscriptions(ctx context.Context, req *connec allowedSubscriptionIDs.Add(strings.TrimPrefix(objectID, "subscription_cody_analytics:")) } - if !subscriptionIDs.IsEmpty() { + if !internalSubscriptionIDs.IsEmpty() { // If subscription IDs were provided, we only want to return the // subscriptions that are part of the provided IDs. - subscriptionIDs = collections.Intersection(subscriptionIDs, allowedSubscriptionIDs) + internalSubscriptionIDs = collections.Intersection(internalSubscriptionIDs, allowedSubscriptionIDs) } else { // Otherwise, only return the allowed subscriptions. - subscriptionIDs = allowedSubscriptionIDs + internalSubscriptionIDs = allowedSubscriptionIDs } // 🚨 SECURITY: If permissions are used as filter, but we found no results, we // should directly return an empty response to not mistaken as list all. - if len(subscriptionIDs) == 0 { + if len(internalSubscriptionIDs) == 0 { return connect.NewResponse(&subscriptionsv1.ListEnterpriseSubscriptionsResponse{}), nil } } @@ -166,7 +200,7 @@ func (s *handlerV1) ListEnterpriseSubscriptions(ctx context.Context, req *connec subs, err := s.store.ListEnterpriseSubscriptions( ctx, subscriptions.ListEnterpriseSubscriptionsOptions{ - IDs: subscriptionIDs.Values(), + IDs: internalSubscriptionIDs.Values(), IsArchived: isArchived, PageSize: int(req.Msg.GetPageSize()), }, @@ -279,6 +313,76 @@ func (s *handlerV1) ListEnterpriseSubscriptionLicenses(ctx context.Context, req return connect.NewResponse(&resp), nil } +func (s *handlerV1) CreateEnterpriseSubscription(ctx context.Context, req *connect.Request[subscriptionsv1.CreateEnterpriseSubscriptionRequest]) (*connect.Response[subscriptionsv1.CreateEnterpriseSubscriptionResponse], error) { + logger := trace.Logger(ctx, s.logger) + + // 🚨 SECURITY: Require appropriate M2M scope. + requiredScope := samsm2m.EnterprisePortalScope("subscription", scopes.ActionWrite) + clientAttrs, err := samsm2m.RequireScope(ctx, logger, s.store, requiredScope, req) + if err != nil { + return nil, err + } + logger = logger.With(clientAttrs...) + + sub := req.Msg.GetSubscription() + if sub == nil { + return nil, connect.NewError(connect.CodeInvalidArgument, errors.New("subscription details are required")) + } + + // Generate a new ID for the subscription. + if sub.Id == "" { + subscriptionID, err := uuid.NewRandom() + if err != nil { + return nil, connectutil.InternalError(ctx, s.logger, err, "failed to generate new subscription ID") + } + sub.Id = subscriptionID.String() + } else { + _, err := uuid.Parse(strings.TrimPrefix(sub.Id, subscriptionsv1.EnterpriseSubscriptionIDPrefix)) + if err != nil { + return nil, connect.NewError(connect.CodeInvalidArgument, errors.Wrap(err, "custom subscription.id must be a UUID")) + } + } + + if _, err := s.store.GetEnterpriseSubscription(ctx, sub.Id); err == nil { + return nil, connect.NewError(connect.CodeAlreadyExists, err) + } else if !errors.Is(err, subscriptions.ErrSubscriptionNotFound) { + return nil, connectutil.InternalError(ctx, logger, err, + "failed to check for existing subscription") + } + + if strings.TrimSpace(sub.GetDisplayName()) == "" { + return nil, connect.NewError(connect.CodeInvalidArgument, errors.New("display_name is required required")) + } + + createdAt := utctime.Now() + createdSub, err := s.store.UpsertEnterpriseSubscription(ctx, sub.Id, + subscriptions.UpsertSubscriptionOptions{ + CreatedAt: createdAt, + DisplayName: pointers.Ptr(database.NewNullString(sub.GetDisplayName())), + InstanceDomain: pointers.Ptr(database.NewNullString(sub.GetInstanceDomain())), + SalesforceSubscriptionID: pointers.Ptr(database.NewNullString(sub.GetSalesforce().GetSubscriptionId())), + SalesforceOpportunityID: pointers.Ptr(database.NewNullString(sub.GetSalesforce().GetOpportunityId())), + }, + subscriptions.CreateSubscriptionConditionOptions{ + Status: subscriptionsv1.EnterpriseSubscriptionCondition_STATUS_CREATED, + TransitionTime: createdAt, + Message: req.Msg.GetMessage(), + }) + if err != nil { + if errors.Is(err, subscriptions.ErrInvalidArgument) { + return nil, connect.NewError(connect.CodeInvalidArgument, err) + } + return nil, connectutil.InternalError(ctx, logger, err, "failed to create subscription") + } + + protoSub := convertSubscriptionToProto(createdSub) + logger.Scoped("audit").Info("CreateEnterpriseSubscription", + log.String("createdSubscription", protoSub.GetId())) + return connect.NewResponse(&subscriptionsv1.CreateEnterpriseSubscriptionResponse{ + Subscription: protoSub, + }), nil +} + func (s *handlerV1) UpdateEnterpriseSubscription(ctx context.Context, req *connect.Request[subscriptionsv1.UpdateEnterpriseSubscriptionRequest]) (*connect.Response[subscriptionsv1.UpdateEnterpriseSubscriptionResponse], error) { logger := trace.Logger(ctx, s.logger) @@ -290,11 +394,18 @@ func (s *handlerV1) UpdateEnterpriseSubscription(ctx context.Context, req *conne } logger = logger.With(clientAttrs...) - subscriptionID := strings.TrimPrefix(req.Msg.GetSubscription().GetId(), subscriptionsv1.EnterpriseSubscriptionIDPrefix) + subscriptionID := req.Msg.GetSubscription().GetId() if subscriptionID == "" { return nil, connect.NewError(connect.CodeInvalidArgument, errors.New("subscription.id is required")) } + if _, err := s.store.GetEnterpriseSubscription(ctx, subscriptionID); err != nil { + if errors.Is(err, subscriptions.ErrSubscriptionNotFound) { + return nil, connect.NewError(connect.CodeNotFound, err) + } + return nil, connectutil.InternalError(ctx, logger, err, "failed to find subscription") + } + var opts subscriptions.UpsertSubscriptionOptions fieldPaths := req.Msg.GetUpdateMask().GetPaths() @@ -306,26 +417,45 @@ func (s *handlerV1) UpdateEnterpriseSubscription(ctx context.Context, req *conne if v := req.Msg.GetSubscription().GetDisplayName(); v != "" { opts.DisplayName = pointers.Ptr(database.NewNullString(v)) } + if v := req.Msg.GetSubscription().GetSalesforce().GetSubscriptionId(); v != "" { + opts.SalesforceSubscriptionID = pointers.Ptr(database.NewNullString(v)) + } + if v := req.Msg.GetSubscription().GetSalesforce().GetOpportunityId(); v != "" { + opts.SalesforceOpportunityID = pointers.Ptr(database.NewNullString(v)) + } } else { for _, p := range fieldPaths { - switch p { - case "instance_domain": + var valid bool + if p == "*" { + valid = true + opts.ForceUpdate = true + } + if p == "instance_domain" || p == "*" { + valid = true opts.InstanceDomain = pointers.Ptr( database.NewNullString(req.Msg.GetSubscription().GetInstanceDomain()), ) - case "display_name": + } + if p == "display_name" || p == "*" { + valid = true opts.DisplayName = pointers.Ptr( database.NewNullString(req.Msg.GetSubscription().GetDisplayName()), ) - case "*": - opts.ForceUpdate = true - opts.InstanceDomain = pointers.Ptr( - database.NewNullString(req.Msg.GetSubscription().GetInstanceDomain()), + } + if p == "salesforce.subscription_id" || p == "*" { + valid = true + opts.SalesforceSubscriptionID = pointers.Ptr( + database.NewNullString(req.Msg.GetSubscription().GetSalesforce().GetSubscriptionId()), ) - opts.DisplayName = pointers.Ptr( - database.NewNullString(req.Msg.GetSubscription().GetDisplayName()), + } + if p == "salesforce.opportunity_id" || p == "*" { + valid = true + opts.SalesforceOpportunityID = pointers.Ptr( + database.NewNullString(req.Msg.GetSubscription().GetSalesforce().GetOpportunityId()), ) - default: + } + + if !valid { return nil, connect.NewError(connect.CodeInvalidArgument, errors.Newf("unknown field path: %s", p)) } } @@ -357,6 +487,157 @@ func (s *handlerV1) UpdateEnterpriseSubscription(ctx context.Context, req *conne ), nil } +func (s *handlerV1) ArchiveEnterpriseSubscription(ctx context.Context, req *connect.Request[subscriptionsv1.ArchiveEnterpriseSubscriptionRequest]) (*connect.Response[subscriptionsv1.ArchiveEnterpriseSubscriptionResponse], error) { + logger := trace.Logger(ctx, s.logger) + + // 🚨 SECURITY: Require appropriate M2M scope. + requiredScope := samsm2m.EnterprisePortalScope("subscription", scopes.ActionWrite) + clientAttrs, err := samsm2m.RequireScope(ctx, logger, s.store, requiredScope, req) + if err != nil { + return nil, err + } + logger = logger.With(clientAttrs...) + + subscriptionID := req.Msg.GetSubscriptionId() + if subscriptionID == "" { + return nil, connect.NewError(connect.CodeInvalidArgument, errors.New("subscription_id is required")) + } + + if _, err := s.store.GetEnterpriseSubscription(ctx, subscriptionID); err != nil { + if errors.Is(err, subscriptions.ErrSubscriptionNotFound) { + return nil, connect.NewError(connect.CodeNotFound, err) + } + return nil, connectutil.InternalError(ctx, logger, err, "failed to find subscription") + } + + archivedAt := utctime.Now() + createdSub, err := s.store.UpsertEnterpriseSubscription(ctx, subscriptionID, + subscriptions.UpsertSubscriptionOptions{ + ArchivedAt: pointers.Ptr(archivedAt), + }, + subscriptions.CreateSubscriptionConditionOptions{ + Status: subscriptionsv1.EnterpriseSubscriptionCondition_STATUS_ARCHIVED, + TransitionTime: archivedAt, + Message: req.Msg.GetReason(), + }) + if err != nil { + if errors.Is(err, subscriptions.ErrInvalidArgument) { + return nil, connect.NewError(connect.CodeInvalidArgument, err) + } + return nil, connectutil.InternalError(ctx, logger, err, "failed to create subscription") + } + + protoSub := convertSubscriptionToProto(createdSub) + logger.Scoped("audit").Info("ArchiveEnterpriseSubscription", + log.String("archivedSubscription", protoSub.GetId())) + return connect.NewResponse(&subscriptionsv1.ArchiveEnterpriseSubscriptionResponse{}), nil +} + +func (s *handlerV1) CreateEnterpriseSubscriptionLicense(ctx context.Context, req *connect.Request[subscriptionsv1.CreateEnterpriseSubscriptionLicenseRequest]) (*connect.Response[subscriptionsv1.CreateEnterpriseSubscriptionLicenseResponse], error) { + logger := trace.Logger(ctx, s.logger) + + // 🚨 SECURITY: Require appropriate M2M scope. + requiredScope := samsm2m.EnterprisePortalScope("subscription", scopes.ActionWrite) + clientAttrs, err := samsm2m.RequireScope(ctx, logger, s.store, requiredScope, req) + if err != nil { + return nil, err + } + logger = logger.With(clientAttrs...) + + create := req.Msg.GetLicense() + subscriptionID := create.GetSubscriptionId() + if subscriptionID == "" { + return nil, connect.NewError(connect.CodeInvalidArgument, errors.New("subscription_id is required")) + } + sub, err := s.store.GetEnterpriseSubscription(ctx, subscriptionID) + if err != nil { + if errors.Is(err, subscriptions.ErrSubscriptionNotFound) { + return nil, connect.NewError(connect.CodeNotFound, err) + } + return nil, connectutil.InternalError(ctx, logger, err, "failed to find subscription") + } + + createdAt := utctime.Now() + + var createdLicense *subscriptions.LicenseWithConditions + switch data := create.License.(type) { + case *subscriptionsv1.EnterpriseSubscriptionLicense_Key: + key := data.Key + expires := key.GetInfo().GetExpireTime().AsTime() + if expires.Before(time.Now()) { + return nil, connect.NewError(connect.CodeInvalidArgument, errors.New("expiry must be in the future")) + } + createdLicense, err = s.store.CreateEnterpriseSubscriptionLicenseKey(ctx, subscriptionID, + &subscriptions.DataLicenseKey{ + Info: license.Info{ + Tags: key.GetInfo().GetTags(), + UserCount: uint(key.GetInfo().GetUserCount()), + CreatedAt: createdAt.AsTime(), + ExpiresAt: expires.UTC(), + + // Inherited from subscription + SalesforceSubscriptionID: sub.SalesforceSubscriptionID, + SalesforceOpportunityID: sub.SalesforceOpportunityID, + }, + }, + subscriptions.CreateLicenseOpts{ + Message: req.Msg.GetMessage(), + Time: &createdAt, + ExpireTime: utctime.FromTime(expires), + }) + if err != nil { + return nil, connectutil.InternalError(ctx, logger, err, "failed to create license key") + } + + default: + return nil, connect.NewError(connect.CodeInvalidArgument, errors.Newf("unsupported licnese type %T", data)) + } + + proto, err := convertLicenseToProto(createdLicense) + if err != nil { + return nil, connectutil.InternalError(ctx, logger, err, "failed to parse license") + } + logger.Scoped("audit").Info("CreateEnterpriseSubscriptionLicense", + log.String("subscription", subscriptionID), + log.String("createdLicense", proto.GetId())) + return connect.NewResponse(&subscriptionsv1.CreateEnterpriseSubscriptionLicenseResponse{ + License: proto, + }), nil +} + +func (s *handlerV1) RevokeEnterpriseSubscriptionLicense(ctx context.Context, req *connect.Request[subscriptionsv1.RevokeEnterpriseSubscriptionLicenseRequest]) (*connect.Response[subscriptionsv1.RevokeEnterpriseSubscriptionLicenseResponse], error) { + logger := trace.Logger(ctx, s.logger) + + // 🚨 SECURITY: Require appropriate M2M scope. + requiredScope := samsm2m.EnterprisePortalScope("subscription", scopes.ActionWrite) + clientAttrs, err := samsm2m.RequireScope(ctx, logger, s.store, requiredScope, req) + if err != nil { + return nil, err + } + logger = logger.With(clientAttrs...) + + licenseID := req.Msg.LicenseId + if licenseID == "" { + return nil, connect.NewError(connect.CodeInvalidArgument, errors.New("license_id is required")) + } + + license, err := s.store.RevokeEnterpriseSubscriptionLicense(ctx, licenseID, subscriptions.RevokeLicenseOpts{ + Message: req.Msg.GetReason(), + Time: pointers.Ptr(utctime.Now()), + }) + if err != nil { + if errors.Is(err, subscriptions.ErrSubscriptionLicenseNotFound) { + return nil, connect.NewError(connect.CodeNotFound, err) + } + return nil, connectutil.InternalError(ctx, logger, err, "failed to revoked license") + } + + logger.Scoped("audit").Info("RevokeEnterpriseSubscriptionLicense", + log.String("subscription", license.SubscriptionID), + log.String("revokedLicense", license.ID)) + return connect.NewResponse(&subscriptionsv1.RevokeEnterpriseSubscriptionLicenseResponse{}), nil +} + func (s *handlerV1) UpdateEnterpriseSubscriptionMembership(ctx context.Context, req *connect.Request[subscriptionsv1.UpdateEnterpriseSubscriptionMembershipRequest]) (*connect.Response[subscriptionsv1.UpdateEnterpriseSubscriptionMembershipResponse], error) { logger := trace.Logger(ctx, s.logger) diff --git a/cmd/enterprise-portal/internal/subscriptionsservice/v1_store.go b/cmd/enterprise-portal/internal/subscriptionsservice/v1_store.go index 1c09368b65ce7..bea154937bf2e 100644 --- a/cmd/enterprise-portal/internal/subscriptionsservice/v1_store.go +++ b/cmd/enterprise-portal/internal/subscriptionsservice/v1_store.go @@ -2,12 +2,15 @@ package subscriptionsservice import ( "context" + "strings" sams "github.com/sourcegraph/sourcegraph-accounts-sdk-go" clientsv1 "github.com/sourcegraph/sourcegraph-accounts-sdk-go/clients/v1" "github.com/sourcegraph/sourcegraph/cmd/enterprise-portal/internal/database" "github.com/sourcegraph/sourcegraph/cmd/enterprise-portal/internal/database/subscriptions" + subscriptionsv1 "github.com/sourcegraph/sourcegraph/lib/enterpriseportal/subscriptions/v1" + "github.com/sourcegraph/sourcegraph/lib/errors" "github.com/sourcegraph/sourcegraph/lib/managedservicesplatform/iam" ) @@ -17,16 +20,28 @@ import ( type StoreV1 interface { // UpsertEnterpriseSubscription upserts a enterprise subscription record based // on the given options. - UpsertEnterpriseSubscription(ctx context.Context, subscriptionID string, opts subscriptions.UpsertSubscriptionOptions) (*subscriptions.SubscriptionWithConditions, error) + UpsertEnterpriseSubscription(ctx context.Context, subscriptionID string, opts subscriptions.UpsertSubscriptionOptions, conditions ...subscriptions.CreateSubscriptionConditionOptions) (*subscriptions.SubscriptionWithConditions, error) // ListEnterpriseSubscriptions returns a list of enterprise subscriptions based // on the given options. ListEnterpriseSubscriptions(ctx context.Context, opts subscriptions.ListEnterpriseSubscriptionsOptions) ([]*subscriptions.SubscriptionWithConditions, error) + // GetEnterpriseSubscriptions returns a specific enterprise subscription. + // + // Returns subscriptions.ErrSubscriptionNotFound if the subscription does + // not exist. + GetEnterpriseSubscription(ctx context.Context, subscriptionID string) (*subscriptions.SubscriptionWithConditions, error) + // ListDotcomEnterpriseSubscriptionLicenses returns a list of enterprise // subscription license attributes with the given filters. It silently ignores // any non-matching filters. The caller should check the length of the returned // slice to ensure all requested licenses were found. ListEnterpriseSubscriptionLicenses(ctx context.Context, opts subscriptions.ListLicensesOpts) ([]*subscriptions.LicenseWithConditions, error) + // CreateLicense creates a new classic offline license for the given subscription. + CreateEnterpriseSubscriptionLicenseKey(ctx context.Context, subscriptionID string, license *subscriptions.DataLicenseKey, opts subscriptions.CreateLicenseOpts) (*subscriptions.LicenseWithConditions, error) + + // RevokeEnterpriseSubscriptionLicense premanently revokes a license. + RevokeEnterpriseSubscriptionLicense(ctx context.Context, licenseID string, opts subscriptions.RevokeLicenseOpts) (*subscriptions.LicenseWithConditions, error) + // IntrospectSAMSToken takes a SAMS access token and returns relevant metadata. // // 🚨SECURITY: SAMS will return a successful result if the token is valid, but @@ -69,18 +84,52 @@ func NewStoreV1(opts NewStoreV1Options) StoreV1 { } } -func (s *storeV1) UpsertEnterpriseSubscription(ctx context.Context, subscriptionID string, opts subscriptions.UpsertSubscriptionOptions) (*subscriptions.SubscriptionWithConditions, error) { - return s.db.Subscriptions().Upsert(ctx, subscriptionID, opts) +func (s *storeV1) UpsertEnterpriseSubscription(ctx context.Context, subscriptionID string, opts subscriptions.UpsertSubscriptionOptions, conditions ...subscriptions.CreateSubscriptionConditionOptions) (*subscriptions.SubscriptionWithConditions, error) { + return s.db.Subscriptions().Upsert( + ctx, + strings.TrimPrefix(subscriptionID, subscriptionsv1.EnterpriseSubscriptionIDPrefix), + opts, + conditions..., + ) } func (s *storeV1) ListEnterpriseSubscriptions(ctx context.Context, opts subscriptions.ListEnterpriseSubscriptionsOptions) ([]*subscriptions.SubscriptionWithConditions, error) { + for idx := range opts.IDs { + opts.IDs[idx] = strings.TrimPrefix(opts.IDs[idx], subscriptionsv1.EnterpriseSubscriptionIDPrefix) + } return s.db.Subscriptions().List(ctx, opts) } +func (s *storeV1) GetEnterpriseSubscription(ctx context.Context, subscriptionID string) (*subscriptions.SubscriptionWithConditions, error) { + return s.db.Subscriptions().Get(ctx, + strings.TrimPrefix(subscriptionID, subscriptionsv1.EnterpriseSubscriptionIDPrefix)) +} + func (s *storeV1) ListEnterpriseSubscriptionLicenses(ctx context.Context, opts subscriptions.ListLicensesOpts) ([]*subscriptions.LicenseWithConditions, error) { + opts.SubscriptionID = strings.TrimPrefix(opts.SubscriptionID, subscriptionsv1.EnterpriseSubscriptionIDPrefix) return s.db.Subscriptions().Licenses().List(ctx, opts) } +func (s *storeV1) CreateEnterpriseSubscriptionLicenseKey(ctx context.Context, subscriptionID string, license *subscriptions.DataLicenseKey, opts subscriptions.CreateLicenseOpts) (*subscriptions.LicenseWithConditions, error) { + if opts.ImportLicenseID != "" { + return nil, errors.New("import license ID not allowed via API") + } + return s.db.Subscriptions().Licenses().CreateLicenseKey( + ctx, + strings.TrimPrefix(subscriptionID, subscriptionsv1.EnterpriseSubscriptionIDPrefix), + license, + opts, + ) +} + +func (s *storeV1) RevokeEnterpriseSubscriptionLicense(ctx context.Context, licenseID string, opts subscriptions.RevokeLicenseOpts) (*subscriptions.LicenseWithConditions, error) { + return s.db.Subscriptions().Licenses().Revoke( + ctx, + strings.TrimPrefix(licenseID, subscriptionsv1.EnterpriseSubscriptionLicenseIDPrefix), + opts, + ) +} + func (s *storeV1) IntrospectSAMSToken(ctx context.Context, token string) (*sams.IntrospectTokenResponse, error) { return s.SAMSClient.Tokens().IntrospectToken(ctx, token) } diff --git a/cmd/enterprise-portal/internal/subscriptionsservice/v1_test.go b/cmd/enterprise-portal/internal/subscriptionsservice/v1_test.go index 341daabee0464..7af923d29f6cf 100644 --- a/cmd/enterprise-portal/internal/subscriptionsservice/v1_test.go +++ b/cmd/enterprise-portal/internal/subscriptionsservice/v1_test.go @@ -257,9 +257,11 @@ func TestHandlerV1_UpdateEnterpriseSubscription(t *testing.T) { }, // All update-able values should be set to their defaults explicitly wantUpdateOpts: autogold.Expect(subscriptions.UpsertSubscriptionOptions{ - InstanceDomain: &sql.NullString{}, - DisplayName: &sql.NullString{}, - ForceUpdate: true, + InstanceDomain: &sql.NullString{}, + DisplayName: &sql.NullString{}, + SalesforceSubscriptionID: &sql.NullString{}, + SalesforceOpportunityID: &sql.NullString{}, + ForceUpdate: true, }), }, { @@ -286,8 +288,9 @@ func TestHandlerV1_UpdateEnterpriseSubscription(t *testing.T) { ID: "80ca12e2-54b4-448c-a61a-390b1a9c1224", }}, }, nil) - h.mockStore.UpsertEnterpriseSubscriptionFunc.SetDefaultHook(func(_ context.Context, _ string, opts subscriptions.UpsertSubscriptionOptions) (*subscriptions.SubscriptionWithConditions, error) { + h.mockStore.UpsertEnterpriseSubscriptionFunc.SetDefaultHook(func(_ context.Context, _ string, opts subscriptions.UpsertSubscriptionOptions, conds ...subscriptions.CreateSubscriptionConditionOptions) (*subscriptions.SubscriptionWithConditions, error) { tc.wantUpdateOpts.Equal(t, opts) + assert.Len(t, conds, 0) // no conditions for standard updates return &subscriptions.SubscriptionWithConditions{}, nil }) _, err := h.UpdateEnterpriseSubscription(ctx, req) diff --git a/lib/enterpriseportal/subscriptions/v1/subscriptions.pb.go b/lib/enterpriseportal/subscriptions/v1/subscriptions.pb.go index bb28cf95a53f6..4faf7f180263b 100644 --- a/lib/enterpriseportal/subscriptions/v1/subscriptions.pb.go +++ b/lib/enterpriseportal/subscriptions/v1/subscriptions.pb.go @@ -1340,6 +1340,8 @@ type CreateEnterpriseSubscriptionLicenseRequest struct { // - license.key.info.user_count // - license.key.info.expire_time License *EnterpriseSubscriptionLicense `protobuf:"bytes,1,opt,name=license,proto3" json:"license,omitempty"` + // Message to associate with the license creation event. + Message string `protobuf:"bytes,2,opt,name=message,proto3" json:"message,omitempty"` } func (x *CreateEnterpriseSubscriptionLicenseRequest) Reset() { @@ -1381,6 +1383,13 @@ func (x *CreateEnterpriseSubscriptionLicenseRequest) GetLicense() *EnterpriseSub return nil } +func (x *CreateEnterpriseSubscriptionLicenseRequest) GetMessage() string { + if x != nil { + return x.Message + } + return "" +} + type CreateEnterpriseSubscriptionLicenseResponse struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -1539,6 +1548,8 @@ type UpdateEnterpriseSubscriptionRequest struct { // Updatable fields are: // - instance_domain // - display_name + // - salesforce.subscription_id + // - salesforce.opportunity_id UpdateMask *fieldmaskpb.FieldMask `protobuf:"bytes,2,opt,name=update_mask,json=updateMask,proto3" json:"update_mask,omitempty"` } @@ -1746,6 +1757,8 @@ type CreateEnterpriseSubscriptionRequest struct { // - salesforce.subscription_id // - salesforce.opportunity_id Subscription *EnterpriseSubscription `protobuf:"bytes,1,opt,name=subscription,proto3" json:"subscription,omitempty"` + // Message to associate with the subscription creation event. + Message string `protobuf:"bytes,2,opt,name=message,proto3" json:"message,omitempty"` } func (x *CreateEnterpriseSubscriptionRequest) Reset() { @@ -1787,6 +1800,13 @@ func (x *CreateEnterpriseSubscriptionRequest) GetSubscription() *EnterpriseSubsc return nil } +func (x *CreateEnterpriseSubscriptionRequest) GetMessage() string { + if x != nil { + return x.Message + } + return "" +} + type CreateEnterpriseSubscriptionResponse struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -2428,7 +2448,7 @@ var file_subscriptions_proto_rawDesc = []byte{ 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x52, 0x08, 0x6c, 0x69, 0x63, 0x65, 0x6e, 0x73, - 0x65, 0x73, 0x22, 0x88, 0x01, 0x0a, 0x2a, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x45, 0x6e, 0x74, + 0x65, 0x73, 0x22, 0xa2, 0x01, 0x0a, 0x2a, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x5a, 0x0a, 0x07, 0x6c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x18, 0x01, 0x20, 0x01, @@ -2436,253 +2456,256 @@ var file_subscriptions_proto_rawDesc = []byte{ 0x6f, 0x72, 0x74, 0x61, 0x6c, 0x2e, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x4c, 0x69, 0x63, - 0x65, 0x6e, 0x73, 0x65, 0x52, 0x07, 0x6c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x22, 0x89, 0x01, - 0x0a, 0x2b, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, - 0x73, 0x65, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x4c, 0x69, - 0x63, 0x65, 0x6e, 0x73, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x5a, 0x0a, - 0x07, 0x6c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x40, - 0x2e, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x61, - 0x6c, 0x2e, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, - 0x76, 0x31, 0x2e, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x53, 0x75, 0x62, - 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, - 0x52, 0x07, 0x6c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x22, 0x63, 0x0a, 0x2a, 0x52, 0x65, 0x76, - 0x6f, 0x6b, 0x65, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x53, 0x75, 0x62, - 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x6c, 0x69, 0x63, 0x65, 0x6e, - 0x73, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6c, 0x69, 0x63, - 0x65, 0x6e, 0x73, 0x65, 0x49, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x22, 0x2d, - 0x0a, 0x2b, 0x52, 0x65, 0x76, 0x6f, 0x6b, 0x65, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, - 0x73, 0x65, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x4c, 0x69, - 0x63, 0x65, 0x6e, 0x73, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0xc1, 0x01, - 0x0a, 0x23, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, - 0x73, 0x65, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x5d, 0x0a, 0x0c, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, - 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x39, 0x2e, 0x65, 0x6e, - 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x61, 0x6c, 0x2e, 0x73, - 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x76, 0x31, 0x2e, - 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, - 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0c, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, - 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x3b, 0x0a, 0x0b, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x5f, 0x6d, - 0x61, 0x73, 0x6b, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, - 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, 0x69, 0x65, 0x6c, - 0x64, 0x4d, 0x61, 0x73, 0x6b, 0x52, 0x0a, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4d, 0x61, 0x73, - 0x6b, 0x22, 0x85, 0x01, 0x0a, 0x24, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x45, 0x6e, 0x74, 0x65, - 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, - 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x5d, 0x0a, 0x0c, 0x73, 0x75, - 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x39, 0x2e, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x70, 0x6f, 0x72, - 0x74, 0x61, 0x6c, 0x2e, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, - 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x53, - 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0c, 0x73, 0x75, 0x62, - 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x67, 0x0a, 0x24, 0x41, 0x72, 0x63, - 0x68, 0x69, 0x76, 0x65, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x53, 0x75, - 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x12, 0x27, 0x0a, 0x0f, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, - 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x73, 0x75, 0x62, 0x73, - 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x72, 0x65, - 0x61, 0x73, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x65, 0x61, 0x73, - 0x6f, 0x6e, 0x22, 0x27, 0x0a, 0x25, 0x41, 0x72, 0x63, 0x68, 0x69, 0x76, 0x65, 0x45, 0x6e, 0x74, + 0x65, 0x6e, 0x73, 0x65, 0x52, 0x07, 0x6c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x12, 0x18, 0x0a, + 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, + 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x89, 0x01, 0x0a, 0x2b, 0x43, 0x72, 0x65, 0x61, + 0x74, 0x65, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x53, 0x75, 0x62, 0x73, + 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x5a, 0x0a, 0x07, 0x6c, 0x69, 0x63, 0x65, 0x6e, + 0x73, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x40, 0x2e, 0x65, 0x6e, 0x74, 0x65, 0x72, + 0x70, 0x72, 0x69, 0x73, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x61, 0x6c, 0x2e, 0x73, 0x75, 0x62, 0x73, + 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, - 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x84, 0x01, 0x0a, 0x23, - 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, - 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x12, 0x5d, 0x0a, 0x0c, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, - 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x39, 0x2e, 0x65, 0x6e, 0x74, 0x65, - 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x61, 0x6c, 0x2e, 0x73, 0x75, 0x62, - 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x6e, - 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, - 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0c, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, - 0x6f, 0x6e, 0x22, 0x85, 0x01, 0x0a, 0x24, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x45, 0x6e, 0x74, + 0x69, 0x6f, 0x6e, 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x52, 0x07, 0x6c, 0x69, 0x63, 0x65, + 0x6e, 0x73, 0x65, 0x22, 0x63, 0x0a, 0x2a, 0x52, 0x65, 0x76, 0x6f, 0x6b, 0x65, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, - 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x5d, 0x0a, 0x0c, 0x73, - 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x39, 0x2e, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x70, 0x6f, - 0x72, 0x74, 0x61, 0x6c, 0x2e, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, - 0x6e, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, - 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0c, 0x73, 0x75, - 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0xf5, 0x01, 0x0a, 0x20, 0x45, + 0x69, 0x6f, 0x6e, 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x6c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x5f, 0x69, 0x64, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x49, 0x64, + 0x12, 0x16, 0x0a, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x22, 0x2d, 0x0a, 0x2b, 0x52, 0x65, 0x76, 0x6f, + 0x6b, 0x65, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x53, 0x75, 0x62, 0x73, + 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0xc1, 0x01, 0x0a, 0x23, 0x55, 0x70, 0x64, 0x61, + 0x74, 0x65, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x53, 0x75, 0x62, 0x73, + 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, + 0x5d, 0x0a, 0x0c, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x39, 0x2e, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, + 0x73, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x61, 0x6c, 0x2e, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, + 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, + 0x72, 0x69, 0x73, 0x65, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, + 0x52, 0x0c, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x3b, + 0x0a, 0x0b, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x5f, 0x6d, 0x61, 0x73, 0x6b, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x4d, 0x61, 0x73, 0x6b, 0x52, + 0x0a, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4d, 0x61, 0x73, 0x6b, 0x22, 0x85, 0x01, 0x0a, 0x24, + 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, + 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x5d, 0x0a, 0x0c, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, + 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x39, 0x2e, 0x65, 0x6e, 0x74, + 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x61, 0x6c, 0x2e, 0x73, 0x75, + 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, - 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x68, 0x69, 0x70, 0x12, - 0x27, 0x0a, 0x0f, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x5f, - 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, - 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x27, 0x0a, 0x0f, 0x69, 0x6e, 0x73, 0x74, - 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x0e, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x44, 0x6f, 0x6d, 0x61, 0x69, - 0x6e, 0x12, 0x33, 0x0a, 0x16, 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x5f, 0x73, 0x61, 0x6d, 0x73, - 0x5f, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x13, 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x53, 0x61, 0x6d, 0x73, 0x41, 0x63, 0x63, - 0x6f, 0x75, 0x6e, 0x74, 0x49, 0x64, 0x12, 0x4a, 0x0a, 0x0c, 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, - 0x5f, 0x72, 0x6f, 0x6c, 0x65, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0e, 0x32, 0x27, 0x2e, 0x65, + 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0c, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, + 0x69, 0x6f, 0x6e, 0x22, 0x67, 0x0a, 0x24, 0x41, 0x72, 0x63, 0x68, 0x69, 0x76, 0x65, 0x45, 0x6e, + 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, + 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x27, 0x0a, 0x0f, 0x73, + 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, + 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x22, 0x27, 0x0a, 0x25, + 0x41, 0x72, 0x63, 0x68, 0x69, 0x76, 0x65, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, + 0x65, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x9e, 0x01, 0x0a, 0x23, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, + 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, + 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x5d, 0x0a, + 0x0c, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x39, 0x2e, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, + 0x70, 0x6f, 0x72, 0x74, 0x61, 0x6c, 0x2e, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, + 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, + 0x73, 0x65, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0c, + 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x18, 0x0a, 0x07, + 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, + 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x85, 0x01, 0x0a, 0x24, 0x43, 0x72, 0x65, 0x61, 0x74, + 0x65, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x53, 0x75, 0x62, 0x73, 0x63, + 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x5d, 0x0a, 0x0c, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x39, 0x2e, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, + 0x73, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x61, 0x6c, 0x2e, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, + 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, + 0x72, 0x69, 0x73, 0x65, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, + 0x52, 0x0c, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0xf5, + 0x01, 0x0a, 0x20, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x53, 0x75, 0x62, + 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, + 0x68, 0x69, 0x70, 0x12, 0x27, 0x0a, 0x0f, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, + 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x73, 0x75, + 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x27, 0x0a, 0x0f, + 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x44, + 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x12, 0x33, 0x0a, 0x16, 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x5f, + 0x73, 0x61, 0x6d, 0x73, 0x5f, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x13, 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x53, 0x61, 0x6d, + 0x73, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x49, 0x64, 0x12, 0x4a, 0x0a, 0x0c, 0x6d, 0x65, + 0x6d, 0x62, 0x65, 0x72, 0x5f, 0x72, 0x6f, 0x6c, 0x65, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0e, + 0x32, 0x27, 0x2e, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x70, 0x6f, 0x72, + 0x74, 0x61, 0x6c, 0x2e, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, + 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x6f, 0x6c, 0x65, 0x52, 0x0b, 0x6d, 0x65, 0x6d, 0x62, 0x65, + 0x72, 0x52, 0x6f, 0x6c, 0x65, 0x73, 0x22, 0x94, 0x01, 0x0a, 0x2d, 0x55, 0x70, 0x64, 0x61, 0x74, + 0x65, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x53, 0x75, 0x62, 0x73, 0x63, + 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x68, 0x69, + 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x63, 0x0a, 0x0a, 0x6d, 0x65, 0x6d, 0x62, + 0x65, 0x72, 0x73, 0x68, 0x69, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x43, 0x2e, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x61, 0x6c, 0x2e, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x76, 0x31, - 0x2e, 0x52, 0x6f, 0x6c, 0x65, 0x52, 0x0b, 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x52, 0x6f, 0x6c, - 0x65, 0x73, 0x22, 0x94, 0x01, 0x0a, 0x2d, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x45, 0x6e, 0x74, - 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, - 0x69, 0x6f, 0x6e, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x68, 0x69, 0x70, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x12, 0x63, 0x0a, 0x0a, 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x68, - 0x69, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x43, 0x2e, 0x65, 0x6e, 0x74, 0x65, 0x72, - 0x70, 0x72, 0x69, 0x73, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x61, 0x6c, 0x2e, 0x73, 0x75, 0x62, 0x73, - 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x6e, 0x74, - 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, - 0x69, 0x6f, 0x6e, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x68, 0x69, 0x70, 0x52, 0x0a, 0x6d, - 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x68, 0x69, 0x70, 0x22, 0x30, 0x0a, 0x2e, 0x55, 0x70, 0x64, - 0x61, 0x74, 0x65, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x53, 0x75, 0x62, - 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, - 0x68, 0x69, 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0xce, 0x01, 0x0a, 0x0a, - 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x45, 0x0a, 0x04, 0x74, 0x79, - 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x31, 0x2e, 0x65, 0x6e, 0x74, 0x65, 0x72, + 0x2e, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x53, 0x75, 0x62, 0x73, 0x63, + 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x68, 0x69, + 0x70, 0x52, 0x0a, 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x68, 0x69, 0x70, 0x22, 0x30, 0x0a, + 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, + 0x65, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x65, 0x6d, + 0x62, 0x65, 0x72, 0x73, 0x68, 0x69, 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, + 0xce, 0x01, 0x0a, 0x0a, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x45, + 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x31, 0x2e, 0x65, + 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x61, 0x6c, 0x2e, + 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x76, 0x31, + 0x2e, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x54, 0x79, 0x70, 0x65, 0x52, + 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x51, 0x0a, 0x08, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x35, 0x2e, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x70, + 0x72, 0x69, 0x73, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x61, 0x6c, 0x2e, 0x73, 0x75, 0x62, 0x73, 0x63, + 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x65, 0x72, 0x6d, + 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x08, + 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x26, 0x0a, 0x0f, 0x73, 0x61, 0x6d, 0x73, + 0x5f, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x0d, 0x73, 0x61, 0x6d, 0x73, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x49, 0x64, + 0x2a, 0x87, 0x01, 0x0a, 0x21, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x53, + 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x4c, 0x69, 0x63, 0x65, 0x6e, + 0x73, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x34, 0x0a, 0x30, 0x45, 0x4e, 0x54, 0x45, 0x52, 0x50, + 0x52, 0x49, 0x53, 0x45, 0x5f, 0x53, 0x55, 0x42, 0x53, 0x43, 0x52, 0x49, 0x50, 0x54, 0x49, 0x4f, + 0x4e, 0x5f, 0x4c, 0x49, 0x43, 0x45, 0x4e, 0x53, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, + 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x2c, 0x0a, 0x28, + 0x45, 0x4e, 0x54, 0x45, 0x52, 0x50, 0x52, 0x49, 0x53, 0x45, 0x5f, 0x53, 0x55, 0x42, 0x53, 0x43, + 0x52, 0x49, 0x50, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x4c, 0x49, 0x43, 0x45, 0x4e, 0x53, 0x45, 0x5f, + 0x54, 0x59, 0x50, 0x45, 0x5f, 0x4b, 0x45, 0x59, 0x10, 0x01, 0x2a, 0x48, 0x0a, 0x04, 0x52, 0x6f, + 0x6c, 0x65, 0x12, 0x14, 0x0a, 0x10, 0x52, 0x4f, 0x4c, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, + 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x24, 0x0a, 0x20, 0x52, 0x4f, 0x4c, 0x45, + 0x5f, 0x53, 0x55, 0x42, 0x53, 0x43, 0x52, 0x49, 0x50, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x43, 0x55, + 0x53, 0x54, 0x4f, 0x4d, 0x45, 0x52, 0x5f, 0x41, 0x44, 0x4d, 0x49, 0x4e, 0x10, 0x02, 0x22, 0x04, + 0x08, 0x01, 0x10, 0x01, 0x2a, 0x62, 0x0a, 0x0e, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, + 0x6f, 0x6e, 0x54, 0x79, 0x70, 0x65, 0x12, 0x1f, 0x0a, 0x1b, 0x50, 0x45, 0x52, 0x4d, 0x49, 0x53, + 0x53, 0x49, 0x4f, 0x4e, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, + 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x2f, 0x0a, 0x2b, 0x50, 0x45, 0x52, 0x4d, 0x49, + 0x53, 0x53, 0x49, 0x4f, 0x4e, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x53, 0x55, 0x42, 0x53, 0x43, + 0x52, 0x49, 0x50, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x43, 0x4f, 0x44, 0x59, 0x5f, 0x41, 0x4e, 0x41, + 0x4c, 0x59, 0x54, 0x49, 0x43, 0x53, 0x10, 0x01, 0x2a, 0x57, 0x0a, 0x12, 0x50, 0x65, 0x72, 0x6d, + 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x23, + 0x0a, 0x1f, 0x50, 0x45, 0x52, 0x4d, 0x49, 0x53, 0x53, 0x49, 0x4f, 0x4e, 0x5f, 0x52, 0x45, 0x4c, + 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, + 0x44, 0x10, 0x00, 0x12, 0x1c, 0x0a, 0x18, 0x50, 0x45, 0x52, 0x4d, 0x49, 0x53, 0x53, 0x49, 0x4f, + 0x4e, 0x5f, 0x52, 0x45, 0x4c, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x56, 0x49, 0x45, 0x57, 0x10, + 0x01, 0x32, 0xd0, 0x0d, 0x0a, 0x14, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, + 0x6f, 0x6e, 0x73, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0xab, 0x01, 0x0a, 0x19, 0x47, + 0x65, 0x74, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x53, 0x75, 0x62, 0x73, + 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x43, 0x2e, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x61, 0x6c, 0x2e, 0x73, 0x75, 0x62, 0x73, - 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x65, 0x72, - 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, - 0x65, 0x12, 0x51, 0x0a, 0x08, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x0e, 0x32, 0x35, 0x2e, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, - 0x70, 0x6f, 0x72, 0x74, 0x61, 0x6c, 0x2e, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, - 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, - 0x6f, 0x6e, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x08, 0x72, 0x65, 0x6c, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x26, 0x0a, 0x0f, 0x73, 0x61, 0x6d, 0x73, 0x5f, 0x61, 0x63, 0x63, - 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x73, - 0x61, 0x6d, 0x73, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x49, 0x64, 0x2a, 0x87, 0x01, 0x0a, - 0x21, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x53, 0x75, 0x62, 0x73, 0x63, - 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x54, 0x79, - 0x70, 0x65, 0x12, 0x34, 0x0a, 0x30, 0x45, 0x4e, 0x54, 0x45, 0x52, 0x50, 0x52, 0x49, 0x53, 0x45, - 0x5f, 0x53, 0x55, 0x42, 0x53, 0x43, 0x52, 0x49, 0x50, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x4c, 0x49, - 0x43, 0x45, 0x4e, 0x53, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, - 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x2c, 0x0a, 0x28, 0x45, 0x4e, 0x54, 0x45, - 0x52, 0x50, 0x52, 0x49, 0x53, 0x45, 0x5f, 0x53, 0x55, 0x42, 0x53, 0x43, 0x52, 0x49, 0x50, 0x54, - 0x49, 0x4f, 0x4e, 0x5f, 0x4c, 0x49, 0x43, 0x45, 0x4e, 0x53, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, - 0x5f, 0x4b, 0x45, 0x59, 0x10, 0x01, 0x2a, 0x48, 0x0a, 0x04, 0x52, 0x6f, 0x6c, 0x65, 0x12, 0x14, - 0x0a, 0x10, 0x52, 0x4f, 0x4c, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, - 0x45, 0x44, 0x10, 0x00, 0x12, 0x24, 0x0a, 0x20, 0x52, 0x4f, 0x4c, 0x45, 0x5f, 0x53, 0x55, 0x42, - 0x53, 0x43, 0x52, 0x49, 0x50, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x43, 0x55, 0x53, 0x54, 0x4f, 0x4d, - 0x45, 0x52, 0x5f, 0x41, 0x44, 0x4d, 0x49, 0x4e, 0x10, 0x02, 0x22, 0x04, 0x08, 0x01, 0x10, 0x01, - 0x2a, 0x62, 0x0a, 0x0e, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x54, 0x79, - 0x70, 0x65, 0x12, 0x1f, 0x0a, 0x1b, 0x50, 0x45, 0x52, 0x4d, 0x49, 0x53, 0x53, 0x49, 0x4f, 0x4e, - 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, - 0x44, 0x10, 0x00, 0x12, 0x2f, 0x0a, 0x2b, 0x50, 0x45, 0x52, 0x4d, 0x49, 0x53, 0x53, 0x49, 0x4f, - 0x4e, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x53, 0x55, 0x42, 0x53, 0x43, 0x52, 0x49, 0x50, 0x54, - 0x49, 0x4f, 0x4e, 0x5f, 0x43, 0x4f, 0x44, 0x59, 0x5f, 0x41, 0x4e, 0x41, 0x4c, 0x59, 0x54, 0x49, - 0x43, 0x53, 0x10, 0x01, 0x2a, 0x57, 0x0a, 0x12, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, - 0x6f, 0x6e, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x23, 0x0a, 0x1f, 0x50, 0x45, - 0x52, 0x4d, 0x49, 0x53, 0x53, 0x49, 0x4f, 0x4e, 0x5f, 0x52, 0x45, 0x4c, 0x41, 0x54, 0x49, 0x4f, - 0x4e, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, - 0x1c, 0x0a, 0x18, 0x50, 0x45, 0x52, 0x4d, 0x49, 0x53, 0x53, 0x49, 0x4f, 0x4e, 0x5f, 0x52, 0x45, - 0x4c, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x56, 0x49, 0x45, 0x57, 0x10, 0x01, 0x32, 0xd0, 0x0d, - 0x0a, 0x14, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x53, - 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0xab, 0x01, 0x0a, 0x19, 0x47, 0x65, 0x74, 0x45, 0x6e, - 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, - 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x43, 0x2e, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, - 0x65, 0x70, 0x6f, 0x72, 0x74, 0x61, 0x6c, 0x2e, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, - 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x45, 0x6e, 0x74, 0x65, - 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, - 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x44, 0x2e, 0x65, 0x6e, 0x74, 0x65, - 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x61, 0x6c, 0x2e, 0x73, 0x75, 0x62, - 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, + 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, + 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, + 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x44, 0x2e, + 0x65, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x61, 0x6c, + 0x2e, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x76, + 0x31, 0x2e, 0x47, 0x65, 0x74, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x53, + 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x22, 0x03, 0x90, 0x02, 0x01, 0x12, 0xb1, 0x01, 0x0a, 0x1b, 0x4c, 0x69, 0x73, 0x74, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x53, 0x75, 0x62, 0x73, 0x63, - 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, - 0x03, 0x90, 0x02, 0x01, 0x12, 0xb1, 0x01, 0x0a, 0x1b, 0x4c, 0x69, 0x73, 0x74, 0x45, 0x6e, 0x74, - 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, - 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x45, 0x2e, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, - 0x65, 0x70, 0x6f, 0x72, 0x74, 0x61, 0x6c, 0x2e, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, - 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x45, 0x6e, 0x74, - 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, - 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x46, 0x2e, 0x65, 0x6e, - 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x61, 0x6c, 0x2e, 0x73, - 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x76, 0x31, 0x2e, - 0x4c, 0x69, 0x73, 0x74, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x53, 0x75, - 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x22, 0x03, 0x90, 0x02, 0x01, 0x12, 0xc6, 0x01, 0x0a, 0x22, 0x4c, 0x69, 0x73, + 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x45, 0x2e, 0x65, 0x6e, 0x74, 0x65, 0x72, + 0x70, 0x72, 0x69, 0x73, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x61, 0x6c, 0x2e, 0x73, 0x75, 0x62, 0x73, + 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x53, 0x75, 0x62, 0x73, 0x63, - 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x73, 0x12, - 0x4c, 0x2e, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x70, 0x6f, 0x72, 0x74, + 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x46, 0x2e, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x61, 0x6c, 0x2e, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, - 0x73, 0x65, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x4c, 0x69, - 0x63, 0x65, 0x6e, 0x73, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x4d, 0x2e, - 0x65, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x61, 0x6c, - 0x2e, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x76, - 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, - 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x4c, 0x69, 0x63, 0x65, - 0x6e, 0x73, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x03, 0x90, 0x02, - 0x01, 0x12, 0xc6, 0x01, 0x0a, 0x23, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x45, 0x6e, 0x74, 0x65, - 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, - 0x6f, 0x6e, 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x12, 0x4d, 0x2e, 0x65, 0x6e, 0x74, 0x65, - 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x61, 0x6c, 0x2e, 0x73, 0x75, 0x62, - 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, - 0x65, 0x61, 0x74, 0x65, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x53, 0x75, - 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, - 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x4e, 0x2e, 0x65, 0x6e, 0x74, 0x65, 0x72, - 0x70, 0x72, 0x69, 0x73, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x61, 0x6c, 0x2e, 0x73, 0x75, 0x62, 0x73, - 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, - 0x61, 0x74, 0x65, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x53, 0x75, 0x62, - 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0xc9, 0x01, 0x0a, 0x23, 0x52, - 0x65, 0x76, 0x6f, 0x6b, 0x65, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x53, + 0x73, 0x65, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x03, 0x90, 0x02, 0x01, 0x12, 0xc6, 0x01, 0x0a, + 0x22, 0x4c, 0x69, 0x73, 0x74, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x4c, 0x69, 0x63, 0x65, 0x6e, - 0x73, 0x65, 0x12, 0x4d, 0x2e, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x70, - 0x6f, 0x72, 0x74, 0x61, 0x6c, 0x2e, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, - 0x6f, 0x6e, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x76, 0x6f, 0x6b, 0x65, 0x45, 0x6e, 0x74, - 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, - 0x69, 0x6f, 0x6e, 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x4e, 0x2e, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x70, 0x6f, - 0x72, 0x74, 0x61, 0x6c, 0x2e, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, - 0x6e, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x76, 0x6f, 0x6b, 0x65, 0x45, 0x6e, 0x74, 0x65, + 0x73, 0x65, 0x73, 0x12, 0x4c, 0x2e, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, + 0x70, 0x6f, 0x72, 0x74, 0x61, 0x6c, 0x2e, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, + 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, - 0x6f, 0x6e, 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x22, 0x03, 0x90, 0x02, 0x02, 0x12, 0xb4, 0x01, 0x0a, 0x1c, 0x55, 0x70, 0x64, 0x61, 0x74, - 0x65, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x53, 0x75, 0x62, 0x73, 0x63, - 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x46, 0x2e, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x70, - 0x72, 0x69, 0x73, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x61, 0x6c, 0x2e, 0x73, 0x75, 0x62, 0x73, 0x63, - 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, - 0x74, 0x65, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x53, 0x75, 0x62, 0x73, - 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x47, 0x2e, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x70, 0x6f, 0x72, 0x74, - 0x61, 0x6c, 0x2e, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, - 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, + 0x6f, 0x6e, 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x4d, 0x2e, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x70, 0x6f, + 0x72, 0x74, 0x61, 0x6c, 0x2e, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, + 0x6e, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x03, 0x90, 0x02, 0x02, 0x12, 0xb7, 0x01, - 0x0a, 0x1d, 0x41, 0x72, 0x63, 0x68, 0x69, 0x76, 0x65, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, - 0x69, 0x73, 0x65, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, - 0x47, 0x2e, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x70, 0x6f, 0x72, 0x74, - 0x61, 0x6c, 0x2e, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, - 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x72, 0x63, 0x68, 0x69, 0x76, 0x65, 0x45, 0x6e, 0x74, 0x65, 0x72, - 0x70, 0x72, 0x69, 0x73, 0x65, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, - 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x48, 0x2e, 0x65, 0x6e, 0x74, 0x65, 0x72, - 0x70, 0x72, 0x69, 0x73, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x61, 0x6c, 0x2e, 0x73, 0x75, 0x62, 0x73, - 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x72, 0x63, - 0x68, 0x69, 0x76, 0x65, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x53, 0x75, - 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x22, 0x03, 0x90, 0x02, 0x02, 0x12, 0xb1, 0x01, 0x0a, 0x1c, 0x43, 0x72, 0x65, 0x61, - 0x74, 0x65, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x53, 0x75, 0x62, 0x73, - 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x46, 0x2e, 0x65, 0x6e, 0x74, 0x65, 0x72, - 0x70, 0x72, 0x69, 0x73, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x61, 0x6c, 0x2e, 0x73, 0x75, 0x62, 0x73, - 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, - 0x61, 0x74, 0x65, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x53, 0x75, 0x62, - 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x47, 0x2e, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x70, 0x6f, 0x72, - 0x74, 0x61, 0x6c, 0x2e, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, - 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x45, 0x6e, 0x74, 0x65, 0x72, - 0x70, 0x72, 0x69, 0x73, 0x65, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, - 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0xd2, 0x01, 0x0a, 0x26, - 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, - 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x65, 0x6d, 0x62, - 0x65, 0x72, 0x73, 0x68, 0x69, 0x70, 0x12, 0x50, 0x2e, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, + 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x22, 0x03, 0x90, 0x02, 0x01, 0x12, 0xc6, 0x01, 0x0a, 0x23, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, + 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, + 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x12, 0x4d, 0x2e, + 0x65, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x61, 0x6c, + 0x2e, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x76, + 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, + 0x73, 0x65, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x4c, 0x69, + 0x63, 0x65, 0x6e, 0x73, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x4e, 0x2e, 0x65, + 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x61, 0x6c, 0x2e, + 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x76, 0x31, + 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, + 0x65, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x4c, 0x69, 0x63, + 0x65, 0x6e, 0x73, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0xc9, + 0x01, 0x0a, 0x23, 0x52, 0x65, 0x76, 0x6f, 0x6b, 0x65, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, + 0x69, 0x73, 0x65, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x4c, + 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x12, 0x4d, 0x2e, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x61, 0x6c, 0x2e, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, - 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, + 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x76, 0x6f, 0x6b, 0x65, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x53, 0x75, 0x62, 0x73, 0x63, - 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x68, 0x69, - 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x51, 0x2e, 0x65, 0x6e, 0x74, 0x65, 0x72, - 0x70, 0x72, 0x69, 0x73, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x61, 0x6c, 0x2e, 0x73, 0x75, 0x62, 0x73, - 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x64, - 0x61, 0x74, 0x65, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x53, 0x75, 0x62, - 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, - 0x68, 0x69, 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x03, 0x90, 0x02, 0x02, - 0x42, 0x4a, 0x5a, 0x48, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x73, - 0x6f, 0x75, 0x72, 0x63, 0x65, 0x67, 0x72, 0x61, 0x70, 0x68, 0x2f, 0x73, 0x6f, 0x75, 0x72, 0x63, - 0x65, 0x67, 0x72, 0x61, 0x70, 0x68, 0x2f, 0x6c, 0x69, 0x62, 0x2f, 0x65, 0x6e, 0x74, 0x65, 0x72, - 0x70, 0x72, 0x69, 0x73, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x61, 0x6c, 0x2f, 0x73, 0x75, 0x62, 0x73, - 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x33, + 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x4e, 0x2e, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, + 0x73, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x61, 0x6c, 0x2e, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, + 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x76, 0x6f, 0x6b, 0x65, + 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, + 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x03, 0x90, 0x02, 0x02, 0x12, 0xb4, 0x01, 0x0a, 0x1c, 0x55, + 0x70, 0x64, 0x61, 0x74, 0x65, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x53, + 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x46, 0x2e, 0x65, 0x6e, + 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x61, 0x6c, 0x2e, 0x73, + 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x76, 0x31, 0x2e, + 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, + 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x47, 0x2e, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, + 0x70, 0x6f, 0x72, 0x74, 0x61, 0x6c, 0x2e, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, + 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x45, 0x6e, + 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, + 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x03, 0x90, 0x02, + 0x02, 0x12, 0xb7, 0x01, 0x0a, 0x1d, 0x41, 0x72, 0x63, 0x68, 0x69, 0x76, 0x65, 0x45, 0x6e, 0x74, + 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, + 0x69, 0x6f, 0x6e, 0x12, 0x47, 0x2e, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, + 0x70, 0x6f, 0x72, 0x74, 0x61, 0x6c, 0x2e, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, + 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x72, 0x63, 0x68, 0x69, 0x76, 0x65, 0x45, + 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, + 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x48, 0x2e, 0x65, + 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x61, 0x6c, 0x2e, + 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x76, 0x31, + 0x2e, 0x41, 0x72, 0x63, 0x68, 0x69, 0x76, 0x65, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, + 0x73, 0x65, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x03, 0x90, 0x02, 0x02, 0x12, 0xb1, 0x01, 0x0a, 0x1c, + 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, + 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x46, 0x2e, 0x65, + 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x61, 0x6c, 0x2e, + 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x76, 0x31, + 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, + 0x65, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x47, 0x2e, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, + 0x65, 0x70, 0x6f, 0x72, 0x74, 0x61, 0x6c, 0x2e, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, + 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x45, + 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, + 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, + 0xd2, 0x01, 0x0a, 0x26, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, + 0x72, 0x69, 0x73, 0x65, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, + 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x68, 0x69, 0x70, 0x12, 0x50, 0x2e, 0x65, 0x6e, 0x74, + 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x61, 0x6c, 0x2e, 0x73, 0x75, + 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x55, + 0x70, 0x64, 0x61, 0x74, 0x65, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x53, + 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x65, 0x6d, 0x62, 0x65, + 0x72, 0x73, 0x68, 0x69, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x51, 0x2e, 0x65, + 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x61, 0x6c, 0x2e, + 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x76, 0x31, + 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, + 0x65, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x65, 0x6d, + 0x62, 0x65, 0x72, 0x73, 0x68, 0x69, 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, + 0x03, 0x90, 0x02, 0x02, 0x42, 0x4a, 0x5a, 0x48, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, + 0x6f, 0x6d, 0x2f, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x67, 0x72, 0x61, 0x70, 0x68, 0x2f, 0x73, + 0x6f, 0x75, 0x72, 0x63, 0x65, 0x67, 0x72, 0x61, 0x70, 0x68, 0x2f, 0x6c, 0x69, 0x62, 0x2f, 0x65, + 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x61, 0x6c, 0x2f, + 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x76, 0x31, + 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/lib/enterpriseportal/subscriptions/v1/subscriptions.proto b/lib/enterpriseportal/subscriptions/v1/subscriptions.proto index 3c5688d21e219..6ca9dec4db472 100644 --- a/lib/enterpriseportal/subscriptions/v1/subscriptions.proto +++ b/lib/enterpriseportal/subscriptions/v1/subscriptions.proto @@ -301,6 +301,9 @@ message CreateEnterpriseSubscriptionLicenseRequest { // - license.key.info.user_count // - license.key.info.expire_time EnterpriseSubscriptionLicense license = 1; + + // Message to associate with the license creation event. + string message = 2; } message CreateEnterpriseSubscriptionLicenseResponse { @@ -328,6 +331,8 @@ message UpdateEnterpriseSubscriptionRequest { // Updatable fields are: // - instance_domain // - display_name + // - salesforce.subscription_id + // - salesforce.opportunity_id google.protobuf.FieldMask update_mask = 2; } @@ -356,6 +361,9 @@ message CreateEnterpriseSubscriptionRequest { // - salesforce.subscription_id // - salesforce.opportunity_id EnterpriseSubscription subscription = 1; + + // Message to associate with the subscription creation event. + string message = 2; } message CreateEnterpriseSubscriptionResponse {