From 724168b5eebdce35e64f4e1b137fa130f10a4dd4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9Cniladrix719=E2=80=9D?= Date: Thu, 27 Nov 2025 02:06:41 +0530 Subject: [PATCH 1/9] feat: Implement project enabling/disabling functionality MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: “niladrix719” --- cmd/pipecd/server.go | 1 + pkg/app/ops/handler/handler.go | 54 + pkg/app/ops/handler/handler_test.go | 14 +- pkg/app/ops/handler/templates/ListProjects | 10 + pkg/app/server/apikeyverifier/verifier.go | 41 +- .../server/apikeyverifier/verifier_test.go | 51 +- pkg/app/server/grpcapi/api.go | 11 + .../grpcapi/api_disabled_project_test.go | 63 + pkg/app/server/grpcapi/piped_api.go | 33 + .../piped_api_disabled_project_test.go | 152 ++ pkg/app/server/grpcapi/web_api.go | 85 + .../grpcapi/web_api_disabled_project_test.go | 374 +++ pkg/app/server/httpapi/callback.go | 6 +- pkg/app/server/httpapi/login.go | 10 +- pkg/app/server/pipedverifier/verifier.go | 16 +- pkg/app/server/pipedverifier/verifier_test.go | 33 +- .../service/webservice/service.pb.auth.go | 4 + .../server/service/webservice/service.pb.go | 2115 +++++++++-------- .../service/webservice/service.pb.validate.go | 408 ++++ .../server/service/webservice/service.proto | 20 + .../service/webservice/service_grpc.pb.go | 72 + pkg/datastore/projectstore.go | 18 + pkg/jwt/jwt.go | 8 +- pkg/jwt/signer_test.go | 2 +- pkg/jwt/verifier_test.go | 4 +- pkg/model/project.pb.go | 297 +-- pkg/model/project.pb.validate.go | 2 + pkg/model/project.proto | 3 + tool/codegen/protoc-gen-auth/file.go | 8 + web/api_client/service_grpc_web_pb.d.ts | 24 + web/api_client/service_grpc_web_pb.js | 122 + web/api_client/service_pb.d.ts | 56 + web/api_client/service_pb.js | 492 ++++ web/model/project_pb.d.ts | 4 + web/model/project_pb.js | 30 + web/src/api/project.ts | 14 + .../components/github-sso-form/index.tsx | 22 +- .../components/project-status-form/index.tsx | 65 + .../add-user-group-dialog/index.test.tsx | 1 + .../components/role-table-row/index.tsx | 6 +- .../rbac-form/components/role/index.tsx | 30 +- .../rbac-form/components/user-group/index.tsx | 30 +- .../project/components/rbac-form/index.tsx | 8 +- .../components/static-admin-form/index.tsx | 23 +- .../settings-page/project/index.tsx | 8 +- web/src/constants/text.ts | 2 + web/src/constants/toast-text.ts | 2 + web/src/queries/project/use-get-project.tsx | 4 + .../use-toggle-project-availability.tsx | 26 + 49 files changed, 3753 insertions(+), 1131 deletions(-) create mode 100644 pkg/app/server/grpcapi/api_disabled_project_test.go create mode 100644 pkg/app/server/grpcapi/piped_api_disabled_project_test.go create mode 100644 pkg/app/server/grpcapi/web_api_disabled_project_test.go create mode 100644 web/src/components/settings-page/project/components/project-status-form/index.tsx create mode 100644 web/src/queries/project/use-toggle-project-availability.tsx diff --git a/cmd/pipecd/server.go b/cmd/pipecd/server.go index 5d25ce6b6d..208e93808e 100644 --- a/cmd/pipecd/server.go +++ b/cmd/pipecd/server.go @@ -246,6 +246,7 @@ func (s *server) run(ctx context.Context, input cli.Input) error { verifier = apikeyverifier.NewVerifier( ctx, datastore.NewAPIKeyStore(ds), + datastore.NewProjectStore(ds), apiKeyLastUsedCache, input.Logger, ) diff --git a/pkg/app/ops/handler/handler.go b/pkg/app/ops/handler/handler.go index 8a646cf037..11127b2046 100644 --- a/pkg/app/ops/handler/handler.go +++ b/pkg/app/ops/handler/handler.go @@ -49,6 +49,8 @@ type projectStore interface { List(ctx context.Context, opts datastore.ListOptions) ([]model.Project, error) Get(ctx context.Context, id string) (*model.Project, error) UpdateProjectStaticAdmin(ctx context.Context, id, username, password string) error + EnableProject(ctx context.Context, id string) error + DisableProject(ctx context.Context, id string) error } type Handler struct { @@ -77,6 +79,7 @@ func NewHandler(port int, ps projectStore, sharedSSOConfigs []config.SharedSSOCo mux.HandleFunc("/projects", h.handleListProjects) mux.HandleFunc("/projects/add", h.handleAddProject) mux.HandleFunc("/projects/reset-password", h.handleResetPassword) + mux.HandleFunc("/projects/toggle-status", h.handleToggleProjectStatus) return h } @@ -150,6 +153,7 @@ func (h *Handler) handleListProjects(w http.ResponseWriter, r *http.Request) { "StaticAdminDisabled": strconv.FormatBool(projects[i].StaticAdminDisabled), "SharedSSOName": projects[i].SharedSsoName, "CreatedAt": time.Unix(projects[i].CreatedAt, 0).String(), + "Disabled": strconv.FormatBool(projects[i].Disabled), }) } if err := listProjectsTmpl.Execute(w, data); err != nil { @@ -337,3 +341,53 @@ func (h *Handler) handleAddProject(w http.ResponseWriter, r *http.Request) { h.logger.Error("failed to render AddedProject page template", zap.Error(err)) } } + +func (h *Handler) handleToggleProjectStatus(w http.ResponseWriter, r *http.Request) { + if r.Method != http.MethodGet { + http.Error(w, "not found", http.StatusNotFound) + return + } + + id := html.EscapeString(r.URL.Query().Get("ID")) + if id == "" { + http.Error(w, "invalid id", http.StatusBadRequest) + return + } + + action := html.EscapeString(r.URL.Query().Get("action")) + if action != "enable" && action != "disable" { + http.Error(w, "invalid action, must be 'enable' or 'disable'", http.StatusBadRequest) + return + } + + ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) + defer cancel() + + var err error + if action == "enable" { + err = h.projectStore.EnableProject(ctx, id) + if err != nil { + h.logger.Error("failed to enable project", + zap.String("id", id), + zap.Error(err), + ) + http.Error(w, fmt.Sprintf("Unable to enable project (%v)", err), http.StatusInternalServerError) + return + } + h.logger.Info("successfully enabled project", zap.String("id", id)) + } else { + err = h.projectStore.DisableProject(ctx, id) + if err != nil { + h.logger.Error("failed to disable project", + zap.String("id", id), + zap.Error(err), + ) + http.Error(w, fmt.Sprintf("Unable to disable project (%v)", err), http.StatusInternalServerError) + return + } + h.logger.Info("successfully disabled project", zap.String("id", id)) + } + + // Redirect back to the projects list + http.Redirect(w, r, "/projects", http.StatusSeeOther) +} diff --git a/pkg/app/ops/handler/handler_test.go b/pkg/app/ops/handler/handler_test.go index 0394148961..9057577694 100644 --- a/pkg/app/ops/handler/handler_test.go +++ b/pkg/app/ops/handler/handler_test.go @@ -34,13 +34,25 @@ import ( "github.com/pipe-cd/pipecd/pkg/model" ) +type mockProjectStoreWrapper struct { + *datastoretest.MockProjectStore +} + +func (m *mockProjectStoreWrapper) EnableProject(ctx context.Context, id string) error { + return nil +} + +func (m *mockProjectStoreWrapper) DisableProject(ctx context.Context, id string) error { + return nil +} + func createMockHandler(ctrl *gomock.Controller) (*datastoretest.MockProjectStore, *Handler) { m := datastoretest.NewMockProjectStore(ctrl) logger, _ := zap.NewProduction() h := NewHandler( 10101, - m, + &mockProjectStoreWrapper{MockProjectStore: m}, []config.SharedSSOConfig{}, 0, logger, diff --git a/pkg/app/ops/handler/templates/ListProjects b/pkg/app/ops/handler/templates/ListProjects index c20eebf807..3e79b94435 100644 --- a/pkg/app/ops/handler/templates/ListProjects +++ b/pkg/app/ops/handler/templates/ListProjects @@ -35,8 +35,10 @@ Description Static Admin Disabled Shared SSO Name + Project Status Created At Reset Static Admin Password + Toggle Status {{ range $index, $project := . }} @@ -45,8 +47,16 @@ {{ $project.Description }} {{ $project.StaticAdminDisabled }} {{ $project.SharedSSOName }} + {{ if eq $project.Disabled "true" }}Disabled{{ else }}Enabled{{ end }} {{ $project.CreatedAt }} Reset Password + + {{ if eq $project.Disabled "true" }} + Enable + {{ else }} + Disable + {{ end }} + {{ end }} diff --git a/pkg/app/server/apikeyverifier/verifier.go b/pkg/app/server/apikeyverifier/verifier.go index 3981dd646e..ee8600b6c6 100644 --- a/pkg/app/server/apikeyverifier/verifier.go +++ b/pkg/app/server/apikeyverifier/verifier.go @@ -30,6 +30,10 @@ type apiKeyGetter interface { Get(ctx context.Context, id string) (*model.APIKey, error) } +type projectGetter interface { + Get(ctx context.Context, id string) (*model.Project, error) +} + type apiKeyLastUsedPutter interface { Put(k string, v interface{}) error } @@ -37,15 +41,19 @@ type apiKeyLastUsedPutter interface { type Verifier struct { apiKeyCache cache.Cache apiKeyStore apiKeyGetter + projectStore projectGetter + projectCache cache.Cache apiKeyLastUsedCache apiKeyLastUsedPutter logger *zap.Logger nowFunc func() time.Time } -func NewVerifier(ctx context.Context, getter apiKeyGetter, akluc apiKeyLastUsedPutter, logger *zap.Logger) *Verifier { +func NewVerifier(ctx context.Context, getter apiKeyGetter, projectGetter projectGetter, akluc apiKeyLastUsedPutter, logger *zap.Logger) *Verifier { return &Verifier{ apiKeyCache: memorycache.NewTTLCache(ctx, 5*time.Minute, time.Minute), apiKeyStore: getter, + projectStore: projectGetter, + projectCache: memorycache.NewTTLCache(ctx, 12*time.Hour, time.Hour), apiKeyLastUsedCache: akluc, logger: logger, nowFunc: time.Now, @@ -86,10 +94,13 @@ func (v *Verifier) Verify(ctx context.Context, key string) (*model.APIKey, error return apiKey, nil } -func (v *Verifier) checkAPIKey(_ context.Context, apiKey *model.APIKey, id, key string) error { +func (v *Verifier) checkAPIKey(ctx context.Context, apiKey *model.APIKey, id, key string) error { if apiKey.Disabled { return fmt.Errorf("the api key %s was already disabled", id) } + if err := v.ensureProjectEnabled(ctx, apiKey.ProjectId); err != nil { + return err + } if err := apiKey.CompareKey(key); err != nil { return fmt.Errorf("invalid api key %s: %w", id, err) @@ -101,3 +112,29 @@ func (v *Verifier) checkAPIKey(_ context.Context, apiKey *model.APIKey, id, key return nil } + +func (v *Verifier) ensureProjectEnabled(ctx context.Context, projectID string) error { + if projectID == "" { + return fmt.Errorf("missing project id for api key") + } + if val, err := v.projectCache.Get(projectID); err == nil { + if enabled, ok := val.(bool); ok { + if enabled { + return nil + } + return fmt.Errorf("project %s is disabled", projectID) + } + } + proj, err := v.projectStore.Get(ctx, projectID) + if err != nil { + return fmt.Errorf("unable to find project %s: %w", projectID, err) + } + if proj.Disabled { + _ = v.projectCache.Put(projectID, false) + return fmt.Errorf("project %s is disabled", projectID) + } + if err := v.projectCache.Put(projectID, true); err != nil { + v.logger.Warn("unable to store project status in memory cache", zap.Error(err)) + } + return nil +} diff --git a/pkg/app/server/apikeyverifier/verifier_test.go b/pkg/app/server/apikeyverifier/verifier_test.go index 58fa1ce305..606b37099d 100644 --- a/pkg/app/server/apikeyverifier/verifier_test.go +++ b/pkg/app/server/apikeyverifier/verifier_test.go @@ -48,6 +48,21 @@ func (f *fakeRedisHashCache) Put(k string, v interface{}) error { return nil } +type fakeProjectGetter struct { + calls int + projects map[string]*model.Project +} + +func (g *fakeProjectGetter) Get(_ context.Context, id string) (*model.Project, error) { + g.calls++ + p, ok := g.projects[id] + if ok { + msg := proto.Clone(p) + return msg.(*model.Project), nil + } + return nil, fmt.Errorf("not found") +} + func TestVerify(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() @@ -60,6 +75,10 @@ func TestVerify(t *testing.T) { key2, hash2, err := model.GenerateAPIKey(id2) require.NoError(t, err) + var id3 = "project-disabled-api-key" + key3, hash3, err := model.GenerateAPIKey(id3) + require.NoError(t, err) + apiKeyGetter := &fakeAPIKeyGetter{ apiKeys: map[string]*model.APIKey{ id1: { @@ -75,10 +94,27 @@ func TestVerify(t *testing.T) { ProjectId: "test-project", Disabled: true, }, + id3: { + Id: id3, + Name: id3, + KeyHash: hash3, + ProjectId: "disabled-project", + }, }, } fakeRedisHashCache := &fakeRedisHashCache{} - v := NewVerifier(ctx, apiKeyGetter, fakeRedisHashCache, zap.NewNop()) + projectGetter := &fakeProjectGetter{ + projects: map[string]*model.Project{ + "test-project": { + Id: "test-project", + }, + "disabled-project": { + Id: "disabled-project", + Disabled: true, + }, + }, + } + v := NewVerifier(ctx, apiKeyGetter, projectGetter, fakeRedisHashCache, zap.NewNop()) // Not found key. notFoundKey, _, err := model.GenerateAPIKey("not-found-api-key") @@ -96,17 +132,26 @@ func TestVerify(t *testing.T) { require.NotNil(t, err) assert.Equal(t, "the api key disabled-api-key was already disabled", err.Error()) require.Equal(t, 2, apiKeyGetter.calls) + require.Equal(t, 0, projectGetter.calls) + + // Found key but project is disabled. + apiKey, err = v.Verify(ctx, key3) + require.Nil(t, apiKey) + require.NotNil(t, err) + assert.Equal(t, "project disabled-project is disabled", err.Error()) + require.Equal(t, 3, apiKeyGetter.calls) + require.Equal(t, 1, projectGetter.calls) // Found key but invalid secret. apiKey, err = v.Verify(ctx, fmt.Sprintf("%s.invalidhash", id1)) require.Nil(t, apiKey) require.NotNil(t, err) assert.Equal(t, "invalid api key test-api-key: wrong api key test-api-key.invalidhash: crypto/bcrypt: hashedPassword is not the hash of the given password", err.Error()) - require.Equal(t, 3, apiKeyGetter.calls) + require.Equal(t, 4, apiKeyGetter.calls) // OK. apiKey, err = v.Verify(ctx, key1) assert.Equal(t, id1, apiKey.Name) assert.Nil(t, err) - require.Equal(t, 3, apiKeyGetter.calls) + require.Equal(t, 4, apiKeyGetter.calls) } diff --git a/pkg/app/server/grpcapi/api.go b/pkg/app/server/grpcapi/api.go index 7c0ab5cafe..c4f3741422 100644 --- a/pkg/app/server/grpcapi/api.go +++ b/pkg/app/server/grpcapi/api.go @@ -80,6 +80,7 @@ type commandOutputGetter interface { type API struct { apiservice.UnimplementedAPIServiceServer + projectStore datastore.ProjectStore applicationStore apiApplicationStore deploymentStore apiDeploymentStore pipedStore apiPipedStore @@ -108,6 +109,7 @@ func NewAPI( logger *zap.Logger, ) *API { a := &API{ + projectStore: datastore.NewProjectStore(ds), applicationStore: datastore.NewApplicationStore(ds), deploymentStore: datastore.NewDeploymentStore(ds), pipedStore: datastore.NewPipedStore(ds), @@ -191,6 +193,15 @@ func (a *API) SyncApplication(ctx context.Context, req *apiservice.SyncApplicati return nil, status.Error(codes.InvalidArgument, "Requested application does not belong to your project") } + // Check if the project is disabled. + project, err := a.projectStore.Get(ctx, app.ProjectId) + if err != nil { + return nil, gRPCStoreError(err, "get project") + } + if project.Disabled { + return nil, status.Error(codes.FailedPrecondition, "Cannot execute command: project is currently disabled. Please contact your administrator to enable the project.") + } + cmd := model.Command{ Id: uuid.New().String(), PipedId: app.PipedId, diff --git a/pkg/app/server/grpcapi/api_disabled_project_test.go b/pkg/app/server/grpcapi/api_disabled_project_test.go new file mode 100644 index 0000000000..361a6624cc --- /dev/null +++ b/pkg/app/server/grpcapi/api_disabled_project_test.go @@ -0,0 +1,63 @@ +package grpcapi + +import ( + "context" + "testing" + + "github.com/stretchr/testify/assert" + "go.uber.org/mock/gomock" + "go.uber.org/zap" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" + + "github.com/pipe-cd/pipecd/pkg/app/server/service/apiservice" + "github.com/pipe-cd/pipecd/pkg/datastore/datastoretest" + "github.com/pipe-cd/pipecd/pkg/model" + "github.com/pipe-cd/pipecd/pkg/rpc/rpcauth" +) + +func TestAPISyncApplication_DisabledProject(t *testing.T) { + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + projectID := "project-id" + appID := "app-id" + apiKeyID := "apikey-id" + + ctx := context.Background() + // Mock API key authentication + ctx = rpcauth.ContextWithAPIKey(ctx, &model.APIKey{ + Id: apiKeyID, + ProjectId: projectID, + Role: model.APIKey_READ_WRITE, + }) + + ps := datastoretest.NewMockProjectStore(ctrl) + ps.EXPECT().Get(gomock.Any(), projectID).Return(&model.Project{ + Id: projectID, + Disabled: true, + }, nil) + + as := datastoretest.NewMockApplicationStore(ctrl) + as.EXPECT().Get(gomock.Any(), appID).Return(&model.Application{ + Id: appID, + ProjectId: projectID, + }, nil) + + api := &API{ + projectStore: &mockProjectStore{MockProjectStore: ps}, + applicationStore: as, + logger: zap.NewNop(), + } + + resp, err := api.SyncApplication(ctx, &apiservice.SyncApplicationRequest{ + ApplicationId: appID, + }) + + assert.Error(t, err) + assert.Nil(t, resp) + st, ok := status.FromError(err) + assert.True(t, ok) + assert.Equal(t, codes.FailedPrecondition, st.Code()) + assert.Contains(t, st.Message(), "project is currently disabled") +} diff --git a/pkg/app/server/grpcapi/piped_api.go b/pkg/app/server/grpcapi/piped_api.go index 3937baa8d4..1e48af5ca0 100644 --- a/pkg/app/server/grpcapi/piped_api.go +++ b/pkg/app/server/grpcapi/piped_api.go @@ -90,6 +90,7 @@ type commandOutputPutter interface { type PipedAPI struct { pipedservice.UnimplementedPipedServiceServer + projectStore datastore.ProjectStore applicationStore pipedAPIApplicationStore deploymentStore pipedAPIDeploymentStore deploymentChainStore pipedAPIDeploymentChainStore @@ -114,6 +115,7 @@ type PipedAPI struct { // NewPipedAPI creates a new PipedAPI instance. func NewPipedAPI(ctx context.Context, ds datastore.DataStore, sc cache.Cache, sls stagelogstore.Store, alss applicationlivestatestore.Store, las analysisresultstore.Store, hc cache.Cache, cop commandOutputPutter, uas unregisteredappstore.Store, aso applicationsharedobjectstore.Store, webBaseURL string, logger *zap.Logger) *PipedAPI { a := &PipedAPI{ + projectStore: datastore.NewProjectStore(ds), applicationStore: datastore.NewApplicationStore(ds), deploymentStore: datastore.NewDeploymentStore(ds), deploymentChainStore: datastore.NewDeploymentChainStore(ds), @@ -219,6 +221,15 @@ func (a *PipedAPI) ListApplications(ctx context.Context, req *pipedservice.ListA if err != nil { return nil, err } + // Check if the project is disabled. + project, err := a.projectStore.Get(ctx, projectID) + if err != nil { + return nil, gRPCStoreError(err, "get project") + } + if project.Disabled { + return &pipedservice.ListApplicationsResponse{}, nil + } + opts := datastore.ListOptions{ Filters: []datastore.ListFilter{ { @@ -393,6 +404,15 @@ func (a *PipedAPI) CreateDeployment(ctx context.Context, req *pipedservice.Creat if err != nil { return nil, err } + // Check if the project is disabled. + project, err := a.projectStore.Get(ctx, projectID) + if err != nil { + return nil, gRPCStoreError(err, "get project") + } + if project.Disabled { + return nil, status.Error(codes.FailedPrecondition, "Cannot create deployment: project is currently disabled. Please contact your administrator to enable the project.") + } + if err := a.validateAppBelongsToPiped(ctx, req.Deployment.ApplicationId, pipedID); err != nil { return nil, err } @@ -620,6 +640,19 @@ func (a *PipedAPI) ListUnhandledCommands(ctx context.Context, req *pipedservice. return nil, err } + // Check if the project is disabled. + projectID, _, _, err := rpcauth.ExtractPipedToken(ctx) + if err != nil { + return nil, err + } + project, err := a.projectStore.Get(ctx, projectID) + if err != nil { + return nil, gRPCStoreError(err, "get project") + } + if project.Disabled { + return &pipedservice.ListUnhandledCommandsResponse{}, nil + } + cmds, err := a.commandStore.ListUnhandledCommands(ctx, pipedID) if err != nil { return nil, gRPCStoreError(err, fmt.Sprintf("list unhandled commands of piped %s", pipedID)) diff --git a/pkg/app/server/grpcapi/piped_api_disabled_project_test.go b/pkg/app/server/grpcapi/piped_api_disabled_project_test.go new file mode 100644 index 0000000000..8a78f24360 --- /dev/null +++ b/pkg/app/server/grpcapi/piped_api_disabled_project_test.go @@ -0,0 +1,152 @@ +package grpcapi + +import ( + "context" + "testing" + + "github.com/stretchr/testify/assert" + "go.uber.org/mock/gomock" + "go.uber.org/zap" + "google.golang.org/grpc" + "google.golang.org/grpc/metadata" + + "github.com/pipe-cd/pipecd/pkg/app/server/service/pipedservice" + "github.com/pipe-cd/pipecd/pkg/datastore/datastoretest" + "github.com/pipe-cd/pipecd/pkg/model" + "github.com/pipe-cd/pipecd/pkg/rpc/rpcauth" +) + +type mockProjectStore struct { + *datastoretest.MockProjectStore +} + +func (m *mockProjectStore) DisableProject(ctx context.Context, id string) error { + return nil +} + +func (m *mockProjectStore) EnableProject(ctx context.Context, id string) error { + return nil +} + +type mockVerifier struct{} + +func (m *mockVerifier) Verify(ctx context.Context, projectID, pipedID, pipedKey string) error { + return nil +} + +func TestListApplications_DisabledProject(t *testing.T) { + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + projectID := "project-id" + pipedID := "piped-id" + pipedKey := "piped-key" + + ctx := context.Background() + token := rpcauth.MakePipedToken(projectID, pipedID, pipedKey) + ctx = metadata.NewIncomingContext(ctx, metadata.MD{ + "authorization": []string{"PIPED-TOKEN " + token}, + }) + + ps := datastoretest.NewMockProjectStore(ctrl) + ps.EXPECT().Get(gomock.Any(), projectID).Return(&model.Project{ + Id: projectID, + Disabled: true, + }, nil) + + api := &PipedAPI{ + projectStore: &mockProjectStore{MockProjectStore: ps}, + logger: zap.NewNop(), + } + + verifier := &mockVerifier{} + interceptor := rpcauth.PipedTokenUnaryServerInterceptor(verifier, zap.NewNop()) + + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return api.ListApplications(ctx, req.(*pipedservice.ListApplicationsRequest)) + } + + resp, err := interceptor(ctx, &pipedservice.ListApplicationsRequest{}, &grpc.UnaryServerInfo{}, handler) + assert.NoError(t, err) + assert.Empty(t, resp.(*pipedservice.ListApplicationsResponse).Applications) +} + +func TestCreateDeployment_DisabledProject(t *testing.T) { + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + projectID := "project-id" + pipedID := "piped-id" + pipedKey := "piped-key" + + ctx := context.Background() + token := rpcauth.MakePipedToken(projectID, pipedID, pipedKey) + ctx = metadata.NewIncomingContext(ctx, metadata.MD{ + "authorization": []string{"PIPED-TOKEN " + token}, + }) + + ps := datastoretest.NewMockProjectStore(ctrl) + ps.EXPECT().Get(gomock.Any(), projectID).Return(&model.Project{ + Id: projectID, + Disabled: true, + }, nil) + + api := &PipedAPI{ + projectStore: &mockProjectStore{MockProjectStore: ps}, + logger: zap.NewNop(), + } + + verifier := &mockVerifier{} + interceptor := rpcauth.PipedTokenUnaryServerInterceptor(verifier, zap.NewNop()) + + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return api.CreateDeployment(ctx, req.(*pipedservice.CreateDeploymentRequest)) + } + + resp, err := interceptor(ctx, &pipedservice.CreateDeploymentRequest{ + Deployment: &model.Deployment{ + ApplicationId: "app-id", + }, + }, &grpc.UnaryServerInfo{}, handler) + + assert.Error(t, err) + assert.Nil(t, resp) +} + +func TestListUnhandledCommands_DisabledProject(t *testing.T) { + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + projectID := "project-id" + pipedID := "piped-id" + pipedKey := "piped-key" + + ctx := context.Background() + token := rpcauth.MakePipedToken(projectID, pipedID, pipedKey) + ctx = metadata.NewIncomingContext(ctx, metadata.MD{ + "authorization": []string{"PIPED-TOKEN " + token}, + }) + + ps := datastoretest.NewMockProjectStore(ctrl) + ps.EXPECT().Get(gomock.Any(), projectID).Return(&model.Project{ + Id: projectID, + Disabled: true, + }, nil) + + api := &PipedAPI{ + projectStore: &mockProjectStore{MockProjectStore: ps}, + logger: zap.NewNop(), + } + + verifier := &mockVerifier{} + interceptor := rpcauth.PipedTokenUnaryServerInterceptor(verifier, zap.NewNop()) + + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return api.ListUnhandledCommands(ctx, req.(*pipedservice.ListUnhandledCommandsRequest)) + } + + resp, err := interceptor(ctx, &pipedservice.ListUnhandledCommandsRequest{}, &grpc.UnaryServerInfo{}, handler) + + assert.NoError(t, err) + assert.Empty(t, resp.(*pipedservice.ListUnhandledCommandsResponse).Commands) +} diff --git a/pkg/app/server/grpcapi/web_api.go b/pkg/app/server/grpcapi/web_api.go index 4fdbedbe71..0b0597be40 100644 --- a/pkg/app/server/grpcapi/web_api.go +++ b/pkg/app/server/grpcapi/web_api.go @@ -88,6 +88,8 @@ type webAPIPipedStore interface { type webAPIProjectStore interface { Get(ctx context.Context, id string) (*model.Project, error) + EnableProject(ctx context.Context, id string) error + DisableProject(ctx context.Context, id string) error UpdateProjectStaticAdmin(ctx context.Context, id, username, password string) error EnableStaticAdmin(ctx context.Context, id string) error DisableStaticAdmin(ctx context.Context, id string) error @@ -418,6 +420,15 @@ func (a *WebAPI) RestartPiped(ctx context.Context, req *webservice.RestartPipedR return nil, status.Error(codes.PermissionDenied, "Requested Piped does not belong to your project") } + // Check if the project is disabled. + project, err := a.projectStore.Get(ctx, piped.ProjectId) + if err != nil { + return nil, gRPCStoreError(err, "get project") + } + if project.Disabled { + return nil, status.Error(codes.FailedPrecondition, "Cannot execute command: project is currently disabled. Please contact your administrator to enable the project.") + } + cmd := model.Command{ Id: uuid.New().String(), PipedId: piped.Id, @@ -719,6 +730,15 @@ func (a *WebAPI) SyncApplication(ctx context.Context, req *webservice.SyncApplic return nil, status.Error(codes.PermissionDenied, "Requested application does not belong to your project") } + // Check if the project is disabled. + project, err := a.projectStore.Get(ctx, app.ProjectId) + if err != nil { + return nil, gRPCStoreError(err, "get project") + } + if project.Disabled { + return nil, status.Error(codes.FailedPrecondition, "Cannot execute command: project is currently disabled. Please contact your administrator to enable the project.") + } + cmd := model.Command{ Id: uuid.New().String(), PipedId: app.PipedId, @@ -1121,6 +1141,15 @@ func (a *WebAPI) CancelDeployment(ctx context.Context, req *webservice.CancelDep return nil, status.Error(codes.FailedPrecondition, "could not cancel the deployment because it was already completed") } + // Check if the project is disabled. + project, err := a.projectStore.Get(ctx, deployment.ProjectId) + if err != nil { + return nil, gRPCStoreError(err, "get project") + } + if project.Disabled { + return nil, status.Error(codes.FailedPrecondition, "Cannot execute command: project is currently disabled. Please contact your administrator to enable the project.") + } + cmd := model.Command{ Id: uuid.New().String(), PipedId: deployment.PipedId, @@ -1158,6 +1187,15 @@ func (a *WebAPI) SkipStage(ctx context.Context, req *webservice.SkipStageRequest if claims.Role.ProjectId != deployment.ProjectId { return nil, status.Error(codes.PermissionDenied, "Requested deployment does not belong to your project") } + // Check if the project is disabled. + project, err := a.projectStore.Get(ctx, deployment.ProjectId) + if err != nil { + return nil, gRPCStoreError(err, "get project") + } + if project.Disabled { + return nil, status.Error(codes.FailedPrecondition, "Cannot execute command: project is currently disabled. Please contact your administrator to enable the project.") + } + stage, ok := deployment.Stage(req.StageId) if !ok { return nil, status.Error(codes.FailedPrecondition, "The stage was not found in the deployment") @@ -1210,6 +1248,15 @@ func (a *WebAPI) ApproveStage(ctx context.Context, req *webservice.ApproveStageR if err := a.validateDeploymentBelongsToProject(ctx, req.DeploymentId, claims.Role.ProjectId); err != nil { return nil, err } + // Check if the project is disabled. + project, err := a.projectStore.Get(ctx, deployment.ProjectId) + if err != nil { + return nil, gRPCStoreError(err, "get project") + } + if project.Disabled { + return nil, status.Error(codes.FailedPrecondition, "Cannot execute command: project is currently disabled. Please contact your administrator to enable the project.") + } + stage, ok := deployment.StageMap()[req.StageId] if !ok { return nil, status.Error(codes.FailedPrecondition, "The stage was not found in the deployment") @@ -1391,6 +1438,44 @@ func (a *WebAPI) DisableStaticAdmin(ctx context.Context, req *webservice.Disable return &webservice.DisableStaticAdminResponse{}, nil } +// EnableProject re-enables a disabled project so that users can log in again. +func (a *WebAPI) EnableProject(ctx context.Context, req *webservice.EnableProjectRequest) (*webservice.EnableProjectResponse, error) { + claims, err := rpcauth.ExtractClaims(ctx) + if err != nil { + a.logger.Error("failed to authenticate the current user", zap.Error(err)) + return nil, err + } + + if _, ok := a.projectsInConfig[claims.Role.ProjectId]; ok { + return nil, status.Error(codes.FailedPrecondition, "Failed to update a debug project specified in the control-plane configuration") + } + + if err := a.projectStore.EnableProject(ctx, claims.Role.ProjectId); err != nil { + a.logger.Error("failed to enable project", zap.Error(err)) + return nil, gRPCStoreError(err, "enable project") + } + return &webservice.EnableProjectResponse{}, nil +} + +// DisableProject marks the project as disabled which blocks all new logins and API calls. +func (a *WebAPI) DisableProject(ctx context.Context, req *webservice.DisableProjectRequest) (*webservice.DisableProjectResponse, error) { + claims, err := rpcauth.ExtractClaims(ctx) + if err != nil { + a.logger.Error("failed to authenticate the current user", zap.Error(err)) + return nil, err + } + + if _, ok := a.projectsInConfig[claims.Role.ProjectId]; ok { + return nil, status.Error(codes.FailedPrecondition, "Failed to update a debug project specified in the control-plane configuration") + } + + if err := a.projectStore.DisableProject(ctx, claims.Role.ProjectId); err != nil { + a.logger.Error("failed to disable project", zap.Error(err)) + return nil, gRPCStoreError(err, "disable project") + } + return &webservice.DisableProjectResponse{}, nil +} + // UpdateProjectSSOConfig updates the sso settings. func (a *WebAPI) UpdateProjectSSOConfig(ctx context.Context, req *webservice.UpdateProjectSSOConfigRequest) (*webservice.UpdateProjectSSOConfigResponse, error) { claims, err := rpcauth.ExtractClaims(ctx) diff --git a/pkg/app/server/grpcapi/web_api_disabled_project_test.go b/pkg/app/server/grpcapi/web_api_disabled_project_test.go new file mode 100644 index 0000000000..2a86a0a8cd --- /dev/null +++ b/pkg/app/server/grpcapi/web_api_disabled_project_test.go @@ -0,0 +1,374 @@ +package grpcapi + +import ( + "context" + "testing" + "time" + + "github.com/stretchr/testify/assert" + "go.uber.org/mock/gomock" + "go.uber.org/zap" + "google.golang.org/grpc" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/metadata" + "google.golang.org/grpc/status" + + "github.com/pipe-cd/pipecd/pkg/app/server/service/webservice" + "github.com/pipe-cd/pipecd/pkg/datastore/datastoretest" + "github.com/pipe-cd/pipecd/pkg/jwt" + "github.com/pipe-cd/pipecd/pkg/model" + "github.com/pipe-cd/pipecd/pkg/rpc/rpcauth" +) + +type mockJWTVerifier struct { + claims *jwt.Claims +} + +func (m *mockJWTVerifier) Verify(token string) (*jwt.Claims, error) { + return m.claims, nil +} + +type mockAuthorizer struct{} + +func (m *mockAuthorizer) Authorize(ctx context.Context, method string, role model.Role) bool { + return true +} + +func TestSyncApplication_DisabledProject(t *testing.T) { + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + projectID := "project-id" + appID := "app-id" + + ctx := context.Background() + // Mock JWT token in cookie + ctx = metadata.NewIncomingContext(ctx, metadata.MD{ + "cookie": []string{"token=dummy-token"}, + }) + + ps := datastoretest.NewMockProjectStore(ctrl) + ps.EXPECT().Get(gomock.Any(), projectID).Return(&model.Project{ + Id: projectID, + Disabled: true, + }, nil) + + as := datastoretest.NewMockApplicationStore(ctrl) + as.EXPECT().Get(gomock.Any(), appID).Return(&model.Application{ + Id: appID, + ProjectId: projectID, + }, nil) + + api := &WebAPI{ + projectStore: &mockProjectStore{MockProjectStore: ps}, + applicationStore: as, + logger: zap.NewNop(), + } + + claims := jwt.NewClaims( + "sub", + "avatar-url", + 10*time.Minute, + &model.Role{ + ProjectId: projectID, + ProjectRbacRoles: []string{"ADMIN"}, + }, + ) + verifier := &mockJWTVerifier{claims: claims} + authorizer := &mockAuthorizer{} + interceptor := rpcauth.JWTUnaryServerInterceptor(verifier, authorizer, zap.NewNop()) + + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return api.SyncApplication(ctx, req.(*webservice.SyncApplicationRequest)) + } + + resp, err := interceptor(ctx, &webservice.SyncApplicationRequest{ + ApplicationId: appID, + }, &grpc.UnaryServerInfo{FullMethod: "/webservice.WebService/SyncApplication"}, handler) + + assert.Error(t, err) + assert.Nil(t, resp) + st, ok := status.FromError(err) + assert.True(t, ok) + assert.Equal(t, codes.FailedPrecondition, st.Code()) + assert.Contains(t, st.Message(), "project is currently disabled") +} + +func TestCancelDeployment_DisabledProject(t *testing.T) { + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + projectID := "project-id" + deploymentID := "deployment-id" + + ctx := context.Background() + ctx = metadata.NewIncomingContext(ctx, metadata.MD{ + "cookie": []string{"token=dummy-token"}, + }) + + ps := datastoretest.NewMockProjectStore(ctrl) + ps.EXPECT().Get(gomock.Any(), projectID).Return(&model.Project{ + Id: projectID, + Disabled: true, + }, nil) + + ds := datastoretest.NewMockDeploymentStore(ctrl) + ds.EXPECT().Get(gomock.Any(), deploymentID).Return(&model.Deployment{ + Id: deploymentID, + ProjectId: projectID, + Status: model.DeploymentStatus_DEPLOYMENT_RUNNING, + }, nil) + + api := &WebAPI{ + projectStore: &mockProjectStore{MockProjectStore: ps}, + deploymentStore: ds, + logger: zap.NewNop(), + } + + claims := jwt.NewClaims( + "sub", + "avatar-url", + 10*time.Minute, + &model.Role{ + ProjectId: projectID, + ProjectRbacRoles: []string{"ADMIN"}, + }, + ) + verifier := &mockJWTVerifier{claims: claims} + authorizer := &mockAuthorizer{} + interceptor := rpcauth.JWTUnaryServerInterceptor(verifier, authorizer, zap.NewNop()) + + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return api.CancelDeployment(ctx, req.(*webservice.CancelDeploymentRequest)) + } + + resp, err := interceptor(ctx, &webservice.CancelDeploymentRequest{ + DeploymentId: deploymentID, + }, &grpc.UnaryServerInfo{FullMethod: "/webservice.WebService/CancelDeployment"}, handler) + + assert.Error(t, err) + assert.Nil(t, resp) + st, ok := status.FromError(err) + assert.True(t, ok) + assert.Equal(t, codes.FailedPrecondition, st.Code()) + assert.Contains(t, st.Message(), "project is currently disabled") +} + +func TestSkipStage_DisabledProject(t *testing.T) { + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + projectID := "project-id" + deploymentID := "deployment-id" + stageID := "stage-id" + + ctx := context.Background() + ctx = metadata.NewIncomingContext(ctx, metadata.MD{ + "cookie": []string{"token=dummy-token"}, + }) + + ps := datastoretest.NewMockProjectStore(ctrl) + ps.EXPECT().Get(gomock.Any(), projectID).Return(&model.Project{ + Id: projectID, + Disabled: true, + }, nil) + + ds := datastoretest.NewMockDeploymentStore(ctrl) + ds.EXPECT().Get(gomock.Any(), deploymentID).Return(&model.Deployment{ + Id: deploymentID, + ProjectId: projectID, + Stages: []*model.PipelineStage{{ + Id: stageID, + Name: "K8S_SYNC", + Status: model.StageStatus_STAGE_RUNNING, + }}, + }, nil) + + api := &WebAPI{ + projectStore: &mockProjectStore{MockProjectStore: ps}, + deploymentStore: ds, + logger: zap.NewNop(), + } + + claims := jwt.NewClaims( + "sub", + "avatar-url", + 10*time.Minute, + &model.Role{ + ProjectId: projectID, + ProjectRbacRoles: []string{"ADMIN"}, + }, + ) + verifier := &mockJWTVerifier{claims: claims} + authorizer := &mockAuthorizer{} + interceptor := rpcauth.JWTUnaryServerInterceptor(verifier, authorizer, zap.NewNop()) + + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return api.SkipStage(ctx, req.(*webservice.SkipStageRequest)) + } + + resp, err := interceptor(ctx, &webservice.SkipStageRequest{ + DeploymentId: deploymentID, + StageId: stageID, + }, &grpc.UnaryServerInfo{FullMethod: "/webservice.WebService/SkipStage"}, handler) + + assert.Error(t, err) + assert.Nil(t, resp) + st, ok := status.FromError(err) + assert.True(t, ok) + assert.Equal(t, codes.FailedPrecondition, st.Code()) + assert.Contains(t, st.Message(), "project is currently disabled") +} + +func TestApproveStage_DisabledProject(t *testing.T) { + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + userID := "user-id" + projectID := "project-id" + deploymentID := "deployment-id" + stageID := "stage-id" + + ctx := context.Background() + ctx = metadata.NewIncomingContext(ctx, metadata.MD{ + "cookie": []string{"token=dummy-token"}, + }) + + ps := datastoretest.NewMockProjectStore(ctrl) + ps.EXPECT().Get(gomock.Any(), projectID).Return(&model.Project{ + Id: projectID, + Disabled: true, + }, nil) + + ds := datastoretest.NewMockDeploymentStore(ctrl) + ds.EXPECT().Get(gomock.Any(), deploymentID).Return(&model.Deployment{ + Id: deploymentID, + ProjectId: projectID, + Stages: []*model.PipelineStage{{ + Id: stageID, + Name: "WAIT_APPROVAL", + Status: model.StageStatus_STAGE_RUNNING, + Metadata: map[string]string{ + "Approvers": userID, + }, + }}, + }, nil).Times(2) + + api := &WebAPI{ + projectStore: &mockProjectStore{MockProjectStore: ps}, + deploymentStore: ds, + deploymentProjectCache: newMockCache(), + logger: zap.NewNop(), + } + + claims := jwt.NewClaims( + userID, + "avatar-url", + 10*time.Minute, + &model.Role{ + ProjectId: projectID, + ProjectRbacRoles: []string{"ADMIN"}, + }, + ) + verifier := &mockJWTVerifier{claims: claims} + authorizer := &mockAuthorizer{} + interceptor := rpcauth.JWTUnaryServerInterceptor(verifier, authorizer, zap.NewNop()) + + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return api.ApproveStage(ctx, req.(*webservice.ApproveStageRequest)) + } + + resp, err := interceptor(ctx, &webservice.ApproveStageRequest{ + DeploymentId: deploymentID, + StageId: stageID, + }, &grpc.UnaryServerInfo{FullMethod: "/webservice.WebService/ApproveStage"}, handler) + + assert.Error(t, err) + assert.Nil(t, resp) + st, ok := status.FromError(err) + assert.True(t, ok) + assert.Equal(t, codes.FailedPrecondition, st.Code()) + assert.Contains(t, st.Message(), "project is currently disabled") +} + +func TestRestartPiped_DisabledProject(t *testing.T) { + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + projectID := "project-id" + pipedID := "piped-id" + + ctx := context.Background() + ctx = metadata.NewIncomingContext(ctx, metadata.MD{ + "cookie": []string{"token=dummy-token"}, + }) + + ps := datastoretest.NewMockProjectStore(ctrl) + ps.EXPECT().Get(gomock.Any(), projectID).Return(&model.Project{ + Id: projectID, + Disabled: true, + }, nil) + + pips := datastoretest.NewMockPipedStore(ctrl) + pips.EXPECT().Get(gomock.Any(), pipedID).Return(&model.Piped{ + Id: pipedID, + ProjectId: projectID, + }, nil) + + api := &WebAPI{ + projectStore: &mockProjectStore{MockProjectStore: ps}, + pipedStore: pips, + logger: zap.NewNop(), + } + + claims := jwt.NewClaims( + "sub", + "avatar-url", + 10*time.Minute, + &model.Role{ + ProjectId: projectID, + ProjectRbacRoles: []string{"ADMIN"}, + }, + ) + verifier := &mockJWTVerifier{claims: claims} + authorizer := &mockAuthorizer{} + interceptor := rpcauth.JWTUnaryServerInterceptor(verifier, authorizer, zap.NewNop()) + + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return api.RestartPiped(ctx, req.(*webservice.RestartPipedRequest)) + } + + resp, err := interceptor(ctx, &webservice.RestartPipedRequest{ + PipedId: pipedID, + }, &grpc.UnaryServerInfo{FullMethod: "/webservice.WebService/RestartPiped"}, handler) + + assert.Error(t, err) + assert.Nil(t, resp) + st, ok := status.FromError(err) + assert.True(t, ok) + assert.Equal(t, codes.FailedPrecondition, st.Code()) + assert.Contains(t, st.Message(), "project is currently disabled") +} + +// mockCache is a simple mock implementation of cache.Cache for testing +type mockCache struct{} + +func newMockCache() *mockCache { + return &mockCache{} +} + +func (c *mockCache) Get(key string) (interface{}, error) { + return nil, assert.AnError +} + +func (c *mockCache) Put(key string, value interface{}) error { + return nil +} + +func (c *mockCache) Delete(key string) error { + return nil +} + +func (c *mockCache) GetAll() (map[string]interface{}, error) { + return nil, nil +} diff --git a/pkg/app/server/httpapi/callback.go b/pkg/app/server/httpapi/callback.go index 68809dfc04..e10b095405 100644 --- a/pkg/app/server/httpapi/callback.go +++ b/pkg/app/server/httpapi/callback.go @@ -64,6 +64,10 @@ func (h *authHandler) handleCallback(w http.ResponseWriter, r *http.Request) { h.handleError(w, r, fmt.Sprintf("Unable to find project %s", projectID), err) return } + if proj.Disabled { + h.handleError(w, r, fmt.Sprintf("Project %s is disabled", projectID), nil) + return + } if proj.UserGroups == nil { h.handleError(w, r, "Missing User Group configuration", nil) @@ -99,7 +103,7 @@ func (h *authHandler) handleCallback(w http.ResponseWriter, r *http.Request) { user.Username, user.AvatarUrl, tokenTTL, - *user.Role, + user.Role, ) signedToken, err := h.signer.Sign(claims) if err != nil { diff --git a/pkg/app/server/httpapi/login.go b/pkg/app/server/httpapi/login.go index 83a75ad85b..7550616e13 100644 --- a/pkg/app/server/httpapi/login.go +++ b/pkg/app/server/httpapi/login.go @@ -51,6 +51,10 @@ func (h *authHandler) handleSSOLogin(w http.ResponseWriter, r *http.Request) { h.handleError(w, r, fmt.Sprintf("Unable to find project %s", projectID), err) return } + if proj.Disabled { + h.handleError(w, r, fmt.Sprintf("Project %s is disabled", projectID), nil) + return + } sso, shared, err := h.findSSOConfig(proj) if err != nil { @@ -119,6 +123,10 @@ func (h *authHandler) handleStaticAdminLogin(w http.ResponseWriter, r *http.Requ h.handleError(w, r, fmt.Sprintf("Unable to find project: %s", projectID), err) return } + if proj.Disabled { + h.handleError(w, r, fmt.Sprintf("Project %s is disabled", projectID), nil) + return + } if proj.StaticAdminDisabled { h.handleError(w, r, "Static admin is disabling", nil) return @@ -135,7 +143,7 @@ func (h *authHandler) handleStaticAdminLogin(w http.ResponseWriter, r *http.Requ admin.Username, "", defaultTokenTTL, - model.Role{ + &model.Role{ ProjectId: projectID, ProjectRbacRoles: []string{model.BuiltinRBACRoleAdmin.String()}, }, diff --git a/pkg/app/server/pipedverifier/verifier.go b/pkg/app/server/pipedverifier/verifier.go index 020b5a0910..025224c9f5 100644 --- a/pkg/app/server/pipedverifier/verifier.go +++ b/pkg/app/server/pipedverifier/verifier.go @@ -121,13 +121,23 @@ func (v *Verifier) verifyProject(ctx context.Context, projectID, pipedID string) } // If not found, we check from the list inside datastore. - if _, err := v.projectCache.Get(projectID); err == nil { - return nil + if val, err := v.projectCache.Get(projectID); err == nil { + if enabled, ok := val.(bool); ok { + if !enabled { + return fmt.Errorf("project %s for piped %s was disabled", projectID, pipedID) + } + return nil + } } - if _, err := v.projectStore.Get(ctx, projectID); err != nil { + proj, err := v.projectStore.Get(ctx, projectID) + if err != nil { return fmt.Errorf("project %s for piped %s was not found", projectID, pipedID) } + if proj.Disabled { + _ = v.projectCache.Put(projectID, false) + return fmt.Errorf("project %s for piped %s was disabled", projectID, pipedID) + } if err := v.projectCache.Put(projectID, true); err != nil { v.logger.Warn("unable to store project in memory cache", zap.Error(err)) diff --git a/pkg/app/server/pipedverifier/verifier_test.go b/pkg/app/server/pipedverifier/verifier_test.go index 09680bda28..e032ae0aba 100644 --- a/pkg/app/server/pipedverifier/verifier_test.go +++ b/pkg/app/server/pipedverifier/verifier_test.go @@ -73,6 +73,10 @@ func TestVerify(t *testing.T) { "project-1": { Id: "project-1", }, + "project-disabled": { + Id: "project-disabled", + Disabled: true, + }, }, } pipedGetter := &fakePipedGetter{ @@ -114,6 +118,15 @@ func TestVerify(t *testing.T) { }, Disabled: true, }, + "piped-2-1": { + Id: "piped-2-1", + ProjectId: "project-disabled", + Keys: []*model.PipedKey{ + { + Hash: hashGenerator("piped-key-2-1"), + }, + }, + }, }, } v := NewVerifier( @@ -142,41 +155,47 @@ func TestVerify(t *testing.T) { require.Equal(t, 1, projectGetter.calls) require.Equal(t, 1, pipedGetter.calls) + // Disabled project. + err = v.Verify(ctx, "project-disabled", "piped-2-1", "piped-key-2-1") + assert.Equal(t, fmt.Errorf("project project-disabled for piped piped-2-1 was disabled"), err) + require.Equal(t, 2, projectGetter.calls) + require.Equal(t, 1, pipedGetter.calls) + // Found piped but project id was not correct. err = v.Verify(ctx, "project-1", "piped-1-2", "piped-key-1-2") assert.Equal(t, fmt.Errorf("the project of piped piped-1-2 is not matched, expected=project-1, got=project-non-existence"), err) - require.Equal(t, 2, projectGetter.calls) + require.Equal(t, 3, projectGetter.calls) require.Equal(t, 2, pipedGetter.calls) // Found piped but it was disabled. err = v.Verify(ctx, "project-1", "piped-1-3", "piped-key-1-3") assert.Equal(t, fmt.Errorf("piped piped-1-3 was already disabled"), err) - require.Equal(t, 2, projectGetter.calls) + require.Equal(t, 3, projectGetter.calls) require.Equal(t, 3, pipedGetter.calls) piped13 := pipedGetter.pipeds["piped-1-3"] piped13.Disabled = false err = v.Verify(ctx, "project-1", "piped-1-3", "piped-key-1-3") assert.Equal(t, nil, err) - require.Equal(t, 2, projectGetter.calls) + require.Equal(t, 3, projectGetter.calls) require.Equal(t, 4, pipedGetter.calls) // OK. err = v.Verify(ctx, "project-1", "piped-1-1", "piped-key-1-1") assert.Equal(t, nil, err) - require.Equal(t, 2, projectGetter.calls) + require.Equal(t, 3, projectGetter.calls) require.Equal(t, 5, pipedGetter.calls) // Wrong piped key. err = v.Verify(ctx, "project-1", "piped-1-1", "piped-key-1-1-wrong") assert.Equal(t, fmt.Errorf("the key of piped piped-1-1 is not matched, crypto/bcrypt: hashedPassword is not the hash of the given password"), err) - require.Equal(t, 2, projectGetter.calls) + require.Equal(t, 3, projectGetter.calls) require.Equal(t, 6, pipedGetter.calls) // The invalid key should be cached. err = v.Verify(ctx, "project-1", "piped-1-1", "piped-key-1-1-wrong") assert.Equal(t, fmt.Errorf("the key of piped piped-1-1 is not matched, crypto/bcrypt: hashedPassword is not the hash of the given password"), err) - require.Equal(t, 2, projectGetter.calls) + require.Equal(t, 3, projectGetter.calls) require.Equal(t, 6, pipedGetter.calls) // OK for newly added key. @@ -186,6 +205,6 @@ func TestVerify(t *testing.T) { }) err = v.Verify(ctx, "project-1", "piped-1-1", "piped-key-1-1-new") assert.Equal(t, nil, err) - require.Equal(t, 2, projectGetter.calls) + require.Equal(t, 3, projectGetter.calls) require.Equal(t, 7, pipedGetter.calls) } diff --git a/pkg/app/server/service/webservice/service.pb.auth.go b/pkg/app/server/service/webservice/service.pb.auth.go index 83f3761d5c..50da1a9c41 100644 --- a/pkg/app/server/service/webservice/service.pb.auth.go +++ b/pkg/app/server/service/webservice/service.pb.auth.go @@ -206,6 +206,10 @@ func (a *authorizer) Authorize(ctx context.Context, method string, r model.Role) return verify(model.ProjectRBACResource_PROJECT, model.ProjectRBACPolicy_UPDATE) case "/grpc.service.webservice.WebService/UpdateProjectRBACConfig": return verify(model.ProjectRBACResource_PROJECT, model.ProjectRBACPolicy_UPDATE) + case "/grpc.service.webservice.WebService/EnableProject": + return verify(model.ProjectRBACResource_PROJECT, model.ProjectRBACPolicy_UPDATE) + case "/grpc.service.webservice.WebService/DisableProject": + return verify(model.ProjectRBACResource_PROJECT, model.ProjectRBACPolicy_UPDATE) case "/grpc.service.webservice.WebService/GetMe": return verify(model.ProjectRBACResource_PROJECT, model.ProjectRBACPolicy_GET) case "/grpc.service.webservice.WebService/AddProjectRBACRole": diff --git a/pkg/app/server/service/webservice/service.pb.go b/pkg/app/server/service/webservice/service.pb.go index 7acd5e98b7..3d0b5baa58 100644 --- a/pkg/app/server/service/webservice/service.pb.go +++ b/pkg/app/server/service/webservice/service.pb.go @@ -3569,6 +3569,158 @@ func (*DisableStaticAdminResponse) Descriptor() ([]byte, []int) { return file_pkg_app_server_service_webservice_service_proto_rawDescGZIP(), []int{71} } +type EnableProjectRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *EnableProjectRequest) Reset() { + *x = EnableProjectRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_pkg_app_server_service_webservice_service_proto_msgTypes[72] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *EnableProjectRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*EnableProjectRequest) ProtoMessage() {} + +func (x *EnableProjectRequest) ProtoReflect() protoreflect.Message { + mi := &file_pkg_app_server_service_webservice_service_proto_msgTypes[72] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use EnableProjectRequest.ProtoReflect.Descriptor instead. +func (*EnableProjectRequest) Descriptor() ([]byte, []int) { + return file_pkg_app_server_service_webservice_service_proto_rawDescGZIP(), []int{72} +} + +type EnableProjectResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *EnableProjectResponse) Reset() { + *x = EnableProjectResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_pkg_app_server_service_webservice_service_proto_msgTypes[73] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *EnableProjectResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*EnableProjectResponse) ProtoMessage() {} + +func (x *EnableProjectResponse) ProtoReflect() protoreflect.Message { + mi := &file_pkg_app_server_service_webservice_service_proto_msgTypes[73] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use EnableProjectResponse.ProtoReflect.Descriptor instead. +func (*EnableProjectResponse) Descriptor() ([]byte, []int) { + return file_pkg_app_server_service_webservice_service_proto_rawDescGZIP(), []int{73} +} + +type DisableProjectRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *DisableProjectRequest) Reset() { + *x = DisableProjectRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_pkg_app_server_service_webservice_service_proto_msgTypes[74] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *DisableProjectRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*DisableProjectRequest) ProtoMessage() {} + +func (x *DisableProjectRequest) ProtoReflect() protoreflect.Message { + mi := &file_pkg_app_server_service_webservice_service_proto_msgTypes[74] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use DisableProjectRequest.ProtoReflect.Descriptor instead. +func (*DisableProjectRequest) Descriptor() ([]byte, []int) { + return file_pkg_app_server_service_webservice_service_proto_rawDescGZIP(), []int{74} +} + +type DisableProjectResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *DisableProjectResponse) Reset() { + *x = DisableProjectResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_pkg_app_server_service_webservice_service_proto_msgTypes[75] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *DisableProjectResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*DisableProjectResponse) ProtoMessage() {} + +func (x *DisableProjectResponse) ProtoReflect() protoreflect.Message { + mi := &file_pkg_app_server_service_webservice_service_proto_msgTypes[75] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use DisableProjectResponse.ProtoReflect.Descriptor instead. +func (*DisableProjectResponse) Descriptor() ([]byte, []int) { + return file_pkg_app_server_service_webservice_service_proto_rawDescGZIP(), []int{75} +} + type GetMeRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -3578,7 +3730,7 @@ type GetMeRequest struct { func (x *GetMeRequest) Reset() { *x = GetMeRequest{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_app_server_service_webservice_service_proto_msgTypes[72] + mi := &file_pkg_app_server_service_webservice_service_proto_msgTypes[76] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3591,7 +3743,7 @@ func (x *GetMeRequest) String() string { func (*GetMeRequest) ProtoMessage() {} func (x *GetMeRequest) ProtoReflect() protoreflect.Message { - mi := &file_pkg_app_server_service_webservice_service_proto_msgTypes[72] + mi := &file_pkg_app_server_service_webservice_service_proto_msgTypes[76] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3604,7 +3756,7 @@ func (x *GetMeRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GetMeRequest.ProtoReflect.Descriptor instead. func (*GetMeRequest) Descriptor() ([]byte, []int) { - return file_pkg_app_server_service_webservice_service_proto_rawDescGZIP(), []int{72} + return file_pkg_app_server_service_webservice_service_proto_rawDescGZIP(), []int{76} } type GetMeResponse struct { @@ -3620,7 +3772,7 @@ type GetMeResponse struct { func (x *GetMeResponse) Reset() { *x = GetMeResponse{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_app_server_service_webservice_service_proto_msgTypes[73] + mi := &file_pkg_app_server_service_webservice_service_proto_msgTypes[77] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3633,7 +3785,7 @@ func (x *GetMeResponse) String() string { func (*GetMeResponse) ProtoMessage() {} func (x *GetMeResponse) ProtoReflect() protoreflect.Message { - mi := &file_pkg_app_server_service_webservice_service_proto_msgTypes[73] + mi := &file_pkg_app_server_service_webservice_service_proto_msgTypes[77] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3646,7 +3798,7 @@ func (x *GetMeResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use GetMeResponse.ProtoReflect.Descriptor instead. func (*GetMeResponse) Descriptor() ([]byte, []int) { - return file_pkg_app_server_service_webservice_service_proto_rawDescGZIP(), []int{73} + return file_pkg_app_server_service_webservice_service_proto_rawDescGZIP(), []int{77} } func (x *GetMeResponse) GetSubject() string { @@ -3682,7 +3834,7 @@ type AddProjectRBACRoleRequest struct { func (x *AddProjectRBACRoleRequest) Reset() { *x = AddProjectRBACRoleRequest{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_app_server_service_webservice_service_proto_msgTypes[74] + mi := &file_pkg_app_server_service_webservice_service_proto_msgTypes[78] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3695,7 +3847,7 @@ func (x *AddProjectRBACRoleRequest) String() string { func (*AddProjectRBACRoleRequest) ProtoMessage() {} func (x *AddProjectRBACRoleRequest) ProtoReflect() protoreflect.Message { - mi := &file_pkg_app_server_service_webservice_service_proto_msgTypes[74] + mi := &file_pkg_app_server_service_webservice_service_proto_msgTypes[78] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3708,7 +3860,7 @@ func (x *AddProjectRBACRoleRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use AddProjectRBACRoleRequest.ProtoReflect.Descriptor instead. func (*AddProjectRBACRoleRequest) Descriptor() ([]byte, []int) { - return file_pkg_app_server_service_webservice_service_proto_rawDescGZIP(), []int{74} + return file_pkg_app_server_service_webservice_service_proto_rawDescGZIP(), []int{78} } func (x *AddProjectRBACRoleRequest) GetName() string { @@ -3734,7 +3886,7 @@ type AddProjectRBACRoleResponse struct { func (x *AddProjectRBACRoleResponse) Reset() { *x = AddProjectRBACRoleResponse{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_app_server_service_webservice_service_proto_msgTypes[75] + mi := &file_pkg_app_server_service_webservice_service_proto_msgTypes[79] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3747,7 +3899,7 @@ func (x *AddProjectRBACRoleResponse) String() string { func (*AddProjectRBACRoleResponse) ProtoMessage() {} func (x *AddProjectRBACRoleResponse) ProtoReflect() protoreflect.Message { - mi := &file_pkg_app_server_service_webservice_service_proto_msgTypes[75] + mi := &file_pkg_app_server_service_webservice_service_proto_msgTypes[79] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3760,7 +3912,7 @@ func (x *AddProjectRBACRoleResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use AddProjectRBACRoleResponse.ProtoReflect.Descriptor instead. func (*AddProjectRBACRoleResponse) Descriptor() ([]byte, []int) { - return file_pkg_app_server_service_webservice_service_proto_rawDescGZIP(), []int{75} + return file_pkg_app_server_service_webservice_service_proto_rawDescGZIP(), []int{79} } type UpdateProjectRBACRoleRequest struct { @@ -3775,7 +3927,7 @@ type UpdateProjectRBACRoleRequest struct { func (x *UpdateProjectRBACRoleRequest) Reset() { *x = UpdateProjectRBACRoleRequest{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_app_server_service_webservice_service_proto_msgTypes[76] + mi := &file_pkg_app_server_service_webservice_service_proto_msgTypes[80] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3788,7 +3940,7 @@ func (x *UpdateProjectRBACRoleRequest) String() string { func (*UpdateProjectRBACRoleRequest) ProtoMessage() {} func (x *UpdateProjectRBACRoleRequest) ProtoReflect() protoreflect.Message { - mi := &file_pkg_app_server_service_webservice_service_proto_msgTypes[76] + mi := &file_pkg_app_server_service_webservice_service_proto_msgTypes[80] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3801,7 +3953,7 @@ func (x *UpdateProjectRBACRoleRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use UpdateProjectRBACRoleRequest.ProtoReflect.Descriptor instead. func (*UpdateProjectRBACRoleRequest) Descriptor() ([]byte, []int) { - return file_pkg_app_server_service_webservice_service_proto_rawDescGZIP(), []int{76} + return file_pkg_app_server_service_webservice_service_proto_rawDescGZIP(), []int{80} } func (x *UpdateProjectRBACRoleRequest) GetName() string { @@ -3827,7 +3979,7 @@ type UpdateProjectRBACRoleResponse struct { func (x *UpdateProjectRBACRoleResponse) Reset() { *x = UpdateProjectRBACRoleResponse{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_app_server_service_webservice_service_proto_msgTypes[77] + mi := &file_pkg_app_server_service_webservice_service_proto_msgTypes[81] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3840,7 +3992,7 @@ func (x *UpdateProjectRBACRoleResponse) String() string { func (*UpdateProjectRBACRoleResponse) ProtoMessage() {} func (x *UpdateProjectRBACRoleResponse) ProtoReflect() protoreflect.Message { - mi := &file_pkg_app_server_service_webservice_service_proto_msgTypes[77] + mi := &file_pkg_app_server_service_webservice_service_proto_msgTypes[81] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3853,7 +4005,7 @@ func (x *UpdateProjectRBACRoleResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use UpdateProjectRBACRoleResponse.ProtoReflect.Descriptor instead. func (*UpdateProjectRBACRoleResponse) Descriptor() ([]byte, []int) { - return file_pkg_app_server_service_webservice_service_proto_rawDescGZIP(), []int{77} + return file_pkg_app_server_service_webservice_service_proto_rawDescGZIP(), []int{81} } type DeleteProjectRBACRoleRequest struct { @@ -3867,7 +4019,7 @@ type DeleteProjectRBACRoleRequest struct { func (x *DeleteProjectRBACRoleRequest) Reset() { *x = DeleteProjectRBACRoleRequest{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_app_server_service_webservice_service_proto_msgTypes[78] + mi := &file_pkg_app_server_service_webservice_service_proto_msgTypes[82] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3880,7 +4032,7 @@ func (x *DeleteProjectRBACRoleRequest) String() string { func (*DeleteProjectRBACRoleRequest) ProtoMessage() {} func (x *DeleteProjectRBACRoleRequest) ProtoReflect() protoreflect.Message { - mi := &file_pkg_app_server_service_webservice_service_proto_msgTypes[78] + mi := &file_pkg_app_server_service_webservice_service_proto_msgTypes[82] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3893,7 +4045,7 @@ func (x *DeleteProjectRBACRoleRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use DeleteProjectRBACRoleRequest.ProtoReflect.Descriptor instead. func (*DeleteProjectRBACRoleRequest) Descriptor() ([]byte, []int) { - return file_pkg_app_server_service_webservice_service_proto_rawDescGZIP(), []int{78} + return file_pkg_app_server_service_webservice_service_proto_rawDescGZIP(), []int{82} } func (x *DeleteProjectRBACRoleRequest) GetName() string { @@ -3912,7 +4064,7 @@ type DeleteProjectRBACRoleResponse struct { func (x *DeleteProjectRBACRoleResponse) Reset() { *x = DeleteProjectRBACRoleResponse{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_app_server_service_webservice_service_proto_msgTypes[79] + mi := &file_pkg_app_server_service_webservice_service_proto_msgTypes[83] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3925,7 +4077,7 @@ func (x *DeleteProjectRBACRoleResponse) String() string { func (*DeleteProjectRBACRoleResponse) ProtoMessage() {} func (x *DeleteProjectRBACRoleResponse) ProtoReflect() protoreflect.Message { - mi := &file_pkg_app_server_service_webservice_service_proto_msgTypes[79] + mi := &file_pkg_app_server_service_webservice_service_proto_msgTypes[83] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3938,7 +4090,7 @@ func (x *DeleteProjectRBACRoleResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use DeleteProjectRBACRoleResponse.ProtoReflect.Descriptor instead. func (*DeleteProjectRBACRoleResponse) Descriptor() ([]byte, []int) { - return file_pkg_app_server_service_webservice_service_proto_rawDescGZIP(), []int{79} + return file_pkg_app_server_service_webservice_service_proto_rawDescGZIP(), []int{83} } type AddProjectUserGroupRequest struct { @@ -3953,7 +4105,7 @@ type AddProjectUserGroupRequest struct { func (x *AddProjectUserGroupRequest) Reset() { *x = AddProjectUserGroupRequest{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_app_server_service_webservice_service_proto_msgTypes[80] + mi := &file_pkg_app_server_service_webservice_service_proto_msgTypes[84] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3966,7 +4118,7 @@ func (x *AddProjectUserGroupRequest) String() string { func (*AddProjectUserGroupRequest) ProtoMessage() {} func (x *AddProjectUserGroupRequest) ProtoReflect() protoreflect.Message { - mi := &file_pkg_app_server_service_webservice_service_proto_msgTypes[80] + mi := &file_pkg_app_server_service_webservice_service_proto_msgTypes[84] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3979,7 +4131,7 @@ func (x *AddProjectUserGroupRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use AddProjectUserGroupRequest.ProtoReflect.Descriptor instead. func (*AddProjectUserGroupRequest) Descriptor() ([]byte, []int) { - return file_pkg_app_server_service_webservice_service_proto_rawDescGZIP(), []int{80} + return file_pkg_app_server_service_webservice_service_proto_rawDescGZIP(), []int{84} } func (x *AddProjectUserGroupRequest) GetSsoGroup() string { @@ -4005,7 +4157,7 @@ type AddProjectUserGroupResponse struct { func (x *AddProjectUserGroupResponse) Reset() { *x = AddProjectUserGroupResponse{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_app_server_service_webservice_service_proto_msgTypes[81] + mi := &file_pkg_app_server_service_webservice_service_proto_msgTypes[85] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4018,7 +4170,7 @@ func (x *AddProjectUserGroupResponse) String() string { func (*AddProjectUserGroupResponse) ProtoMessage() {} func (x *AddProjectUserGroupResponse) ProtoReflect() protoreflect.Message { - mi := &file_pkg_app_server_service_webservice_service_proto_msgTypes[81] + mi := &file_pkg_app_server_service_webservice_service_proto_msgTypes[85] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4031,7 +4183,7 @@ func (x *AddProjectUserGroupResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use AddProjectUserGroupResponse.ProtoReflect.Descriptor instead. func (*AddProjectUserGroupResponse) Descriptor() ([]byte, []int) { - return file_pkg_app_server_service_webservice_service_proto_rawDescGZIP(), []int{81} + return file_pkg_app_server_service_webservice_service_proto_rawDescGZIP(), []int{85} } type DeleteProjectUserGroupRequest struct { @@ -4045,7 +4197,7 @@ type DeleteProjectUserGroupRequest struct { func (x *DeleteProjectUserGroupRequest) Reset() { *x = DeleteProjectUserGroupRequest{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_app_server_service_webservice_service_proto_msgTypes[82] + mi := &file_pkg_app_server_service_webservice_service_proto_msgTypes[86] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4058,7 +4210,7 @@ func (x *DeleteProjectUserGroupRequest) String() string { func (*DeleteProjectUserGroupRequest) ProtoMessage() {} func (x *DeleteProjectUserGroupRequest) ProtoReflect() protoreflect.Message { - mi := &file_pkg_app_server_service_webservice_service_proto_msgTypes[82] + mi := &file_pkg_app_server_service_webservice_service_proto_msgTypes[86] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4071,7 +4223,7 @@ func (x *DeleteProjectUserGroupRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use DeleteProjectUserGroupRequest.ProtoReflect.Descriptor instead. func (*DeleteProjectUserGroupRequest) Descriptor() ([]byte, []int) { - return file_pkg_app_server_service_webservice_service_proto_rawDescGZIP(), []int{82} + return file_pkg_app_server_service_webservice_service_proto_rawDescGZIP(), []int{86} } func (x *DeleteProjectUserGroupRequest) GetSsoGroup() string { @@ -4090,7 +4242,7 @@ type DeleteProjectUserGroupResponse struct { func (x *DeleteProjectUserGroupResponse) Reset() { *x = DeleteProjectUserGroupResponse{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_app_server_service_webservice_service_proto_msgTypes[83] + mi := &file_pkg_app_server_service_webservice_service_proto_msgTypes[87] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4103,7 +4255,7 @@ func (x *DeleteProjectUserGroupResponse) String() string { func (*DeleteProjectUserGroupResponse) ProtoMessage() {} func (x *DeleteProjectUserGroupResponse) ProtoReflect() protoreflect.Message { - mi := &file_pkg_app_server_service_webservice_service_proto_msgTypes[83] + mi := &file_pkg_app_server_service_webservice_service_proto_msgTypes[87] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4116,7 +4268,7 @@ func (x *DeleteProjectUserGroupResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use DeleteProjectUserGroupResponse.ProtoReflect.Descriptor instead. func (*DeleteProjectUserGroupResponse) Descriptor() ([]byte, []int) { - return file_pkg_app_server_service_webservice_service_proto_rawDescGZIP(), []int{83} + return file_pkg_app_server_service_webservice_service_proto_rawDescGZIP(), []int{87} } type GetCommandRequest struct { @@ -4130,7 +4282,7 @@ type GetCommandRequest struct { func (x *GetCommandRequest) Reset() { *x = GetCommandRequest{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_app_server_service_webservice_service_proto_msgTypes[84] + mi := &file_pkg_app_server_service_webservice_service_proto_msgTypes[88] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4143,7 +4295,7 @@ func (x *GetCommandRequest) String() string { func (*GetCommandRequest) ProtoMessage() {} func (x *GetCommandRequest) ProtoReflect() protoreflect.Message { - mi := &file_pkg_app_server_service_webservice_service_proto_msgTypes[84] + mi := &file_pkg_app_server_service_webservice_service_proto_msgTypes[88] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4156,7 +4308,7 @@ func (x *GetCommandRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GetCommandRequest.ProtoReflect.Descriptor instead. func (*GetCommandRequest) Descriptor() ([]byte, []int) { - return file_pkg_app_server_service_webservice_service_proto_rawDescGZIP(), []int{84} + return file_pkg_app_server_service_webservice_service_proto_rawDescGZIP(), []int{88} } func (x *GetCommandRequest) GetCommandId() string { @@ -4177,7 +4329,7 @@ type GetCommandResponse struct { func (x *GetCommandResponse) Reset() { *x = GetCommandResponse{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_app_server_service_webservice_service_proto_msgTypes[85] + mi := &file_pkg_app_server_service_webservice_service_proto_msgTypes[89] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4190,7 +4342,7 @@ func (x *GetCommandResponse) String() string { func (*GetCommandResponse) ProtoMessage() {} func (x *GetCommandResponse) ProtoReflect() protoreflect.Message { - mi := &file_pkg_app_server_service_webservice_service_proto_msgTypes[85] + mi := &file_pkg_app_server_service_webservice_service_proto_msgTypes[89] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4203,7 +4355,7 @@ func (x *GetCommandResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use GetCommandResponse.ProtoReflect.Descriptor instead. func (*GetCommandResponse) Descriptor() ([]byte, []int) { - return file_pkg_app_server_service_webservice_service_proto_rawDescGZIP(), []int{85} + return file_pkg_app_server_service_webservice_service_proto_rawDescGZIP(), []int{89} } func (x *GetCommandResponse) GetCommand() *model.Command { @@ -4225,7 +4377,7 @@ type GenerateAPIKeyRequest struct { func (x *GenerateAPIKeyRequest) Reset() { *x = GenerateAPIKeyRequest{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_app_server_service_webservice_service_proto_msgTypes[86] + mi := &file_pkg_app_server_service_webservice_service_proto_msgTypes[90] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4238,7 +4390,7 @@ func (x *GenerateAPIKeyRequest) String() string { func (*GenerateAPIKeyRequest) ProtoMessage() {} func (x *GenerateAPIKeyRequest) ProtoReflect() protoreflect.Message { - mi := &file_pkg_app_server_service_webservice_service_proto_msgTypes[86] + mi := &file_pkg_app_server_service_webservice_service_proto_msgTypes[90] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4251,7 +4403,7 @@ func (x *GenerateAPIKeyRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GenerateAPIKeyRequest.ProtoReflect.Descriptor instead. func (*GenerateAPIKeyRequest) Descriptor() ([]byte, []int) { - return file_pkg_app_server_service_webservice_service_proto_rawDescGZIP(), []int{86} + return file_pkg_app_server_service_webservice_service_proto_rawDescGZIP(), []int{90} } func (x *GenerateAPIKeyRequest) GetName() string { @@ -4279,7 +4431,7 @@ type GenerateAPIKeyResponse struct { func (x *GenerateAPIKeyResponse) Reset() { *x = GenerateAPIKeyResponse{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_app_server_service_webservice_service_proto_msgTypes[87] + mi := &file_pkg_app_server_service_webservice_service_proto_msgTypes[91] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4292,7 +4444,7 @@ func (x *GenerateAPIKeyResponse) String() string { func (*GenerateAPIKeyResponse) ProtoMessage() {} func (x *GenerateAPIKeyResponse) ProtoReflect() protoreflect.Message { - mi := &file_pkg_app_server_service_webservice_service_proto_msgTypes[87] + mi := &file_pkg_app_server_service_webservice_service_proto_msgTypes[91] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4305,7 +4457,7 @@ func (x *GenerateAPIKeyResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use GenerateAPIKeyResponse.ProtoReflect.Descriptor instead. func (*GenerateAPIKeyResponse) Descriptor() ([]byte, []int) { - return file_pkg_app_server_service_webservice_service_proto_rawDescGZIP(), []int{87} + return file_pkg_app_server_service_webservice_service_proto_rawDescGZIP(), []int{91} } func (x *GenerateAPIKeyResponse) GetKey() string { @@ -4326,7 +4478,7 @@ type DisableAPIKeyRequest struct { func (x *DisableAPIKeyRequest) Reset() { *x = DisableAPIKeyRequest{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_app_server_service_webservice_service_proto_msgTypes[88] + mi := &file_pkg_app_server_service_webservice_service_proto_msgTypes[92] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4339,7 +4491,7 @@ func (x *DisableAPIKeyRequest) String() string { func (*DisableAPIKeyRequest) ProtoMessage() {} func (x *DisableAPIKeyRequest) ProtoReflect() protoreflect.Message { - mi := &file_pkg_app_server_service_webservice_service_proto_msgTypes[88] + mi := &file_pkg_app_server_service_webservice_service_proto_msgTypes[92] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4352,7 +4504,7 @@ func (x *DisableAPIKeyRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use DisableAPIKeyRequest.ProtoReflect.Descriptor instead. func (*DisableAPIKeyRequest) Descriptor() ([]byte, []int) { - return file_pkg_app_server_service_webservice_service_proto_rawDescGZIP(), []int{88} + return file_pkg_app_server_service_webservice_service_proto_rawDescGZIP(), []int{92} } func (x *DisableAPIKeyRequest) GetId() string { @@ -4371,7 +4523,7 @@ type DisableAPIKeyResponse struct { func (x *DisableAPIKeyResponse) Reset() { *x = DisableAPIKeyResponse{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_app_server_service_webservice_service_proto_msgTypes[89] + mi := &file_pkg_app_server_service_webservice_service_proto_msgTypes[93] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4384,7 +4536,7 @@ func (x *DisableAPIKeyResponse) String() string { func (*DisableAPIKeyResponse) ProtoMessage() {} func (x *DisableAPIKeyResponse) ProtoReflect() protoreflect.Message { - mi := &file_pkg_app_server_service_webservice_service_proto_msgTypes[89] + mi := &file_pkg_app_server_service_webservice_service_proto_msgTypes[93] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4397,7 +4549,7 @@ func (x *DisableAPIKeyResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use DisableAPIKeyResponse.ProtoReflect.Descriptor instead. func (*DisableAPIKeyResponse) Descriptor() ([]byte, []int) { - return file_pkg_app_server_service_webservice_service_proto_rawDescGZIP(), []int{89} + return file_pkg_app_server_service_webservice_service_proto_rawDescGZIP(), []int{93} } type ListAPIKeysRequest struct { @@ -4411,7 +4563,7 @@ type ListAPIKeysRequest struct { func (x *ListAPIKeysRequest) Reset() { *x = ListAPIKeysRequest{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_app_server_service_webservice_service_proto_msgTypes[90] + mi := &file_pkg_app_server_service_webservice_service_proto_msgTypes[94] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4424,7 +4576,7 @@ func (x *ListAPIKeysRequest) String() string { func (*ListAPIKeysRequest) ProtoMessage() {} func (x *ListAPIKeysRequest) ProtoReflect() protoreflect.Message { - mi := &file_pkg_app_server_service_webservice_service_proto_msgTypes[90] + mi := &file_pkg_app_server_service_webservice_service_proto_msgTypes[94] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4437,7 +4589,7 @@ func (x *ListAPIKeysRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ListAPIKeysRequest.ProtoReflect.Descriptor instead. func (*ListAPIKeysRequest) Descriptor() ([]byte, []int) { - return file_pkg_app_server_service_webservice_service_proto_rawDescGZIP(), []int{90} + return file_pkg_app_server_service_webservice_service_proto_rawDescGZIP(), []int{94} } func (x *ListAPIKeysRequest) GetOptions() *ListAPIKeysRequest_Options { @@ -4458,7 +4610,7 @@ type ListAPIKeysResponse struct { func (x *ListAPIKeysResponse) Reset() { *x = ListAPIKeysResponse{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_app_server_service_webservice_service_proto_msgTypes[91] + mi := &file_pkg_app_server_service_webservice_service_proto_msgTypes[95] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4471,7 +4623,7 @@ func (x *ListAPIKeysResponse) String() string { func (*ListAPIKeysResponse) ProtoMessage() {} func (x *ListAPIKeysResponse) ProtoReflect() protoreflect.Message { - mi := &file_pkg_app_server_service_webservice_service_proto_msgTypes[91] + mi := &file_pkg_app_server_service_webservice_service_proto_msgTypes[95] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4484,7 +4636,7 @@ func (x *ListAPIKeysResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ListAPIKeysResponse.ProtoReflect.Descriptor instead. func (*ListAPIKeysResponse) Descriptor() ([]byte, []int) { - return file_pkg_app_server_service_webservice_service_proto_rawDescGZIP(), []int{91} + return file_pkg_app_server_service_webservice_service_proto_rawDescGZIP(), []int{95} } func (x *ListAPIKeysResponse) GetKeys() []*model.APIKey { @@ -4510,7 +4662,7 @@ type GetInsightDataRequest struct { func (x *GetInsightDataRequest) Reset() { *x = GetInsightDataRequest{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_app_server_service_webservice_service_proto_msgTypes[92] + mi := &file_pkg_app_server_service_webservice_service_proto_msgTypes[96] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4523,7 +4675,7 @@ func (x *GetInsightDataRequest) String() string { func (*GetInsightDataRequest) ProtoMessage() {} func (x *GetInsightDataRequest) ProtoReflect() protoreflect.Message { - mi := &file_pkg_app_server_service_webservice_service_proto_msgTypes[92] + mi := &file_pkg_app_server_service_webservice_service_proto_msgTypes[96] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4536,7 +4688,7 @@ func (x *GetInsightDataRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GetInsightDataRequest.ProtoReflect.Descriptor instead. func (*GetInsightDataRequest) Descriptor() ([]byte, []int) { - return file_pkg_app_server_service_webservice_service_proto_rawDescGZIP(), []int{92} + return file_pkg_app_server_service_webservice_service_proto_rawDescGZIP(), []int{96} } func (x *GetInsightDataRequest) GetMetricsKind() model.InsightMetricsKind { @@ -4595,7 +4747,7 @@ type GetInsightDataResponse struct { func (x *GetInsightDataResponse) Reset() { *x = GetInsightDataResponse{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_app_server_service_webservice_service_proto_msgTypes[93] + mi := &file_pkg_app_server_service_webservice_service_proto_msgTypes[97] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4608,7 +4760,7 @@ func (x *GetInsightDataResponse) String() string { func (*GetInsightDataResponse) ProtoMessage() {} func (x *GetInsightDataResponse) ProtoReflect() protoreflect.Message { - mi := &file_pkg_app_server_service_webservice_service_proto_msgTypes[93] + mi := &file_pkg_app_server_service_webservice_service_proto_msgTypes[97] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4621,7 +4773,7 @@ func (x *GetInsightDataResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use GetInsightDataResponse.ProtoReflect.Descriptor instead. func (*GetInsightDataResponse) Descriptor() ([]byte, []int) { - return file_pkg_app_server_service_webservice_service_proto_rawDescGZIP(), []int{93} + return file_pkg_app_server_service_webservice_service_proto_rawDescGZIP(), []int{97} } func (x *GetInsightDataResponse) GetUpdatedAt() int64 { @@ -4661,7 +4813,7 @@ type GetInsightApplicationCountRequest struct { func (x *GetInsightApplicationCountRequest) Reset() { *x = GetInsightApplicationCountRequest{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_app_server_service_webservice_service_proto_msgTypes[94] + mi := &file_pkg_app_server_service_webservice_service_proto_msgTypes[98] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4674,7 +4826,7 @@ func (x *GetInsightApplicationCountRequest) String() string { func (*GetInsightApplicationCountRequest) ProtoMessage() {} func (x *GetInsightApplicationCountRequest) ProtoReflect() protoreflect.Message { - mi := &file_pkg_app_server_service_webservice_service_proto_msgTypes[94] + mi := &file_pkg_app_server_service_webservice_service_proto_msgTypes[98] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4687,7 +4839,7 @@ func (x *GetInsightApplicationCountRequest) ProtoReflect() protoreflect.Message // Deprecated: Use GetInsightApplicationCountRequest.ProtoReflect.Descriptor instead. func (*GetInsightApplicationCountRequest) Descriptor() ([]byte, []int) { - return file_pkg_app_server_service_webservice_service_proto_rawDescGZIP(), []int{94} + return file_pkg_app_server_service_webservice_service_proto_rawDescGZIP(), []int{98} } type GetInsightApplicationCountResponse struct { @@ -4702,7 +4854,7 @@ type GetInsightApplicationCountResponse struct { func (x *GetInsightApplicationCountResponse) Reset() { *x = GetInsightApplicationCountResponse{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_app_server_service_webservice_service_proto_msgTypes[95] + mi := &file_pkg_app_server_service_webservice_service_proto_msgTypes[99] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4715,7 +4867,7 @@ func (x *GetInsightApplicationCountResponse) String() string { func (*GetInsightApplicationCountResponse) ProtoMessage() {} func (x *GetInsightApplicationCountResponse) ProtoReflect() protoreflect.Message { - mi := &file_pkg_app_server_service_webservice_service_proto_msgTypes[95] + mi := &file_pkg_app_server_service_webservice_service_proto_msgTypes[99] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4728,7 +4880,7 @@ func (x *GetInsightApplicationCountResponse) ProtoReflect() protoreflect.Message // Deprecated: Use GetInsightApplicationCountResponse.ProtoReflect.Descriptor instead. func (*GetInsightApplicationCountResponse) Descriptor() ([]byte, []int) { - return file_pkg_app_server_service_webservice_service_proto_rawDescGZIP(), []int{95} + return file_pkg_app_server_service_webservice_service_proto_rawDescGZIP(), []int{99} } func (x *GetInsightApplicationCountResponse) GetUpdatedAt() int64 { @@ -4761,7 +4913,7 @@ type ListDeploymentChainsRequest struct { func (x *ListDeploymentChainsRequest) Reset() { *x = ListDeploymentChainsRequest{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_app_server_service_webservice_service_proto_msgTypes[96] + mi := &file_pkg_app_server_service_webservice_service_proto_msgTypes[100] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4774,7 +4926,7 @@ func (x *ListDeploymentChainsRequest) String() string { func (*ListDeploymentChainsRequest) ProtoMessage() {} func (x *ListDeploymentChainsRequest) ProtoReflect() protoreflect.Message { - mi := &file_pkg_app_server_service_webservice_service_proto_msgTypes[96] + mi := &file_pkg_app_server_service_webservice_service_proto_msgTypes[100] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4787,7 +4939,7 @@ func (x *ListDeploymentChainsRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ListDeploymentChainsRequest.ProtoReflect.Descriptor instead. func (*ListDeploymentChainsRequest) Descriptor() ([]byte, []int) { - return file_pkg_app_server_service_webservice_service_proto_rawDescGZIP(), []int{96} + return file_pkg_app_server_service_webservice_service_proto_rawDescGZIP(), []int{100} } func (x *ListDeploymentChainsRequest) GetOptions() *ListDeploymentChainsRequest_Options { @@ -4830,7 +4982,7 @@ type ListDeploymentChainsResponse struct { func (x *ListDeploymentChainsResponse) Reset() { *x = ListDeploymentChainsResponse{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_app_server_service_webservice_service_proto_msgTypes[97] + mi := &file_pkg_app_server_service_webservice_service_proto_msgTypes[101] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4843,7 +4995,7 @@ func (x *ListDeploymentChainsResponse) String() string { func (*ListDeploymentChainsResponse) ProtoMessage() {} func (x *ListDeploymentChainsResponse) ProtoReflect() protoreflect.Message { - mi := &file_pkg_app_server_service_webservice_service_proto_msgTypes[97] + mi := &file_pkg_app_server_service_webservice_service_proto_msgTypes[101] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4856,7 +5008,7 @@ func (x *ListDeploymentChainsResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ListDeploymentChainsResponse.ProtoReflect.Descriptor instead. func (*ListDeploymentChainsResponse) Descriptor() ([]byte, []int) { - return file_pkg_app_server_service_webservice_service_proto_rawDescGZIP(), []int{97} + return file_pkg_app_server_service_webservice_service_proto_rawDescGZIP(), []int{101} } func (x *ListDeploymentChainsResponse) GetDeploymentChains() []*model.DeploymentChain { @@ -4884,7 +5036,7 @@ type GetDeploymentChainRequest struct { func (x *GetDeploymentChainRequest) Reset() { *x = GetDeploymentChainRequest{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_app_server_service_webservice_service_proto_msgTypes[98] + mi := &file_pkg_app_server_service_webservice_service_proto_msgTypes[102] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4897,7 +5049,7 @@ func (x *GetDeploymentChainRequest) String() string { func (*GetDeploymentChainRequest) ProtoMessage() {} func (x *GetDeploymentChainRequest) ProtoReflect() protoreflect.Message { - mi := &file_pkg_app_server_service_webservice_service_proto_msgTypes[98] + mi := &file_pkg_app_server_service_webservice_service_proto_msgTypes[102] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4910,7 +5062,7 @@ func (x *GetDeploymentChainRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GetDeploymentChainRequest.ProtoReflect.Descriptor instead. func (*GetDeploymentChainRequest) Descriptor() ([]byte, []int) { - return file_pkg_app_server_service_webservice_service_proto_rawDescGZIP(), []int{98} + return file_pkg_app_server_service_webservice_service_proto_rawDescGZIP(), []int{102} } func (x *GetDeploymentChainRequest) GetDeploymentChainId() string { @@ -4931,7 +5083,7 @@ type GetDeploymentChainResponse struct { func (x *GetDeploymentChainResponse) Reset() { *x = GetDeploymentChainResponse{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_app_server_service_webservice_service_proto_msgTypes[99] + mi := &file_pkg_app_server_service_webservice_service_proto_msgTypes[103] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4944,7 +5096,7 @@ func (x *GetDeploymentChainResponse) String() string { func (*GetDeploymentChainResponse) ProtoMessage() {} func (x *GetDeploymentChainResponse) ProtoReflect() protoreflect.Message { - mi := &file_pkg_app_server_service_webservice_service_proto_msgTypes[99] + mi := &file_pkg_app_server_service_webservice_service_proto_msgTypes[103] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4957,7 +5109,7 @@ func (x *GetDeploymentChainResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use GetDeploymentChainResponse.ProtoReflect.Descriptor instead. func (*GetDeploymentChainResponse) Descriptor() ([]byte, []int) { - return file_pkg_app_server_service_webservice_service_proto_rawDescGZIP(), []int{99} + return file_pkg_app_server_service_webservice_service_proto_rawDescGZIP(), []int{103} } func (x *GetDeploymentChainResponse) GetDeploymentChain() *model.DeploymentChain { @@ -4983,7 +5135,7 @@ type ListEventsRequest struct { func (x *ListEventsRequest) Reset() { *x = ListEventsRequest{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_app_server_service_webservice_service_proto_msgTypes[100] + mi := &file_pkg_app_server_service_webservice_service_proto_msgTypes[104] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4996,7 +5148,7 @@ func (x *ListEventsRequest) String() string { func (*ListEventsRequest) ProtoMessage() {} func (x *ListEventsRequest) ProtoReflect() protoreflect.Message { - mi := &file_pkg_app_server_service_webservice_service_proto_msgTypes[100] + mi := &file_pkg_app_server_service_webservice_service_proto_msgTypes[104] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5009,7 +5161,7 @@ func (x *ListEventsRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ListEventsRequest.ProtoReflect.Descriptor instead. func (*ListEventsRequest) Descriptor() ([]byte, []int) { - return file_pkg_app_server_service_webservice_service_proto_rawDescGZIP(), []int{100} + return file_pkg_app_server_service_webservice_service_proto_rawDescGZIP(), []int{104} } func (x *ListEventsRequest) GetOptions() *ListEventsRequest_Options { @@ -5052,7 +5204,7 @@ type ListEventsResponse struct { func (x *ListEventsResponse) Reset() { *x = ListEventsResponse{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_app_server_service_webservice_service_proto_msgTypes[101] + mi := &file_pkg_app_server_service_webservice_service_proto_msgTypes[105] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5065,7 +5217,7 @@ func (x *ListEventsResponse) String() string { func (*ListEventsResponse) ProtoMessage() {} func (x *ListEventsResponse) ProtoReflect() protoreflect.Message { - mi := &file_pkg_app_server_service_webservice_service_proto_msgTypes[101] + mi := &file_pkg_app_server_service_webservice_service_proto_msgTypes[105] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5078,7 +5230,7 @@ func (x *ListEventsResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ListEventsResponse.ProtoReflect.Descriptor instead. func (*ListEventsResponse) Descriptor() ([]byte, []int) { - return file_pkg_app_server_service_webservice_service_proto_rawDescGZIP(), []int{101} + return file_pkg_app_server_service_webservice_service_proto_rawDescGZIP(), []int{105} } func (x *ListEventsResponse) GetEvents() []*model.Event { @@ -5106,7 +5258,7 @@ type ListPipedsRequest_Options struct { func (x *ListPipedsRequest_Options) Reset() { *x = ListPipedsRequest_Options{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_app_server_service_webservice_service_proto_msgTypes[102] + mi := &file_pkg_app_server_service_webservice_service_proto_msgTypes[106] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5119,7 +5271,7 @@ func (x *ListPipedsRequest_Options) String() string { func (*ListPipedsRequest_Options) ProtoMessage() {} func (x *ListPipedsRequest_Options) ProtoReflect() protoreflect.Message { - mi := &file_pkg_app_server_service_webservice_service_proto_msgTypes[102] + mi := &file_pkg_app_server_service_webservice_service_proto_msgTypes[106] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5158,7 +5310,7 @@ type ListApplicationsRequest_Options struct { func (x *ListApplicationsRequest_Options) Reset() { *x = ListApplicationsRequest_Options{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_app_server_service_webservice_service_proto_msgTypes[106] + mi := &file_pkg_app_server_service_webservice_service_proto_msgTypes[110] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5171,7 +5323,7 @@ func (x *ListApplicationsRequest_Options) String() string { func (*ListApplicationsRequest_Options) ProtoMessage() {} func (x *ListApplicationsRequest_Options) ProtoReflect() protoreflect.Message { - mi := &file_pkg_app_server_service_webservice_service_proto_msgTypes[106] + mi := &file_pkg_app_server_service_webservice_service_proto_msgTypes[110] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5244,7 +5396,7 @@ type ListDeploymentsRequest_Options struct { func (x *ListDeploymentsRequest_Options) Reset() { *x = ListDeploymentsRequest_Options{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_app_server_service_webservice_service_proto_msgTypes[108] + mi := &file_pkg_app_server_service_webservice_service_proto_msgTypes[112] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5257,7 +5409,7 @@ func (x *ListDeploymentsRequest_Options) String() string { func (*ListDeploymentsRequest_Options) ProtoMessage() {} func (x *ListDeploymentsRequest_Options) ProtoReflect() protoreflect.Message { - mi := &file_pkg_app_server_service_webservice_service_proto_msgTypes[108] + mi := &file_pkg_app_server_service_webservice_service_proto_msgTypes[112] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5319,7 +5471,7 @@ type ListDeploymentTracesRequest_Options struct { func (x *ListDeploymentTracesRequest_Options) Reset() { *x = ListDeploymentTracesRequest_Options{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_app_server_service_webservice_service_proto_msgTypes[110] + mi := &file_pkg_app_server_service_webservice_service_proto_msgTypes[114] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5332,7 +5484,7 @@ func (x *ListDeploymentTracesRequest_Options) String() string { func (*ListDeploymentTracesRequest_Options) ProtoMessage() {} func (x *ListDeploymentTracesRequest_Options) ProtoReflect() protoreflect.Message { - mi := &file_pkg_app_server_service_webservice_service_proto_msgTypes[110] + mi := &file_pkg_app_server_service_webservice_service_proto_msgTypes[114] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5367,7 +5519,7 @@ type ListDeploymentTracesResponse_DeploymentTraceRes struct { func (x *ListDeploymentTracesResponse_DeploymentTraceRes) Reset() { *x = ListDeploymentTracesResponse_DeploymentTraceRes{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_app_server_service_webservice_service_proto_msgTypes[111] + mi := &file_pkg_app_server_service_webservice_service_proto_msgTypes[115] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5380,7 +5532,7 @@ func (x *ListDeploymentTracesResponse_DeploymentTraceRes) String() string { func (*ListDeploymentTracesResponse_DeploymentTraceRes) ProtoMessage() {} func (x *ListDeploymentTracesResponse_DeploymentTraceRes) ProtoReflect() protoreflect.Message { - mi := &file_pkg_app_server_service_webservice_service_proto_msgTypes[111] + mi := &file_pkg_app_server_service_webservice_service_proto_msgTypes[115] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5421,7 +5573,7 @@ type ListAPIKeysRequest_Options struct { func (x *ListAPIKeysRequest_Options) Reset() { *x = ListAPIKeysRequest_Options{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_app_server_service_webservice_service_proto_msgTypes[112] + mi := &file_pkg_app_server_service_webservice_service_proto_msgTypes[116] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5434,7 +5586,7 @@ func (x *ListAPIKeysRequest_Options) String() string { func (*ListAPIKeysRequest_Options) ProtoMessage() {} func (x *ListAPIKeysRequest_Options) ProtoReflect() protoreflect.Message { - mi := &file_pkg_app_server_service_webservice_service_proto_msgTypes[112] + mi := &file_pkg_app_server_service_webservice_service_proto_msgTypes[116] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5447,7 +5599,7 @@ func (x *ListAPIKeysRequest_Options) ProtoReflect() protoreflect.Message { // Deprecated: Use ListAPIKeysRequest_Options.ProtoReflect.Descriptor instead. func (*ListAPIKeysRequest_Options) Descriptor() ([]byte, []int) { - return file_pkg_app_server_service_webservice_service_proto_rawDescGZIP(), []int{90, 0} + return file_pkg_app_server_service_webservice_service_proto_rawDescGZIP(), []int{94, 0} } func (x *ListAPIKeysRequest_Options) GetEnabled() *wrapperspb.BoolValue { @@ -5466,7 +5618,7 @@ type ListDeploymentChainsRequest_Options struct { func (x *ListDeploymentChainsRequest_Options) Reset() { *x = ListDeploymentChainsRequest_Options{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_app_server_service_webservice_service_proto_msgTypes[114] + mi := &file_pkg_app_server_service_webservice_service_proto_msgTypes[118] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5479,7 +5631,7 @@ func (x *ListDeploymentChainsRequest_Options) String() string { func (*ListDeploymentChainsRequest_Options) ProtoMessage() {} func (x *ListDeploymentChainsRequest_Options) ProtoReflect() protoreflect.Message { - mi := &file_pkg_app_server_service_webservice_service_proto_msgTypes[114] + mi := &file_pkg_app_server_service_webservice_service_proto_msgTypes[118] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5492,7 +5644,7 @@ func (x *ListDeploymentChainsRequest_Options) ProtoReflect() protoreflect.Messag // Deprecated: Use ListDeploymentChainsRequest_Options.ProtoReflect.Descriptor instead. func (*ListDeploymentChainsRequest_Options) Descriptor() ([]byte, []int) { - return file_pkg_app_server_service_webservice_service_proto_rawDescGZIP(), []int{96, 0} + return file_pkg_app_server_service_webservice_service_proto_rawDescGZIP(), []int{100, 0} } type ListEventsRequest_Options struct { @@ -5508,7 +5660,7 @@ type ListEventsRequest_Options struct { func (x *ListEventsRequest_Options) Reset() { *x = ListEventsRequest_Options{} if protoimpl.UnsafeEnabled { - mi := &file_pkg_app_server_service_webservice_service_proto_msgTypes[115] + mi := &file_pkg_app_server_service_webservice_service_proto_msgTypes[119] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5521,7 +5673,7 @@ func (x *ListEventsRequest_Options) String() string { func (*ListEventsRequest_Options) ProtoMessage() {} func (x *ListEventsRequest_Options) ProtoReflect() protoreflect.Message { - mi := &file_pkg_app_server_service_webservice_service_proto_msgTypes[115] + mi := &file_pkg_app_server_service_webservice_service_proto_msgTypes[119] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5534,7 +5686,7 @@ func (x *ListEventsRequest_Options) ProtoReflect() protoreflect.Message { // Deprecated: Use ListEventsRequest_Options.ProtoReflect.Descriptor instead. func (*ListEventsRequest_Options) Descriptor() ([]byte, []int) { - return file_pkg_app_server_service_webservice_service_proto_rawDescGZIP(), []int{100, 0} + return file_pkg_app_server_service_webservice_service_proto_rawDescGZIP(), []int{104, 0} } func (x *ListEventsRequest_Options) GetName() string { @@ -6052,644 +6204,667 @@ var file_pkg_app_server_service_webservice_service_proto_rawDesc = []byte{ 0x53, 0x74, 0x61, 0x74, 0x69, 0x63, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x1c, 0x0a, 0x1a, 0x44, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x53, 0x74, 0x61, 0x74, 0x69, 0x63, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x22, 0x0e, 0x0a, 0x0c, 0x47, 0x65, 0x74, 0x4d, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x22, 0x6d, 0x0a, 0x0d, 0x47, 0x65, 0x74, 0x4d, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x18, 0x0a, 0x07, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x07, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x61, - 0x76, 0x61, 0x74, 0x61, 0x72, 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x09, 0x61, 0x76, 0x61, 0x74, 0x61, 0x72, 0x55, 0x72, 0x6c, 0x12, 0x1d, 0x0a, 0x0a, 0x70, 0x72, - 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, - 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x49, 0x64, 0x4a, 0x04, 0x08, 0x04, 0x10, 0x05, 0x22, - 0x78, 0x0a, 0x19, 0x41, 0x64, 0x64, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x52, 0x42, 0x41, - 0x43, 0x52, 0x6f, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1b, 0x0a, 0x04, - 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xfa, 0x42, 0x04, 0x72, - 0x02, 0x10, 0x01, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x3e, 0x0a, 0x08, 0x70, 0x6f, 0x6c, - 0x69, 0x63, 0x69, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x6d, 0x6f, - 0x64, 0x65, 0x6c, 0x2e, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x52, 0x42, 0x41, 0x43, 0x50, - 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x42, 0x08, 0xfa, 0x42, 0x05, 0x92, 0x01, 0x02, 0x08, 0x01, 0x52, - 0x08, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x22, 0x1c, 0x0a, 0x1a, 0x41, 0x64, 0x64, + 0x22, 0x16, 0x0a, 0x14, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, + 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x17, 0x0a, 0x15, 0x45, 0x6e, 0x61, 0x62, + 0x6c, 0x65, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x22, 0x17, 0x0a, 0x15, 0x44, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x50, 0x72, 0x6f, 0x6a, + 0x65, 0x63, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x18, 0x0a, 0x16, 0x44, 0x69, + 0x73, 0x61, 0x62, 0x6c, 0x65, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x0e, 0x0a, 0x0c, 0x47, 0x65, 0x74, 0x4d, 0x65, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x22, 0x6d, 0x0a, 0x0d, 0x47, 0x65, 0x74, 0x4d, 0x65, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x12, + 0x1d, 0x0a, 0x0a, 0x61, 0x76, 0x61, 0x74, 0x61, 0x72, 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x09, 0x61, 0x76, 0x61, 0x74, 0x61, 0x72, 0x55, 0x72, 0x6c, 0x12, 0x1d, + 0x0a, 0x0a, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x09, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x49, 0x64, 0x4a, 0x04, 0x08, + 0x04, 0x10, 0x05, 0x22, 0x78, 0x0a, 0x19, 0x41, 0x64, 0x64, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, + 0x74, 0x52, 0x42, 0x41, 0x43, 0x52, 0x6f, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x12, 0x1b, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, + 0xfa, 0x42, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x3e, 0x0a, + 0x08, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, + 0x18, 0x2e, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x2e, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x52, + 0x42, 0x41, 0x43, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x42, 0x08, 0xfa, 0x42, 0x05, 0x92, 0x01, + 0x02, 0x08, 0x01, 0x52, 0x08, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x22, 0x1c, 0x0a, + 0x1a, 0x41, 0x64, 0x64, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x52, 0x42, 0x41, 0x43, 0x52, + 0x6f, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x7b, 0x0a, 0x1c, 0x55, + 0x70, 0x64, 0x61, 0x74, 0x65, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x52, 0x42, 0x41, 0x43, + 0x52, 0x6f, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1b, 0x0a, 0x04, 0x6e, + 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xfa, 0x42, 0x04, 0x72, 0x02, + 0x10, 0x01, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x3e, 0x0a, 0x08, 0x70, 0x6f, 0x6c, 0x69, + 0x63, 0x69, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x6d, 0x6f, 0x64, + 0x65, 0x6c, 0x2e, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x52, 0x42, 0x41, 0x43, 0x50, 0x6f, + 0x6c, 0x69, 0x63, 0x79, 0x42, 0x08, 0xfa, 0x42, 0x05, 0x92, 0x01, 0x02, 0x08, 0x01, 0x52, 0x08, + 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x22, 0x1f, 0x0a, 0x1d, 0x55, 0x70, 0x64, 0x61, + 0x74, 0x65, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x52, 0x42, 0x41, 0x43, 0x52, 0x6f, 0x6c, + 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x3b, 0x0a, 0x1c, 0x44, 0x65, 0x6c, + 0x65, 0x74, 0x65, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x52, 0x42, 0x41, 0x43, 0x52, 0x6f, + 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1b, 0x0a, 0x04, 0x6e, 0x61, 0x6d, + 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xfa, 0x42, 0x04, 0x72, 0x02, 0x10, 0x01, + 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x1f, 0x0a, 0x1d, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x52, 0x42, 0x41, 0x43, 0x52, 0x6f, 0x6c, 0x65, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x7b, 0x0a, 0x1c, 0x55, 0x70, 0x64, 0x61, 0x74, - 0x65, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x52, 0x42, 0x41, 0x43, 0x52, 0x6f, 0x6c, 0x65, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1b, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xfa, 0x42, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x04, - 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x3e, 0x0a, 0x08, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, - 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x2e, 0x50, - 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x52, 0x42, 0x41, 0x43, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, - 0x42, 0x08, 0xfa, 0x42, 0x05, 0x92, 0x01, 0x02, 0x08, 0x01, 0x52, 0x08, 0x70, 0x6f, 0x6c, 0x69, - 0x63, 0x69, 0x65, 0x73, 0x22, 0x1f, 0x0a, 0x1d, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x50, 0x72, - 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x52, 0x42, 0x41, 0x43, 0x52, 0x6f, 0x6c, 0x65, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x3b, 0x0a, 0x1c, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x50, - 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x52, 0x42, 0x41, 0x43, 0x52, 0x6f, 0x6c, 0x65, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1b, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x42, 0x07, 0xfa, 0x42, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x04, 0x6e, 0x61, - 0x6d, 0x65, 0x22, 0x1f, 0x0a, 0x1d, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x50, 0x72, 0x6f, 0x6a, - 0x65, 0x63, 0x74, 0x52, 0x42, 0x41, 0x43, 0x52, 0x6f, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x22, 0x5f, 0x0a, 0x1a, 0x41, 0x64, 0x64, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, - 0x74, 0x55, 0x73, 0x65, 0x72, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x12, 0x24, 0x0a, 0x09, 0x73, 0x73, 0x6f, 0x5f, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xfa, 0x42, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x08, 0x73, - 0x73, 0x6f, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x12, 0x1b, 0x0a, 0x04, 0x72, 0x6f, 0x6c, 0x65, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xfa, 0x42, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x04, - 0x72, 0x6f, 0x6c, 0x65, 0x22, 0x1d, 0x0a, 0x1b, 0x41, 0x64, 0x64, 0x50, 0x72, 0x6f, 0x6a, 0x65, - 0x63, 0x74, 0x55, 0x73, 0x65, 0x72, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x22, 0x45, 0x0a, 0x1d, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x50, 0x72, 0x6f, - 0x6a, 0x65, 0x63, 0x74, 0x55, 0x73, 0x65, 0x72, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x12, 0x24, 0x0a, 0x09, 0x73, 0x73, 0x6f, 0x5f, 0x67, 0x72, 0x6f, 0x75, - 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xfa, 0x42, 0x04, 0x72, 0x02, 0x10, 0x01, - 0x52, 0x08, 0x73, 0x73, 0x6f, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x22, 0x20, 0x0a, 0x1e, 0x44, 0x65, - 0x6c, 0x65, 0x74, 0x65, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x55, 0x73, 0x65, 0x72, 0x47, - 0x72, 0x6f, 0x75, 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x3b, 0x0a, 0x11, - 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x12, 0x26, 0x0a, 0x0a, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x5f, 0x69, 0x64, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xfa, 0x42, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x09, - 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x49, 0x64, 0x22, 0x3e, 0x0a, 0x12, 0x47, 0x65, 0x74, - 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x28, 0x0a, 0x07, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x0e, 0x2e, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, - 0x52, 0x07, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x22, 0x66, 0x0a, 0x15, 0x47, 0x65, 0x6e, - 0x65, 0x72, 0x61, 0x74, 0x65, 0x41, 0x50, 0x49, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x12, 0x1b, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x42, 0x07, 0xfa, 0x42, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, - 0x30, 0x0a, 0x04, 0x72, 0x6f, 0x6c, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x12, 0x2e, - 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x2e, 0x41, 0x50, 0x49, 0x4b, 0x65, 0x79, 0x2e, 0x52, 0x6f, 0x6c, - 0x65, 0x42, 0x08, 0xfa, 0x42, 0x05, 0x82, 0x01, 0x02, 0x10, 0x01, 0x52, 0x04, 0x72, 0x6f, 0x6c, - 0x65, 0x22, 0x2a, 0x0a, 0x16, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x41, 0x50, 0x49, - 0x4b, 0x65, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x6b, - 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x22, 0x2f, 0x0a, - 0x14, 0x44, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x41, 0x50, 0x49, 0x4b, 0x65, 0x79, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x17, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x09, 0x42, 0x07, 0xfa, 0x42, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x02, 0x69, 0x64, 0x22, 0x17, - 0x0a, 0x15, 0x44, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x41, 0x50, 0x49, 0x4b, 0x65, 0x79, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0xa4, 0x01, 0x0a, 0x12, 0x4c, 0x69, 0x73, 0x74, - 0x41, 0x50, 0x49, 0x4b, 0x65, 0x79, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x4d, - 0x0a, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x33, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x77, - 0x65, 0x62, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x50, - 0x49, 0x4b, 0x65, 0x79, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x4f, 0x70, 0x74, - 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x1a, 0x3f, 0x0a, - 0x07, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x34, 0x0a, 0x07, 0x65, 0x6e, 0x61, 0x62, - 0x6c, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, - 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x42, 0x6f, 0x6f, 0x6c, - 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x22, 0x38, - 0x0a, 0x13, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x50, 0x49, 0x4b, 0x65, 0x79, 0x73, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x21, 0x0a, 0x04, 0x6b, 0x65, 0x79, 0x73, 0x18, 0x01, 0x20, - 0x03, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x2e, 0x41, 0x50, 0x49, 0x4b, - 0x65, 0x79, 0x52, 0x04, 0x6b, 0x65, 0x79, 0x73, 0x22, 0xa5, 0x03, 0x0a, 0x15, 0x47, 0x65, 0x74, - 0x49, 0x6e, 0x73, 0x69, 0x67, 0x68, 0x74, 0x44, 0x61, 0x74, 0x61, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x12, 0x46, 0x0a, 0x0c, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x5f, 0x6b, 0x69, - 0x6e, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x19, 0x2e, 0x6d, 0x6f, 0x64, 0x65, 0x6c, - 0x2e, 0x49, 0x6e, 0x73, 0x69, 0x67, 0x68, 0x74, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x4b, - 0x69, 0x6e, 0x64, 0x42, 0x08, 0xfa, 0x42, 0x05, 0x82, 0x01, 0x02, 0x10, 0x01, 0x52, 0x0b, 0x6d, - 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x4b, 0x69, 0x6e, 0x64, 0x12, 0x26, 0x0a, 0x0a, 0x72, 0x61, - 0x6e, 0x67, 0x65, 0x5f, 0x66, 0x72, 0x6f, 0x6d, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x42, 0x07, - 0xfa, 0x42, 0x04, 0x22, 0x02, 0x20, 0x00, 0x52, 0x09, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x46, 0x72, - 0x6f, 0x6d, 0x12, 0x22, 0x0a, 0x08, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x5f, 0x74, 0x6f, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x03, 0x42, 0x07, 0xfa, 0x42, 0x04, 0x22, 0x02, 0x20, 0x00, 0x52, 0x07, 0x72, - 0x61, 0x6e, 0x67, 0x65, 0x54, 0x6f, 0x12, 0x42, 0x0a, 0x0a, 0x72, 0x65, 0x73, 0x6f, 0x6c, 0x75, - 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x18, 0x2e, 0x6d, 0x6f, 0x64, - 0x65, 0x6c, 0x2e, 0x49, 0x6e, 0x73, 0x69, 0x67, 0x68, 0x74, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x75, - 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x08, 0xfa, 0x42, 0x05, 0x82, 0x01, 0x02, 0x10, 0x01, 0x52, 0x0a, - 0x72, 0x65, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x25, 0x0a, 0x0e, 0x61, 0x70, - 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x0a, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x0d, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, - 0x64, 0x12, 0x52, 0x0a, 0x06, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x18, 0x0b, 0x20, 0x03, 0x28, - 0x0b, 0x32, 0x3a, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, - 0x2e, 0x77, 0x65, 0x62, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x47, 0x65, 0x74, 0x49, - 0x6e, 0x73, 0x69, 0x67, 0x68, 0x74, 0x44, 0x61, 0x74, 0x61, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x2e, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x06, 0x6c, - 0x61, 0x62, 0x65, 0x6c, 0x73, 0x1a, 0x39, 0x0a, 0x0b, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x45, - 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, - 0x22, 0xc7, 0x01, 0x0a, 0x16, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x73, 0x69, 0x67, 0x68, 0x74, 0x44, - 0x61, 0x74, 0x61, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x75, - 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, - 0x09, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, 0x2c, 0x0a, 0x04, 0x74, 0x79, - 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x18, 0x2e, 0x6d, 0x6f, 0x64, 0x65, 0x6c, - 0x2e, 0x49, 0x6e, 0x73, 0x69, 0x67, 0x68, 0x74, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x54, 0x79, - 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x2c, 0x0a, 0x06, 0x76, 0x65, 0x63, 0x74, - 0x6f, 0x72, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x6d, 0x6f, 0x64, 0x65, 0x6c, - 0x2e, 0x49, 0x6e, 0x73, 0x69, 0x67, 0x68, 0x74, 0x53, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x52, 0x06, - 0x76, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x12, 0x32, 0x0a, 0x06, 0x6d, 0x61, 0x74, 0x72, 0x69, 0x78, - 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x2e, 0x49, - 0x6e, 0x73, 0x69, 0x67, 0x68, 0x74, 0x53, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x53, 0x74, 0x72, 0x65, - 0x61, 0x6d, 0x52, 0x06, 0x6d, 0x61, 0x74, 0x72, 0x69, 0x78, 0x22, 0x23, 0x0a, 0x21, 0x47, 0x65, - 0x74, 0x49, 0x6e, 0x73, 0x69, 0x67, 0x68, 0x74, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, - 0x7b, 0x0a, 0x22, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x73, 0x69, 0x67, 0x68, 0x74, 0x41, 0x70, 0x70, - 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, - 0x5f, 0x61, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x75, 0x70, 0x64, 0x61, 0x74, - 0x65, 0x64, 0x41, 0x74, 0x12, 0x36, 0x0a, 0x06, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x18, 0x02, - 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x2e, 0x49, 0x6e, 0x73, - 0x69, 0x67, 0x68, 0x74, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x43, - 0x6f, 0x75, 0x6e, 0x74, 0x52, 0x06, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x22, 0xe4, 0x01, 0x0a, - 0x1b, 0x4c, 0x69, 0x73, 0x74, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x43, - 0x68, 0x61, 0x69, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x56, 0x0a, 0x07, - 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3c, 0x2e, - 0x67, 0x72, 0x70, 0x63, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x77, 0x65, 0x62, - 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x44, 0x65, 0x70, 0x6c, - 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x2e, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x07, 0x6f, 0x70, 0x74, - 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x1b, 0x0a, 0x09, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x73, 0x69, 0x7a, - 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x70, 0x61, 0x67, 0x65, 0x53, 0x69, 0x7a, - 0x65, 0x12, 0x16, 0x0a, 0x06, 0x63, 0x75, 0x72, 0x73, 0x6f, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x06, 0x63, 0x75, 0x72, 0x73, 0x6f, 0x72, 0x12, 0x2d, 0x0a, 0x13, 0x70, 0x61, 0x67, - 0x65, 0x5f, 0x6d, 0x69, 0x6e, 0x5f, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, - 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x10, 0x70, 0x61, 0x67, 0x65, 0x4d, 0x69, 0x6e, 0x55, - 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x1a, 0x09, 0x0a, 0x07, 0x4f, 0x70, 0x74, 0x69, - 0x6f, 0x6e, 0x73, 0x22, 0x7b, 0x0a, 0x1c, 0x4c, 0x69, 0x73, 0x74, 0x44, 0x65, 0x70, 0x6c, 0x6f, - 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x12, 0x43, 0x0a, 0x11, 0x64, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, - 0x74, 0x5f, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x16, - 0x2e, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x2e, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, - 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x52, 0x10, 0x64, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, - 0x6e, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x63, 0x75, 0x72, 0x73, - 0x6f, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x63, 0x75, 0x72, 0x73, 0x6f, 0x72, - 0x22, 0x54, 0x0a, 0x19, 0x47, 0x65, 0x74, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, - 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x37, 0x0a, - 0x13, 0x64, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x63, 0x68, 0x61, 0x69, - 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xfa, 0x42, 0x04, 0x72, - 0x02, 0x10, 0x01, 0x52, 0x11, 0x64, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x43, - 0x68, 0x61, 0x69, 0x6e, 0x49, 0x64, 0x22, 0x5f, 0x0a, 0x1a, 0x47, 0x65, 0x74, 0x44, 0x65, 0x70, - 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x41, 0x0a, 0x10, 0x64, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, - 0x6e, 0x74, 0x5f, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, - 0x2e, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x2e, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, - 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x52, 0x0f, 0x64, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, - 0x6e, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x22, 0xa8, 0x03, 0x0a, 0x11, 0x4c, 0x69, 0x73, 0x74, - 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x4c, 0x0a, - 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x32, - 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x77, 0x65, - 0x62, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x45, 0x76, 0x65, - 0x6e, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x4f, 0x70, 0x74, 0x69, 0x6f, - 0x6e, 0x73, 0x52, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x1b, 0x0a, 0x09, 0x70, - 0x61, 0x67, 0x65, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, - 0x70, 0x61, 0x67, 0x65, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x63, 0x75, 0x72, 0x73, - 0x6f, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x63, 0x75, 0x72, 0x73, 0x6f, 0x72, - 0x12, 0x2d, 0x0a, 0x13, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x6d, 0x69, 0x6e, 0x5f, 0x75, 0x70, 0x64, - 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x10, 0x70, - 0x61, 0x67, 0x65, 0x4d, 0x69, 0x6e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x1a, - 0xe0, 0x01, 0x0a, 0x07, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x6e, - 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, - 0x2e, 0x0a, 0x08, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, - 0x0e, 0x32, 0x12, 0x2e, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x2e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x53, - 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x08, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x65, 0x73, 0x12, - 0x56, 0x0a, 0x06, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, - 0x3e, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x77, - 0x65, 0x62, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x45, 0x76, - 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x4f, 0x70, 0x74, 0x69, - 0x6f, 0x6e, 0x73, 0x2e, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, - 0x06, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x1a, 0x39, 0x0a, 0x0b, 0x4c, 0x61, 0x62, 0x65, 0x6c, - 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, - 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, - 0x38, 0x01, 0x22, 0x52, 0x0a, 0x12, 0x4c, 0x69, 0x73, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x24, 0x0a, 0x06, 0x65, 0x76, 0x65, 0x6e, - 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x6d, 0x6f, 0x64, 0x65, 0x6c, - 0x2e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x52, 0x06, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x16, - 0x0a, 0x06, 0x63, 0x75, 0x72, 0x73, 0x6f, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, - 0x63, 0x75, 0x72, 0x73, 0x6f, 0x72, 0x32, 0xaf, 0x36, 0x0a, 0x0a, 0x57, 0x65, 0x62, 0x53, 0x65, - 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x7c, 0x0a, 0x0d, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, - 0x72, 0x50, 0x69, 0x70, 0x65, 0x64, 0x12, 0x2d, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x73, 0x65, - 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x77, 0x65, 0x62, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, - 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x50, 0x69, 0x70, 0x65, 0x64, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2e, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x73, 0x65, 0x72, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x5f, 0x0a, 0x1a, 0x41, 0x64, 0x64, 0x50, 0x72, + 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x55, 0x73, 0x65, 0x72, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x24, 0x0a, 0x09, 0x73, 0x73, 0x6f, 0x5f, 0x67, 0x72, 0x6f, + 0x75, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xfa, 0x42, 0x04, 0x72, 0x02, 0x10, + 0x01, 0x52, 0x08, 0x73, 0x73, 0x6f, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x12, 0x1b, 0x0a, 0x04, 0x72, + 0x6f, 0x6c, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xfa, 0x42, 0x04, 0x72, 0x02, + 0x10, 0x01, 0x52, 0x04, 0x72, 0x6f, 0x6c, 0x65, 0x22, 0x1d, 0x0a, 0x1b, 0x41, 0x64, 0x64, 0x50, + 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x55, 0x73, 0x65, 0x72, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x45, 0x0a, 0x1d, 0x44, 0x65, 0x6c, 0x65, 0x74, + 0x65, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x55, 0x73, 0x65, 0x72, 0x47, 0x72, 0x6f, 0x75, + 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x24, 0x0a, 0x09, 0x73, 0x73, 0x6f, 0x5f, + 0x67, 0x72, 0x6f, 0x75, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xfa, 0x42, 0x04, + 0x72, 0x02, 0x10, 0x01, 0x52, 0x08, 0x73, 0x73, 0x6f, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x22, 0x20, + 0x0a, 0x1e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x55, + 0x73, 0x65, 0x72, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x22, 0x3b, 0x0a, 0x11, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x26, 0x0a, 0x0a, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, + 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xfa, 0x42, 0x04, 0x72, 0x02, + 0x10, 0x01, 0x52, 0x09, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x49, 0x64, 0x22, 0x3e, 0x0a, + 0x12, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x28, 0x0a, 0x07, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x2e, 0x43, 0x6f, 0x6d, + 0x6d, 0x61, 0x6e, 0x64, 0x52, 0x07, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x22, 0x66, 0x0a, + 0x15, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x41, 0x50, 0x49, 0x4b, 0x65, 0x79, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1b, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xfa, 0x42, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x04, 0x6e, + 0x61, 0x6d, 0x65, 0x12, 0x30, 0x0a, 0x04, 0x72, 0x6f, 0x6c, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x0e, 0x32, 0x12, 0x2e, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x2e, 0x41, 0x50, 0x49, 0x4b, 0x65, 0x79, + 0x2e, 0x52, 0x6f, 0x6c, 0x65, 0x42, 0x08, 0xfa, 0x42, 0x05, 0x82, 0x01, 0x02, 0x10, 0x01, 0x52, + 0x04, 0x72, 0x6f, 0x6c, 0x65, 0x22, 0x2a, 0x0a, 0x16, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, + 0x65, 0x41, 0x50, 0x49, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, + 0x79, 0x22, 0x2f, 0x0a, 0x14, 0x44, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x41, 0x50, 0x49, 0x4b, + 0x65, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x17, 0x0a, 0x02, 0x69, 0x64, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xfa, 0x42, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x02, + 0x69, 0x64, 0x22, 0x17, 0x0a, 0x15, 0x44, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x41, 0x50, 0x49, + 0x4b, 0x65, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0xa4, 0x01, 0x0a, 0x12, + 0x4c, 0x69, 0x73, 0x74, 0x41, 0x50, 0x49, 0x4b, 0x65, 0x79, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x12, 0x4d, 0x0a, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x33, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, + 0x63, 0x65, 0x2e, 0x77, 0x65, 0x62, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x4c, 0x69, + 0x73, 0x74, 0x41, 0x50, 0x49, 0x4b, 0x65, 0x79, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x2e, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, + 0x73, 0x1a, 0x3f, 0x0a, 0x07, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x34, 0x0a, 0x07, + 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, + 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, + 0x42, 0x6f, 0x6f, 0x6c, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, + 0x65, 0x64, 0x22, 0x38, 0x0a, 0x13, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x50, 0x49, 0x4b, 0x65, 0x79, + 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x21, 0x0a, 0x04, 0x6b, 0x65, 0x79, + 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x2e, + 0x41, 0x50, 0x49, 0x4b, 0x65, 0x79, 0x52, 0x04, 0x6b, 0x65, 0x79, 0x73, 0x22, 0xa5, 0x03, 0x0a, + 0x15, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x73, 0x69, 0x67, 0x68, 0x74, 0x44, 0x61, 0x74, 0x61, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x46, 0x0a, 0x0c, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, + 0x73, 0x5f, 0x6b, 0x69, 0x6e, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x19, 0x2e, 0x6d, + 0x6f, 0x64, 0x65, 0x6c, 0x2e, 0x49, 0x6e, 0x73, 0x69, 0x67, 0x68, 0x74, 0x4d, 0x65, 0x74, 0x72, + 0x69, 0x63, 0x73, 0x4b, 0x69, 0x6e, 0x64, 0x42, 0x08, 0xfa, 0x42, 0x05, 0x82, 0x01, 0x02, 0x10, + 0x01, 0x52, 0x0b, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x4b, 0x69, 0x6e, 0x64, 0x12, 0x26, + 0x0a, 0x0a, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x5f, 0x66, 0x72, 0x6f, 0x6d, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x03, 0x42, 0x07, 0xfa, 0x42, 0x04, 0x22, 0x02, 0x20, 0x00, 0x52, 0x09, 0x72, 0x61, 0x6e, + 0x67, 0x65, 0x46, 0x72, 0x6f, 0x6d, 0x12, 0x22, 0x0a, 0x08, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x5f, + 0x74, 0x6f, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x42, 0x07, 0xfa, 0x42, 0x04, 0x22, 0x02, 0x20, + 0x00, 0x52, 0x07, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x54, 0x6f, 0x12, 0x42, 0x0a, 0x0a, 0x72, 0x65, + 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x18, + 0x2e, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x2e, 0x49, 0x6e, 0x73, 0x69, 0x67, 0x68, 0x74, 0x52, 0x65, + 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x08, 0xfa, 0x42, 0x05, 0x82, 0x01, 0x02, + 0x10, 0x01, 0x52, 0x0a, 0x72, 0x65, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x25, + 0x0a, 0x0e, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, + 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x52, 0x0a, 0x06, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x18, + 0x0b, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x3a, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x77, 0x65, 0x62, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, - 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x50, 0x69, 0x70, 0x65, 0x64, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x0c, 0x9a, 0xed, 0x1c, 0x02, 0x08, 0x04, 0x9a, 0xed, 0x1c, - 0x02, 0x10, 0x03, 0x12, 0x76, 0x0a, 0x0b, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x50, 0x69, 0x70, - 0x65, 0x64, 0x12, 0x2b, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, - 0x65, 0x2e, 0x77, 0x65, 0x62, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x55, 0x70, 0x64, - 0x61, 0x74, 0x65, 0x50, 0x69, 0x70, 0x65, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x2c, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x77, - 0x65, 0x62, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, - 0x50, 0x69, 0x70, 0x65, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x0c, 0x9a, - 0xed, 0x1c, 0x02, 0x08, 0x04, 0x9a, 0xed, 0x1c, 0x02, 0x10, 0x04, 0x12, 0x85, 0x01, 0x0a, 0x10, - 0x52, 0x65, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x50, 0x69, 0x70, 0x65, 0x64, 0x4b, 0x65, 0x79, - 0x12, 0x30, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, - 0x77, 0x65, 0x62, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x52, 0x65, 0x63, 0x72, 0x65, - 0x61, 0x74, 0x65, 0x50, 0x69, 0x70, 0x65, 0x64, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x31, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, - 0x65, 0x2e, 0x77, 0x65, 0x62, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x52, 0x65, 0x63, - 0x72, 0x65, 0x61, 0x74, 0x65, 0x50, 0x69, 0x70, 0x65, 0x64, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x0c, 0x9a, 0xed, 0x1c, 0x02, 0x08, 0x04, 0x9a, 0xed, 0x1c, - 0x02, 0x10, 0x04, 0x12, 0x8b, 0x01, 0x0a, 0x12, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4f, 0x6c, - 0x64, 0x50, 0x69, 0x70, 0x65, 0x64, 0x4b, 0x65, 0x79, 0x73, 0x12, 0x32, 0x2e, 0x67, 0x72, 0x70, + 0x47, 0x65, 0x74, 0x49, 0x6e, 0x73, 0x69, 0x67, 0x68, 0x74, 0x44, 0x61, 0x74, 0x61, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x45, 0x6e, 0x74, 0x72, + 0x79, 0x52, 0x06, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x1a, 0x39, 0x0a, 0x0b, 0x4c, 0x61, 0x62, + 0x65, 0x6c, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, + 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, + 0x3a, 0x02, 0x38, 0x01, 0x22, 0xc7, 0x01, 0x0a, 0x16, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x73, 0x69, + 0x67, 0x68, 0x74, 0x44, 0x61, 0x74, 0x61, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x1d, 0x0a, 0x0a, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x03, 0x52, 0x09, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, 0x2c, + 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x18, 0x2e, 0x6d, + 0x6f, 0x64, 0x65, 0x6c, 0x2e, 0x49, 0x6e, 0x73, 0x69, 0x67, 0x68, 0x74, 0x52, 0x65, 0x73, 0x75, + 0x6c, 0x74, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x2c, 0x0a, 0x06, + 0x76, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x6d, + 0x6f, 0x64, 0x65, 0x6c, 0x2e, 0x49, 0x6e, 0x73, 0x69, 0x67, 0x68, 0x74, 0x53, 0x61, 0x6d, 0x70, + 0x6c, 0x65, 0x52, 0x06, 0x76, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x12, 0x32, 0x0a, 0x06, 0x6d, 0x61, + 0x74, 0x72, 0x69, 0x78, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x6d, 0x6f, 0x64, + 0x65, 0x6c, 0x2e, 0x49, 0x6e, 0x73, 0x69, 0x67, 0x68, 0x74, 0x53, 0x61, 0x6d, 0x70, 0x6c, 0x65, + 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x52, 0x06, 0x6d, 0x61, 0x74, 0x72, 0x69, 0x78, 0x22, 0x23, + 0x0a, 0x21, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x73, 0x69, 0x67, 0x68, 0x74, 0x41, 0x70, 0x70, 0x6c, + 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x22, 0x7b, 0x0a, 0x22, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x73, 0x69, 0x67, 0x68, + 0x74, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x75, 0x6e, + 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x75, 0x70, 0x64, + 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x75, + 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, 0x36, 0x0a, 0x06, 0x63, 0x6f, 0x75, 0x6e, + 0x74, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x6d, 0x6f, 0x64, 0x65, 0x6c, + 0x2e, 0x49, 0x6e, 0x73, 0x69, 0x67, 0x68, 0x74, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x52, 0x06, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x73, + 0x22, 0xe4, 0x01, 0x0a, 0x1b, 0x4c, 0x69, 0x73, 0x74, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, + 0x65, 0x6e, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x12, 0x56, 0x0a, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x3c, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, + 0x2e, 0x77, 0x65, 0x62, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x4c, 0x69, 0x73, 0x74, + 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x73, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, + 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x1b, 0x0a, 0x09, 0x70, 0x61, 0x67, 0x65, + 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x70, 0x61, 0x67, + 0x65, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x63, 0x75, 0x72, 0x73, 0x6f, 0x72, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x63, 0x75, 0x72, 0x73, 0x6f, 0x72, 0x12, 0x2d, 0x0a, + 0x13, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x6d, 0x69, 0x6e, 0x5f, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, + 0x64, 0x5f, 0x61, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x10, 0x70, 0x61, 0x67, 0x65, + 0x4d, 0x69, 0x6e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x1a, 0x09, 0x0a, 0x07, + 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0x7b, 0x0a, 0x1c, 0x4c, 0x69, 0x73, 0x74, 0x44, + 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x73, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x43, 0x0a, 0x11, 0x64, 0x65, 0x70, 0x6c, 0x6f, + 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x03, + 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x2e, 0x44, 0x65, 0x70, 0x6c, 0x6f, + 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x52, 0x10, 0x64, 0x65, 0x70, 0x6c, + 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x73, 0x12, 0x16, 0x0a, 0x06, + 0x63, 0x75, 0x72, 0x73, 0x6f, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x63, 0x75, + 0x72, 0x73, 0x6f, 0x72, 0x22, 0x54, 0x0a, 0x19, 0x47, 0x65, 0x74, 0x44, 0x65, 0x70, 0x6c, 0x6f, + 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x12, 0x37, 0x0a, 0x13, 0x64, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x5f, + 0x63, 0x68, 0x61, 0x69, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, + 0xfa, 0x42, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x11, 0x64, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, + 0x65, 0x6e, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x49, 0x64, 0x22, 0x5f, 0x0a, 0x1a, 0x47, 0x65, + 0x74, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x41, 0x0a, 0x10, 0x64, 0x65, 0x70, 0x6c, + 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x2e, 0x44, 0x65, 0x70, 0x6c, 0x6f, + 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x52, 0x0f, 0x64, 0x65, 0x70, 0x6c, + 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x22, 0xa8, 0x03, 0x0a, 0x11, + 0x4c, 0x69, 0x73, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x12, 0x4c, 0x0a, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x32, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, + 0x65, 0x2e, 0x77, 0x65, 0x62, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x4c, 0x69, 0x73, + 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x4f, + 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, + 0x1b, 0x0a, 0x09, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x05, 0x52, 0x08, 0x70, 0x61, 0x67, 0x65, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x16, 0x0a, 0x06, + 0x63, 0x75, 0x72, 0x73, 0x6f, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x63, 0x75, + 0x72, 0x73, 0x6f, 0x72, 0x12, 0x2d, 0x0a, 0x13, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x6d, 0x69, 0x6e, + 0x5f, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, + 0x03, 0x52, 0x10, 0x70, 0x61, 0x67, 0x65, 0x4d, 0x69, 0x6e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, + 0x64, 0x41, 0x74, 0x1a, 0xe0, 0x01, 0x0a, 0x07, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, + 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, + 0x61, 0x6d, 0x65, 0x12, 0x2e, 0x0a, 0x08, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x65, 0x73, 0x18, + 0x02, 0x20, 0x03, 0x28, 0x0e, 0x32, 0x12, 0x2e, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x2e, 0x45, 0x76, + 0x65, 0x6e, 0x74, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x08, 0x73, 0x74, 0x61, 0x74, 0x75, + 0x73, 0x65, 0x73, 0x12, 0x56, 0x0a, 0x06, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x18, 0x03, 0x20, + 0x03, 0x28, 0x0b, 0x32, 0x3e, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, + 0x63, 0x65, 0x2e, 0x77, 0x65, 0x62, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x4c, 0x69, + 0x73, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, + 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x45, 0x6e, + 0x74, 0x72, 0x79, 0x52, 0x06, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x1a, 0x39, 0x0a, 0x0b, 0x4c, + 0x61, 0x62, 0x65, 0x6c, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, + 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, + 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, + 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x52, 0x0a, 0x12, 0x4c, 0x69, 0x73, 0x74, 0x45, 0x76, + 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x24, 0x0a, 0x06, + 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x6d, + 0x6f, 0x64, 0x65, 0x6c, 0x2e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x52, 0x06, 0x65, 0x76, 0x65, 0x6e, + 0x74, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x63, 0x75, 0x72, 0x73, 0x6f, 0x72, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x06, 0x63, 0x75, 0x72, 0x73, 0x6f, 0x72, 0x32, 0xae, 0x38, 0x0a, 0x0a, 0x57, + 0x65, 0x62, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x7c, 0x0a, 0x0d, 0x52, 0x65, 0x67, + 0x69, 0x73, 0x74, 0x65, 0x72, 0x50, 0x69, 0x70, 0x65, 0x64, 0x12, 0x2d, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x77, 0x65, 0x62, 0x73, 0x65, 0x72, - 0x76, 0x69, 0x63, 0x65, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4f, 0x6c, 0x64, 0x50, 0x69, - 0x70, 0x65, 0x64, 0x4b, 0x65, 0x79, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x33, + 0x76, 0x69, 0x63, 0x65, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x50, 0x69, 0x70, + 0x65, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2e, 0x2e, 0x67, 0x72, 0x70, 0x63, + 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x77, 0x65, 0x62, 0x73, 0x65, 0x72, 0x76, + 0x69, 0x63, 0x65, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x50, 0x69, 0x70, 0x65, + 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x0c, 0x9a, 0xed, 0x1c, 0x02, 0x08, + 0x04, 0x9a, 0xed, 0x1c, 0x02, 0x10, 0x03, 0x12, 0x76, 0x0a, 0x0b, 0x55, 0x70, 0x64, 0x61, 0x74, + 0x65, 0x50, 0x69, 0x70, 0x65, 0x64, 0x12, 0x2b, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x73, 0x65, + 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x77, 0x65, 0x62, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, + 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x50, 0x69, 0x70, 0x65, 0x64, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x2c, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, + 0x63, 0x65, 0x2e, 0x77, 0x65, 0x62, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x55, 0x70, + 0x64, 0x61, 0x74, 0x65, 0x50, 0x69, 0x70, 0x65, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x22, 0x0c, 0x9a, 0xed, 0x1c, 0x02, 0x08, 0x04, 0x9a, 0xed, 0x1c, 0x02, 0x10, 0x04, 0x12, + 0x85, 0x01, 0x0a, 0x10, 0x52, 0x65, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x50, 0x69, 0x70, 0x65, + 0x64, 0x4b, 0x65, 0x79, 0x12, 0x30, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x73, 0x65, 0x72, 0x76, + 0x69, 0x63, 0x65, 0x2e, 0x77, 0x65, 0x62, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x52, + 0x65, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x50, 0x69, 0x70, 0x65, 0x64, 0x4b, 0x65, 0x79, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x31, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x73, 0x65, + 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x77, 0x65, 0x62, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, + 0x2e, 0x52, 0x65, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x50, 0x69, 0x70, 0x65, 0x64, 0x4b, 0x65, + 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x0c, 0x9a, 0xed, 0x1c, 0x02, 0x08, + 0x04, 0x9a, 0xed, 0x1c, 0x02, 0x10, 0x04, 0x12, 0x8b, 0x01, 0x0a, 0x12, 0x44, 0x65, 0x6c, 0x65, + 0x74, 0x65, 0x4f, 0x6c, 0x64, 0x50, 0x69, 0x70, 0x65, 0x64, 0x4b, 0x65, 0x79, 0x73, 0x12, 0x32, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x77, 0x65, 0x62, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4f, - 0x6c, 0x64, 0x50, 0x69, 0x70, 0x65, 0x64, 0x4b, 0x65, 0x79, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x22, 0x0c, 0x9a, 0xed, 0x1c, 0x02, 0x08, 0x04, 0x9a, 0xed, 0x1c, 0x02, 0x10, - 0x04, 0x12, 0x76, 0x0a, 0x0b, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x50, 0x69, 0x70, 0x65, 0x64, - 0x12, 0x2b, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, - 0x77, 0x65, 0x62, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x45, 0x6e, 0x61, 0x62, 0x6c, - 0x65, 0x50, 0x69, 0x70, 0x65, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2c, 0x2e, + 0x6c, 0x64, 0x50, 0x69, 0x70, 0x65, 0x64, 0x4b, 0x65, 0x79, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x33, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, + 0x65, 0x2e, 0x77, 0x65, 0x62, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x44, 0x65, 0x6c, + 0x65, 0x74, 0x65, 0x4f, 0x6c, 0x64, 0x50, 0x69, 0x70, 0x65, 0x64, 0x4b, 0x65, 0x79, 0x73, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x0c, 0x9a, 0xed, 0x1c, 0x02, 0x08, 0x04, 0x9a, + 0xed, 0x1c, 0x02, 0x10, 0x04, 0x12, 0x76, 0x0a, 0x0b, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x50, + 0x69, 0x70, 0x65, 0x64, 0x12, 0x2b, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x73, 0x65, 0x72, 0x76, + 0x69, 0x63, 0x65, 0x2e, 0x77, 0x65, 0x62, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x45, + 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x50, 0x69, 0x70, 0x65, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x2c, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, + 0x2e, 0x77, 0x65, 0x62, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x45, 0x6e, 0x61, 0x62, + 0x6c, 0x65, 0x50, 0x69, 0x70, 0x65, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, + 0x0c, 0x9a, 0xed, 0x1c, 0x02, 0x08, 0x04, 0x9a, 0xed, 0x1c, 0x02, 0x10, 0x04, 0x12, 0x79, 0x0a, + 0x0c, 0x44, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x50, 0x69, 0x70, 0x65, 0x64, 0x12, 0x2c, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x77, 0x65, 0x62, - 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x50, 0x69, - 0x70, 0x65, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x0c, 0x9a, 0xed, 0x1c, - 0x02, 0x08, 0x04, 0x9a, 0xed, 0x1c, 0x02, 0x10, 0x04, 0x12, 0x79, 0x0a, 0x0c, 0x44, 0x69, 0x73, - 0x61, 0x62, 0x6c, 0x65, 0x50, 0x69, 0x70, 0x65, 0x64, 0x12, 0x2c, 0x2e, 0x67, 0x72, 0x70, 0x63, - 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x77, 0x65, 0x62, 0x73, 0x65, 0x72, 0x76, - 0x69, 0x63, 0x65, 0x2e, 0x44, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x50, 0x69, 0x70, 0x65, 0x64, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2d, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x73, - 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x77, 0x65, 0x62, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, - 0x65, 0x2e, 0x44, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x50, 0x69, 0x70, 0x65, 0x64, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x0c, 0x9a, 0xed, 0x1c, 0x02, 0x08, 0x04, 0x9a, 0xed, - 0x1c, 0x02, 0x10, 0x04, 0x12, 0x73, 0x0a, 0x0a, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x69, 0x70, 0x65, - 0x64, 0x73, 0x12, 0x2a, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, - 0x65, 0x2e, 0x77, 0x65, 0x62, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x4c, 0x69, 0x73, - 0x74, 0x50, 0x69, 0x70, 0x65, 0x64, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2b, - 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x77, 0x65, - 0x62, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x69, 0x70, - 0x65, 0x64, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x0c, 0x9a, 0xed, 0x1c, - 0x02, 0x08, 0x04, 0x9a, 0xed, 0x1c, 0x02, 0x10, 0x02, 0x12, 0x6d, 0x0a, 0x08, 0x47, 0x65, 0x74, - 0x50, 0x69, 0x70, 0x65, 0x64, 0x12, 0x28, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x73, 0x65, 0x72, - 0x76, 0x69, 0x63, 0x65, 0x2e, 0x77, 0x65, 0x62, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, - 0x47, 0x65, 0x74, 0x50, 0x69, 0x70, 0x65, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x29, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x77, - 0x65, 0x62, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x47, 0x65, 0x74, 0x50, 0x69, 0x70, + 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x44, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x50, + 0x69, 0x70, 0x65, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2d, 0x2e, 0x67, 0x72, + 0x70, 0x63, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x77, 0x65, 0x62, 0x73, 0x65, + 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x44, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x50, 0x69, 0x70, 0x65, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x0c, 0x9a, 0xed, 0x1c, 0x02, - 0x08, 0x04, 0x9a, 0xed, 0x1c, 0x02, 0x10, 0x01, 0x12, 0xa0, 0x01, 0x0a, 0x19, 0x55, 0x70, 0x64, - 0x61, 0x74, 0x65, 0x50, 0x69, 0x70, 0x65, 0x64, 0x44, 0x65, 0x73, 0x69, 0x72, 0x65, 0x64, 0x56, - 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x39, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x73, 0x65, + 0x08, 0x04, 0x9a, 0xed, 0x1c, 0x02, 0x10, 0x04, 0x12, 0x73, 0x0a, 0x0a, 0x4c, 0x69, 0x73, 0x74, + 0x50, 0x69, 0x70, 0x65, 0x64, 0x73, 0x12, 0x2a, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x77, 0x65, 0x62, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, - 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x50, 0x69, 0x70, 0x65, 0x64, 0x44, 0x65, 0x73, 0x69, - 0x72, 0x65, 0x64, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x3a, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, - 0x2e, 0x77, 0x65, 0x62, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x55, 0x70, 0x64, 0x61, - 0x74, 0x65, 0x50, 0x69, 0x70, 0x65, 0x64, 0x44, 0x65, 0x73, 0x69, 0x72, 0x65, 0x64, 0x56, 0x65, - 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x0c, 0x9a, - 0xed, 0x1c, 0x02, 0x08, 0x04, 0x9a, 0xed, 0x1c, 0x02, 0x10, 0x04, 0x12, 0x79, 0x0a, 0x0c, 0x52, - 0x65, 0x73, 0x74, 0x61, 0x72, 0x74, 0x50, 0x69, 0x70, 0x65, 0x64, 0x12, 0x2c, 0x2e, 0x67, 0x72, - 0x70, 0x63, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x77, 0x65, 0x62, 0x73, 0x65, - 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x52, 0x65, 0x73, 0x74, 0x61, 0x72, 0x74, 0x50, 0x69, 0x70, - 0x65, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2d, 0x2e, 0x67, 0x72, 0x70, 0x63, - 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x77, 0x65, 0x62, 0x73, 0x65, 0x72, 0x76, - 0x69, 0x63, 0x65, 0x2e, 0x52, 0x65, 0x73, 0x74, 0x61, 0x72, 0x74, 0x50, 0x69, 0x70, 0x65, 0x64, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x0c, 0x9a, 0xed, 0x1c, 0x02, 0x08, 0x04, - 0x9a, 0xed, 0x1c, 0x02, 0x10, 0x04, 0x12, 0x91, 0x01, 0x0a, 0x14, 0x4c, 0x69, 0x73, 0x74, 0x52, - 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x64, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x12, - 0x34, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x77, - 0x65, 0x62, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, - 0x6c, 0x65, 0x61, 0x73, 0x65, 0x64, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x35, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x73, 0x65, 0x72, - 0x76, 0x69, 0x63, 0x65, 0x2e, 0x77, 0x65, 0x62, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, - 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x64, 0x56, 0x65, 0x72, 0x73, - 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x0c, 0x9a, 0xed, - 0x1c, 0x02, 0x08, 0x04, 0x9a, 0xed, 0x1c, 0x02, 0x10, 0x02, 0x12, 0x8e, 0x01, 0x0a, 0x13, 0x4c, - 0x69, 0x73, 0x74, 0x44, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x4e, 0x6f, 0x74, - 0x65, 0x73, 0x12, 0x33, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, + 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x69, 0x70, 0x65, 0x64, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x2b, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x77, 0x65, 0x62, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x4c, 0x69, 0x73, - 0x74, 0x44, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x4e, 0x6f, 0x74, 0x65, 0x73, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x34, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x73, - 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x77, 0x65, 0x62, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, - 0x65, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x44, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, - 0x4e, 0x6f, 0x74, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x0c, 0x9a, - 0xed, 0x1c, 0x02, 0x08, 0x04, 0x9a, 0xed, 0x1c, 0x02, 0x10, 0x02, 0x12, 0x7f, 0x0a, 0x0e, 0x41, - 0x64, 0x64, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x2e, 0x2e, - 0x67, 0x72, 0x70, 0x63, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x77, 0x65, 0x62, - 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x41, 0x64, 0x64, 0x41, 0x70, 0x70, 0x6c, 0x69, - 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2f, 0x2e, - 0x67, 0x72, 0x70, 0x63, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x77, 0x65, 0x62, - 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x41, 0x64, 0x64, 0x41, 0x70, 0x70, 0x6c, 0x69, - 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x0c, - 0x9a, 0xed, 0x1c, 0x02, 0x08, 0x01, 0x9a, 0xed, 0x1c, 0x02, 0x10, 0x03, 0x12, 0x88, 0x01, 0x0a, - 0x11, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x12, 0x31, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, - 0x65, 0x2e, 0x77, 0x65, 0x62, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x55, 0x70, 0x64, - 0x61, 0x74, 0x65, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x32, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x73, 0x65, 0x72, + 0x74, 0x50, 0x69, 0x70, 0x65, 0x64, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, + 0x0c, 0x9a, 0xed, 0x1c, 0x02, 0x08, 0x04, 0x9a, 0xed, 0x1c, 0x02, 0x10, 0x02, 0x12, 0x6d, 0x0a, + 0x08, 0x47, 0x65, 0x74, 0x50, 0x69, 0x70, 0x65, 0x64, 0x12, 0x28, 0x2e, 0x67, 0x72, 0x70, 0x63, + 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x77, 0x65, 0x62, 0x73, 0x65, 0x72, 0x76, + 0x69, 0x63, 0x65, 0x2e, 0x47, 0x65, 0x74, 0x50, 0x69, 0x70, 0x65, 0x64, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x29, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, + 0x63, 0x65, 0x2e, 0x77, 0x65, 0x62, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x47, 0x65, + 0x74, 0x50, 0x69, 0x70, 0x65, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x0c, + 0x9a, 0xed, 0x1c, 0x02, 0x08, 0x04, 0x9a, 0xed, 0x1c, 0x02, 0x10, 0x01, 0x12, 0xa0, 0x01, 0x0a, + 0x19, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x50, 0x69, 0x70, 0x65, 0x64, 0x44, 0x65, 0x73, 0x69, + 0x72, 0x65, 0x64, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x39, 0x2e, 0x67, 0x72, 0x70, + 0x63, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x77, 0x65, 0x62, 0x73, 0x65, 0x72, + 0x76, 0x69, 0x63, 0x65, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x50, 0x69, 0x70, 0x65, 0x64, + 0x44, 0x65, 0x73, 0x69, 0x72, 0x65, 0x64, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x3a, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x77, 0x65, 0x62, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, - 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x0c, 0x9a, 0xed, 0x1c, 0x02, 0x08, - 0x01, 0x9a, 0xed, 0x1c, 0x02, 0x10, 0x04, 0x12, 0x88, 0x01, 0x0a, 0x11, 0x45, 0x6e, 0x61, 0x62, - 0x6c, 0x65, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x31, 0x2e, + 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x50, 0x69, 0x70, 0x65, 0x64, 0x44, 0x65, 0x73, 0x69, 0x72, + 0x65, 0x64, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x22, 0x0c, 0x9a, 0xed, 0x1c, 0x02, 0x08, 0x04, 0x9a, 0xed, 0x1c, 0x02, 0x10, 0x04, 0x12, + 0x79, 0x0a, 0x0c, 0x52, 0x65, 0x73, 0x74, 0x61, 0x72, 0x74, 0x50, 0x69, 0x70, 0x65, 0x64, 0x12, + 0x2c, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x77, + 0x65, 0x62, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x52, 0x65, 0x73, 0x74, 0x61, 0x72, + 0x74, 0x50, 0x69, 0x70, 0x65, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2d, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x77, 0x65, 0x62, - 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x41, 0x70, - 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x32, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, - 0x77, 0x65, 0x62, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x45, 0x6e, 0x61, 0x62, 0x6c, - 0x65, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x0c, 0x9a, 0xed, 0x1c, 0x02, 0x08, 0x01, 0x9a, 0xed, 0x1c, 0x02, - 0x10, 0x04, 0x12, 0x8b, 0x01, 0x0a, 0x12, 0x44, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x41, 0x70, - 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x32, 0x2e, 0x67, 0x72, 0x70, 0x63, + 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x52, 0x65, 0x73, 0x74, 0x61, 0x72, 0x74, 0x50, + 0x69, 0x70, 0x65, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x0c, 0x9a, 0xed, + 0x1c, 0x02, 0x08, 0x04, 0x9a, 0xed, 0x1c, 0x02, 0x10, 0x04, 0x12, 0x91, 0x01, 0x0a, 0x14, 0x4c, + 0x69, 0x73, 0x74, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x64, 0x56, 0x65, 0x72, 0x73, 0x69, + 0x6f, 0x6e, 0x73, 0x12, 0x34, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, + 0x63, 0x65, 0x2e, 0x77, 0x65, 0x62, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x4c, 0x69, + 0x73, 0x74, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x64, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, + 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x35, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x77, 0x65, 0x62, 0x73, 0x65, 0x72, 0x76, - 0x69, 0x63, 0x65, 0x2e, 0x44, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x41, 0x70, 0x70, 0x6c, 0x69, - 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x33, 0x2e, - 0x67, 0x72, 0x70, 0x63, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x77, 0x65, 0x62, - 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x44, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x41, + 0x69, 0x63, 0x65, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x64, + 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x22, 0x0c, 0x9a, 0xed, 0x1c, 0x02, 0x08, 0x04, 0x9a, 0xed, 0x1c, 0x02, 0x10, 0x02, 0x12, 0x8e, + 0x01, 0x0a, 0x13, 0x4c, 0x69, 0x73, 0x74, 0x44, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, + 0x64, 0x4e, 0x6f, 0x74, 0x65, 0x73, 0x12, 0x33, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x73, 0x65, + 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x77, 0x65, 0x62, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, + 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x44, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x4e, + 0x6f, 0x74, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x34, 0x2e, 0x67, 0x72, + 0x70, 0x63, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x77, 0x65, 0x62, 0x73, 0x65, + 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x44, 0x65, 0x70, 0x72, 0x65, 0x63, + 0x61, 0x74, 0x65, 0x64, 0x4e, 0x6f, 0x74, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x22, 0x0c, 0x9a, 0xed, 0x1c, 0x02, 0x08, 0x04, 0x9a, 0xed, 0x1c, 0x02, 0x10, 0x02, 0x12, + 0x7f, 0x0a, 0x0e, 0x41, 0x64, 0x64, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x12, 0x2e, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, + 0x2e, 0x77, 0x65, 0x62, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x41, 0x64, 0x64, 0x41, + 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x2f, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, + 0x2e, 0x77, 0x65, 0x62, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x41, 0x64, 0x64, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x22, 0x0c, 0x9a, 0xed, 0x1c, 0x02, 0x08, 0x01, 0x9a, 0xed, 0x1c, 0x02, 0x10, 0x04, - 0x12, 0x88, 0x01, 0x0a, 0x11, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x41, 0x70, 0x70, 0x6c, 0x69, + 0x73, 0x65, 0x22, 0x0c, 0x9a, 0xed, 0x1c, 0x02, 0x08, 0x01, 0x9a, 0xed, 0x1c, 0x02, 0x10, 0x03, + 0x12, 0x88, 0x01, 0x0a, 0x11, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x31, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x77, 0x65, 0x62, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, - 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, + 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x32, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x77, 0x65, 0x62, 0x73, 0x65, 0x72, 0x76, - 0x69, 0x63, 0x65, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, + 0x69, 0x63, 0x65, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x0c, 0x9a, - 0xed, 0x1c, 0x02, 0x08, 0x01, 0x9a, 0xed, 0x1c, 0x02, 0x10, 0x05, 0x12, 0x85, 0x01, 0x0a, 0x10, - 0x4c, 0x69, 0x73, 0x74, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, - 0x12, 0x30, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, - 0x77, 0x65, 0x62, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x41, - 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x31, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, - 0x65, 0x2e, 0x77, 0x65, 0x62, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x4c, 0x69, 0x73, - 0x74, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x0c, 0x9a, 0xed, 0x1c, 0x02, 0x08, 0x01, 0x9a, 0xed, 0x1c, - 0x02, 0x10, 0x02, 0x12, 0x82, 0x01, 0x0a, 0x0f, 0x53, 0x79, 0x6e, 0x63, 0x41, 0x70, 0x70, 0x6c, - 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x2f, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x73, - 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x77, 0x65, 0x62, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, - 0x65, 0x2e, 0x53, 0x79, 0x6e, 0x63, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x30, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, - 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x77, 0x65, 0x62, 0x73, 0x65, 0x72, 0x76, 0x69, - 0x63, 0x65, 0x2e, 0x53, 0x79, 0x6e, 0x63, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x0c, 0x9a, 0xed, 0x1c, 0x02, - 0x08, 0x01, 0x9a, 0xed, 0x1c, 0x02, 0x10, 0x04, 0x12, 0x7f, 0x0a, 0x0e, 0x47, 0x65, 0x74, 0x41, - 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x2e, 0x2e, 0x67, 0x72, 0x70, - 0x63, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x77, 0x65, 0x62, 0x73, 0x65, 0x72, - 0x76, 0x69, 0x63, 0x65, 0x2e, 0x47, 0x65, 0x74, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2f, 0x2e, 0x67, 0x72, 0x70, + 0xed, 0x1c, 0x02, 0x08, 0x01, 0x9a, 0xed, 0x1c, 0x02, 0x10, 0x04, 0x12, 0x88, 0x01, 0x0a, 0x11, + 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x12, 0x31, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, + 0x2e, 0x77, 0x65, 0x62, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x45, 0x6e, 0x61, 0x62, + 0x6c, 0x65, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x32, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x73, 0x65, 0x72, 0x76, + 0x69, 0x63, 0x65, 0x2e, 0x77, 0x65, 0x62, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x45, + 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x0c, 0x9a, 0xed, 0x1c, 0x02, 0x08, 0x01, + 0x9a, 0xed, 0x1c, 0x02, 0x10, 0x04, 0x12, 0x8b, 0x01, 0x0a, 0x12, 0x44, 0x69, 0x73, 0x61, 0x62, + 0x6c, 0x65, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x32, 0x2e, + 0x67, 0x72, 0x70, 0x63, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x77, 0x65, 0x62, + 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x44, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x41, + 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x33, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, + 0x2e, 0x77, 0x65, 0x62, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x44, 0x69, 0x73, 0x61, + 0x62, 0x6c, 0x65, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x0c, 0x9a, 0xed, 0x1c, 0x02, 0x08, 0x01, 0x9a, 0xed, + 0x1c, 0x02, 0x10, 0x04, 0x12, 0x88, 0x01, 0x0a, 0x11, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x41, + 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x31, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x77, 0x65, 0x62, 0x73, 0x65, 0x72, - 0x76, 0x69, 0x63, 0x65, 0x2e, 0x47, 0x65, 0x74, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x0c, 0x9a, 0xed, 0x1c, - 0x02, 0x08, 0x01, 0x9a, 0xed, 0x1c, 0x02, 0x10, 0x01, 0x12, 0xb2, 0x01, 0x0a, 0x1f, 0x47, 0x65, - 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x53, 0x65, 0x61, 0x6c, 0x65, 0x64, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x12, 0x3f, 0x2e, + 0x76, 0x69, 0x63, 0x65, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x41, 0x70, 0x70, 0x6c, 0x69, + 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x32, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x77, 0x65, 0x62, - 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, - 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x61, 0x6c, 0x65, - 0x64, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x40, + 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x41, 0x70, + 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x22, 0x0c, 0x9a, 0xed, 0x1c, 0x02, 0x08, 0x01, 0x9a, 0xed, 0x1c, 0x02, 0x10, 0x05, 0x12, + 0x85, 0x01, 0x0a, 0x10, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x30, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x73, 0x65, 0x72, 0x76, + 0x69, 0x63, 0x65, 0x2e, 0x77, 0x65, 0x62, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x4c, + 0x69, 0x73, 0x74, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x31, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x73, 0x65, + 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x77, 0x65, 0x62, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, + 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x0c, 0x9a, 0xed, 0x1c, 0x02, 0x08, + 0x01, 0x9a, 0xed, 0x1c, 0x02, 0x10, 0x02, 0x12, 0x82, 0x01, 0x0a, 0x0f, 0x53, 0x79, 0x6e, 0x63, + 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x2f, 0x2e, 0x67, 0x72, + 0x70, 0x63, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x77, 0x65, 0x62, 0x73, 0x65, + 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x53, 0x79, 0x6e, 0x63, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x30, 0x2e, 0x67, + 0x72, 0x70, 0x63, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x77, 0x65, 0x62, 0x73, + 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x53, 0x79, 0x6e, 0x63, 0x41, 0x70, 0x70, 0x6c, 0x69, + 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x0c, + 0x9a, 0xed, 0x1c, 0x02, 0x08, 0x01, 0x9a, 0xed, 0x1c, 0x02, 0x10, 0x04, 0x12, 0x7f, 0x0a, 0x0e, + 0x47, 0x65, 0x74, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x2e, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x77, 0x65, - 0x62, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, - 0x65, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x61, 0x6c, - 0x65, 0x64, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x22, 0x0c, 0x9a, 0xed, 0x1c, 0x02, 0x08, 0x01, 0x9a, 0xed, 0x1c, 0x02, 0x10, 0x04, 0x12, 0xa9, - 0x01, 0x0a, 0x1c, 0x4c, 0x69, 0x73, 0x74, 0x55, 0x6e, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, - 0x72, 0x65, 0x64, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, - 0x3c, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x77, - 0x65, 0x62, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x55, 0x6e, - 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x65, 0x64, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x3d, 0x2e, - 0x67, 0x72, 0x70, 0x63, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x77, 0x65, 0x62, - 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x55, 0x6e, 0x72, 0x65, - 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x65, 0x64, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x0c, 0x9a, 0xed, - 0x1c, 0x02, 0x08, 0x01, 0x9a, 0xed, 0x1c, 0x02, 0x10, 0x02, 0x12, 0x82, 0x01, 0x0a, 0x0f, 0x4c, - 0x69, 0x73, 0x74, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x2f, + 0x62, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x47, 0x65, 0x74, 0x41, 0x70, 0x70, 0x6c, + 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2f, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x77, 0x65, - 0x62, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x44, 0x65, 0x70, - 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x30, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x77, - 0x65, 0x62, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x44, 0x65, - 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x22, 0x0c, 0x9a, 0xed, 0x1c, 0x02, 0x08, 0x02, 0x9a, 0xed, 0x1c, 0x02, 0x10, 0x02, 0x12, - 0x7c, 0x0a, 0x0d, 0x47, 0x65, 0x74, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, - 0x12, 0x2d, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, - 0x77, 0x65, 0x62, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x47, 0x65, 0x74, 0x44, 0x65, - 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x2e, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x77, - 0x65, 0x62, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x47, 0x65, 0x74, 0x44, 0x65, 0x70, - 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, - 0x0c, 0x9a, 0xed, 0x1c, 0x02, 0x08, 0x02, 0x9a, 0xed, 0x1c, 0x02, 0x10, 0x01, 0x12, 0x76, 0x0a, - 0x0b, 0x47, 0x65, 0x74, 0x53, 0x74, 0x61, 0x67, 0x65, 0x4c, 0x6f, 0x67, 0x12, 0x2b, 0x2e, 0x67, - 0x72, 0x70, 0x63, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x77, 0x65, 0x62, 0x73, - 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x74, 0x61, 0x67, 0x65, 0x4c, - 0x6f, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2c, 0x2e, 0x67, 0x72, 0x70, 0x63, - 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x77, 0x65, 0x62, 0x73, 0x65, 0x72, 0x76, - 0x69, 0x63, 0x65, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x74, 0x61, 0x67, 0x65, 0x4c, 0x6f, 0x67, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x0c, 0x9a, 0xed, 0x1c, 0x02, 0x08, 0x02, 0x9a, - 0xed, 0x1c, 0x02, 0x10, 0x01, 0x12, 0x85, 0x01, 0x0a, 0x10, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, - 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x30, 0x2e, 0x67, 0x72, 0x70, - 0x63, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x77, 0x65, 0x62, 0x73, 0x65, 0x72, - 0x76, 0x69, 0x63, 0x65, 0x2e, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x44, 0x65, 0x70, 0x6c, 0x6f, - 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x31, 0x2e, 0x67, - 0x72, 0x70, 0x63, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x77, 0x65, 0x62, 0x73, - 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x44, 0x65, 0x70, - 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, - 0x0c, 0x9a, 0xed, 0x1c, 0x02, 0x08, 0x02, 0x9a, 0xed, 0x1c, 0x02, 0x10, 0x04, 0x12, 0x70, 0x0a, - 0x09, 0x53, 0x6b, 0x69, 0x70, 0x53, 0x74, 0x61, 0x67, 0x65, 0x12, 0x29, 0x2e, 0x67, 0x72, 0x70, - 0x63, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x77, 0x65, 0x62, 0x73, 0x65, 0x72, - 0x76, 0x69, 0x63, 0x65, 0x2e, 0x53, 0x6b, 0x69, 0x70, 0x53, 0x74, 0x61, 0x67, 0x65, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x73, 0x65, 0x72, - 0x76, 0x69, 0x63, 0x65, 0x2e, 0x77, 0x65, 0x62, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, - 0x53, 0x6b, 0x69, 0x70, 0x53, 0x74, 0x61, 0x67, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x22, 0x0c, 0x9a, 0xed, 0x1c, 0x02, 0x08, 0x02, 0x9a, 0xed, 0x1c, 0x02, 0x10, 0x04, 0x12, - 0x79, 0x0a, 0x0c, 0x41, 0x70, 0x70, 0x72, 0x6f, 0x76, 0x65, 0x53, 0x74, 0x61, 0x67, 0x65, 0x12, - 0x2c, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x77, - 0x65, 0x62, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x41, 0x70, 0x70, 0x72, 0x6f, 0x76, - 0x65, 0x53, 0x74, 0x61, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2d, 0x2e, - 0x67, 0x72, 0x70, 0x63, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x77, 0x65, 0x62, - 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x41, 0x70, 0x70, 0x72, 0x6f, 0x76, 0x65, 0x53, - 0x74, 0x61, 0x67, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x0c, 0x9a, 0xed, - 0x1c, 0x02, 0x08, 0x02, 0x9a, 0xed, 0x1c, 0x02, 0x10, 0x04, 0x12, 0x91, 0x01, 0x0a, 0x14, 0x4c, - 0x69, 0x73, 0x74, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x54, 0x72, 0x61, - 0x63, 0x65, 0x73, 0x12, 0x34, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, + 0x62, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x47, 0x65, 0x74, 0x41, 0x70, 0x70, 0x6c, + 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, + 0x0c, 0x9a, 0xed, 0x1c, 0x02, 0x08, 0x01, 0x9a, 0xed, 0x1c, 0x02, 0x10, 0x01, 0x12, 0xb2, 0x01, + 0x0a, 0x1f, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x61, 0x6c, 0x65, 0x64, 0x53, 0x65, 0x63, 0x72, 0x65, + 0x74, 0x12, 0x3f, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, + 0x2e, 0x77, 0x65, 0x62, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x47, 0x65, 0x6e, 0x65, + 0x72, 0x61, 0x74, 0x65, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, + 0x65, 0x61, 0x6c, 0x65, 0x64, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x40, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, + 0x65, 0x2e, 0x77, 0x65, 0x62, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x47, 0x65, 0x6e, + 0x65, 0x72, 0x61, 0x74, 0x65, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x53, 0x65, 0x61, 0x6c, 0x65, 0x64, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x0c, 0x9a, 0xed, 0x1c, 0x02, 0x08, 0x01, 0x9a, 0xed, 0x1c, 0x02, + 0x10, 0x04, 0x12, 0xa9, 0x01, 0x0a, 0x1c, 0x4c, 0x69, 0x73, 0x74, 0x55, 0x6e, 0x72, 0x65, 0x67, + 0x69, 0x73, 0x74, 0x65, 0x72, 0x65, 0x64, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x73, 0x12, 0x3c, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x77, 0x65, 0x62, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x4c, 0x69, - 0x73, 0x74, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x54, 0x72, 0x61, 0x63, - 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x35, 0x2e, 0x67, 0x72, 0x70, 0x63, - 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x77, 0x65, 0x62, 0x73, 0x65, 0x72, 0x76, - 0x69, 0x63, 0x65, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, - 0x6e, 0x74, 0x54, 0x72, 0x61, 0x63, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x22, 0x0c, 0x9a, 0xed, 0x1c, 0x02, 0x08, 0x02, 0x9a, 0xed, 0x1c, 0x02, 0x10, 0x02, 0x12, 0x9a, - 0x01, 0x0a, 0x17, 0x47, 0x65, 0x74, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x4c, 0x69, 0x76, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x37, 0x2e, 0x67, 0x72, 0x70, - 0x63, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x77, 0x65, 0x62, 0x73, 0x65, 0x72, - 0x76, 0x69, 0x63, 0x65, 0x2e, 0x47, 0x65, 0x74, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x4c, 0x69, 0x76, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x38, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, + 0x73, 0x74, 0x55, 0x6e, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x65, 0x64, 0x41, 0x70, + 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x3d, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, + 0x2e, 0x77, 0x65, 0x62, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x4c, 0x69, 0x73, 0x74, + 0x55, 0x6e, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x65, 0x64, 0x41, 0x70, 0x70, 0x6c, + 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x22, 0x0c, 0x9a, 0xed, 0x1c, 0x02, 0x08, 0x01, 0x9a, 0xed, 0x1c, 0x02, 0x10, 0x02, 0x12, 0x82, + 0x01, 0x0a, 0x0f, 0x4c, 0x69, 0x73, 0x74, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, + 0x74, 0x73, 0x12, 0x2f, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, + 0x65, 0x2e, 0x77, 0x65, 0x62, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x4c, 0x69, 0x73, + 0x74, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x30, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, + 0x63, 0x65, 0x2e, 0x77, 0x65, 0x62, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x4c, 0x69, + 0x73, 0x74, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x0c, 0x9a, 0xed, 0x1c, 0x02, 0x08, 0x02, 0x9a, 0xed, 0x1c, + 0x02, 0x10, 0x02, 0x12, 0x7c, 0x0a, 0x0d, 0x47, 0x65, 0x74, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, + 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x2d, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x73, 0x65, 0x72, 0x76, + 0x69, 0x63, 0x65, 0x2e, 0x77, 0x65, 0x62, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x47, + 0x65, 0x74, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x2e, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x77, 0x65, 0x62, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x47, 0x65, - 0x74, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4c, 0x69, 0x76, 0x65, - 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x0c, 0x9a, - 0xed, 0x1c, 0x02, 0x08, 0x01, 0x9a, 0xed, 0x1c, 0x02, 0x10, 0x01, 0x12, 0x73, 0x0a, 0x0a, 0x47, - 0x65, 0x74, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x12, 0x2a, 0x2e, 0x67, 0x72, 0x70, 0x63, + 0x74, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x22, 0x0c, 0x9a, 0xed, 0x1c, 0x02, 0x08, 0x02, 0x9a, 0xed, 0x1c, 0x02, 0x10, + 0x01, 0x12, 0x76, 0x0a, 0x0b, 0x47, 0x65, 0x74, 0x53, 0x74, 0x61, 0x67, 0x65, 0x4c, 0x6f, 0x67, + 0x12, 0x2b, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, + 0x77, 0x65, 0x62, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x74, + 0x61, 0x67, 0x65, 0x4c, 0x6f, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2c, 0x2e, + 0x67, 0x72, 0x70, 0x63, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x77, 0x65, 0x62, + 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x74, 0x61, 0x67, 0x65, + 0x4c, 0x6f, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x0c, 0x9a, 0xed, 0x1c, + 0x02, 0x08, 0x02, 0x9a, 0xed, 0x1c, 0x02, 0x10, 0x01, 0x12, 0x85, 0x01, 0x0a, 0x10, 0x43, 0x61, + 0x6e, 0x63, 0x65, 0x6c, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x30, + 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x77, 0x65, + 0x62, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x44, + 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x31, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, + 0x77, 0x65, 0x62, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x43, 0x61, 0x6e, 0x63, 0x65, + 0x6c, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x22, 0x0c, 0x9a, 0xed, 0x1c, 0x02, 0x08, 0x02, 0x9a, 0xed, 0x1c, 0x02, 0x10, + 0x04, 0x12, 0x70, 0x0a, 0x09, 0x53, 0x6b, 0x69, 0x70, 0x53, 0x74, 0x61, 0x67, 0x65, 0x12, 0x29, + 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x77, 0x65, + 0x62, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x53, 0x6b, 0x69, 0x70, 0x53, 0x74, 0x61, + 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x77, 0x65, 0x62, 0x73, 0x65, 0x72, 0x76, - 0x69, 0x63, 0x65, 0x2e, 0x47, 0x65, 0x74, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2b, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x73, 0x65, 0x72, - 0x76, 0x69, 0x63, 0x65, 0x2e, 0x77, 0x65, 0x62, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, - 0x47, 0x65, 0x74, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x22, 0x0c, 0x9a, 0xed, 0x1c, 0x02, 0x08, 0x06, 0x9a, 0xed, 0x1c, 0x02, 0x10, 0x01, - 0x12, 0x9d, 0x01, 0x0a, 0x18, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x50, 0x72, 0x6f, 0x6a, 0x65, - 0x63, 0x74, 0x53, 0x74, 0x61, 0x74, 0x69, 0x63, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x12, 0x38, 0x2e, + 0x69, 0x63, 0x65, 0x2e, 0x53, 0x6b, 0x69, 0x70, 0x53, 0x74, 0x61, 0x67, 0x65, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x0c, 0x9a, 0xed, 0x1c, 0x02, 0x08, 0x02, 0x9a, 0xed, 0x1c, + 0x02, 0x10, 0x04, 0x12, 0x79, 0x0a, 0x0c, 0x41, 0x70, 0x70, 0x72, 0x6f, 0x76, 0x65, 0x53, 0x74, + 0x61, 0x67, 0x65, 0x12, 0x2c, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, + 0x63, 0x65, 0x2e, 0x77, 0x65, 0x62, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x41, 0x70, + 0x70, 0x72, 0x6f, 0x76, 0x65, 0x53, 0x74, 0x61, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x2d, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, + 0x2e, 0x77, 0x65, 0x62, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x41, 0x70, 0x70, 0x72, + 0x6f, 0x76, 0x65, 0x53, 0x74, 0x61, 0x67, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x22, 0x0c, 0x9a, 0xed, 0x1c, 0x02, 0x08, 0x02, 0x9a, 0xed, 0x1c, 0x02, 0x10, 0x04, 0x12, 0x91, + 0x01, 0x0a, 0x14, 0x4c, 0x69, 0x73, 0x74, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, + 0x74, 0x54, 0x72, 0x61, 0x63, 0x65, 0x73, 0x12, 0x34, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x73, + 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x77, 0x65, 0x62, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, + 0x65, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, + 0x54, 0x72, 0x61, 0x63, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x35, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x77, 0x65, 0x62, - 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x50, 0x72, - 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x53, 0x74, 0x61, 0x74, 0x69, 0x63, 0x41, 0x64, 0x6d, 0x69, 0x6e, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x39, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x73, + 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x44, 0x65, 0x70, 0x6c, + 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x54, 0x72, 0x61, 0x63, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x0c, 0x9a, 0xed, 0x1c, 0x02, 0x08, 0x02, 0x9a, 0xed, 0x1c, 0x02, + 0x10, 0x02, 0x12, 0x9a, 0x01, 0x0a, 0x17, 0x47, 0x65, 0x74, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4c, 0x69, 0x76, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x37, + 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x77, 0x65, + 0x62, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x47, 0x65, 0x74, 0x41, 0x70, 0x70, 0x6c, + 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4c, 0x69, 0x76, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x38, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x77, 0x65, 0x62, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, - 0x65, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x53, - 0x74, 0x61, 0x74, 0x69, 0x63, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x22, 0x0c, 0x9a, 0xed, 0x1c, 0x02, 0x08, 0x06, 0x9a, 0xed, 0x1c, 0x02, 0x10, 0x04, - 0x12, 0x88, 0x01, 0x0a, 0x11, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x53, 0x74, 0x61, 0x74, 0x69, - 0x63, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x12, 0x31, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x73, 0x65, - 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x77, 0x65, 0x62, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, - 0x2e, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x53, 0x74, 0x61, 0x74, 0x69, 0x63, 0x41, 0x64, 0x6d, - 0x69, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x32, 0x2e, 0x67, 0x72, 0x70, 0x63, + 0x65, 0x2e, 0x47, 0x65, 0x74, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x4c, 0x69, 0x76, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x22, 0x0c, 0x9a, 0xed, 0x1c, 0x02, 0x08, 0x01, 0x9a, 0xed, 0x1c, 0x02, 0x10, 0x01, 0x12, + 0x73, 0x0a, 0x0a, 0x47, 0x65, 0x74, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x12, 0x2a, 0x2e, + 0x67, 0x72, 0x70, 0x63, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x77, 0x65, 0x62, + 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x47, 0x65, 0x74, 0x50, 0x72, 0x6f, 0x6a, 0x65, + 0x63, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2b, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x77, 0x65, 0x62, 0x73, 0x65, 0x72, 0x76, - 0x69, 0x63, 0x65, 0x2e, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x53, 0x74, 0x61, 0x74, 0x69, 0x63, - 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x0c, 0x9a, - 0xed, 0x1c, 0x02, 0x08, 0x06, 0x9a, 0xed, 0x1c, 0x02, 0x10, 0x04, 0x12, 0x8b, 0x01, 0x0a, 0x12, - 0x44, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x53, 0x74, 0x61, 0x74, 0x69, 0x63, 0x41, 0x64, 0x6d, - 0x69, 0x6e, 0x12, 0x32, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, - 0x65, 0x2e, 0x77, 0x65, 0x62, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x44, 0x69, 0x73, - 0x61, 0x62, 0x6c, 0x65, 0x53, 0x74, 0x61, 0x74, 0x69, 0x63, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x33, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x73, 0x65, + 0x69, 0x63, 0x65, 0x2e, 0x47, 0x65, 0x74, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x0c, 0x9a, 0xed, 0x1c, 0x02, 0x08, 0x06, 0x9a, 0xed, + 0x1c, 0x02, 0x10, 0x01, 0x12, 0x9d, 0x01, 0x0a, 0x18, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x50, + 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x53, 0x74, 0x61, 0x74, 0x69, 0x63, 0x41, 0x64, 0x6d, 0x69, + 0x6e, 0x12, 0x38, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, + 0x2e, 0x77, 0x65, 0x62, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x55, 0x70, 0x64, 0x61, + 0x74, 0x65, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x53, 0x74, 0x61, 0x74, 0x69, 0x63, 0x41, + 0x64, 0x6d, 0x69, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x39, 0x2e, 0x67, 0x72, + 0x70, 0x63, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x77, 0x65, 0x62, 0x73, 0x65, + 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x50, 0x72, 0x6f, 0x6a, + 0x65, 0x63, 0x74, 0x53, 0x74, 0x61, 0x74, 0x69, 0x63, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x0c, 0x9a, 0xed, 0x1c, 0x02, 0x08, 0x06, 0x9a, 0xed, + 0x1c, 0x02, 0x10, 0x04, 0x12, 0x88, 0x01, 0x0a, 0x11, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x53, + 0x74, 0x61, 0x74, 0x69, 0x63, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x12, 0x31, 0x2e, 0x67, 0x72, 0x70, + 0x63, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x77, 0x65, 0x62, 0x73, 0x65, 0x72, + 0x76, 0x69, 0x63, 0x65, 0x2e, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x53, 0x74, 0x61, 0x74, 0x69, + 0x63, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x32, 0x2e, + 0x67, 0x72, 0x70, 0x63, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x77, 0x65, 0x62, + 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x53, 0x74, + 0x61, 0x74, 0x69, 0x63, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x22, 0x0c, 0x9a, 0xed, 0x1c, 0x02, 0x08, 0x06, 0x9a, 0xed, 0x1c, 0x02, 0x10, 0x04, 0x12, + 0x8b, 0x01, 0x0a, 0x12, 0x44, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x53, 0x74, 0x61, 0x74, 0x69, + 0x63, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x12, 0x32, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x77, 0x65, 0x62, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x44, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x53, 0x74, 0x61, 0x74, 0x69, 0x63, 0x41, 0x64, - 0x6d, 0x69, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x0c, 0x9a, 0xed, 0x1c, - 0x02, 0x08, 0x06, 0x9a, 0xed, 0x1c, 0x02, 0x10, 0x04, 0x12, 0x97, 0x01, 0x0a, 0x16, 0x55, 0x70, - 0x64, 0x61, 0x74, 0x65, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x53, 0x53, 0x4f, 0x43, 0x6f, - 0x6e, 0x66, 0x69, 0x67, 0x12, 0x36, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x73, 0x65, 0x72, 0x76, - 0x69, 0x63, 0x65, 0x2e, 0x77, 0x65, 0x62, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x55, - 0x70, 0x64, 0x61, 0x74, 0x65, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x53, 0x53, 0x4f, 0x43, - 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x37, 0x2e, 0x67, + 0x6d, 0x69, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x33, 0x2e, 0x67, 0x72, 0x70, + 0x63, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x77, 0x65, 0x62, 0x73, 0x65, 0x72, + 0x76, 0x69, 0x63, 0x65, 0x2e, 0x44, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x53, 0x74, 0x61, 0x74, + 0x69, 0x63, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, + 0x0c, 0x9a, 0xed, 0x1c, 0x02, 0x08, 0x06, 0x9a, 0xed, 0x1c, 0x02, 0x10, 0x04, 0x12, 0x97, 0x01, + 0x0a, 0x16, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x53, + 0x53, 0x4f, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x36, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, + 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x77, 0x65, 0x62, 0x73, 0x65, 0x72, 0x76, 0x69, + 0x63, 0x65, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, + 0x53, 0x53, 0x4f, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x37, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, + 0x77, 0x65, 0x62, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, + 0x65, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x53, 0x53, 0x4f, 0x43, 0x6f, 0x6e, 0x66, 0x69, + 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x0c, 0x9a, 0xed, 0x1c, 0x02, 0x08, + 0x06, 0x9a, 0xed, 0x1c, 0x02, 0x10, 0x04, 0x12, 0x9a, 0x01, 0x0a, 0x17, 0x55, 0x70, 0x64, 0x61, + 0x74, 0x65, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x52, 0x42, 0x41, 0x43, 0x43, 0x6f, 0x6e, + 0x66, 0x69, 0x67, 0x12, 0x37, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, + 0x63, 0x65, 0x2e, 0x77, 0x65, 0x62, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x55, 0x70, + 0x64, 0x61, 0x74, 0x65, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x52, 0x42, 0x41, 0x43, 0x43, + 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x38, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x77, 0x65, 0x62, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x50, 0x72, 0x6f, - 0x6a, 0x65, 0x63, 0x74, 0x53, 0x53, 0x4f, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x73, + 0x6a, 0x65, 0x63, 0x74, 0x52, 0x42, 0x41, 0x43, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x0c, 0x9a, 0xed, 0x1c, 0x02, 0x08, 0x06, 0x9a, 0xed, + 0x1c, 0x02, 0x10, 0x04, 0x12, 0x7c, 0x0a, 0x0d, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x50, 0x72, + 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x12, 0x2d, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x73, 0x65, 0x72, + 0x76, 0x69, 0x63, 0x65, 0x2e, 0x77, 0x65, 0x62, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, + 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2e, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x73, 0x65, 0x72, 0x76, + 0x69, 0x63, 0x65, 0x2e, 0x77, 0x65, 0x62, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x45, + 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x0c, 0x9a, 0xed, 0x1c, 0x02, 0x08, 0x06, 0x9a, 0xed, 0x1c, 0x02, + 0x10, 0x04, 0x12, 0x7f, 0x0a, 0x0e, 0x44, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x50, 0x72, 0x6f, + 0x6a, 0x65, 0x63, 0x74, 0x12, 0x2e, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x73, 0x65, 0x72, 0x76, + 0x69, 0x63, 0x65, 0x2e, 0x77, 0x65, 0x62, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x44, + 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2f, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x73, 0x65, 0x72, 0x76, + 0x69, 0x63, 0x65, 0x2e, 0x77, 0x65, 0x62, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x44, + 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x0c, 0x9a, 0xed, 0x1c, 0x02, 0x08, 0x06, 0x9a, 0xed, 0x1c, - 0x02, 0x10, 0x04, 0x12, 0x9a, 0x01, 0x0a, 0x17, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x50, 0x72, - 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x52, 0x42, 0x41, 0x43, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, - 0x37, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x77, - 0x65, 0x62, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, - 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x52, 0x42, 0x41, 0x43, 0x43, 0x6f, 0x6e, 0x66, 0x69, - 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x38, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, + 0x02, 0x10, 0x04, 0x12, 0x64, 0x0a, 0x05, 0x47, 0x65, 0x74, 0x4d, 0x65, 0x12, 0x25, 0x2e, 0x67, + 0x72, 0x70, 0x63, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x77, 0x65, 0x62, 0x73, + 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x47, 0x65, 0x74, 0x4d, 0x65, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x26, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, + 0x63, 0x65, 0x2e, 0x77, 0x65, 0x62, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x47, 0x65, + 0x74, 0x4d, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x0c, 0x9a, 0xed, 0x1c, + 0x02, 0x08, 0x06, 0x9a, 0xed, 0x1c, 0x02, 0x10, 0x01, 0x12, 0x8b, 0x01, 0x0a, 0x12, 0x41, 0x64, + 0x64, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x52, 0x42, 0x41, 0x43, 0x52, 0x6f, 0x6c, 0x65, + 0x12, 0x32, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, + 0x77, 0x65, 0x62, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x41, 0x64, 0x64, 0x50, 0x72, + 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x52, 0x42, 0x41, 0x43, 0x52, 0x6f, 0x6c, 0x65, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x33, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x73, 0x65, 0x72, 0x76, + 0x69, 0x63, 0x65, 0x2e, 0x77, 0x65, 0x62, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x41, + 0x64, 0x64, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x52, 0x42, 0x41, 0x43, 0x52, 0x6f, 0x6c, + 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x0c, 0x9a, 0xed, 0x1c, 0x02, 0x08, + 0x06, 0x9a, 0xed, 0x1c, 0x02, 0x10, 0x04, 0x12, 0x94, 0x01, 0x0a, 0x15, 0x55, 0x70, 0x64, 0x61, + 0x74, 0x65, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x52, 0x42, 0x41, 0x43, 0x52, 0x6f, 0x6c, + 0x65, 0x12, 0x35, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, + 0x2e, 0x77, 0x65, 0x62, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x55, 0x70, 0x64, 0x61, + 0x74, 0x65, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x52, 0x42, 0x41, 0x43, 0x52, 0x6f, 0x6c, + 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x36, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x77, 0x65, 0x62, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, - 0x52, 0x42, 0x41, 0x43, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x22, 0x0c, 0x9a, 0xed, 0x1c, 0x02, 0x08, 0x06, 0x9a, 0xed, 0x1c, 0x02, 0x10, 0x04, - 0x12, 0x64, 0x0a, 0x05, 0x47, 0x65, 0x74, 0x4d, 0x65, 0x12, 0x25, 0x2e, 0x67, 0x72, 0x70, 0x63, - 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x77, 0x65, 0x62, 0x73, 0x65, 0x72, 0x76, - 0x69, 0x63, 0x65, 0x2e, 0x47, 0x65, 0x74, 0x4d, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x26, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, - 0x77, 0x65, 0x62, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x47, 0x65, 0x74, 0x4d, 0x65, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x0c, 0x9a, 0xed, 0x1c, 0x02, 0x08, 0x06, - 0x9a, 0xed, 0x1c, 0x02, 0x10, 0x01, 0x12, 0x8b, 0x01, 0x0a, 0x12, 0x41, 0x64, 0x64, 0x50, 0x72, - 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x52, 0x42, 0x41, 0x43, 0x52, 0x6f, 0x6c, 0x65, 0x12, 0x32, 0x2e, + 0x52, 0x42, 0x41, 0x43, 0x52, 0x6f, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x22, 0x0c, 0x9a, 0xed, 0x1c, 0x02, 0x08, 0x06, 0x9a, 0xed, 0x1c, 0x02, 0x10, 0x04, 0x12, 0x94, + 0x01, 0x0a, 0x15, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, + 0x52, 0x42, 0x41, 0x43, 0x52, 0x6f, 0x6c, 0x65, 0x12, 0x35, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, + 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x77, 0x65, 0x62, 0x73, 0x65, 0x72, 0x76, 0x69, + 0x63, 0x65, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, + 0x52, 0x42, 0x41, 0x43, 0x52, 0x6f, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x36, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x77, + 0x65, 0x62, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, + 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x52, 0x42, 0x41, 0x43, 0x52, 0x6f, 0x6c, 0x65, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x0c, 0x9a, 0xed, 0x1c, 0x02, 0x08, 0x06, 0x9a, + 0xed, 0x1c, 0x02, 0x10, 0x04, 0x12, 0x8e, 0x01, 0x0a, 0x13, 0x41, 0x64, 0x64, 0x50, 0x72, 0x6f, + 0x6a, 0x65, 0x63, 0x74, 0x55, 0x73, 0x65, 0x72, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x12, 0x33, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x77, 0x65, 0x62, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x41, 0x64, 0x64, 0x50, 0x72, 0x6f, 0x6a, 0x65, - 0x63, 0x74, 0x52, 0x42, 0x41, 0x43, 0x52, 0x6f, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x33, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, - 0x2e, 0x77, 0x65, 0x62, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x41, 0x64, 0x64, 0x50, - 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x52, 0x42, 0x41, 0x43, 0x52, 0x6f, 0x6c, 0x65, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x0c, 0x9a, 0xed, 0x1c, 0x02, 0x08, 0x06, 0x9a, 0xed, - 0x1c, 0x02, 0x10, 0x04, 0x12, 0x94, 0x01, 0x0a, 0x15, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x50, - 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x52, 0x42, 0x41, 0x43, 0x52, 0x6f, 0x6c, 0x65, 0x12, 0x35, + 0x63, 0x74, 0x55, 0x73, 0x65, 0x72, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x34, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, + 0x65, 0x2e, 0x77, 0x65, 0x62, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x41, 0x64, 0x64, + 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x55, 0x73, 0x65, 0x72, 0x47, 0x72, 0x6f, 0x75, 0x70, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x0c, 0x9a, 0xed, 0x1c, 0x02, 0x08, 0x06, + 0x9a, 0xed, 0x1c, 0x02, 0x10, 0x04, 0x12, 0x97, 0x01, 0x0a, 0x16, 0x44, 0x65, 0x6c, 0x65, 0x74, + 0x65, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x55, 0x73, 0x65, 0x72, 0x47, 0x72, 0x6f, 0x75, + 0x70, 0x12, 0x36, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, + 0x2e, 0x77, 0x65, 0x62, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x44, 0x65, 0x6c, 0x65, + 0x74, 0x65, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x55, 0x73, 0x65, 0x72, 0x47, 0x72, 0x6f, + 0x75, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x37, 0x2e, 0x67, 0x72, 0x70, 0x63, + 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x77, 0x65, 0x62, 0x73, 0x65, 0x72, 0x76, + 0x69, 0x63, 0x65, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, + 0x74, 0x55, 0x73, 0x65, 0x72, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x22, 0x0c, 0x9a, 0xed, 0x1c, 0x02, 0x08, 0x06, 0x9a, 0xed, 0x1c, 0x02, 0x10, 0x04, + 0x12, 0x6d, 0x0a, 0x0a, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x12, 0x2a, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x77, 0x65, - 0x62, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x50, - 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x52, 0x42, 0x41, 0x43, 0x52, 0x6f, 0x6c, 0x65, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x36, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x73, 0x65, 0x72, - 0x76, 0x69, 0x63, 0x65, 0x2e, 0x77, 0x65, 0x62, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, - 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x52, 0x42, 0x41, - 0x43, 0x52, 0x6f, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x0c, 0x9a, - 0xed, 0x1c, 0x02, 0x08, 0x06, 0x9a, 0xed, 0x1c, 0x02, 0x10, 0x04, 0x12, 0x94, 0x01, 0x0a, 0x15, - 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x52, 0x42, 0x41, - 0x43, 0x52, 0x6f, 0x6c, 0x65, 0x12, 0x35, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x73, 0x65, 0x72, - 0x76, 0x69, 0x63, 0x65, 0x2e, 0x77, 0x65, 0x62, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, - 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x52, 0x42, 0x41, - 0x43, 0x52, 0x6f, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x36, 0x2e, 0x67, - 0x72, 0x70, 0x63, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x77, 0x65, 0x62, 0x73, - 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x50, 0x72, 0x6f, - 0x6a, 0x65, 0x63, 0x74, 0x52, 0x42, 0x41, 0x43, 0x52, 0x6f, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x0c, 0x9a, 0xed, 0x1c, 0x02, 0x08, 0x06, 0x9a, 0xed, 0x1c, 0x02, - 0x10, 0x04, 0x12, 0x8e, 0x01, 0x0a, 0x13, 0x41, 0x64, 0x64, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, - 0x74, 0x55, 0x73, 0x65, 0x72, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x12, 0x33, 0x2e, 0x67, 0x72, 0x70, + 0x62, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6d, 0x6d, + 0x61, 0x6e, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2b, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x77, 0x65, 0x62, 0x73, 0x65, 0x72, - 0x76, 0x69, 0x63, 0x65, 0x2e, 0x41, 0x64, 0x64, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x55, - 0x73, 0x65, 0x72, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x34, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x77, - 0x65, 0x62, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x41, 0x64, 0x64, 0x50, 0x72, 0x6f, - 0x6a, 0x65, 0x63, 0x74, 0x55, 0x73, 0x65, 0x72, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x0c, 0x9a, 0xed, 0x1c, 0x02, 0x08, 0x06, 0x9a, 0xed, 0x1c, - 0x02, 0x10, 0x04, 0x12, 0x97, 0x01, 0x0a, 0x16, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x50, 0x72, - 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x55, 0x73, 0x65, 0x72, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x12, 0x36, - 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x77, 0x65, - 0x62, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x50, - 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x55, 0x73, 0x65, 0x72, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x37, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x73, 0x65, - 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x77, 0x65, 0x62, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, - 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x55, 0x73, - 0x65, 0x72, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, - 0x0c, 0x9a, 0xed, 0x1c, 0x02, 0x08, 0x06, 0x9a, 0xed, 0x1c, 0x02, 0x10, 0x04, 0x12, 0x6d, 0x0a, - 0x0a, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x12, 0x2a, 0x2e, 0x67, 0x72, - 0x70, 0x63, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x77, 0x65, 0x62, 0x73, 0x65, - 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2b, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x73, - 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x77, 0x65, 0x62, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, - 0x65, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x06, 0x9a, 0xed, 0x1c, 0x02, 0x18, 0x01, 0x12, 0x7f, 0x0a, 0x0e, - 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x41, 0x50, 0x49, 0x4b, 0x65, 0x79, 0x12, 0x2e, - 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x77, 0x65, - 0x62, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, - 0x65, 0x41, 0x50, 0x49, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2f, - 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x77, 0x65, - 0x62, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, - 0x65, 0x41, 0x50, 0x49, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, - 0x0c, 0x9a, 0xed, 0x1c, 0x02, 0x08, 0x07, 0x9a, 0xed, 0x1c, 0x02, 0x10, 0x03, 0x12, 0x7c, 0x0a, - 0x0d, 0x44, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x41, 0x50, 0x49, 0x4b, 0x65, 0x79, 0x12, 0x2d, - 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x77, 0x65, - 0x62, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x44, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, - 0x41, 0x50, 0x49, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2e, 0x2e, + 0x76, 0x69, 0x63, 0x65, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x06, 0x9a, 0xed, 0x1c, 0x02, 0x18, 0x01, 0x12, + 0x7f, 0x0a, 0x0e, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x41, 0x50, 0x49, 0x4b, 0x65, + 0x79, 0x12, 0x2e, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, + 0x2e, 0x77, 0x65, 0x62, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x47, 0x65, 0x6e, 0x65, + 0x72, 0x61, 0x74, 0x65, 0x41, 0x50, 0x49, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x2f, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, + 0x2e, 0x77, 0x65, 0x62, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x47, 0x65, 0x6e, 0x65, + 0x72, 0x61, 0x74, 0x65, 0x41, 0x50, 0x49, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x22, 0x0c, 0x9a, 0xed, 0x1c, 0x02, 0x08, 0x07, 0x9a, 0xed, 0x1c, 0x02, 0x10, 0x03, + 0x12, 0x7c, 0x0a, 0x0d, 0x44, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x41, 0x50, 0x49, 0x4b, 0x65, + 0x79, 0x12, 0x2d, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, + 0x2e, 0x77, 0x65, 0x62, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x44, 0x69, 0x73, 0x61, + 0x62, 0x6c, 0x65, 0x41, 0x50, 0x49, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x2e, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, + 0x77, 0x65, 0x62, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x44, 0x69, 0x73, 0x61, 0x62, + 0x6c, 0x65, 0x41, 0x50, 0x49, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x22, 0x0c, 0x9a, 0xed, 0x1c, 0x02, 0x08, 0x07, 0x9a, 0xed, 0x1c, 0x02, 0x10, 0x04, 0x12, 0x76, + 0x0a, 0x0b, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x50, 0x49, 0x4b, 0x65, 0x79, 0x73, 0x12, 0x2b, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x77, 0x65, 0x62, - 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x44, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x41, - 0x50, 0x49, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x0c, 0x9a, - 0xed, 0x1c, 0x02, 0x08, 0x07, 0x9a, 0xed, 0x1c, 0x02, 0x10, 0x04, 0x12, 0x76, 0x0a, 0x0b, 0x4c, - 0x69, 0x73, 0x74, 0x41, 0x50, 0x49, 0x4b, 0x65, 0x79, 0x73, 0x12, 0x2b, 0x2e, 0x67, 0x72, 0x70, + 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x50, 0x49, 0x4b, + 0x65, 0x79, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2c, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x77, 0x65, 0x62, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x50, 0x49, 0x4b, 0x65, 0x79, 0x73, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2c, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x73, - 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x77, 0x65, 0x62, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, - 0x65, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x50, 0x49, 0x4b, 0x65, 0x79, 0x73, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x0c, 0x9a, 0xed, 0x1c, 0x02, 0x08, 0x07, 0x9a, 0xed, 0x1c, - 0x02, 0x10, 0x02, 0x12, 0x7f, 0x0a, 0x0e, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x73, 0x69, 0x67, 0x68, - 0x74, 0x44, 0x61, 0x74, 0x61, 0x12, 0x2e, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x73, 0x65, 0x72, - 0x76, 0x69, 0x63, 0x65, 0x2e, 0x77, 0x65, 0x62, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, - 0x47, 0x65, 0x74, 0x49, 0x6e, 0x73, 0x69, 0x67, 0x68, 0x74, 0x44, 0x61, 0x74, 0x61, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2f, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x73, 0x65, 0x72, - 0x76, 0x69, 0x63, 0x65, 0x2e, 0x77, 0x65, 0x62, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, - 0x47, 0x65, 0x74, 0x49, 0x6e, 0x73, 0x69, 0x67, 0x68, 0x74, 0x44, 0x61, 0x74, 0x61, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x0c, 0x9a, 0xed, 0x1c, 0x02, 0x08, 0x08, 0x9a, 0xed, - 0x1c, 0x02, 0x10, 0x01, 0x12, 0xa3, 0x01, 0x0a, 0x1a, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x73, 0x69, - 0x67, 0x68, 0x74, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6f, - 0x75, 0x6e, 0x74, 0x12, 0x3a, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, - 0x63, 0x65, 0x2e, 0x77, 0x65, 0x62, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x47, 0x65, - 0x74, 0x49, 0x6e, 0x73, 0x69, 0x67, 0x68, 0x74, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x3b, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x77, - 0x65, 0x62, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x73, - 0x69, 0x67, 0x68, 0x74, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x43, - 0x6f, 0x75, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x0c, 0x9a, 0xed, - 0x1c, 0x02, 0x08, 0x08, 0x9a, 0xed, 0x1c, 0x02, 0x10, 0x01, 0x12, 0x85, 0x01, 0x0a, 0x14, 0x4c, - 0x69, 0x73, 0x74, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x43, 0x68, 0x61, - 0x69, 0x6e, 0x73, 0x12, 0x34, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, - 0x63, 0x65, 0x2e, 0x77, 0x65, 0x62, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x4c, 0x69, - 0x73, 0x74, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x43, 0x68, 0x61, 0x69, - 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x35, 0x2e, 0x67, 0x72, 0x70, 0x63, - 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x77, 0x65, 0x62, 0x73, 0x65, 0x72, 0x76, - 0x69, 0x63, 0x65, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, - 0x6e, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x22, 0x00, 0x12, 0x7f, 0x0a, 0x12, 0x47, 0x65, 0x74, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, - 0x65, 0x6e, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x12, 0x32, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x0c, 0x9a, 0xed, 0x1c, 0x02, 0x08, 0x07, + 0x9a, 0xed, 0x1c, 0x02, 0x10, 0x02, 0x12, 0x7f, 0x0a, 0x0e, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x73, + 0x69, 0x67, 0x68, 0x74, 0x44, 0x61, 0x74, 0x61, 0x12, 0x2e, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, + 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x77, 0x65, 0x62, 0x73, 0x65, 0x72, 0x76, 0x69, + 0x63, 0x65, 0x2e, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x73, 0x69, 0x67, 0x68, 0x74, 0x44, 0x61, 0x74, + 0x61, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2f, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x77, 0x65, 0x62, 0x73, 0x65, 0x72, 0x76, 0x69, - 0x63, 0x65, 0x2e, 0x47, 0x65, 0x74, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, - 0x43, 0x68, 0x61, 0x69, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x33, 0x2e, 0x67, + 0x63, 0x65, 0x2e, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x73, 0x69, 0x67, 0x68, 0x74, 0x44, 0x61, 0x74, + 0x61, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x0c, 0x9a, 0xed, 0x1c, 0x02, 0x08, + 0x08, 0x9a, 0xed, 0x1c, 0x02, 0x10, 0x01, 0x12, 0xa3, 0x01, 0x0a, 0x1a, 0x47, 0x65, 0x74, 0x49, + 0x6e, 0x73, 0x69, 0x67, 0x68, 0x74, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x3a, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x73, 0x65, + 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x77, 0x65, 0x62, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, + 0x2e, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x73, 0x69, 0x67, 0x68, 0x74, 0x41, 0x70, 0x70, 0x6c, 0x69, + 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x3b, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, + 0x65, 0x2e, 0x77, 0x65, 0x62, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x47, 0x65, 0x74, + 0x49, 0x6e, 0x73, 0x69, 0x67, 0x68, 0x74, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, + 0x0c, 0x9a, 0xed, 0x1c, 0x02, 0x08, 0x08, 0x9a, 0xed, 0x1c, 0x02, 0x10, 0x01, 0x12, 0x85, 0x01, + 0x0a, 0x14, 0x4c, 0x69, 0x73, 0x74, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, + 0x43, 0x68, 0x61, 0x69, 0x6e, 0x73, 0x12, 0x34, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x73, 0x65, + 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x77, 0x65, 0x62, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, + 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x43, + 0x68, 0x61, 0x69, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x35, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x77, 0x65, 0x62, 0x73, - 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x47, 0x65, 0x74, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, - 0x6d, 0x65, 0x6e, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x22, 0x00, 0x12, 0x73, 0x0a, 0x0a, 0x4c, 0x69, 0x73, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, - 0x73, 0x12, 0x2a, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, - 0x2e, 0x77, 0x65, 0x62, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x4c, 0x69, 0x73, 0x74, - 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2b, 0x2e, - 0x67, 0x72, 0x70, 0x63, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x77, 0x65, 0x62, - 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x45, 0x76, 0x65, 0x6e, - 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x0c, 0x9a, 0xed, 0x1c, 0x02, - 0x08, 0x03, 0x9a, 0xed, 0x1c, 0x02, 0x10, 0x02, 0x42, 0x3d, 0x5a, 0x3b, 0x67, 0x69, 0x74, 0x68, - 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x69, 0x70, 0x65, 0x2d, 0x63, 0x64, 0x2f, 0x70, - 0x69, 0x70, 0x65, 0x63, 0x64, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x61, 0x70, 0x70, 0x2f, 0x73, 0x65, - 0x72, 0x76, 0x65, 0x72, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2f, 0x77, 0x65, 0x62, - 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x44, 0x65, 0x70, 0x6c, 0x6f, + 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x7f, 0x0a, 0x12, 0x47, 0x65, 0x74, 0x44, 0x65, 0x70, 0x6c, + 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x12, 0x32, 0x2e, 0x67, 0x72, + 0x70, 0x63, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x77, 0x65, 0x62, 0x73, 0x65, + 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x47, 0x65, 0x74, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, + 0x65, 0x6e, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x33, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x77, + 0x65, 0x62, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x47, 0x65, 0x74, 0x44, 0x65, 0x70, + 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x73, 0x0a, 0x0a, 0x4c, 0x69, 0x73, 0x74, 0x45, 0x76, + 0x65, 0x6e, 0x74, 0x73, 0x12, 0x2a, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x73, 0x65, 0x72, 0x76, + 0x69, 0x63, 0x65, 0x2e, 0x77, 0x65, 0x62, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x4c, + 0x69, 0x73, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x2b, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, + 0x77, 0x65, 0x62, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x45, + 0x76, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x0c, 0x9a, + 0xed, 0x1c, 0x02, 0x08, 0x03, 0x9a, 0xed, 0x1c, 0x02, 0x10, 0x02, 0x42, 0x3d, 0x5a, 0x3b, 0x67, + 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x69, 0x70, 0x65, 0x2d, 0x63, + 0x64, 0x2f, 0x70, 0x69, 0x70, 0x65, 0x63, 0x64, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x61, 0x70, 0x70, + 0x2f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2f, + 0x77, 0x65, 0x62, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x33, } var ( @@ -6704,7 +6879,7 @@ func file_pkg_app_server_service_webservice_service_proto_rawDescGZIP() []byte { return file_pkg_app_server_service_webservice_service_proto_rawDescData } -var file_pkg_app_server_service_webservice_service_proto_msgTypes = make([]protoimpl.MessageInfo, 117) +var file_pkg_app_server_service_webservice_service_proto_msgTypes = make([]protoimpl.MessageInfo, 121) var file_pkg_app_server_service_webservice_service_proto_goTypes = []interface{}{ (*RegisterPipedRequest)(nil), // 0: grpc.service.webservice.RegisterPipedRequest (*RegisterPipedResponse)(nil), // 1: grpc.service.webservice.RegisterPipedResponse @@ -6778,140 +6953,144 @@ var file_pkg_app_server_service_webservice_service_proto_goTypes = []interface{} (*EnableStaticAdminResponse)(nil), // 69: grpc.service.webservice.EnableStaticAdminResponse (*DisableStaticAdminRequest)(nil), // 70: grpc.service.webservice.DisableStaticAdminRequest (*DisableStaticAdminResponse)(nil), // 71: grpc.service.webservice.DisableStaticAdminResponse - (*GetMeRequest)(nil), // 72: grpc.service.webservice.GetMeRequest - (*GetMeResponse)(nil), // 73: grpc.service.webservice.GetMeResponse - (*AddProjectRBACRoleRequest)(nil), // 74: grpc.service.webservice.AddProjectRBACRoleRequest - (*AddProjectRBACRoleResponse)(nil), // 75: grpc.service.webservice.AddProjectRBACRoleResponse - (*UpdateProjectRBACRoleRequest)(nil), // 76: grpc.service.webservice.UpdateProjectRBACRoleRequest - (*UpdateProjectRBACRoleResponse)(nil), // 77: grpc.service.webservice.UpdateProjectRBACRoleResponse - (*DeleteProjectRBACRoleRequest)(nil), // 78: grpc.service.webservice.DeleteProjectRBACRoleRequest - (*DeleteProjectRBACRoleResponse)(nil), // 79: grpc.service.webservice.DeleteProjectRBACRoleResponse - (*AddProjectUserGroupRequest)(nil), // 80: grpc.service.webservice.AddProjectUserGroupRequest - (*AddProjectUserGroupResponse)(nil), // 81: grpc.service.webservice.AddProjectUserGroupResponse - (*DeleteProjectUserGroupRequest)(nil), // 82: grpc.service.webservice.DeleteProjectUserGroupRequest - (*DeleteProjectUserGroupResponse)(nil), // 83: grpc.service.webservice.DeleteProjectUserGroupResponse - (*GetCommandRequest)(nil), // 84: grpc.service.webservice.GetCommandRequest - (*GetCommandResponse)(nil), // 85: grpc.service.webservice.GetCommandResponse - (*GenerateAPIKeyRequest)(nil), // 86: grpc.service.webservice.GenerateAPIKeyRequest - (*GenerateAPIKeyResponse)(nil), // 87: grpc.service.webservice.GenerateAPIKeyResponse - (*DisableAPIKeyRequest)(nil), // 88: grpc.service.webservice.DisableAPIKeyRequest - (*DisableAPIKeyResponse)(nil), // 89: grpc.service.webservice.DisableAPIKeyResponse - (*ListAPIKeysRequest)(nil), // 90: grpc.service.webservice.ListAPIKeysRequest - (*ListAPIKeysResponse)(nil), // 91: grpc.service.webservice.ListAPIKeysResponse - (*GetInsightDataRequest)(nil), // 92: grpc.service.webservice.GetInsightDataRequest - (*GetInsightDataResponse)(nil), // 93: grpc.service.webservice.GetInsightDataResponse - (*GetInsightApplicationCountRequest)(nil), // 94: grpc.service.webservice.GetInsightApplicationCountRequest - (*GetInsightApplicationCountResponse)(nil), // 95: grpc.service.webservice.GetInsightApplicationCountResponse - (*ListDeploymentChainsRequest)(nil), // 96: grpc.service.webservice.ListDeploymentChainsRequest - (*ListDeploymentChainsResponse)(nil), // 97: grpc.service.webservice.ListDeploymentChainsResponse - (*GetDeploymentChainRequest)(nil), // 98: grpc.service.webservice.GetDeploymentChainRequest - (*GetDeploymentChainResponse)(nil), // 99: grpc.service.webservice.GetDeploymentChainResponse - (*ListEventsRequest)(nil), // 100: grpc.service.webservice.ListEventsRequest - (*ListEventsResponse)(nil), // 101: grpc.service.webservice.ListEventsResponse - (*ListPipedsRequest_Options)(nil), // 102: grpc.service.webservice.ListPipedsRequest.Options - nil, // 103: grpc.service.webservice.AddApplicationRequest.DeployTargetsByPluginEntry - nil, // 104: grpc.service.webservice.AddApplicationRequest.LabelsEntry - nil, // 105: grpc.service.webservice.UpdateApplicationRequest.DeployTargetsByPluginEntry - (*ListApplicationsRequest_Options)(nil), // 106: grpc.service.webservice.ListApplicationsRequest.Options - nil, // 107: grpc.service.webservice.ListApplicationsRequest.Options.LabelsEntry - (*ListDeploymentsRequest_Options)(nil), // 108: grpc.service.webservice.ListDeploymentsRequest.Options - nil, // 109: grpc.service.webservice.ListDeploymentsRequest.Options.LabelsEntry - (*ListDeploymentTracesRequest_Options)(nil), // 110: grpc.service.webservice.ListDeploymentTracesRequest.Options - (*ListDeploymentTracesResponse_DeploymentTraceRes)(nil), // 111: grpc.service.webservice.ListDeploymentTracesResponse.DeploymentTraceRes - (*ListAPIKeysRequest_Options)(nil), // 112: grpc.service.webservice.ListAPIKeysRequest.Options - nil, // 113: grpc.service.webservice.GetInsightDataRequest.LabelsEntry - (*ListDeploymentChainsRequest_Options)(nil), // 114: grpc.service.webservice.ListDeploymentChainsRequest.Options - (*ListEventsRequest_Options)(nil), // 115: grpc.service.webservice.ListEventsRequest.Options - nil, // 116: grpc.service.webservice.ListEventsRequest.Options.LabelsEntry - (*model.Piped)(nil), // 117: model.Piped - (*model.ApplicationGitPath)(nil), // 118: model.ApplicationGitPath - (model.ApplicationKind)(0), // 119: model.ApplicationKind - (*model.Application)(nil), // 120: model.Application - (model.SyncStrategy)(0), // 121: model.SyncStrategy - (*model.ApplicationInfo)(nil), // 122: model.ApplicationInfo - (*model.Deployment)(nil), // 123: model.Deployment - (*model.LogBlock)(nil), // 124: model.LogBlock - (*model.ApplicationLiveStateSnapshot)(nil), // 125: model.ApplicationLiveStateSnapshot - (*model.Project)(nil), // 126: model.Project - (*model.ProjectSSOConfig)(nil), // 127: model.ProjectSSOConfig - (*model.ProjectRBACConfig)(nil), // 128: model.ProjectRBACConfig - (*model.ProjectRBACPolicy)(nil), // 129: model.ProjectRBACPolicy - (*model.Command)(nil), // 130: model.Command - (model.APIKey_Role)(0), // 131: model.APIKey.Role - (*model.APIKey)(nil), // 132: model.APIKey - (model.InsightMetricsKind)(0), // 133: model.InsightMetricsKind - (model.InsightResolution)(0), // 134: model.InsightResolution - (model.InsightResultType)(0), // 135: model.InsightResultType - (*model.InsightSample)(nil), // 136: model.InsightSample - (*model.InsightSampleStream)(nil), // 137: model.InsightSampleStream - (*model.InsightApplicationCount)(nil), // 138: model.InsightApplicationCount - (*model.DeploymentChain)(nil), // 139: model.DeploymentChain - (*model.Event)(nil), // 140: model.Event - (*wrapperspb.BoolValue)(nil), // 141: google.protobuf.BoolValue - (*model.DeployTargets)(nil), // 142: model.DeployTargets - (model.ApplicationSyncStatus)(0), // 143: model.ApplicationSyncStatus - (model.DeploymentStatus)(0), // 144: model.DeploymentStatus - (*model.DeploymentTrace)(nil), // 145: model.DeploymentTrace - (model.EventStatus)(0), // 146: model.EventStatus + (*EnableProjectRequest)(nil), // 72: grpc.service.webservice.EnableProjectRequest + (*EnableProjectResponse)(nil), // 73: grpc.service.webservice.EnableProjectResponse + (*DisableProjectRequest)(nil), // 74: grpc.service.webservice.DisableProjectRequest + (*DisableProjectResponse)(nil), // 75: grpc.service.webservice.DisableProjectResponse + (*GetMeRequest)(nil), // 76: grpc.service.webservice.GetMeRequest + (*GetMeResponse)(nil), // 77: grpc.service.webservice.GetMeResponse + (*AddProjectRBACRoleRequest)(nil), // 78: grpc.service.webservice.AddProjectRBACRoleRequest + (*AddProjectRBACRoleResponse)(nil), // 79: grpc.service.webservice.AddProjectRBACRoleResponse + (*UpdateProjectRBACRoleRequest)(nil), // 80: grpc.service.webservice.UpdateProjectRBACRoleRequest + (*UpdateProjectRBACRoleResponse)(nil), // 81: grpc.service.webservice.UpdateProjectRBACRoleResponse + (*DeleteProjectRBACRoleRequest)(nil), // 82: grpc.service.webservice.DeleteProjectRBACRoleRequest + (*DeleteProjectRBACRoleResponse)(nil), // 83: grpc.service.webservice.DeleteProjectRBACRoleResponse + (*AddProjectUserGroupRequest)(nil), // 84: grpc.service.webservice.AddProjectUserGroupRequest + (*AddProjectUserGroupResponse)(nil), // 85: grpc.service.webservice.AddProjectUserGroupResponse + (*DeleteProjectUserGroupRequest)(nil), // 86: grpc.service.webservice.DeleteProjectUserGroupRequest + (*DeleteProjectUserGroupResponse)(nil), // 87: grpc.service.webservice.DeleteProjectUserGroupResponse + (*GetCommandRequest)(nil), // 88: grpc.service.webservice.GetCommandRequest + (*GetCommandResponse)(nil), // 89: grpc.service.webservice.GetCommandResponse + (*GenerateAPIKeyRequest)(nil), // 90: grpc.service.webservice.GenerateAPIKeyRequest + (*GenerateAPIKeyResponse)(nil), // 91: grpc.service.webservice.GenerateAPIKeyResponse + (*DisableAPIKeyRequest)(nil), // 92: grpc.service.webservice.DisableAPIKeyRequest + (*DisableAPIKeyResponse)(nil), // 93: grpc.service.webservice.DisableAPIKeyResponse + (*ListAPIKeysRequest)(nil), // 94: grpc.service.webservice.ListAPIKeysRequest + (*ListAPIKeysResponse)(nil), // 95: grpc.service.webservice.ListAPIKeysResponse + (*GetInsightDataRequest)(nil), // 96: grpc.service.webservice.GetInsightDataRequest + (*GetInsightDataResponse)(nil), // 97: grpc.service.webservice.GetInsightDataResponse + (*GetInsightApplicationCountRequest)(nil), // 98: grpc.service.webservice.GetInsightApplicationCountRequest + (*GetInsightApplicationCountResponse)(nil), // 99: grpc.service.webservice.GetInsightApplicationCountResponse + (*ListDeploymentChainsRequest)(nil), // 100: grpc.service.webservice.ListDeploymentChainsRequest + (*ListDeploymentChainsResponse)(nil), // 101: grpc.service.webservice.ListDeploymentChainsResponse + (*GetDeploymentChainRequest)(nil), // 102: grpc.service.webservice.GetDeploymentChainRequest + (*GetDeploymentChainResponse)(nil), // 103: grpc.service.webservice.GetDeploymentChainResponse + (*ListEventsRequest)(nil), // 104: grpc.service.webservice.ListEventsRequest + (*ListEventsResponse)(nil), // 105: grpc.service.webservice.ListEventsResponse + (*ListPipedsRequest_Options)(nil), // 106: grpc.service.webservice.ListPipedsRequest.Options + nil, // 107: grpc.service.webservice.AddApplicationRequest.DeployTargetsByPluginEntry + nil, // 108: grpc.service.webservice.AddApplicationRequest.LabelsEntry + nil, // 109: grpc.service.webservice.UpdateApplicationRequest.DeployTargetsByPluginEntry + (*ListApplicationsRequest_Options)(nil), // 110: grpc.service.webservice.ListApplicationsRequest.Options + nil, // 111: grpc.service.webservice.ListApplicationsRequest.Options.LabelsEntry + (*ListDeploymentsRequest_Options)(nil), // 112: grpc.service.webservice.ListDeploymentsRequest.Options + nil, // 113: grpc.service.webservice.ListDeploymentsRequest.Options.LabelsEntry + (*ListDeploymentTracesRequest_Options)(nil), // 114: grpc.service.webservice.ListDeploymentTracesRequest.Options + (*ListDeploymentTracesResponse_DeploymentTraceRes)(nil), // 115: grpc.service.webservice.ListDeploymentTracesResponse.DeploymentTraceRes + (*ListAPIKeysRequest_Options)(nil), // 116: grpc.service.webservice.ListAPIKeysRequest.Options + nil, // 117: grpc.service.webservice.GetInsightDataRequest.LabelsEntry + (*ListDeploymentChainsRequest_Options)(nil), // 118: grpc.service.webservice.ListDeploymentChainsRequest.Options + (*ListEventsRequest_Options)(nil), // 119: grpc.service.webservice.ListEventsRequest.Options + nil, // 120: grpc.service.webservice.ListEventsRequest.Options.LabelsEntry + (*model.Piped)(nil), // 121: model.Piped + (*model.ApplicationGitPath)(nil), // 122: model.ApplicationGitPath + (model.ApplicationKind)(0), // 123: model.ApplicationKind + (*model.Application)(nil), // 124: model.Application + (model.SyncStrategy)(0), // 125: model.SyncStrategy + (*model.ApplicationInfo)(nil), // 126: model.ApplicationInfo + (*model.Deployment)(nil), // 127: model.Deployment + (*model.LogBlock)(nil), // 128: model.LogBlock + (*model.ApplicationLiveStateSnapshot)(nil), // 129: model.ApplicationLiveStateSnapshot + (*model.Project)(nil), // 130: model.Project + (*model.ProjectSSOConfig)(nil), // 131: model.ProjectSSOConfig + (*model.ProjectRBACConfig)(nil), // 132: model.ProjectRBACConfig + (*model.ProjectRBACPolicy)(nil), // 133: model.ProjectRBACPolicy + (*model.Command)(nil), // 134: model.Command + (model.APIKey_Role)(0), // 135: model.APIKey.Role + (*model.APIKey)(nil), // 136: model.APIKey + (model.InsightMetricsKind)(0), // 137: model.InsightMetricsKind + (model.InsightResolution)(0), // 138: model.InsightResolution + (model.InsightResultType)(0), // 139: model.InsightResultType + (*model.InsightSample)(nil), // 140: model.InsightSample + (*model.InsightSampleStream)(nil), // 141: model.InsightSampleStream + (*model.InsightApplicationCount)(nil), // 142: model.InsightApplicationCount + (*model.DeploymentChain)(nil), // 143: model.DeploymentChain + (*model.Event)(nil), // 144: model.Event + (*wrapperspb.BoolValue)(nil), // 145: google.protobuf.BoolValue + (*model.DeployTargets)(nil), // 146: model.DeployTargets + (model.ApplicationSyncStatus)(0), // 147: model.ApplicationSyncStatus + (model.DeploymentStatus)(0), // 148: model.DeploymentStatus + (*model.DeploymentTrace)(nil), // 149: model.DeploymentTrace + (model.EventStatus)(0), // 150: model.EventStatus } var file_pkg_app_server_service_webservice_service_proto_depIdxs = []int32{ - 102, // 0: grpc.service.webservice.ListPipedsRequest.options:type_name -> grpc.service.webservice.ListPipedsRequest.Options - 117, // 1: grpc.service.webservice.ListPipedsResponse.pipeds:type_name -> model.Piped - 117, // 2: grpc.service.webservice.GetPipedResponse.piped:type_name -> model.Piped - 118, // 3: grpc.service.webservice.AddApplicationRequest.git_path:type_name -> model.ApplicationGitPath - 119, // 4: grpc.service.webservice.AddApplicationRequest.kind:type_name -> model.ApplicationKind - 103, // 5: grpc.service.webservice.AddApplicationRequest.deploy_targets_by_plugin:type_name -> grpc.service.webservice.AddApplicationRequest.DeployTargetsByPluginEntry - 104, // 6: grpc.service.webservice.AddApplicationRequest.labels:type_name -> grpc.service.webservice.AddApplicationRequest.LabelsEntry - 119, // 7: grpc.service.webservice.UpdateApplicationRequest.kind:type_name -> model.ApplicationKind - 105, // 8: grpc.service.webservice.UpdateApplicationRequest.deploy_targets_by_plugin:type_name -> grpc.service.webservice.UpdateApplicationRequest.DeployTargetsByPluginEntry - 106, // 9: grpc.service.webservice.ListApplicationsRequest.options:type_name -> grpc.service.webservice.ListApplicationsRequest.Options - 120, // 10: grpc.service.webservice.ListApplicationsResponse.applications:type_name -> model.Application - 121, // 11: grpc.service.webservice.SyncApplicationRequest.sync_strategy:type_name -> model.SyncStrategy - 120, // 12: grpc.service.webservice.GetApplicationResponse.application:type_name -> model.Application - 122, // 13: grpc.service.webservice.ListUnregisteredApplicationsResponse.applications:type_name -> model.ApplicationInfo - 108, // 14: grpc.service.webservice.ListDeploymentsRequest.options:type_name -> grpc.service.webservice.ListDeploymentsRequest.Options - 123, // 15: grpc.service.webservice.ListDeploymentsResponse.deployments:type_name -> model.Deployment - 123, // 16: grpc.service.webservice.GetDeploymentResponse.deployment:type_name -> model.Deployment - 124, // 17: grpc.service.webservice.GetStageLogResponse.blocks:type_name -> model.LogBlock - 110, // 18: grpc.service.webservice.ListDeploymentTracesRequest.options:type_name -> grpc.service.webservice.ListDeploymentTracesRequest.Options - 111, // 19: grpc.service.webservice.ListDeploymentTracesResponse.traces:type_name -> grpc.service.webservice.ListDeploymentTracesResponse.DeploymentTraceRes - 125, // 20: grpc.service.webservice.GetApplicationLiveStateResponse.snapshot:type_name -> model.ApplicationLiveStateSnapshot - 126, // 21: grpc.service.webservice.GetProjectResponse.project:type_name -> model.Project - 127, // 22: grpc.service.webservice.UpdateProjectSSOConfigRequest.sso:type_name -> model.ProjectSSOConfig - 128, // 23: grpc.service.webservice.UpdateProjectRBACConfigRequest.rbac:type_name -> model.ProjectRBACConfig - 129, // 24: grpc.service.webservice.AddProjectRBACRoleRequest.policies:type_name -> model.ProjectRBACPolicy - 129, // 25: grpc.service.webservice.UpdateProjectRBACRoleRequest.policies:type_name -> model.ProjectRBACPolicy - 130, // 26: grpc.service.webservice.GetCommandResponse.command:type_name -> model.Command - 131, // 27: grpc.service.webservice.GenerateAPIKeyRequest.role:type_name -> model.APIKey.Role - 112, // 28: grpc.service.webservice.ListAPIKeysRequest.options:type_name -> grpc.service.webservice.ListAPIKeysRequest.Options - 132, // 29: grpc.service.webservice.ListAPIKeysResponse.keys:type_name -> model.APIKey - 133, // 30: grpc.service.webservice.GetInsightDataRequest.metrics_kind:type_name -> model.InsightMetricsKind - 134, // 31: grpc.service.webservice.GetInsightDataRequest.resolution:type_name -> model.InsightResolution - 113, // 32: grpc.service.webservice.GetInsightDataRequest.labels:type_name -> grpc.service.webservice.GetInsightDataRequest.LabelsEntry - 135, // 33: grpc.service.webservice.GetInsightDataResponse.type:type_name -> model.InsightResultType - 136, // 34: grpc.service.webservice.GetInsightDataResponse.vector:type_name -> model.InsightSample - 137, // 35: grpc.service.webservice.GetInsightDataResponse.matrix:type_name -> model.InsightSampleStream - 138, // 36: grpc.service.webservice.GetInsightApplicationCountResponse.counts:type_name -> model.InsightApplicationCount - 114, // 37: grpc.service.webservice.ListDeploymentChainsRequest.options:type_name -> grpc.service.webservice.ListDeploymentChainsRequest.Options - 139, // 38: grpc.service.webservice.ListDeploymentChainsResponse.deployment_chains:type_name -> model.DeploymentChain - 139, // 39: grpc.service.webservice.GetDeploymentChainResponse.deployment_chain:type_name -> model.DeploymentChain - 115, // 40: grpc.service.webservice.ListEventsRequest.options:type_name -> grpc.service.webservice.ListEventsRequest.Options - 140, // 41: grpc.service.webservice.ListEventsResponse.events:type_name -> model.Event - 141, // 42: grpc.service.webservice.ListPipedsRequest.Options.enabled:type_name -> google.protobuf.BoolValue - 142, // 43: grpc.service.webservice.AddApplicationRequest.DeployTargetsByPluginEntry.value:type_name -> model.DeployTargets - 142, // 44: grpc.service.webservice.UpdateApplicationRequest.DeployTargetsByPluginEntry.value:type_name -> model.DeployTargets - 141, // 45: grpc.service.webservice.ListApplicationsRequest.Options.enabled:type_name -> google.protobuf.BoolValue - 119, // 46: grpc.service.webservice.ListApplicationsRequest.Options.kinds:type_name -> model.ApplicationKind - 143, // 47: grpc.service.webservice.ListApplicationsRequest.Options.sync_statuses:type_name -> model.ApplicationSyncStatus - 107, // 48: grpc.service.webservice.ListApplicationsRequest.Options.labels:type_name -> grpc.service.webservice.ListApplicationsRequest.Options.LabelsEntry - 144, // 49: grpc.service.webservice.ListDeploymentsRequest.Options.statuses:type_name -> model.DeploymentStatus - 119, // 50: grpc.service.webservice.ListDeploymentsRequest.Options.kinds:type_name -> model.ApplicationKind - 109, // 51: grpc.service.webservice.ListDeploymentsRequest.Options.labels:type_name -> grpc.service.webservice.ListDeploymentsRequest.Options.LabelsEntry - 145, // 52: grpc.service.webservice.ListDeploymentTracesResponse.DeploymentTraceRes.trace:type_name -> model.DeploymentTrace - 123, // 53: grpc.service.webservice.ListDeploymentTracesResponse.DeploymentTraceRes.deployments:type_name -> model.Deployment - 141, // 54: grpc.service.webservice.ListAPIKeysRequest.Options.enabled:type_name -> google.protobuf.BoolValue - 146, // 55: grpc.service.webservice.ListEventsRequest.Options.statuses:type_name -> model.EventStatus - 116, // 56: grpc.service.webservice.ListEventsRequest.Options.labels:type_name -> grpc.service.webservice.ListEventsRequest.Options.LabelsEntry + 106, // 0: grpc.service.webservice.ListPipedsRequest.options:type_name -> grpc.service.webservice.ListPipedsRequest.Options + 121, // 1: grpc.service.webservice.ListPipedsResponse.pipeds:type_name -> model.Piped + 121, // 2: grpc.service.webservice.GetPipedResponse.piped:type_name -> model.Piped + 122, // 3: grpc.service.webservice.AddApplicationRequest.git_path:type_name -> model.ApplicationGitPath + 123, // 4: grpc.service.webservice.AddApplicationRequest.kind:type_name -> model.ApplicationKind + 107, // 5: grpc.service.webservice.AddApplicationRequest.deploy_targets_by_plugin:type_name -> grpc.service.webservice.AddApplicationRequest.DeployTargetsByPluginEntry + 108, // 6: grpc.service.webservice.AddApplicationRequest.labels:type_name -> grpc.service.webservice.AddApplicationRequest.LabelsEntry + 123, // 7: grpc.service.webservice.UpdateApplicationRequest.kind:type_name -> model.ApplicationKind + 109, // 8: grpc.service.webservice.UpdateApplicationRequest.deploy_targets_by_plugin:type_name -> grpc.service.webservice.UpdateApplicationRequest.DeployTargetsByPluginEntry + 110, // 9: grpc.service.webservice.ListApplicationsRequest.options:type_name -> grpc.service.webservice.ListApplicationsRequest.Options + 124, // 10: grpc.service.webservice.ListApplicationsResponse.applications:type_name -> model.Application + 125, // 11: grpc.service.webservice.SyncApplicationRequest.sync_strategy:type_name -> model.SyncStrategy + 124, // 12: grpc.service.webservice.GetApplicationResponse.application:type_name -> model.Application + 126, // 13: grpc.service.webservice.ListUnregisteredApplicationsResponse.applications:type_name -> model.ApplicationInfo + 112, // 14: grpc.service.webservice.ListDeploymentsRequest.options:type_name -> grpc.service.webservice.ListDeploymentsRequest.Options + 127, // 15: grpc.service.webservice.ListDeploymentsResponse.deployments:type_name -> model.Deployment + 127, // 16: grpc.service.webservice.GetDeploymentResponse.deployment:type_name -> model.Deployment + 128, // 17: grpc.service.webservice.GetStageLogResponse.blocks:type_name -> model.LogBlock + 114, // 18: grpc.service.webservice.ListDeploymentTracesRequest.options:type_name -> grpc.service.webservice.ListDeploymentTracesRequest.Options + 115, // 19: grpc.service.webservice.ListDeploymentTracesResponse.traces:type_name -> grpc.service.webservice.ListDeploymentTracesResponse.DeploymentTraceRes + 129, // 20: grpc.service.webservice.GetApplicationLiveStateResponse.snapshot:type_name -> model.ApplicationLiveStateSnapshot + 130, // 21: grpc.service.webservice.GetProjectResponse.project:type_name -> model.Project + 131, // 22: grpc.service.webservice.UpdateProjectSSOConfigRequest.sso:type_name -> model.ProjectSSOConfig + 132, // 23: grpc.service.webservice.UpdateProjectRBACConfigRequest.rbac:type_name -> model.ProjectRBACConfig + 133, // 24: grpc.service.webservice.AddProjectRBACRoleRequest.policies:type_name -> model.ProjectRBACPolicy + 133, // 25: grpc.service.webservice.UpdateProjectRBACRoleRequest.policies:type_name -> model.ProjectRBACPolicy + 134, // 26: grpc.service.webservice.GetCommandResponse.command:type_name -> model.Command + 135, // 27: grpc.service.webservice.GenerateAPIKeyRequest.role:type_name -> model.APIKey.Role + 116, // 28: grpc.service.webservice.ListAPIKeysRequest.options:type_name -> grpc.service.webservice.ListAPIKeysRequest.Options + 136, // 29: grpc.service.webservice.ListAPIKeysResponse.keys:type_name -> model.APIKey + 137, // 30: grpc.service.webservice.GetInsightDataRequest.metrics_kind:type_name -> model.InsightMetricsKind + 138, // 31: grpc.service.webservice.GetInsightDataRequest.resolution:type_name -> model.InsightResolution + 117, // 32: grpc.service.webservice.GetInsightDataRequest.labels:type_name -> grpc.service.webservice.GetInsightDataRequest.LabelsEntry + 139, // 33: grpc.service.webservice.GetInsightDataResponse.type:type_name -> model.InsightResultType + 140, // 34: grpc.service.webservice.GetInsightDataResponse.vector:type_name -> model.InsightSample + 141, // 35: grpc.service.webservice.GetInsightDataResponse.matrix:type_name -> model.InsightSampleStream + 142, // 36: grpc.service.webservice.GetInsightApplicationCountResponse.counts:type_name -> model.InsightApplicationCount + 118, // 37: grpc.service.webservice.ListDeploymentChainsRequest.options:type_name -> grpc.service.webservice.ListDeploymentChainsRequest.Options + 143, // 38: grpc.service.webservice.ListDeploymentChainsResponse.deployment_chains:type_name -> model.DeploymentChain + 143, // 39: grpc.service.webservice.GetDeploymentChainResponse.deployment_chain:type_name -> model.DeploymentChain + 119, // 40: grpc.service.webservice.ListEventsRequest.options:type_name -> grpc.service.webservice.ListEventsRequest.Options + 144, // 41: grpc.service.webservice.ListEventsResponse.events:type_name -> model.Event + 145, // 42: grpc.service.webservice.ListPipedsRequest.Options.enabled:type_name -> google.protobuf.BoolValue + 146, // 43: grpc.service.webservice.AddApplicationRequest.DeployTargetsByPluginEntry.value:type_name -> model.DeployTargets + 146, // 44: grpc.service.webservice.UpdateApplicationRequest.DeployTargetsByPluginEntry.value:type_name -> model.DeployTargets + 145, // 45: grpc.service.webservice.ListApplicationsRequest.Options.enabled:type_name -> google.protobuf.BoolValue + 123, // 46: grpc.service.webservice.ListApplicationsRequest.Options.kinds:type_name -> model.ApplicationKind + 147, // 47: grpc.service.webservice.ListApplicationsRequest.Options.sync_statuses:type_name -> model.ApplicationSyncStatus + 111, // 48: grpc.service.webservice.ListApplicationsRequest.Options.labels:type_name -> grpc.service.webservice.ListApplicationsRequest.Options.LabelsEntry + 148, // 49: grpc.service.webservice.ListDeploymentsRequest.Options.statuses:type_name -> model.DeploymentStatus + 123, // 50: grpc.service.webservice.ListDeploymentsRequest.Options.kinds:type_name -> model.ApplicationKind + 113, // 51: grpc.service.webservice.ListDeploymentsRequest.Options.labels:type_name -> grpc.service.webservice.ListDeploymentsRequest.Options.LabelsEntry + 149, // 52: grpc.service.webservice.ListDeploymentTracesResponse.DeploymentTraceRes.trace:type_name -> model.DeploymentTrace + 127, // 53: grpc.service.webservice.ListDeploymentTracesResponse.DeploymentTraceRes.deployments:type_name -> model.Deployment + 145, // 54: grpc.service.webservice.ListAPIKeysRequest.Options.enabled:type_name -> google.protobuf.BoolValue + 150, // 55: grpc.service.webservice.ListEventsRequest.Options.statuses:type_name -> model.EventStatus + 120, // 56: grpc.service.webservice.ListEventsRequest.Options.labels:type_name -> grpc.service.webservice.ListEventsRequest.Options.LabelsEntry 0, // 57: grpc.service.webservice.WebService.RegisterPiped:input_type -> grpc.service.webservice.RegisterPipedRequest 2, // 58: grpc.service.webservice.WebService.UpdatePiped:input_type -> grpc.service.webservice.UpdatePipedRequest 4, // 59: grpc.service.webservice.WebService.RecreatePipedKey:input_type -> grpc.service.webservice.RecreatePipedKeyRequest @@ -6948,74 +7127,78 @@ var file_pkg_app_server_service_webservice_service_proto_depIdxs = []int32{ 70, // 90: grpc.service.webservice.WebService.DisableStaticAdmin:input_type -> grpc.service.webservice.DisableStaticAdminRequest 64, // 91: grpc.service.webservice.WebService.UpdateProjectSSOConfig:input_type -> grpc.service.webservice.UpdateProjectSSOConfigRequest 66, // 92: grpc.service.webservice.WebService.UpdateProjectRBACConfig:input_type -> grpc.service.webservice.UpdateProjectRBACConfigRequest - 72, // 93: grpc.service.webservice.WebService.GetMe:input_type -> grpc.service.webservice.GetMeRequest - 74, // 94: grpc.service.webservice.WebService.AddProjectRBACRole:input_type -> grpc.service.webservice.AddProjectRBACRoleRequest - 76, // 95: grpc.service.webservice.WebService.UpdateProjectRBACRole:input_type -> grpc.service.webservice.UpdateProjectRBACRoleRequest - 78, // 96: grpc.service.webservice.WebService.DeleteProjectRBACRole:input_type -> grpc.service.webservice.DeleteProjectRBACRoleRequest - 80, // 97: grpc.service.webservice.WebService.AddProjectUserGroup:input_type -> grpc.service.webservice.AddProjectUserGroupRequest - 82, // 98: grpc.service.webservice.WebService.DeleteProjectUserGroup:input_type -> grpc.service.webservice.DeleteProjectUserGroupRequest - 84, // 99: grpc.service.webservice.WebService.GetCommand:input_type -> grpc.service.webservice.GetCommandRequest - 86, // 100: grpc.service.webservice.WebService.GenerateAPIKey:input_type -> grpc.service.webservice.GenerateAPIKeyRequest - 88, // 101: grpc.service.webservice.WebService.DisableAPIKey:input_type -> grpc.service.webservice.DisableAPIKeyRequest - 90, // 102: grpc.service.webservice.WebService.ListAPIKeys:input_type -> grpc.service.webservice.ListAPIKeysRequest - 92, // 103: grpc.service.webservice.WebService.GetInsightData:input_type -> grpc.service.webservice.GetInsightDataRequest - 94, // 104: grpc.service.webservice.WebService.GetInsightApplicationCount:input_type -> grpc.service.webservice.GetInsightApplicationCountRequest - 96, // 105: grpc.service.webservice.WebService.ListDeploymentChains:input_type -> grpc.service.webservice.ListDeploymentChainsRequest - 98, // 106: grpc.service.webservice.WebService.GetDeploymentChain:input_type -> grpc.service.webservice.GetDeploymentChainRequest - 100, // 107: grpc.service.webservice.WebService.ListEvents:input_type -> grpc.service.webservice.ListEventsRequest - 1, // 108: grpc.service.webservice.WebService.RegisterPiped:output_type -> grpc.service.webservice.RegisterPipedResponse - 3, // 109: grpc.service.webservice.WebService.UpdatePiped:output_type -> grpc.service.webservice.UpdatePipedResponse - 5, // 110: grpc.service.webservice.WebService.RecreatePipedKey:output_type -> grpc.service.webservice.RecreatePipedKeyResponse - 7, // 111: grpc.service.webservice.WebService.DeleteOldPipedKeys:output_type -> grpc.service.webservice.DeleteOldPipedKeysResponse - 9, // 112: grpc.service.webservice.WebService.EnablePiped:output_type -> grpc.service.webservice.EnablePipedResponse - 11, // 113: grpc.service.webservice.WebService.DisablePiped:output_type -> grpc.service.webservice.DisablePipedResponse - 13, // 114: grpc.service.webservice.WebService.ListPipeds:output_type -> grpc.service.webservice.ListPipedsResponse - 15, // 115: grpc.service.webservice.WebService.GetPiped:output_type -> grpc.service.webservice.GetPipedResponse - 17, // 116: grpc.service.webservice.WebService.UpdatePipedDesiredVersion:output_type -> grpc.service.webservice.UpdatePipedDesiredVersionResponse - 19, // 117: grpc.service.webservice.WebService.RestartPiped:output_type -> grpc.service.webservice.RestartPipedResponse - 21, // 118: grpc.service.webservice.WebService.ListReleasedVersions:output_type -> grpc.service.webservice.ListReleasedVersionsResponse - 23, // 119: grpc.service.webservice.WebService.ListDeprecatedNotes:output_type -> grpc.service.webservice.ListDeprecatedNotesResponse - 25, // 120: grpc.service.webservice.WebService.AddApplication:output_type -> grpc.service.webservice.AddApplicationResponse - 27, // 121: grpc.service.webservice.WebService.UpdateApplication:output_type -> grpc.service.webservice.UpdateApplicationResponse - 29, // 122: grpc.service.webservice.WebService.EnableApplication:output_type -> grpc.service.webservice.EnableApplicationResponse - 31, // 123: grpc.service.webservice.WebService.DisableApplication:output_type -> grpc.service.webservice.DisableApplicationResponse - 33, // 124: grpc.service.webservice.WebService.DeleteApplication:output_type -> grpc.service.webservice.DeleteApplicationResponse - 35, // 125: grpc.service.webservice.WebService.ListApplications:output_type -> grpc.service.webservice.ListApplicationsResponse - 37, // 126: grpc.service.webservice.WebService.SyncApplication:output_type -> grpc.service.webservice.SyncApplicationResponse - 39, // 127: grpc.service.webservice.WebService.GetApplication:output_type -> grpc.service.webservice.GetApplicationResponse - 41, // 128: grpc.service.webservice.WebService.GenerateApplicationSealedSecret:output_type -> grpc.service.webservice.GenerateApplicationSealedSecretResponse - 43, // 129: grpc.service.webservice.WebService.ListUnregisteredApplications:output_type -> grpc.service.webservice.ListUnregisteredApplicationsResponse - 45, // 130: grpc.service.webservice.WebService.ListDeployments:output_type -> grpc.service.webservice.ListDeploymentsResponse - 47, // 131: grpc.service.webservice.WebService.GetDeployment:output_type -> grpc.service.webservice.GetDeploymentResponse - 49, // 132: grpc.service.webservice.WebService.GetStageLog:output_type -> grpc.service.webservice.GetStageLogResponse - 51, // 133: grpc.service.webservice.WebService.CancelDeployment:output_type -> grpc.service.webservice.CancelDeploymentResponse - 53, // 134: grpc.service.webservice.WebService.SkipStage:output_type -> grpc.service.webservice.SkipStageResponse - 55, // 135: grpc.service.webservice.WebService.ApproveStage:output_type -> grpc.service.webservice.ApproveStageResponse - 57, // 136: grpc.service.webservice.WebService.ListDeploymentTraces:output_type -> grpc.service.webservice.ListDeploymentTracesResponse - 59, // 137: grpc.service.webservice.WebService.GetApplicationLiveState:output_type -> grpc.service.webservice.GetApplicationLiveStateResponse - 61, // 138: grpc.service.webservice.WebService.GetProject:output_type -> grpc.service.webservice.GetProjectResponse - 63, // 139: grpc.service.webservice.WebService.UpdateProjectStaticAdmin:output_type -> grpc.service.webservice.UpdateProjectStaticAdminResponse - 69, // 140: grpc.service.webservice.WebService.EnableStaticAdmin:output_type -> grpc.service.webservice.EnableStaticAdminResponse - 71, // 141: grpc.service.webservice.WebService.DisableStaticAdmin:output_type -> grpc.service.webservice.DisableStaticAdminResponse - 65, // 142: grpc.service.webservice.WebService.UpdateProjectSSOConfig:output_type -> grpc.service.webservice.UpdateProjectSSOConfigResponse - 67, // 143: grpc.service.webservice.WebService.UpdateProjectRBACConfig:output_type -> grpc.service.webservice.UpdateProjectRBACConfigResponse - 73, // 144: grpc.service.webservice.WebService.GetMe:output_type -> grpc.service.webservice.GetMeResponse - 75, // 145: grpc.service.webservice.WebService.AddProjectRBACRole:output_type -> grpc.service.webservice.AddProjectRBACRoleResponse - 77, // 146: grpc.service.webservice.WebService.UpdateProjectRBACRole:output_type -> grpc.service.webservice.UpdateProjectRBACRoleResponse - 79, // 147: grpc.service.webservice.WebService.DeleteProjectRBACRole:output_type -> grpc.service.webservice.DeleteProjectRBACRoleResponse - 81, // 148: grpc.service.webservice.WebService.AddProjectUserGroup:output_type -> grpc.service.webservice.AddProjectUserGroupResponse - 83, // 149: grpc.service.webservice.WebService.DeleteProjectUserGroup:output_type -> grpc.service.webservice.DeleteProjectUserGroupResponse - 85, // 150: grpc.service.webservice.WebService.GetCommand:output_type -> grpc.service.webservice.GetCommandResponse - 87, // 151: grpc.service.webservice.WebService.GenerateAPIKey:output_type -> grpc.service.webservice.GenerateAPIKeyResponse - 89, // 152: grpc.service.webservice.WebService.DisableAPIKey:output_type -> grpc.service.webservice.DisableAPIKeyResponse - 91, // 153: grpc.service.webservice.WebService.ListAPIKeys:output_type -> grpc.service.webservice.ListAPIKeysResponse - 93, // 154: grpc.service.webservice.WebService.GetInsightData:output_type -> grpc.service.webservice.GetInsightDataResponse - 95, // 155: grpc.service.webservice.WebService.GetInsightApplicationCount:output_type -> grpc.service.webservice.GetInsightApplicationCountResponse - 97, // 156: grpc.service.webservice.WebService.ListDeploymentChains:output_type -> grpc.service.webservice.ListDeploymentChainsResponse - 99, // 157: grpc.service.webservice.WebService.GetDeploymentChain:output_type -> grpc.service.webservice.GetDeploymentChainResponse - 101, // 158: grpc.service.webservice.WebService.ListEvents:output_type -> grpc.service.webservice.ListEventsResponse - 108, // [108:159] is the sub-list for method output_type - 57, // [57:108] is the sub-list for method input_type + 72, // 93: grpc.service.webservice.WebService.EnableProject:input_type -> grpc.service.webservice.EnableProjectRequest + 74, // 94: grpc.service.webservice.WebService.DisableProject:input_type -> grpc.service.webservice.DisableProjectRequest + 76, // 95: grpc.service.webservice.WebService.GetMe:input_type -> grpc.service.webservice.GetMeRequest + 78, // 96: grpc.service.webservice.WebService.AddProjectRBACRole:input_type -> grpc.service.webservice.AddProjectRBACRoleRequest + 80, // 97: grpc.service.webservice.WebService.UpdateProjectRBACRole:input_type -> grpc.service.webservice.UpdateProjectRBACRoleRequest + 82, // 98: grpc.service.webservice.WebService.DeleteProjectRBACRole:input_type -> grpc.service.webservice.DeleteProjectRBACRoleRequest + 84, // 99: grpc.service.webservice.WebService.AddProjectUserGroup:input_type -> grpc.service.webservice.AddProjectUserGroupRequest + 86, // 100: grpc.service.webservice.WebService.DeleteProjectUserGroup:input_type -> grpc.service.webservice.DeleteProjectUserGroupRequest + 88, // 101: grpc.service.webservice.WebService.GetCommand:input_type -> grpc.service.webservice.GetCommandRequest + 90, // 102: grpc.service.webservice.WebService.GenerateAPIKey:input_type -> grpc.service.webservice.GenerateAPIKeyRequest + 92, // 103: grpc.service.webservice.WebService.DisableAPIKey:input_type -> grpc.service.webservice.DisableAPIKeyRequest + 94, // 104: grpc.service.webservice.WebService.ListAPIKeys:input_type -> grpc.service.webservice.ListAPIKeysRequest + 96, // 105: grpc.service.webservice.WebService.GetInsightData:input_type -> grpc.service.webservice.GetInsightDataRequest + 98, // 106: grpc.service.webservice.WebService.GetInsightApplicationCount:input_type -> grpc.service.webservice.GetInsightApplicationCountRequest + 100, // 107: grpc.service.webservice.WebService.ListDeploymentChains:input_type -> grpc.service.webservice.ListDeploymentChainsRequest + 102, // 108: grpc.service.webservice.WebService.GetDeploymentChain:input_type -> grpc.service.webservice.GetDeploymentChainRequest + 104, // 109: grpc.service.webservice.WebService.ListEvents:input_type -> grpc.service.webservice.ListEventsRequest + 1, // 110: grpc.service.webservice.WebService.RegisterPiped:output_type -> grpc.service.webservice.RegisterPipedResponse + 3, // 111: grpc.service.webservice.WebService.UpdatePiped:output_type -> grpc.service.webservice.UpdatePipedResponse + 5, // 112: grpc.service.webservice.WebService.RecreatePipedKey:output_type -> grpc.service.webservice.RecreatePipedKeyResponse + 7, // 113: grpc.service.webservice.WebService.DeleteOldPipedKeys:output_type -> grpc.service.webservice.DeleteOldPipedKeysResponse + 9, // 114: grpc.service.webservice.WebService.EnablePiped:output_type -> grpc.service.webservice.EnablePipedResponse + 11, // 115: grpc.service.webservice.WebService.DisablePiped:output_type -> grpc.service.webservice.DisablePipedResponse + 13, // 116: grpc.service.webservice.WebService.ListPipeds:output_type -> grpc.service.webservice.ListPipedsResponse + 15, // 117: grpc.service.webservice.WebService.GetPiped:output_type -> grpc.service.webservice.GetPipedResponse + 17, // 118: grpc.service.webservice.WebService.UpdatePipedDesiredVersion:output_type -> grpc.service.webservice.UpdatePipedDesiredVersionResponse + 19, // 119: grpc.service.webservice.WebService.RestartPiped:output_type -> grpc.service.webservice.RestartPipedResponse + 21, // 120: grpc.service.webservice.WebService.ListReleasedVersions:output_type -> grpc.service.webservice.ListReleasedVersionsResponse + 23, // 121: grpc.service.webservice.WebService.ListDeprecatedNotes:output_type -> grpc.service.webservice.ListDeprecatedNotesResponse + 25, // 122: grpc.service.webservice.WebService.AddApplication:output_type -> grpc.service.webservice.AddApplicationResponse + 27, // 123: grpc.service.webservice.WebService.UpdateApplication:output_type -> grpc.service.webservice.UpdateApplicationResponse + 29, // 124: grpc.service.webservice.WebService.EnableApplication:output_type -> grpc.service.webservice.EnableApplicationResponse + 31, // 125: grpc.service.webservice.WebService.DisableApplication:output_type -> grpc.service.webservice.DisableApplicationResponse + 33, // 126: grpc.service.webservice.WebService.DeleteApplication:output_type -> grpc.service.webservice.DeleteApplicationResponse + 35, // 127: grpc.service.webservice.WebService.ListApplications:output_type -> grpc.service.webservice.ListApplicationsResponse + 37, // 128: grpc.service.webservice.WebService.SyncApplication:output_type -> grpc.service.webservice.SyncApplicationResponse + 39, // 129: grpc.service.webservice.WebService.GetApplication:output_type -> grpc.service.webservice.GetApplicationResponse + 41, // 130: grpc.service.webservice.WebService.GenerateApplicationSealedSecret:output_type -> grpc.service.webservice.GenerateApplicationSealedSecretResponse + 43, // 131: grpc.service.webservice.WebService.ListUnregisteredApplications:output_type -> grpc.service.webservice.ListUnregisteredApplicationsResponse + 45, // 132: grpc.service.webservice.WebService.ListDeployments:output_type -> grpc.service.webservice.ListDeploymentsResponse + 47, // 133: grpc.service.webservice.WebService.GetDeployment:output_type -> grpc.service.webservice.GetDeploymentResponse + 49, // 134: grpc.service.webservice.WebService.GetStageLog:output_type -> grpc.service.webservice.GetStageLogResponse + 51, // 135: grpc.service.webservice.WebService.CancelDeployment:output_type -> grpc.service.webservice.CancelDeploymentResponse + 53, // 136: grpc.service.webservice.WebService.SkipStage:output_type -> grpc.service.webservice.SkipStageResponse + 55, // 137: grpc.service.webservice.WebService.ApproveStage:output_type -> grpc.service.webservice.ApproveStageResponse + 57, // 138: grpc.service.webservice.WebService.ListDeploymentTraces:output_type -> grpc.service.webservice.ListDeploymentTracesResponse + 59, // 139: grpc.service.webservice.WebService.GetApplicationLiveState:output_type -> grpc.service.webservice.GetApplicationLiveStateResponse + 61, // 140: grpc.service.webservice.WebService.GetProject:output_type -> grpc.service.webservice.GetProjectResponse + 63, // 141: grpc.service.webservice.WebService.UpdateProjectStaticAdmin:output_type -> grpc.service.webservice.UpdateProjectStaticAdminResponse + 69, // 142: grpc.service.webservice.WebService.EnableStaticAdmin:output_type -> grpc.service.webservice.EnableStaticAdminResponse + 71, // 143: grpc.service.webservice.WebService.DisableStaticAdmin:output_type -> grpc.service.webservice.DisableStaticAdminResponse + 65, // 144: grpc.service.webservice.WebService.UpdateProjectSSOConfig:output_type -> grpc.service.webservice.UpdateProjectSSOConfigResponse + 67, // 145: grpc.service.webservice.WebService.UpdateProjectRBACConfig:output_type -> grpc.service.webservice.UpdateProjectRBACConfigResponse + 73, // 146: grpc.service.webservice.WebService.EnableProject:output_type -> grpc.service.webservice.EnableProjectResponse + 75, // 147: grpc.service.webservice.WebService.DisableProject:output_type -> grpc.service.webservice.DisableProjectResponse + 77, // 148: grpc.service.webservice.WebService.GetMe:output_type -> grpc.service.webservice.GetMeResponse + 79, // 149: grpc.service.webservice.WebService.AddProjectRBACRole:output_type -> grpc.service.webservice.AddProjectRBACRoleResponse + 81, // 150: grpc.service.webservice.WebService.UpdateProjectRBACRole:output_type -> grpc.service.webservice.UpdateProjectRBACRoleResponse + 83, // 151: grpc.service.webservice.WebService.DeleteProjectRBACRole:output_type -> grpc.service.webservice.DeleteProjectRBACRoleResponse + 85, // 152: grpc.service.webservice.WebService.AddProjectUserGroup:output_type -> grpc.service.webservice.AddProjectUserGroupResponse + 87, // 153: grpc.service.webservice.WebService.DeleteProjectUserGroup:output_type -> grpc.service.webservice.DeleteProjectUserGroupResponse + 89, // 154: grpc.service.webservice.WebService.GetCommand:output_type -> grpc.service.webservice.GetCommandResponse + 91, // 155: grpc.service.webservice.WebService.GenerateAPIKey:output_type -> grpc.service.webservice.GenerateAPIKeyResponse + 93, // 156: grpc.service.webservice.WebService.DisableAPIKey:output_type -> grpc.service.webservice.DisableAPIKeyResponse + 95, // 157: grpc.service.webservice.WebService.ListAPIKeys:output_type -> grpc.service.webservice.ListAPIKeysResponse + 97, // 158: grpc.service.webservice.WebService.GetInsightData:output_type -> grpc.service.webservice.GetInsightDataResponse + 99, // 159: grpc.service.webservice.WebService.GetInsightApplicationCount:output_type -> grpc.service.webservice.GetInsightApplicationCountResponse + 101, // 160: grpc.service.webservice.WebService.ListDeploymentChains:output_type -> grpc.service.webservice.ListDeploymentChainsResponse + 103, // 161: grpc.service.webservice.WebService.GetDeploymentChain:output_type -> grpc.service.webservice.GetDeploymentChainResponse + 105, // 162: grpc.service.webservice.WebService.ListEvents:output_type -> grpc.service.webservice.ListEventsResponse + 110, // [110:163] is the sub-list for method output_type + 57, // [57:110] is the sub-list for method input_type 57, // [57:57] is the sub-list for extension type_name 57, // [57:57] is the sub-list for extension extendee 0, // [0:57] is the sub-list for field type_name @@ -7892,7 +8075,7 @@ func file_pkg_app_server_service_webservice_service_proto_init() { } } file_pkg_app_server_service_webservice_service_proto_msgTypes[72].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetMeRequest); i { + switch v := v.(*EnableProjectRequest); i { case 0: return &v.state case 1: @@ -7904,7 +8087,7 @@ func file_pkg_app_server_service_webservice_service_proto_init() { } } file_pkg_app_server_service_webservice_service_proto_msgTypes[73].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetMeResponse); i { + switch v := v.(*EnableProjectResponse); i { case 0: return &v.state case 1: @@ -7916,7 +8099,7 @@ func file_pkg_app_server_service_webservice_service_proto_init() { } } file_pkg_app_server_service_webservice_service_proto_msgTypes[74].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*AddProjectRBACRoleRequest); i { + switch v := v.(*DisableProjectRequest); i { case 0: return &v.state case 1: @@ -7928,7 +8111,7 @@ func file_pkg_app_server_service_webservice_service_proto_init() { } } file_pkg_app_server_service_webservice_service_proto_msgTypes[75].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*AddProjectRBACRoleResponse); i { + switch v := v.(*DisableProjectResponse); i { case 0: return &v.state case 1: @@ -7940,7 +8123,7 @@ func file_pkg_app_server_service_webservice_service_proto_init() { } } file_pkg_app_server_service_webservice_service_proto_msgTypes[76].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*UpdateProjectRBACRoleRequest); i { + switch v := v.(*GetMeRequest); i { case 0: return &v.state case 1: @@ -7952,7 +8135,7 @@ func file_pkg_app_server_service_webservice_service_proto_init() { } } file_pkg_app_server_service_webservice_service_proto_msgTypes[77].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*UpdateProjectRBACRoleResponse); i { + switch v := v.(*GetMeResponse); i { case 0: return &v.state case 1: @@ -7964,7 +8147,7 @@ func file_pkg_app_server_service_webservice_service_proto_init() { } } file_pkg_app_server_service_webservice_service_proto_msgTypes[78].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DeleteProjectRBACRoleRequest); i { + switch v := v.(*AddProjectRBACRoleRequest); i { case 0: return &v.state case 1: @@ -7976,7 +8159,7 @@ func file_pkg_app_server_service_webservice_service_proto_init() { } } file_pkg_app_server_service_webservice_service_proto_msgTypes[79].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DeleteProjectRBACRoleResponse); i { + switch v := v.(*AddProjectRBACRoleResponse); i { case 0: return &v.state case 1: @@ -7988,7 +8171,7 @@ func file_pkg_app_server_service_webservice_service_proto_init() { } } file_pkg_app_server_service_webservice_service_proto_msgTypes[80].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*AddProjectUserGroupRequest); i { + switch v := v.(*UpdateProjectRBACRoleRequest); i { case 0: return &v.state case 1: @@ -8000,7 +8183,7 @@ func file_pkg_app_server_service_webservice_service_proto_init() { } } file_pkg_app_server_service_webservice_service_proto_msgTypes[81].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*AddProjectUserGroupResponse); i { + switch v := v.(*UpdateProjectRBACRoleResponse); i { case 0: return &v.state case 1: @@ -8012,7 +8195,7 @@ func file_pkg_app_server_service_webservice_service_proto_init() { } } file_pkg_app_server_service_webservice_service_proto_msgTypes[82].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DeleteProjectUserGroupRequest); i { + switch v := v.(*DeleteProjectRBACRoleRequest); i { case 0: return &v.state case 1: @@ -8024,7 +8207,7 @@ func file_pkg_app_server_service_webservice_service_proto_init() { } } file_pkg_app_server_service_webservice_service_proto_msgTypes[83].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DeleteProjectUserGroupResponse); i { + switch v := v.(*DeleteProjectRBACRoleResponse); i { case 0: return &v.state case 1: @@ -8036,7 +8219,7 @@ func file_pkg_app_server_service_webservice_service_proto_init() { } } file_pkg_app_server_service_webservice_service_proto_msgTypes[84].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetCommandRequest); i { + switch v := v.(*AddProjectUserGroupRequest); i { case 0: return &v.state case 1: @@ -8048,7 +8231,7 @@ func file_pkg_app_server_service_webservice_service_proto_init() { } } file_pkg_app_server_service_webservice_service_proto_msgTypes[85].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetCommandResponse); i { + switch v := v.(*AddProjectUserGroupResponse); i { case 0: return &v.state case 1: @@ -8060,7 +8243,7 @@ func file_pkg_app_server_service_webservice_service_proto_init() { } } file_pkg_app_server_service_webservice_service_proto_msgTypes[86].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GenerateAPIKeyRequest); i { + switch v := v.(*DeleteProjectUserGroupRequest); i { case 0: return &v.state case 1: @@ -8072,7 +8255,7 @@ func file_pkg_app_server_service_webservice_service_proto_init() { } } file_pkg_app_server_service_webservice_service_proto_msgTypes[87].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GenerateAPIKeyResponse); i { + switch v := v.(*DeleteProjectUserGroupResponse); i { case 0: return &v.state case 1: @@ -8084,7 +8267,7 @@ func file_pkg_app_server_service_webservice_service_proto_init() { } } file_pkg_app_server_service_webservice_service_proto_msgTypes[88].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DisableAPIKeyRequest); i { + switch v := v.(*GetCommandRequest); i { case 0: return &v.state case 1: @@ -8096,7 +8279,7 @@ func file_pkg_app_server_service_webservice_service_proto_init() { } } file_pkg_app_server_service_webservice_service_proto_msgTypes[89].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DisableAPIKeyResponse); i { + switch v := v.(*GetCommandResponse); i { case 0: return &v.state case 1: @@ -8108,7 +8291,7 @@ func file_pkg_app_server_service_webservice_service_proto_init() { } } file_pkg_app_server_service_webservice_service_proto_msgTypes[90].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ListAPIKeysRequest); i { + switch v := v.(*GenerateAPIKeyRequest); i { case 0: return &v.state case 1: @@ -8120,7 +8303,7 @@ func file_pkg_app_server_service_webservice_service_proto_init() { } } file_pkg_app_server_service_webservice_service_proto_msgTypes[91].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ListAPIKeysResponse); i { + switch v := v.(*GenerateAPIKeyResponse); i { case 0: return &v.state case 1: @@ -8132,7 +8315,7 @@ func file_pkg_app_server_service_webservice_service_proto_init() { } } file_pkg_app_server_service_webservice_service_proto_msgTypes[92].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetInsightDataRequest); i { + switch v := v.(*DisableAPIKeyRequest); i { case 0: return &v.state case 1: @@ -8144,7 +8327,7 @@ func file_pkg_app_server_service_webservice_service_proto_init() { } } file_pkg_app_server_service_webservice_service_proto_msgTypes[93].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetInsightDataResponse); i { + switch v := v.(*DisableAPIKeyResponse); i { case 0: return &v.state case 1: @@ -8156,7 +8339,7 @@ func file_pkg_app_server_service_webservice_service_proto_init() { } } file_pkg_app_server_service_webservice_service_proto_msgTypes[94].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetInsightApplicationCountRequest); i { + switch v := v.(*ListAPIKeysRequest); i { case 0: return &v.state case 1: @@ -8168,7 +8351,7 @@ func file_pkg_app_server_service_webservice_service_proto_init() { } } file_pkg_app_server_service_webservice_service_proto_msgTypes[95].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetInsightApplicationCountResponse); i { + switch v := v.(*ListAPIKeysResponse); i { case 0: return &v.state case 1: @@ -8180,7 +8363,7 @@ func file_pkg_app_server_service_webservice_service_proto_init() { } } file_pkg_app_server_service_webservice_service_proto_msgTypes[96].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ListDeploymentChainsRequest); i { + switch v := v.(*GetInsightDataRequest); i { case 0: return &v.state case 1: @@ -8192,7 +8375,7 @@ func file_pkg_app_server_service_webservice_service_proto_init() { } } file_pkg_app_server_service_webservice_service_proto_msgTypes[97].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ListDeploymentChainsResponse); i { + switch v := v.(*GetInsightDataResponse); i { case 0: return &v.state case 1: @@ -8204,7 +8387,7 @@ func file_pkg_app_server_service_webservice_service_proto_init() { } } file_pkg_app_server_service_webservice_service_proto_msgTypes[98].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetDeploymentChainRequest); i { + switch v := v.(*GetInsightApplicationCountRequest); i { case 0: return &v.state case 1: @@ -8216,7 +8399,7 @@ func file_pkg_app_server_service_webservice_service_proto_init() { } } file_pkg_app_server_service_webservice_service_proto_msgTypes[99].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetDeploymentChainResponse); i { + switch v := v.(*GetInsightApplicationCountResponse); i { case 0: return &v.state case 1: @@ -8228,7 +8411,7 @@ func file_pkg_app_server_service_webservice_service_proto_init() { } } file_pkg_app_server_service_webservice_service_proto_msgTypes[100].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ListEventsRequest); i { + switch v := v.(*ListDeploymentChainsRequest); i { case 0: return &v.state case 1: @@ -8240,7 +8423,7 @@ func file_pkg_app_server_service_webservice_service_proto_init() { } } file_pkg_app_server_service_webservice_service_proto_msgTypes[101].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ListEventsResponse); i { + switch v := v.(*ListDeploymentChainsResponse); i { case 0: return &v.state case 1: @@ -8252,7 +8435,43 @@ func file_pkg_app_server_service_webservice_service_proto_init() { } } file_pkg_app_server_service_webservice_service_proto_msgTypes[102].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ListPipedsRequest_Options); i { + switch v := v.(*GetDeploymentChainRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_pkg_app_server_service_webservice_service_proto_msgTypes[103].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GetDeploymentChainResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_pkg_app_server_service_webservice_service_proto_msgTypes[104].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ListEventsRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_pkg_app_server_service_webservice_service_proto_msgTypes[105].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ListEventsResponse); i { case 0: return &v.state case 1: @@ -8264,6 +8483,18 @@ func file_pkg_app_server_service_webservice_service_proto_init() { } } file_pkg_app_server_service_webservice_service_proto_msgTypes[106].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ListPipedsRequest_Options); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_pkg_app_server_service_webservice_service_proto_msgTypes[110].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*ListApplicationsRequest_Options); i { case 0: return &v.state @@ -8275,7 +8506,7 @@ func file_pkg_app_server_service_webservice_service_proto_init() { return nil } } - file_pkg_app_server_service_webservice_service_proto_msgTypes[108].Exporter = func(v interface{}, i int) interface{} { + file_pkg_app_server_service_webservice_service_proto_msgTypes[112].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*ListDeploymentsRequest_Options); i { case 0: return &v.state @@ -8287,7 +8518,7 @@ func file_pkg_app_server_service_webservice_service_proto_init() { return nil } } - file_pkg_app_server_service_webservice_service_proto_msgTypes[110].Exporter = func(v interface{}, i int) interface{} { + file_pkg_app_server_service_webservice_service_proto_msgTypes[114].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*ListDeploymentTracesRequest_Options); i { case 0: return &v.state @@ -8299,7 +8530,7 @@ func file_pkg_app_server_service_webservice_service_proto_init() { return nil } } - file_pkg_app_server_service_webservice_service_proto_msgTypes[111].Exporter = func(v interface{}, i int) interface{} { + file_pkg_app_server_service_webservice_service_proto_msgTypes[115].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*ListDeploymentTracesResponse_DeploymentTraceRes); i { case 0: return &v.state @@ -8311,7 +8542,7 @@ func file_pkg_app_server_service_webservice_service_proto_init() { return nil } } - file_pkg_app_server_service_webservice_service_proto_msgTypes[112].Exporter = func(v interface{}, i int) interface{} { + file_pkg_app_server_service_webservice_service_proto_msgTypes[116].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*ListAPIKeysRequest_Options); i { case 0: return &v.state @@ -8323,7 +8554,7 @@ func file_pkg_app_server_service_webservice_service_proto_init() { return nil } } - file_pkg_app_server_service_webservice_service_proto_msgTypes[114].Exporter = func(v interface{}, i int) interface{} { + file_pkg_app_server_service_webservice_service_proto_msgTypes[118].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*ListDeploymentChainsRequest_Options); i { case 0: return &v.state @@ -8335,7 +8566,7 @@ func file_pkg_app_server_service_webservice_service_proto_init() { return nil } } - file_pkg_app_server_service_webservice_service_proto_msgTypes[115].Exporter = func(v interface{}, i int) interface{} { + file_pkg_app_server_service_webservice_service_proto_msgTypes[119].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*ListEventsRequest_Options); i { case 0: return &v.state @@ -8354,7 +8585,7 @@ func file_pkg_app_server_service_webservice_service_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_pkg_app_server_service_webservice_service_proto_rawDesc, NumEnums: 0, - NumMessages: 117, + NumMessages: 121, NumExtensions: 0, NumServices: 1, }, diff --git a/pkg/app/server/service/webservice/service.pb.validate.go b/pkg/app/server/service/webservice/service.pb.validate.go index 813de7f1d1..5cea694140 100644 --- a/pkg/app/server/service/webservice/service.pb.validate.go +++ b/pkg/app/server/service/webservice/service.pb.validate.go @@ -8564,6 +8564,414 @@ var _ interface { ErrorName() string } = DisableStaticAdminResponseValidationError{} +// Validate checks the field values on EnableProjectRequest with the rules +// defined in the proto definition for this message. If any rules are +// violated, the first error encountered is returned, or nil if there are no violations. +func (m *EnableProjectRequest) Validate() error { + return m.validate(false) +} + +// ValidateAll checks the field values on EnableProjectRequest with the rules +// defined in the proto definition for this message. If any rules are +// violated, the result is a list of violation errors wrapped in +// EnableProjectRequestMultiError, or nil if none found. +func (m *EnableProjectRequest) ValidateAll() error { + return m.validate(true) +} + +func (m *EnableProjectRequest) validate(all bool) error { + if m == nil { + return nil + } + + var errors []error + + if len(errors) > 0 { + return EnableProjectRequestMultiError(errors) + } + + return nil +} + +// EnableProjectRequestMultiError is an error wrapping multiple validation +// errors returned by EnableProjectRequest.ValidateAll() if the designated +// constraints aren't met. +type EnableProjectRequestMultiError []error + +// Error returns a concatenation of all the error messages it wraps. +func (m EnableProjectRequestMultiError) Error() string { + var msgs []string + for _, err := range m { + msgs = append(msgs, err.Error()) + } + return strings.Join(msgs, "; ") +} + +// AllErrors returns a list of validation violation errors. +func (m EnableProjectRequestMultiError) AllErrors() []error { return m } + +// EnableProjectRequestValidationError is the validation error returned by +// EnableProjectRequest.Validate if the designated constraints aren't met. +type EnableProjectRequestValidationError struct { + field string + reason string + cause error + key bool +} + +// Field function returns field value. +func (e EnableProjectRequestValidationError) Field() string { return e.field } + +// Reason function returns reason value. +func (e EnableProjectRequestValidationError) Reason() string { return e.reason } + +// Cause function returns cause value. +func (e EnableProjectRequestValidationError) Cause() error { return e.cause } + +// Key function returns key value. +func (e EnableProjectRequestValidationError) Key() bool { return e.key } + +// ErrorName returns error name. +func (e EnableProjectRequestValidationError) ErrorName() string { + return "EnableProjectRequestValidationError" +} + +// Error satisfies the builtin error interface +func (e EnableProjectRequestValidationError) Error() string { + cause := "" + if e.cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.cause) + } + + key := "" + if e.key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sEnableProjectRequest.%s: %s%s", + key, + e.field, + e.reason, + cause) +} + +var _ error = EnableProjectRequestValidationError{} + +var _ interface { + Field() string + Reason() string + Key() bool + Cause() error + ErrorName() string +} = EnableProjectRequestValidationError{} + +// Validate checks the field values on EnableProjectResponse with the rules +// defined in the proto definition for this message. If any rules are +// violated, the first error encountered is returned, or nil if there are no violations. +func (m *EnableProjectResponse) Validate() error { + return m.validate(false) +} + +// ValidateAll checks the field values on EnableProjectResponse with the rules +// defined in the proto definition for this message. If any rules are +// violated, the result is a list of violation errors wrapped in +// EnableProjectResponseMultiError, or nil if none found. +func (m *EnableProjectResponse) ValidateAll() error { + return m.validate(true) +} + +func (m *EnableProjectResponse) validate(all bool) error { + if m == nil { + return nil + } + + var errors []error + + if len(errors) > 0 { + return EnableProjectResponseMultiError(errors) + } + + return nil +} + +// EnableProjectResponseMultiError is an error wrapping multiple validation +// errors returned by EnableProjectResponse.ValidateAll() if the designated +// constraints aren't met. +type EnableProjectResponseMultiError []error + +// Error returns a concatenation of all the error messages it wraps. +func (m EnableProjectResponseMultiError) Error() string { + var msgs []string + for _, err := range m { + msgs = append(msgs, err.Error()) + } + return strings.Join(msgs, "; ") +} + +// AllErrors returns a list of validation violation errors. +func (m EnableProjectResponseMultiError) AllErrors() []error { return m } + +// EnableProjectResponseValidationError is the validation error returned by +// EnableProjectResponse.Validate if the designated constraints aren't met. +type EnableProjectResponseValidationError struct { + field string + reason string + cause error + key bool +} + +// Field function returns field value. +func (e EnableProjectResponseValidationError) Field() string { return e.field } + +// Reason function returns reason value. +func (e EnableProjectResponseValidationError) Reason() string { return e.reason } + +// Cause function returns cause value. +func (e EnableProjectResponseValidationError) Cause() error { return e.cause } + +// Key function returns key value. +func (e EnableProjectResponseValidationError) Key() bool { return e.key } + +// ErrorName returns error name. +func (e EnableProjectResponseValidationError) ErrorName() string { + return "EnableProjectResponseValidationError" +} + +// Error satisfies the builtin error interface +func (e EnableProjectResponseValidationError) Error() string { + cause := "" + if e.cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.cause) + } + + key := "" + if e.key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sEnableProjectResponse.%s: %s%s", + key, + e.field, + e.reason, + cause) +} + +var _ error = EnableProjectResponseValidationError{} + +var _ interface { + Field() string + Reason() string + Key() bool + Cause() error + ErrorName() string +} = EnableProjectResponseValidationError{} + +// Validate checks the field values on DisableProjectRequest with the rules +// defined in the proto definition for this message. If any rules are +// violated, the first error encountered is returned, or nil if there are no violations. +func (m *DisableProjectRequest) Validate() error { + return m.validate(false) +} + +// ValidateAll checks the field values on DisableProjectRequest with the rules +// defined in the proto definition for this message. If any rules are +// violated, the result is a list of violation errors wrapped in +// DisableProjectRequestMultiError, or nil if none found. +func (m *DisableProjectRequest) ValidateAll() error { + return m.validate(true) +} + +func (m *DisableProjectRequest) validate(all bool) error { + if m == nil { + return nil + } + + var errors []error + + if len(errors) > 0 { + return DisableProjectRequestMultiError(errors) + } + + return nil +} + +// DisableProjectRequestMultiError is an error wrapping multiple validation +// errors returned by DisableProjectRequest.ValidateAll() if the designated +// constraints aren't met. +type DisableProjectRequestMultiError []error + +// Error returns a concatenation of all the error messages it wraps. +func (m DisableProjectRequestMultiError) Error() string { + var msgs []string + for _, err := range m { + msgs = append(msgs, err.Error()) + } + return strings.Join(msgs, "; ") +} + +// AllErrors returns a list of validation violation errors. +func (m DisableProjectRequestMultiError) AllErrors() []error { return m } + +// DisableProjectRequestValidationError is the validation error returned by +// DisableProjectRequest.Validate if the designated constraints aren't met. +type DisableProjectRequestValidationError struct { + field string + reason string + cause error + key bool +} + +// Field function returns field value. +func (e DisableProjectRequestValidationError) Field() string { return e.field } + +// Reason function returns reason value. +func (e DisableProjectRequestValidationError) Reason() string { return e.reason } + +// Cause function returns cause value. +func (e DisableProjectRequestValidationError) Cause() error { return e.cause } + +// Key function returns key value. +func (e DisableProjectRequestValidationError) Key() bool { return e.key } + +// ErrorName returns error name. +func (e DisableProjectRequestValidationError) ErrorName() string { + return "DisableProjectRequestValidationError" +} + +// Error satisfies the builtin error interface +func (e DisableProjectRequestValidationError) Error() string { + cause := "" + if e.cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.cause) + } + + key := "" + if e.key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sDisableProjectRequest.%s: %s%s", + key, + e.field, + e.reason, + cause) +} + +var _ error = DisableProjectRequestValidationError{} + +var _ interface { + Field() string + Reason() string + Key() bool + Cause() error + ErrorName() string +} = DisableProjectRequestValidationError{} + +// Validate checks the field values on DisableProjectResponse with the rules +// defined in the proto definition for this message. If any rules are +// violated, the first error encountered is returned, or nil if there are no violations. +func (m *DisableProjectResponse) Validate() error { + return m.validate(false) +} + +// ValidateAll checks the field values on DisableProjectResponse with the rules +// defined in the proto definition for this message. If any rules are +// violated, the result is a list of violation errors wrapped in +// DisableProjectResponseMultiError, or nil if none found. +func (m *DisableProjectResponse) ValidateAll() error { + return m.validate(true) +} + +func (m *DisableProjectResponse) validate(all bool) error { + if m == nil { + return nil + } + + var errors []error + + if len(errors) > 0 { + return DisableProjectResponseMultiError(errors) + } + + return nil +} + +// DisableProjectResponseMultiError is an error wrapping multiple validation +// errors returned by DisableProjectResponse.ValidateAll() if the designated +// constraints aren't met. +type DisableProjectResponseMultiError []error + +// Error returns a concatenation of all the error messages it wraps. +func (m DisableProjectResponseMultiError) Error() string { + var msgs []string + for _, err := range m { + msgs = append(msgs, err.Error()) + } + return strings.Join(msgs, "; ") +} + +// AllErrors returns a list of validation violation errors. +func (m DisableProjectResponseMultiError) AllErrors() []error { return m } + +// DisableProjectResponseValidationError is the validation error returned by +// DisableProjectResponse.Validate if the designated constraints aren't met. +type DisableProjectResponseValidationError struct { + field string + reason string + cause error + key bool +} + +// Field function returns field value. +func (e DisableProjectResponseValidationError) Field() string { return e.field } + +// Reason function returns reason value. +func (e DisableProjectResponseValidationError) Reason() string { return e.reason } + +// Cause function returns cause value. +func (e DisableProjectResponseValidationError) Cause() error { return e.cause } + +// Key function returns key value. +func (e DisableProjectResponseValidationError) Key() bool { return e.key } + +// ErrorName returns error name. +func (e DisableProjectResponseValidationError) ErrorName() string { + return "DisableProjectResponseValidationError" +} + +// Error satisfies the builtin error interface +func (e DisableProjectResponseValidationError) Error() string { + cause := "" + if e.cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.cause) + } + + key := "" + if e.key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sDisableProjectResponse.%s: %s%s", + key, + e.field, + e.reason, + cause) +} + +var _ error = DisableProjectResponseValidationError{} + +var _ interface { + Field() string + Reason() string + Key() bool + Cause() error + ErrorName() string +} = DisableProjectResponseValidationError{} + // Validate checks the field values on GetMeRequest with the rules defined in // the proto definition for this message. If any rules are violated, the first // error encountered is returned, or nil if there are no violations. diff --git a/pkg/app/server/service/webservice/service.proto b/pkg/app/server/service/webservice/service.proto index 489283d9be..0ac48eba24 100644 --- a/pkg/app/server/service/webservice/service.proto +++ b/pkg/app/server/service/webservice/service.proto @@ -193,6 +193,14 @@ service WebService { option (model.rbac).resource = PROJECT; option (model.rbac).action = UPDATE; } + rpc EnableProject(EnableProjectRequest) returns (EnableProjectResponse) { + option (model.rbac).resource = PROJECT; + option (model.rbac).action = UPDATE; + } + rpc DisableProject(DisableProjectRequest) returns (DisableProjectResponse) { + option (model.rbac).resource = PROJECT; + option (model.rbac).action = UPDATE; + } rpc GetMe(GetMeRequest) returns (GetMeResponse) { option (model.rbac).resource = PROJECT; option (model.rbac).action = GET; @@ -611,6 +619,18 @@ message DisableStaticAdminRequest { message DisableStaticAdminResponse { } +message EnableProjectRequest { +} + +message EnableProjectResponse { +} + +message DisableProjectRequest { +} + +message DisableProjectResponse { +} + message GetMeRequest { } diff --git a/pkg/app/server/service/webservice/service_grpc.pb.go b/pkg/app/server/service/webservice/service_grpc.pb.go index 6fc94220be..3ef9ff6e64 100644 --- a/pkg/app/server/service/webservice/service_grpc.pb.go +++ b/pkg/app/server/service/webservice/service_grpc.pb.go @@ -64,6 +64,8 @@ type WebServiceClient interface { DisableStaticAdmin(ctx context.Context, in *DisableStaticAdminRequest, opts ...grpc.CallOption) (*DisableStaticAdminResponse, error) UpdateProjectSSOConfig(ctx context.Context, in *UpdateProjectSSOConfigRequest, opts ...grpc.CallOption) (*UpdateProjectSSOConfigResponse, error) UpdateProjectRBACConfig(ctx context.Context, in *UpdateProjectRBACConfigRequest, opts ...grpc.CallOption) (*UpdateProjectRBACConfigResponse, error) + EnableProject(ctx context.Context, in *EnableProjectRequest, opts ...grpc.CallOption) (*EnableProjectResponse, error) + DisableProject(ctx context.Context, in *DisableProjectRequest, opts ...grpc.CallOption) (*DisableProjectResponse, error) GetMe(ctx context.Context, in *GetMeRequest, opts ...grpc.CallOption) (*GetMeResponse, error) AddProjectRBACRole(ctx context.Context, in *AddProjectRBACRoleRequest, opts ...grpc.CallOption) (*AddProjectRBACRoleResponse, error) UpdateProjectRBACRole(ctx context.Context, in *UpdateProjectRBACRoleRequest, opts ...grpc.CallOption) (*UpdateProjectRBACRoleResponse, error) @@ -418,6 +420,24 @@ func (c *webServiceClient) UpdateProjectRBACConfig(ctx context.Context, in *Upda return out, nil } +func (c *webServiceClient) EnableProject(ctx context.Context, in *EnableProjectRequest, opts ...grpc.CallOption) (*EnableProjectResponse, error) { + out := new(EnableProjectResponse) + err := c.cc.Invoke(ctx, "/grpc.service.webservice.WebService/EnableProject", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *webServiceClient) DisableProject(ctx context.Context, in *DisableProjectRequest, opts ...grpc.CallOption) (*DisableProjectResponse, error) { + out := new(DisableProjectResponse) + err := c.cc.Invoke(ctx, "/grpc.service.webservice.WebService/DisableProject", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + func (c *webServiceClient) GetMe(ctx context.Context, in *GetMeRequest, opts ...grpc.CallOption) (*GetMeResponse, error) { out := new(GetMeResponse) err := c.cc.Invoke(ctx, "/grpc.service.webservice.WebService/GetMe", in, out, opts...) @@ -599,6 +619,8 @@ type WebServiceServer interface { DisableStaticAdmin(context.Context, *DisableStaticAdminRequest) (*DisableStaticAdminResponse, error) UpdateProjectSSOConfig(context.Context, *UpdateProjectSSOConfigRequest) (*UpdateProjectSSOConfigResponse, error) UpdateProjectRBACConfig(context.Context, *UpdateProjectRBACConfigRequest) (*UpdateProjectRBACConfigResponse, error) + EnableProject(context.Context, *EnableProjectRequest) (*EnableProjectResponse, error) + DisableProject(context.Context, *DisableProjectRequest) (*DisableProjectResponse, error) GetMe(context.Context, *GetMeRequest) (*GetMeResponse, error) AddProjectRBACRole(context.Context, *AddProjectRBACRoleRequest) (*AddProjectRBACRoleResponse, error) UpdateProjectRBACRole(context.Context, *UpdateProjectRBACRoleRequest) (*UpdateProjectRBACRoleResponse, error) @@ -734,6 +756,12 @@ func (UnimplementedWebServiceServer) UpdateProjectSSOConfig(context.Context, *Up func (UnimplementedWebServiceServer) UpdateProjectRBACConfig(context.Context, *UpdateProjectRBACConfigRequest) (*UpdateProjectRBACConfigResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method UpdateProjectRBACConfig not implemented") } +func (UnimplementedWebServiceServer) EnableProject(context.Context, *EnableProjectRequest) (*EnableProjectResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method EnableProject not implemented") +} +func (UnimplementedWebServiceServer) DisableProject(context.Context, *DisableProjectRequest) (*DisableProjectResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method DisableProject not implemented") +} func (UnimplementedWebServiceServer) GetMe(context.Context, *GetMeRequest) (*GetMeResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method GetMe not implemented") } @@ -1440,6 +1468,42 @@ func _WebService_UpdateProjectRBACConfig_Handler(srv interface{}, ctx context.Co return interceptor(ctx, in, info, handler) } +func _WebService_EnableProject_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(EnableProjectRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(WebServiceServer).EnableProject(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/grpc.service.webservice.WebService/EnableProject", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(WebServiceServer).EnableProject(ctx, req.(*EnableProjectRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _WebService_DisableProject_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(DisableProjectRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(WebServiceServer).DisableProject(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/grpc.service.webservice.WebService/DisableProject", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(WebServiceServer).DisableProject(ctx, req.(*DisableProjectRequest)) + } + return interceptor(ctx, in, info, handler) +} + func _WebService_GetMe_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(GetMeRequest) if err := dec(in); err != nil { @@ -1861,6 +1925,14 @@ var WebService_ServiceDesc = grpc.ServiceDesc{ MethodName: "UpdateProjectRBACConfig", Handler: _WebService_UpdateProjectRBACConfig_Handler, }, + { + MethodName: "EnableProject", + Handler: _WebService_EnableProject_Handler, + }, + { + MethodName: "DisableProject", + Handler: _WebService_DisableProject_Handler, + }, { MethodName: "GetMe", Handler: _WebService_GetMe_Handler, diff --git a/pkg/datastore/projectstore.go b/pkg/datastore/projectstore.go index e9eee14fdb..200aa918ec 100644 --- a/pkg/datastore/projectstore.go +++ b/pkg/datastore/projectstore.go @@ -38,6 +38,8 @@ type ProjectStore interface { Add(ctx context.Context, proj *model.Project) error Get(ctx context.Context, id string) (*model.Project, error) List(ctx context.Context, opts ListOptions) ([]model.Project, error) + EnableProject(ctx context.Context, id string) error + DisableProject(ctx context.Context, id string) error UpdateProjectStaticAdmin(ctx context.Context, id, username, password string) error EnableStaticAdmin(ctx context.Context, id string) error DisableStaticAdmin(ctx context.Context, id string) error @@ -121,6 +123,22 @@ func (s *projectStore) update(ctx context.Context, id string, updater func(proje }) } +// EnableProject marks a project as active so clients can authenticate again. +func (s *projectStore) EnableProject(ctx context.Context, id string) error { + return s.update(ctx, id, func(p *model.Project) error { + p.Disabled = false + return nil + }) +} + +// DisableProject marks a project as disabled to block logins and API calls. +func (s *projectStore) DisableProject(ctx context.Context, id string) error { + return s.update(ctx, id, func(p *model.Project) error { + p.Disabled = true + return nil + }) +} + // UpdateProjectStaticAdmin updates the static admin user settings. func (s *projectStore) UpdateProjectStaticAdmin(ctx context.Context, id, username, password string) error { return s.update(ctx, id, func(p *model.Project) error { diff --git a/pkg/jwt/jwt.go b/pkg/jwt/jwt.go index ffd2cc3f6f..152bdb2074 100644 --- a/pkg/jwt/jwt.go +++ b/pkg/jwt/jwt.go @@ -39,8 +39,12 @@ type Claims struct { } // NewClaims creates a new claims for a given github user. -func NewClaims(githubUserID, avatarURL string, ttl time.Duration, role model.Role) *Claims { +func NewClaims(githubUserID, avatarURL string, ttl time.Duration, role *model.Role) *Claims { now := time.Now().UTC() + var roleValue model.Role + if role != nil { + roleValue = *role //nolint:govet // Copying proto role into the token snapshot is intentional. + } return &Claims{ RegisteredClaims: jwtgo.RegisteredClaims{ Subject: githubUserID, @@ -50,7 +54,7 @@ func NewClaims(githubUserID, avatarURL string, ttl time.Duration, role model.Rol ExpiresAt: jwtgo.NewNumericDate(now.Add(ttl)), }, AvatarURL: avatarURL, - Role: role, + Role: roleValue, } } diff --git a/pkg/jwt/signer_test.go b/pkg/jwt/signer_test.go index e60287dc58..a8b8917238 100644 --- a/pkg/jwt/signer_test.go +++ b/pkg/jwt/signer_test.go @@ -25,7 +25,7 @@ import ( ) func TestSign(t *testing.T) { - claims := NewClaims("user-1", "avatar-url", time.Hour, model.Role{ + claims := NewClaims("user-1", "avatar-url", time.Hour, &model.Role{ ProjectId: "project-1", }) diff --git a/pkg/jwt/verifier_test.go b/pkg/jwt/verifier_test.go index a12eb4e409..5a949b730f 100644 --- a/pkg/jwt/verifier_test.go +++ b/pkg/jwt/verifier_test.go @@ -40,7 +40,7 @@ func TestVerify(t *testing.T) { }{ { name: "ok", - claims: NewClaims("user-1", "avatar-url", time.Hour, model.Role{ + claims: NewClaims("user-1", "avatar-url", time.Hour, &model.Role{ ProjectId: "project-1", }), fail: false, @@ -129,7 +129,7 @@ func TestVerify(t *testing.T) { testFunc(hsS, hsV) - c := NewClaims("user", "avatar-url", time.Hour, model.Role{ + c := NewClaims("user", "avatar-url", time.Hour, &model.Role{ ProjectId: "project", }) diff --git a/pkg/model/project.pb.go b/pkg/model/project.pb.go index 4108dc26ac..ca46026a92 100644 --- a/pkg/model/project.pb.go +++ b/pkg/model/project.pb.go @@ -242,6 +242,8 @@ type Project struct { RbacRoles []*ProjectRBACRole `protobuf:"bytes,9,rep,name=rbac_roles,json=rbacRoles,proto3" json:"rbac_roles,omitempty"` // Mapping SSO group and RBAC role. UserGroups []*ProjectUserGroup `protobuf:"bytes,10,rep,name=user_groups,json=userGroups,proto3" json:"user_groups,omitempty"` + // Whether the project is disabled. Disabled projects cannot log in or issue new API calls. + Disabled bool `protobuf:"varint,11,opt,name=disabled,proto3" json:"disabled,omitempty"` // Unix time when the project is created. CreatedAt int64 `protobuf:"varint,14,opt,name=created_at,json=createdAt,proto3" json:"created_at,omitempty"` // Unix time of the last time when the project is updated. @@ -350,6 +352,13 @@ func (x *Project) GetUserGroups() []*ProjectUserGroup { return nil } +func (x *Project) GetDisabled() bool { + if x != nil { + return x.Disabled + } + return false +} + func (x *Project) GetCreatedAt() int64 { if x != nil { return x.CreatedAt @@ -1101,7 +1110,7 @@ var file_pkg_model_project_proto_rawDesc = []byte{ 0x1a, 0x17, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x20, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x64, 0x65, 0x73, 0x63, 0x72, - 0x69, 0x70, 0x74, 0x6f, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xa6, 0x04, 0x0a, 0x07, + 0x69, 0x70, 0x74, 0x6f, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xc2, 0x04, 0x0a, 0x07, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x12, 0x17, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xfa, 0x42, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x02, 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x64, 0x65, 0x73, 0x63, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, @@ -1131,150 +1140,152 @@ var file_pkg_model_project_proto_rawDesc = []byte{ 0x65, 0x72, 0x5f, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x18, 0x0a, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x2e, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x55, 0x73, 0x65, 0x72, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x52, 0x0a, 0x75, 0x73, 0x65, 0x72, 0x47, 0x72, - 0x6f, 0x75, 0x70, 0x73, 0x12, 0x26, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, - 0x61, 0x74, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x03, 0x42, 0x07, 0xfa, 0x42, 0x04, 0x22, 0x02, 0x20, - 0x00, 0x52, 0x09, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, 0x26, 0x0a, 0x0a, - 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x03, - 0x42, 0x07, 0xfa, 0x42, 0x04, 0x22, 0x02, 0x20, 0x00, 0x52, 0x09, 0x75, 0x70, 0x64, 0x61, 0x74, - 0x65, 0x64, 0x41, 0x74, 0x22, 0x66, 0x0a, 0x11, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x53, - 0x74, 0x61, 0x74, 0x69, 0x63, 0x55, 0x73, 0x65, 0x72, 0x12, 0x23, 0x0a, 0x08, 0x75, 0x73, 0x65, - 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xfa, 0x42, 0x04, - 0x72, 0x02, 0x10, 0x01, 0x52, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x2c, - 0x0a, 0x0d, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xfa, 0x42, 0x04, 0x72, 0x02, 0x10, 0x06, 0x52, 0x0c, - 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x48, 0x61, 0x73, 0x68, 0x22, 0xce, 0x08, 0x0a, - 0x10, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x53, 0x53, 0x4f, 0x43, 0x6f, 0x6e, 0x66, 0x69, - 0x67, 0x12, 0x46, 0x0a, 0x08, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x0e, 0x32, 0x20, 0x2e, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x2e, 0x50, 0x72, 0x6f, 0x6a, - 0x65, 0x63, 0x74, 0x53, 0x53, 0x4f, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x50, 0x72, 0x6f, - 0x76, 0x69, 0x64, 0x65, 0x72, 0x42, 0x08, 0xfa, 0x42, 0x05, 0x82, 0x01, 0x02, 0x10, 0x01, 0x52, - 0x08, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x12, 0x28, 0x0a, 0x0b, 0x73, 0x65, 0x73, - 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x74, 0x74, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x42, 0x07, - 0xfa, 0x42, 0x04, 0x22, 0x02, 0x20, 0x00, 0x52, 0x0a, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, - 0x54, 0x74, 0x6c, 0x12, 0x36, 0x0a, 0x06, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x18, 0x0a, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x2e, 0x50, 0x72, 0x6f, 0x6a, - 0x65, 0x63, 0x74, 0x53, 0x53, 0x4f, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x47, 0x69, 0x74, - 0x48, 0x75, 0x62, 0x52, 0x06, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x12, 0x36, 0x0a, 0x06, 0x67, - 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x6d, 0x6f, - 0x64, 0x65, 0x6c, 0x2e, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x53, 0x53, 0x4f, 0x43, 0x6f, - 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x47, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x52, 0x06, 0x67, 0x6f, 0x6f, - 0x67, 0x6c, 0x65, 0x12, 0x30, 0x0a, 0x04, 0x6f, 0x69, 0x64, 0x63, 0x18, 0x0c, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x1c, 0x2e, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x2e, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, - 0x74, 0x53, 0x53, 0x4f, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x4f, 0x69, 0x64, 0x63, 0x52, - 0x04, 0x6f, 0x69, 0x64, 0x63, 0x1a, 0xb3, 0x01, 0x0a, 0x06, 0x47, 0x69, 0x74, 0x48, 0x75, 0x62, - 0x12, 0x24, 0x0a, 0x09, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x42, 0x07, 0xfa, 0x42, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x08, 0x63, 0x6c, - 0x69, 0x65, 0x6e, 0x74, 0x49, 0x64, 0x12, 0x2c, 0x0a, 0x0d, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, - 0x5f, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xfa, - 0x42, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x0c, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x53, 0x65, - 0x63, 0x72, 0x65, 0x74, 0x12, 0x19, 0x0a, 0x08, 0x62, 0x61, 0x73, 0x65, 0x5f, 0x75, 0x72, 0x6c, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x62, 0x61, 0x73, 0x65, 0x55, 0x72, 0x6c, 0x12, - 0x1d, 0x0a, 0x0a, 0x75, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x04, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x09, 0x75, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x55, 0x72, 0x6c, 0x12, 0x1b, - 0x0a, 0x09, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x05, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x08, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x55, 0x72, 0x6c, 0x1a, 0x5c, 0x0a, 0x06, 0x47, - 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x12, 0x24, 0x0a, 0x09, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, - 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xfa, 0x42, 0x04, 0x72, 0x02, 0x10, - 0x01, 0x52, 0x08, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x64, 0x12, 0x2c, 0x0a, 0x0d, 0x63, - 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x09, 0x42, 0x07, 0xfa, 0x42, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x0c, 0x63, 0x6c, 0x69, - 0x65, 0x6e, 0x74, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x1a, 0xdd, 0x03, 0x0a, 0x04, 0x4f, 0x69, - 0x64, 0x63, 0x12, 0x24, 0x0a, 0x09, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xfa, 0x42, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x08, - 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x64, 0x12, 0x2c, 0x0a, 0x0d, 0x63, 0x6c, 0x69, 0x65, - 0x6e, 0x74, 0x5f, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, - 0x07, 0xfa, 0x42, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x0c, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, - 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x69, 0x73, 0x73, 0x75, 0x65, 0x72, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x69, 0x73, 0x73, 0x75, 0x65, 0x72, 0x12, 0x21, - 0x0a, 0x0c, 0x72, 0x65, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x5f, 0x75, 0x72, 0x69, 0x18, 0x04, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x72, 0x65, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x55, 0x72, - 0x69, 0x12, 0x35, 0x0a, 0x16, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x5f, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x15, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x25, 0x0a, 0x0e, 0x74, 0x6f, 0x6b, 0x65, - 0x6e, 0x5f, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x0d, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x12, - 0x2c, 0x0a, 0x12, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x5f, 0x65, 0x6e, 0x64, - 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x75, 0x73, 0x65, - 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x1b, 0x0a, - 0x09, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x08, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x55, 0x72, 0x6c, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x63, - 0x6f, 0x70, 0x65, 0x73, 0x18, 0x09, 0x20, 0x03, 0x28, 0x09, 0x52, 0x06, 0x73, 0x63, 0x6f, 0x70, - 0x65, 0x73, 0x12, 0x26, 0x0a, 0x0f, 0x72, 0x6f, 0x6c, 0x65, 0x73, 0x5f, 0x63, 0x6c, 0x61, 0x69, - 0x6d, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x72, 0x6f, 0x6c, - 0x65, 0x73, 0x43, 0x6c, 0x61, 0x69, 0x6d, 0x4b, 0x65, 0x79, 0x12, 0x2c, 0x0a, 0x12, 0x75, 0x73, - 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x5f, 0x63, 0x6c, 0x61, 0x69, 0x6d, 0x5f, 0x6b, 0x65, 0x79, - 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, - 0x43, 0x6c, 0x61, 0x69, 0x6d, 0x4b, 0x65, 0x79, 0x12, 0x2f, 0x0a, 0x14, 0x61, 0x76, 0x61, 0x74, - 0x61, 0x72, 0x5f, 0x75, 0x72, 0x6c, 0x5f, 0x63, 0x6c, 0x61, 0x69, 0x6d, 0x5f, 0x6b, 0x65, 0x79, - 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x61, 0x76, 0x61, 0x74, 0x61, 0x72, 0x55, 0x72, - 0x6c, 0x43, 0x6c, 0x61, 0x69, 0x6d, 0x4b, 0x65, 0x79, 0x22, 0x32, 0x0a, 0x08, 0x50, 0x72, 0x6f, - 0x76, 0x69, 0x64, 0x65, 0x72, 0x12, 0x0a, 0x0a, 0x06, 0x47, 0x49, 0x54, 0x48, 0x55, 0x42, 0x10, - 0x00, 0x12, 0x0a, 0x0a, 0x06, 0x47, 0x4f, 0x4f, 0x47, 0x4c, 0x45, 0x10, 0x02, 0x12, 0x08, 0x0a, - 0x04, 0x4f, 0x49, 0x44, 0x43, 0x10, 0x03, 0x22, 0x04, 0x08, 0x01, 0x10, 0x01, 0x22, 0x59, 0x0a, - 0x11, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x52, 0x42, 0x41, 0x43, 0x43, 0x6f, 0x6e, 0x66, - 0x69, 0x67, 0x12, 0x14, 0x0a, 0x05, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x05, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x12, 0x16, 0x0a, 0x06, 0x65, 0x64, 0x69, 0x74, - 0x6f, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x65, 0x64, 0x69, 0x74, 0x6f, 0x72, - 0x12, 0x16, 0x0a, 0x06, 0x76, 0x69, 0x65, 0x77, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x06, 0x76, 0x69, 0x65, 0x77, 0x65, 0x72, 0x22, 0x55, 0x0a, 0x10, 0x50, 0x72, 0x6f, 0x6a, - 0x65, 0x63, 0x74, 0x55, 0x73, 0x65, 0x72, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x12, 0x24, 0x0a, 0x09, - 0x73, 0x73, 0x6f, 0x5f, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, - 0x07, 0xfa, 0x42, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x08, 0x73, 0x73, 0x6f, 0x47, 0x72, 0x6f, - 0x75, 0x70, 0x12, 0x1b, 0x0a, 0x04, 0x72, 0x6f, 0x6c, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, - 0x42, 0x07, 0xfa, 0x42, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x04, 0x72, 0x6f, 0x6c, 0x65, 0x22, - 0x8d, 0x01, 0x0a, 0x0f, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x52, 0x42, 0x41, 0x43, 0x52, - 0x6f, 0x6c, 0x65, 0x12, 0x1b, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x09, 0x42, 0x07, 0xfa, 0x42, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, - 0x12, 0x3e, 0x0a, 0x08, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, - 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x2e, 0x50, 0x72, 0x6f, 0x6a, 0x65, - 0x63, 0x74, 0x52, 0x42, 0x41, 0x43, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x42, 0x08, 0xfa, 0x42, - 0x05, 0x92, 0x01, 0x02, 0x08, 0x01, 0x52, 0x08, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, - 0x12, 0x1d, 0x0a, 0x0a, 0x69, 0x73, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x74, 0x69, 0x6e, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x69, 0x73, 0x42, 0x75, 0x69, 0x6c, 0x74, 0x69, 0x6e, 0x22, - 0xff, 0x02, 0x0a, 0x13, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x52, 0x42, 0x41, 0x43, 0x52, - 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x45, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x27, 0x2e, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x2e, 0x50, 0x72, - 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x52, 0x42, 0x41, 0x43, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, - 0x65, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x42, 0x08, - 0xfa, 0x42, 0x05, 0x82, 0x01, 0x02, 0x10, 0x01, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x58, - 0x0a, 0x06, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x26, + 0x6f, 0x75, 0x70, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x64, + 0x18, 0x0b, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x64, + 0x12, 0x26, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x0e, + 0x20, 0x01, 0x28, 0x03, 0x42, 0x07, 0xfa, 0x42, 0x04, 0x22, 0x02, 0x20, 0x00, 0x52, 0x09, 0x63, + 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, 0x26, 0x0a, 0x0a, 0x75, 0x70, 0x64, 0x61, + 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x03, 0x42, 0x07, 0xfa, 0x42, + 0x04, 0x22, 0x02, 0x20, 0x00, 0x52, 0x09, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, + 0x22, 0x66, 0x0a, 0x11, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x53, 0x74, 0x61, 0x74, 0x69, + 0x63, 0x55, 0x73, 0x65, 0x72, 0x12, 0x23, 0x0a, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, + 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xfa, 0x42, 0x04, 0x72, 0x02, 0x10, 0x01, + 0x52, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x2c, 0x0a, 0x0d, 0x70, 0x61, + 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x09, 0x42, 0x07, 0xfa, 0x42, 0x04, 0x72, 0x02, 0x10, 0x06, 0x52, 0x0c, 0x70, 0x61, 0x73, 0x73, + 0x77, 0x6f, 0x72, 0x64, 0x48, 0x61, 0x73, 0x68, 0x22, 0xce, 0x08, 0x0a, 0x10, 0x50, 0x72, 0x6f, + 0x6a, 0x65, 0x63, 0x74, 0x53, 0x53, 0x4f, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x46, 0x0a, + 0x08, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, + 0x20, 0x2e, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x2e, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x53, + 0x53, 0x4f, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, + 0x72, 0x42, 0x08, 0xfa, 0x42, 0x05, 0x82, 0x01, 0x02, 0x10, 0x01, 0x52, 0x08, 0x70, 0x72, 0x6f, + 0x76, 0x69, 0x64, 0x65, 0x72, 0x12, 0x28, 0x0a, 0x0b, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, + 0x5f, 0x74, 0x74, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x42, 0x07, 0xfa, 0x42, 0x04, 0x22, + 0x02, 0x20, 0x00, 0x52, 0x0a, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x54, 0x74, 0x6c, 0x12, + 0x36, 0x0a, 0x06, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x1e, 0x2e, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x2e, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x53, + 0x53, 0x4f, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x47, 0x69, 0x74, 0x48, 0x75, 0x62, 0x52, + 0x06, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x12, 0x36, 0x0a, 0x06, 0x67, 0x6f, 0x6f, 0x67, 0x6c, + 0x65, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x2e, + 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x53, 0x53, 0x4f, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, + 0x2e, 0x47, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x52, 0x06, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x12, + 0x30, 0x0a, 0x04, 0x6f, 0x69, 0x64, 0x63, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, + 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x2e, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x53, 0x53, 0x4f, + 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x4f, 0x69, 0x64, 0x63, 0x52, 0x04, 0x6f, 0x69, 0x64, + 0x63, 0x1a, 0xb3, 0x01, 0x0a, 0x06, 0x47, 0x69, 0x74, 0x48, 0x75, 0x62, 0x12, 0x24, 0x0a, 0x09, + 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, + 0x07, 0xfa, 0x42, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x08, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, + 0x49, 0x64, 0x12, 0x2c, 0x0a, 0x0d, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x65, 0x63, + 0x72, 0x65, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xfa, 0x42, 0x04, 0x72, 0x02, + 0x10, 0x01, 0x52, 0x0c, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, + 0x12, 0x19, 0x0a, 0x08, 0x62, 0x61, 0x73, 0x65, 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x07, 0x62, 0x61, 0x73, 0x65, 0x55, 0x72, 0x6c, 0x12, 0x1d, 0x0a, 0x0a, 0x75, + 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x09, 0x75, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x55, 0x72, 0x6c, 0x12, 0x1b, 0x0a, 0x09, 0x70, 0x72, + 0x6f, 0x78, 0x79, 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, + 0x72, 0x6f, 0x78, 0x79, 0x55, 0x72, 0x6c, 0x1a, 0x5c, 0x0a, 0x06, 0x47, 0x6f, 0x6f, 0x67, 0x6c, + 0x65, 0x12, 0x24, 0x0a, 0x09, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xfa, 0x42, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x08, 0x63, + 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x64, 0x12, 0x2c, 0x0a, 0x0d, 0x63, 0x6c, 0x69, 0x65, 0x6e, + 0x74, 0x5f, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, + 0xfa, 0x42, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x0c, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x53, + 0x65, 0x63, 0x72, 0x65, 0x74, 0x1a, 0xdd, 0x03, 0x0a, 0x04, 0x4f, 0x69, 0x64, 0x63, 0x12, 0x24, + 0x0a, 0x09, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x42, 0x07, 0xfa, 0x42, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x08, 0x63, 0x6c, 0x69, 0x65, + 0x6e, 0x74, 0x49, 0x64, 0x12, 0x2c, 0x0a, 0x0d, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x73, + 0x65, 0x63, 0x72, 0x65, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xfa, 0x42, 0x04, + 0x72, 0x02, 0x10, 0x01, 0x52, 0x0c, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x53, 0x65, 0x63, 0x72, + 0x65, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x69, 0x73, 0x73, 0x75, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x06, 0x69, 0x73, 0x73, 0x75, 0x65, 0x72, 0x12, 0x21, 0x0a, 0x0c, 0x72, 0x65, + 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x5f, 0x75, 0x72, 0x69, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x0b, 0x72, 0x65, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x55, 0x72, 0x69, 0x12, 0x35, 0x0a, + 0x16, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x65, + 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x15, 0x61, + 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x6e, 0x64, 0x70, + 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x25, 0x0a, 0x0e, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x5f, 0x65, 0x6e, + 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x74, 0x6f, + 0x6b, 0x65, 0x6e, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x2c, 0x0a, 0x12, 0x75, + 0x73, 0x65, 0x72, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x5f, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, + 0x74, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x75, 0x73, 0x65, 0x72, 0x49, 0x6e, 0x66, + 0x6f, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x70, 0x72, 0x6f, + 0x78, 0x79, 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x72, + 0x6f, 0x78, 0x79, 0x55, 0x72, 0x6c, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x73, + 0x18, 0x09, 0x20, 0x03, 0x28, 0x09, 0x52, 0x06, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x73, 0x12, 0x26, + 0x0a, 0x0f, 0x72, 0x6f, 0x6c, 0x65, 0x73, 0x5f, 0x63, 0x6c, 0x61, 0x69, 0x6d, 0x5f, 0x6b, 0x65, + 0x79, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x72, 0x6f, 0x6c, 0x65, 0x73, 0x43, 0x6c, + 0x61, 0x69, 0x6d, 0x4b, 0x65, 0x79, 0x12, 0x2c, 0x0a, 0x12, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, + 0x6d, 0x65, 0x5f, 0x63, 0x6c, 0x61, 0x69, 0x6d, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x0b, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x10, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x43, 0x6c, 0x61, 0x69, + 0x6d, 0x4b, 0x65, 0x79, 0x12, 0x2f, 0x0a, 0x14, 0x61, 0x76, 0x61, 0x74, 0x61, 0x72, 0x5f, 0x75, + 0x72, 0x6c, 0x5f, 0x63, 0x6c, 0x61, 0x69, 0x6d, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x0c, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x11, 0x61, 0x76, 0x61, 0x74, 0x61, 0x72, 0x55, 0x72, 0x6c, 0x43, 0x6c, 0x61, + 0x69, 0x6d, 0x4b, 0x65, 0x79, 0x22, 0x32, 0x0a, 0x08, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, + 0x72, 0x12, 0x0a, 0x0a, 0x06, 0x47, 0x49, 0x54, 0x48, 0x55, 0x42, 0x10, 0x00, 0x12, 0x0a, 0x0a, + 0x06, 0x47, 0x4f, 0x4f, 0x47, 0x4c, 0x45, 0x10, 0x02, 0x12, 0x08, 0x0a, 0x04, 0x4f, 0x49, 0x44, + 0x43, 0x10, 0x03, 0x22, 0x04, 0x08, 0x01, 0x10, 0x01, 0x22, 0x59, 0x0a, 0x11, 0x50, 0x72, 0x6f, + 0x6a, 0x65, 0x63, 0x74, 0x52, 0x42, 0x41, 0x43, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x14, + 0x0a, 0x05, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x61, + 0x64, 0x6d, 0x69, 0x6e, 0x12, 0x16, 0x0a, 0x06, 0x65, 0x64, 0x69, 0x74, 0x6f, 0x72, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x65, 0x64, 0x69, 0x74, 0x6f, 0x72, 0x12, 0x16, 0x0a, 0x06, + 0x76, 0x69, 0x65, 0x77, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x76, 0x69, + 0x65, 0x77, 0x65, 0x72, 0x22, 0x55, 0x0a, 0x10, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x55, + 0x73, 0x65, 0x72, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x12, 0x24, 0x0a, 0x09, 0x73, 0x73, 0x6f, 0x5f, + 0x67, 0x72, 0x6f, 0x75, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xfa, 0x42, 0x04, + 0x72, 0x02, 0x10, 0x01, 0x52, 0x08, 0x73, 0x73, 0x6f, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x12, 0x1b, + 0x0a, 0x04, 0x72, 0x6f, 0x6c, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xfa, 0x42, + 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x04, 0x72, 0x6f, 0x6c, 0x65, 0x22, 0x8d, 0x01, 0x0a, 0x0f, + 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x52, 0x42, 0x41, 0x43, 0x52, 0x6f, 0x6c, 0x65, 0x12, + 0x1b, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xfa, + 0x42, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x3e, 0x0a, 0x08, + 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x2e, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x52, 0x42, - 0x41, 0x43, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x4c, 0x61, 0x62, 0x65, 0x6c, - 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x42, 0x18, 0xfa, 0x42, 0x09, 0x9a, 0x01, 0x06, 0x22, 0x04, - 0x72, 0x02, 0x10, 0x01, 0xfa, 0x42, 0x09, 0x9a, 0x01, 0x06, 0x2a, 0x04, 0x72, 0x02, 0x10, 0x01, - 0x52, 0x06, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x1a, 0x39, 0x0a, 0x0b, 0x4c, 0x61, 0x62, 0x65, - 0x6c, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, - 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, - 0x02, 0x38, 0x01, 0x22, 0x8b, 0x01, 0x0a, 0x0c, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, - 0x54, 0x79, 0x70, 0x65, 0x12, 0x07, 0x0a, 0x03, 0x41, 0x4c, 0x4c, 0x10, 0x00, 0x12, 0x0f, 0x0a, - 0x0b, 0x41, 0x50, 0x50, 0x4c, 0x49, 0x43, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x10, 0x01, 0x12, 0x0e, - 0x0a, 0x0a, 0x44, 0x45, 0x50, 0x4c, 0x4f, 0x59, 0x4d, 0x45, 0x4e, 0x54, 0x10, 0x02, 0x12, 0x09, - 0x0a, 0x05, 0x45, 0x56, 0x45, 0x4e, 0x54, 0x10, 0x03, 0x12, 0x09, 0x0a, 0x05, 0x50, 0x49, 0x50, - 0x45, 0x44, 0x10, 0x04, 0x12, 0x14, 0x0a, 0x10, 0x44, 0x45, 0x50, 0x4c, 0x4f, 0x59, 0x4d, 0x45, - 0x4e, 0x54, 0x5f, 0x43, 0x48, 0x41, 0x49, 0x4e, 0x10, 0x05, 0x12, 0x0b, 0x0a, 0x07, 0x50, 0x52, - 0x4f, 0x4a, 0x45, 0x43, 0x54, 0x10, 0x06, 0x12, 0x0b, 0x0a, 0x07, 0x41, 0x50, 0x49, 0x5f, 0x4b, - 0x45, 0x59, 0x10, 0x07, 0x12, 0x0b, 0x0a, 0x07, 0x49, 0x4e, 0x53, 0x49, 0x47, 0x48, 0x54, 0x10, - 0x08, 0x22, 0xf3, 0x01, 0x0a, 0x11, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x52, 0x42, 0x41, - 0x43, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, 0x42, 0x0a, 0x09, 0x72, 0x65, 0x73, 0x6f, 0x75, - 0x72, 0x63, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x6d, 0x6f, 0x64, + 0x41, 0x43, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x42, 0x08, 0xfa, 0x42, 0x05, 0x92, 0x01, 0x02, + 0x08, 0x01, 0x52, 0x08, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x12, 0x1d, 0x0a, 0x0a, + 0x69, 0x73, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x74, 0x69, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, + 0x52, 0x09, 0x69, 0x73, 0x42, 0x75, 0x69, 0x6c, 0x74, 0x69, 0x6e, 0x22, 0xff, 0x02, 0x0a, 0x13, + 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x52, 0x42, 0x41, 0x43, 0x52, 0x65, 0x73, 0x6f, 0x75, + 0x72, 0x63, 0x65, 0x12, 0x45, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x0e, 0x32, 0x27, 0x2e, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x2e, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, + 0x74, 0x52, 0x42, 0x41, 0x43, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x52, 0x65, + 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x42, 0x08, 0xfa, 0x42, 0x05, 0x82, + 0x01, 0x02, 0x10, 0x01, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x58, 0x0a, 0x06, 0x6c, 0x61, + 0x62, 0x65, 0x6c, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x2e, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x52, 0x42, 0x41, 0x43, 0x52, 0x65, - 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x42, 0x08, 0xfa, 0x42, 0x05, 0x92, 0x01, 0x02, 0x08, 0x01, - 0x52, 0x09, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x12, 0x50, 0x0a, 0x07, 0x61, - 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0e, 0x32, 0x1f, 0x2e, 0x6d, - 0x6f, 0x64, 0x65, 0x6c, 0x2e, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x52, 0x42, 0x41, 0x43, - 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x15, 0xfa, - 0x42, 0x05, 0x92, 0x01, 0x02, 0x08, 0x01, 0xfa, 0x42, 0x0a, 0x92, 0x01, 0x07, 0x22, 0x05, 0x82, - 0x01, 0x02, 0x10, 0x01, 0x52, 0x07, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0x48, 0x0a, - 0x06, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x07, 0x0a, 0x03, 0x41, 0x4c, 0x4c, 0x10, 0x00, - 0x12, 0x07, 0x0a, 0x03, 0x47, 0x45, 0x54, 0x10, 0x01, 0x12, 0x08, 0x0a, 0x04, 0x4c, 0x49, 0x53, - 0x54, 0x10, 0x02, 0x12, 0x0a, 0x0a, 0x06, 0x43, 0x52, 0x45, 0x41, 0x54, 0x45, 0x10, 0x03, 0x12, - 0x0a, 0x0a, 0x06, 0x55, 0x50, 0x44, 0x41, 0x54, 0x45, 0x10, 0x04, 0x12, 0x0a, 0x0a, 0x06, 0x44, - 0x45, 0x4c, 0x45, 0x54, 0x45, 0x10, 0x05, 0x42, 0x25, 0x5a, 0x23, 0x67, 0x69, 0x74, 0x68, 0x75, - 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x69, 0x70, 0x65, 0x2d, 0x63, 0x64, 0x2f, 0x70, 0x69, - 0x70, 0x65, 0x63, 0x64, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x62, 0x06, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x45, 0x6e, 0x74, + 0x72, 0x79, 0x42, 0x18, 0xfa, 0x42, 0x09, 0x9a, 0x01, 0x06, 0x22, 0x04, 0x72, 0x02, 0x10, 0x01, + 0xfa, 0x42, 0x09, 0x9a, 0x01, 0x06, 0x2a, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x06, 0x6c, 0x61, + 0x62, 0x65, 0x6c, 0x73, 0x1a, 0x39, 0x0a, 0x0b, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x45, 0x6e, + 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, + 0x8b, 0x01, 0x0a, 0x0c, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, + 0x12, 0x07, 0x0a, 0x03, 0x41, 0x4c, 0x4c, 0x10, 0x00, 0x12, 0x0f, 0x0a, 0x0b, 0x41, 0x50, 0x50, + 0x4c, 0x49, 0x43, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x10, 0x01, 0x12, 0x0e, 0x0a, 0x0a, 0x44, 0x45, + 0x50, 0x4c, 0x4f, 0x59, 0x4d, 0x45, 0x4e, 0x54, 0x10, 0x02, 0x12, 0x09, 0x0a, 0x05, 0x45, 0x56, + 0x45, 0x4e, 0x54, 0x10, 0x03, 0x12, 0x09, 0x0a, 0x05, 0x50, 0x49, 0x50, 0x45, 0x44, 0x10, 0x04, + 0x12, 0x14, 0x0a, 0x10, 0x44, 0x45, 0x50, 0x4c, 0x4f, 0x59, 0x4d, 0x45, 0x4e, 0x54, 0x5f, 0x43, + 0x48, 0x41, 0x49, 0x4e, 0x10, 0x05, 0x12, 0x0b, 0x0a, 0x07, 0x50, 0x52, 0x4f, 0x4a, 0x45, 0x43, + 0x54, 0x10, 0x06, 0x12, 0x0b, 0x0a, 0x07, 0x41, 0x50, 0x49, 0x5f, 0x4b, 0x45, 0x59, 0x10, 0x07, + 0x12, 0x0b, 0x0a, 0x07, 0x49, 0x4e, 0x53, 0x49, 0x47, 0x48, 0x54, 0x10, 0x08, 0x22, 0xf3, 0x01, + 0x0a, 0x11, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x52, 0x42, 0x41, 0x43, 0x50, 0x6f, 0x6c, + 0x69, 0x63, 0x79, 0x12, 0x42, 0x0a, 0x09, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, + 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x2e, 0x50, + 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x52, 0x42, 0x41, 0x43, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, + 0x63, 0x65, 0x42, 0x08, 0xfa, 0x42, 0x05, 0x92, 0x01, 0x02, 0x08, 0x01, 0x52, 0x09, 0x72, 0x65, + 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x12, 0x50, 0x0a, 0x07, 0x61, 0x63, 0x74, 0x69, 0x6f, + 0x6e, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0e, 0x32, 0x1f, 0x2e, 0x6d, 0x6f, 0x64, 0x65, 0x6c, + 0x2e, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x52, 0x42, 0x41, 0x43, 0x50, 0x6f, 0x6c, 0x69, + 0x63, 0x79, 0x2e, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x15, 0xfa, 0x42, 0x05, 0x92, 0x01, + 0x02, 0x08, 0x01, 0xfa, 0x42, 0x0a, 0x92, 0x01, 0x07, 0x22, 0x05, 0x82, 0x01, 0x02, 0x10, 0x01, + 0x52, 0x07, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0x48, 0x0a, 0x06, 0x41, 0x63, 0x74, + 0x69, 0x6f, 0x6e, 0x12, 0x07, 0x0a, 0x03, 0x41, 0x4c, 0x4c, 0x10, 0x00, 0x12, 0x07, 0x0a, 0x03, + 0x47, 0x45, 0x54, 0x10, 0x01, 0x12, 0x08, 0x0a, 0x04, 0x4c, 0x49, 0x53, 0x54, 0x10, 0x02, 0x12, + 0x0a, 0x0a, 0x06, 0x43, 0x52, 0x45, 0x41, 0x54, 0x45, 0x10, 0x03, 0x12, 0x0a, 0x0a, 0x06, 0x55, + 0x50, 0x44, 0x41, 0x54, 0x45, 0x10, 0x04, 0x12, 0x0a, 0x0a, 0x06, 0x44, 0x45, 0x4c, 0x45, 0x54, + 0x45, 0x10, 0x05, 0x42, 0x25, 0x5a, 0x23, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, + 0x6d, 0x2f, 0x70, 0x69, 0x70, 0x65, 0x2d, 0x63, 0x64, 0x2f, 0x70, 0x69, 0x70, 0x65, 0x63, 0x64, + 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x33, } var ( diff --git a/pkg/model/project.pb.validate.go b/pkg/model/project.pb.validate.go index 07f117acd8..809f91a6e5 100644 --- a/pkg/model/project.pb.validate.go +++ b/pkg/model/project.pb.validate.go @@ -241,6 +241,8 @@ func (m *Project) validate(all bool) error { } + // no validation rules for Disabled + if m.GetCreatedAt() <= 0 { err := ProjectValidationError{ field: "CreatedAt", diff --git a/pkg/model/project.proto b/pkg/model/project.proto index ec6bfa739d..3a319b6c47 100644 --- a/pkg/model/project.proto +++ b/pkg/model/project.proto @@ -53,6 +53,9 @@ message Project { // Mapping SSO group and RBAC role. repeated ProjectUserGroup user_groups = 10; + // Whether the project is disabled. Disabled projects cannot log in or issue new API calls. + bool disabled = 11; + // Unix time when the project is created. int64 created_at = 14 [(validate.rules).int64.gt = 0]; // Unix time of the last time when the project is updated. diff --git a/tool/codegen/protoc-gen-auth/file.go b/tool/codegen/protoc-gen-auth/file.go index 415ce3e91a..ea7063087f 100644 --- a/tool/codegen/protoc-gen-auth/file.go +++ b/tool/codegen/protoc-gen-auth/file.go @@ -21,6 +21,7 @@ package webservice import ( "context" + "fmt" "time" "go.uber.org/zap" @@ -98,6 +99,13 @@ func (a *authorizer) getAllProjectRBACRoles(ctx context.Context, projectID strin return nil, err } + if p.Disabled { + a.logger.Warn("project is disabled", + zap.String("project", projectID), + ) + return nil, fmt.Errorf("project %s is disabled", projectID) + } + if err = a.rbacCache.Put(projectID, p.RbacRoles); err != nil { a.logger.Warn("unable to store the rbac in memory cache", zap.String("project", projectID), diff --git a/web/api_client/service_grpc_web_pb.d.ts b/web/api_client/service_grpc_web_pb.d.ts index d8ed538362..cd5346d279 100644 --- a/web/api_client/service_grpc_web_pb.d.ts +++ b/web/api_client/service_grpc_web_pb.d.ts @@ -260,6 +260,20 @@ export class WebServiceClient { response: pkg_app_server_service_webservice_service_pb.UpdateProjectRBACConfigResponse) => void ): grpcWeb.ClientReadableStream; + enableProject( + request: pkg_app_server_service_webservice_service_pb.EnableProjectRequest, + metadata: grpcWeb.Metadata | undefined, + callback: (err: grpcWeb.RpcError, + response: pkg_app_server_service_webservice_service_pb.EnableProjectResponse) => void + ): grpcWeb.ClientReadableStream; + + disableProject( + request: pkg_app_server_service_webservice_service_pb.DisableProjectRequest, + metadata: grpcWeb.Metadata | undefined, + callback: (err: grpcWeb.RpcError, + response: pkg_app_server_service_webservice_service_pb.DisableProjectResponse) => void + ): grpcWeb.ClientReadableStream; + getMe( request: pkg_app_server_service_webservice_service_pb.GetMeRequest, metadata: grpcWeb.Metadata | undefined, @@ -552,6 +566,16 @@ export class WebServicePromiseClient { metadata?: grpcWeb.Metadata ): Promise; + enableProject( + request: pkg_app_server_service_webservice_service_pb.EnableProjectRequest, + metadata?: grpcWeb.Metadata + ): Promise; + + disableProject( + request: pkg_app_server_service_webservice_service_pb.DisableProjectRequest, + metadata?: grpcWeb.Metadata + ): Promise; + getMe( request: pkg_app_server_service_webservice_service_pb.GetMeRequest, metadata?: grpcWeb.Metadata diff --git a/web/api_client/service_grpc_web_pb.js b/web/api_client/service_grpc_web_pb.js index 4156354422..412465ec38 100644 --- a/web/api_client/service_grpc_web_pb.js +++ b/web/api_client/service_grpc_web_pb.js @@ -2302,6 +2302,128 @@ proto.grpc.service.webservice.WebServicePromiseClient.prototype.updateProjectRBA }; +/** + * @const + * @type {!grpc.web.MethodDescriptor< + * !proto.grpc.service.webservice.EnableProjectRequest, + * !proto.grpc.service.webservice.EnableProjectResponse>} + */ +const methodDescriptor_WebService_EnableProject = new grpc.web.MethodDescriptor( + '/grpc.service.webservice.WebService/EnableProject', + grpc.web.MethodType.UNARY, + proto.grpc.service.webservice.EnableProjectRequest, + proto.grpc.service.webservice.EnableProjectResponse, + /** + * @param {!proto.grpc.service.webservice.EnableProjectRequest} request + * @return {!Uint8Array} + */ + function(request) { + return request.serializeBinary(); + }, + proto.grpc.service.webservice.EnableProjectResponse.deserializeBinary +); + + +/** + * @param {!proto.grpc.service.webservice.EnableProjectRequest} request The + * request proto + * @param {?Object} metadata User defined + * call metadata + * @param {function(?grpc.web.RpcError, ?proto.grpc.service.webservice.EnableProjectResponse)} + * callback The callback function(error, response) + * @return {!grpc.web.ClientReadableStream|undefined} + * The XHR Node Readable Stream + */ +proto.grpc.service.webservice.WebServiceClient.prototype.enableProject = + function(request, metadata, callback) { + return this.client_.rpcCall(this.hostname_ + + '/grpc.service.webservice.WebService/EnableProject', + request, + metadata || {}, + methodDescriptor_WebService_EnableProject, + callback); +}; + + +/** + * @param {!proto.grpc.service.webservice.EnableProjectRequest} request The + * request proto + * @param {?Object=} metadata User defined + * call metadata + * @return {!Promise} + * Promise that resolves to the response + */ +proto.grpc.service.webservice.WebServicePromiseClient.prototype.enableProject = + function(request, metadata) { + return this.client_.unaryCall(this.hostname_ + + '/grpc.service.webservice.WebService/EnableProject', + request, + metadata || {}, + methodDescriptor_WebService_EnableProject); +}; + + +/** + * @const + * @type {!grpc.web.MethodDescriptor< + * !proto.grpc.service.webservice.DisableProjectRequest, + * !proto.grpc.service.webservice.DisableProjectResponse>} + */ +const methodDescriptor_WebService_DisableProject = new grpc.web.MethodDescriptor( + '/grpc.service.webservice.WebService/DisableProject', + grpc.web.MethodType.UNARY, + proto.grpc.service.webservice.DisableProjectRequest, + proto.grpc.service.webservice.DisableProjectResponse, + /** + * @param {!proto.grpc.service.webservice.DisableProjectRequest} request + * @return {!Uint8Array} + */ + function(request) { + return request.serializeBinary(); + }, + proto.grpc.service.webservice.DisableProjectResponse.deserializeBinary +); + + +/** + * @param {!proto.grpc.service.webservice.DisableProjectRequest} request The + * request proto + * @param {?Object} metadata User defined + * call metadata + * @param {function(?grpc.web.RpcError, ?proto.grpc.service.webservice.DisableProjectResponse)} + * callback The callback function(error, response) + * @return {!grpc.web.ClientReadableStream|undefined} + * The XHR Node Readable Stream + */ +proto.grpc.service.webservice.WebServiceClient.prototype.disableProject = + function(request, metadata, callback) { + return this.client_.rpcCall(this.hostname_ + + '/grpc.service.webservice.WebService/DisableProject', + request, + metadata || {}, + methodDescriptor_WebService_DisableProject, + callback); +}; + + +/** + * @param {!proto.grpc.service.webservice.DisableProjectRequest} request The + * request proto + * @param {?Object=} metadata User defined + * call metadata + * @return {!Promise} + * Promise that resolves to the response + */ +proto.grpc.service.webservice.WebServicePromiseClient.prototype.disableProject = + function(request, metadata) { + return this.client_.unaryCall(this.hostname_ + + '/grpc.service.webservice.WebService/DisableProject', + request, + metadata || {}, + methodDescriptor_WebService_DisableProject); +}; + + /** * @const * @type {!grpc.web.MethodDescriptor< diff --git a/web/api_client/service_pb.d.ts b/web/api_client/service_pb.d.ts index a69a99101a..6314afe7b1 100644 --- a/web/api_client/service_pb.d.ts +++ b/web/api_client/service_pb.d.ts @@ -1588,6 +1588,62 @@ export namespace DisableStaticAdminResponse { } } +export class EnableProjectRequest extends jspb.Message { + serializeBinary(): Uint8Array; + toObject(includeInstance?: boolean): EnableProjectRequest.AsObject; + static toObject(includeInstance: boolean, msg: EnableProjectRequest): EnableProjectRequest.AsObject; + static serializeBinaryToWriter(message: EnableProjectRequest, writer: jspb.BinaryWriter): void; + static deserializeBinary(bytes: Uint8Array): EnableProjectRequest; + static deserializeBinaryFromReader(message: EnableProjectRequest, reader: jspb.BinaryReader): EnableProjectRequest; +} + +export namespace EnableProjectRequest { + export type AsObject = { + } +} + +export class EnableProjectResponse extends jspb.Message { + serializeBinary(): Uint8Array; + toObject(includeInstance?: boolean): EnableProjectResponse.AsObject; + static toObject(includeInstance: boolean, msg: EnableProjectResponse): EnableProjectResponse.AsObject; + static serializeBinaryToWriter(message: EnableProjectResponse, writer: jspb.BinaryWriter): void; + static deserializeBinary(bytes: Uint8Array): EnableProjectResponse; + static deserializeBinaryFromReader(message: EnableProjectResponse, reader: jspb.BinaryReader): EnableProjectResponse; +} + +export namespace EnableProjectResponse { + export type AsObject = { + } +} + +export class DisableProjectRequest extends jspb.Message { + serializeBinary(): Uint8Array; + toObject(includeInstance?: boolean): DisableProjectRequest.AsObject; + static toObject(includeInstance: boolean, msg: DisableProjectRequest): DisableProjectRequest.AsObject; + static serializeBinaryToWriter(message: DisableProjectRequest, writer: jspb.BinaryWriter): void; + static deserializeBinary(bytes: Uint8Array): DisableProjectRequest; + static deserializeBinaryFromReader(message: DisableProjectRequest, reader: jspb.BinaryReader): DisableProjectRequest; +} + +export namespace DisableProjectRequest { + export type AsObject = { + } +} + +export class DisableProjectResponse extends jspb.Message { + serializeBinary(): Uint8Array; + toObject(includeInstance?: boolean): DisableProjectResponse.AsObject; + static toObject(includeInstance: boolean, msg: DisableProjectResponse): DisableProjectResponse.AsObject; + static serializeBinaryToWriter(message: DisableProjectResponse, writer: jspb.BinaryWriter): void; + static deserializeBinary(bytes: Uint8Array): DisableProjectResponse; + static deserializeBinaryFromReader(message: DisableProjectResponse, reader: jspb.BinaryReader): DisableProjectResponse; +} + +export namespace DisableProjectResponse { + export type AsObject = { + } +} + export class GetMeRequest extends jspb.Message { serializeBinary(): Uint8Array; toObject(includeInstance?: boolean): GetMeRequest.AsObject; diff --git a/web/api_client/service_pb.js b/web/api_client/service_pb.js index c48672acff..8d54c046ec 100644 --- a/web/api_client/service_pb.js +++ b/web/api_client/service_pb.js @@ -79,12 +79,16 @@ goog.exportSymbol('proto.grpc.service.webservice.DisableApplicationRequest', nul goog.exportSymbol('proto.grpc.service.webservice.DisableApplicationResponse', null, global); goog.exportSymbol('proto.grpc.service.webservice.DisablePipedRequest', null, global); goog.exportSymbol('proto.grpc.service.webservice.DisablePipedResponse', null, global); +goog.exportSymbol('proto.grpc.service.webservice.DisableProjectRequest', null, global); +goog.exportSymbol('proto.grpc.service.webservice.DisableProjectResponse', null, global); goog.exportSymbol('proto.grpc.service.webservice.DisableStaticAdminRequest', null, global); goog.exportSymbol('proto.grpc.service.webservice.DisableStaticAdminResponse', null, global); goog.exportSymbol('proto.grpc.service.webservice.EnableApplicationRequest', null, global); goog.exportSymbol('proto.grpc.service.webservice.EnableApplicationResponse', null, global); goog.exportSymbol('proto.grpc.service.webservice.EnablePipedRequest', null, global); goog.exportSymbol('proto.grpc.service.webservice.EnablePipedResponse', null, global); +goog.exportSymbol('proto.grpc.service.webservice.EnableProjectRequest', null, global); +goog.exportSymbol('proto.grpc.service.webservice.EnableProjectResponse', null, global); goog.exportSymbol('proto.grpc.service.webservice.EnableStaticAdminRequest', null, global); goog.exportSymbol('proto.grpc.service.webservice.EnableStaticAdminResponse', null, global); goog.exportSymbol('proto.grpc.service.webservice.GenerateAPIKeyRequest', null, global); @@ -1782,6 +1786,90 @@ if (goog.DEBUG && !COMPILED) { */ proto.grpc.service.webservice.DisableStaticAdminResponse.displayName = 'proto.grpc.service.webservice.DisableStaticAdminResponse'; } +/** + * Generated by JsPbCodeGenerator. + * @param {Array=} opt_data Optional initial data array, typically from a + * server response, or constructed directly in Javascript. The array is used + * in place and becomes part of the constructed object. It is not cloned. + * If no data is provided, the constructed object will be empty, but still + * valid. + * @extends {jspb.Message} + * @constructor + */ +proto.grpc.service.webservice.EnableProjectRequest = function(opt_data) { + jspb.Message.initialize(this, opt_data, 0, -1, null, null); +}; +goog.inherits(proto.grpc.service.webservice.EnableProjectRequest, jspb.Message); +if (goog.DEBUG && !COMPILED) { + /** + * @public + * @override + */ + proto.grpc.service.webservice.EnableProjectRequest.displayName = 'proto.grpc.service.webservice.EnableProjectRequest'; +} +/** + * Generated by JsPbCodeGenerator. + * @param {Array=} opt_data Optional initial data array, typically from a + * server response, or constructed directly in Javascript. The array is used + * in place and becomes part of the constructed object. It is not cloned. + * If no data is provided, the constructed object will be empty, but still + * valid. + * @extends {jspb.Message} + * @constructor + */ +proto.grpc.service.webservice.EnableProjectResponse = function(opt_data) { + jspb.Message.initialize(this, opt_data, 0, -1, null, null); +}; +goog.inherits(proto.grpc.service.webservice.EnableProjectResponse, jspb.Message); +if (goog.DEBUG && !COMPILED) { + /** + * @public + * @override + */ + proto.grpc.service.webservice.EnableProjectResponse.displayName = 'proto.grpc.service.webservice.EnableProjectResponse'; +} +/** + * Generated by JsPbCodeGenerator. + * @param {Array=} opt_data Optional initial data array, typically from a + * server response, or constructed directly in Javascript. The array is used + * in place and becomes part of the constructed object. It is not cloned. + * If no data is provided, the constructed object will be empty, but still + * valid. + * @extends {jspb.Message} + * @constructor + */ +proto.grpc.service.webservice.DisableProjectRequest = function(opt_data) { + jspb.Message.initialize(this, opt_data, 0, -1, null, null); +}; +goog.inherits(proto.grpc.service.webservice.DisableProjectRequest, jspb.Message); +if (goog.DEBUG && !COMPILED) { + /** + * @public + * @override + */ + proto.grpc.service.webservice.DisableProjectRequest.displayName = 'proto.grpc.service.webservice.DisableProjectRequest'; +} +/** + * Generated by JsPbCodeGenerator. + * @param {Array=} opt_data Optional initial data array, typically from a + * server response, or constructed directly in Javascript. The array is used + * in place and becomes part of the constructed object. It is not cloned. + * If no data is provided, the constructed object will be empty, but still + * valid. + * @extends {jspb.Message} + * @constructor + */ +proto.grpc.service.webservice.DisableProjectResponse = function(opt_data) { + jspb.Message.initialize(this, opt_data, 0, -1, null, null); +}; +goog.inherits(proto.grpc.service.webservice.DisableProjectResponse, jspb.Message); +if (goog.DEBUG && !COMPILED) { + /** + * @public + * @override + */ + proto.grpc.service.webservice.DisableProjectResponse.displayName = 'proto.grpc.service.webservice.DisableProjectResponse'; +} /** * Generated by JsPbCodeGenerator. * @param {Array=} opt_data Optional initial data array, typically from a @@ -14121,6 +14209,410 @@ proto.grpc.service.webservice.DisableStaticAdminResponse.serializeBinaryToWriter +if (jspb.Message.GENERATE_TO_OBJECT) { +/** + * Creates an object representation of this proto. + * Field names that are reserved in JavaScript and will be renamed to pb_name. + * Optional fields that are not set will be set to undefined. + * To access a reserved field use, foo.pb_, eg, foo.pb_default. + * For the list of reserved names please see: + * net/proto2/compiler/js/internal/generator.cc#kKeyword. + * @param {boolean=} opt_includeInstance Deprecated. whether to include the + * JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @return {!Object} + */ +proto.grpc.service.webservice.EnableProjectRequest.prototype.toObject = function(opt_includeInstance) { + return proto.grpc.service.webservice.EnableProjectRequest.toObject(opt_includeInstance, this); +}; + + +/** + * Static version of the {@see toObject} method. + * @param {boolean|undefined} includeInstance Deprecated. Whether to include + * the JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @param {!proto.grpc.service.webservice.EnableProjectRequest} msg The msg instance to transform. + * @return {!Object} + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.grpc.service.webservice.EnableProjectRequest.toObject = function(includeInstance, msg) { + var f, obj = { + + }; + + if (includeInstance) { + obj.$jspbMessageInstance = msg; + } + return obj; +}; +} + + +/** + * Deserializes binary data (in protobuf wire format). + * @param {jspb.ByteSource} bytes The bytes to deserialize. + * @return {!proto.grpc.service.webservice.EnableProjectRequest} + */ +proto.grpc.service.webservice.EnableProjectRequest.deserializeBinary = function(bytes) { + var reader = new jspb.BinaryReader(bytes); + var msg = new proto.grpc.service.webservice.EnableProjectRequest; + return proto.grpc.service.webservice.EnableProjectRequest.deserializeBinaryFromReader(msg, reader); +}; + + +/** + * Deserializes binary data (in protobuf wire format) from the + * given reader into the given message object. + * @param {!proto.grpc.service.webservice.EnableProjectRequest} msg The message object to deserialize into. + * @param {!jspb.BinaryReader} reader The BinaryReader to use. + * @return {!proto.grpc.service.webservice.EnableProjectRequest} + */ +proto.grpc.service.webservice.EnableProjectRequest.deserializeBinaryFromReader = function(msg, reader) { + while (reader.nextField()) { + if (reader.isEndGroup()) { + break; + } + var field = reader.getFieldNumber(); + switch (field) { + default: + reader.skipField(); + break; + } + } + return msg; +}; + + +/** + * Serializes the message to binary data (in protobuf wire format). + * @return {!Uint8Array} + */ +proto.grpc.service.webservice.EnableProjectRequest.prototype.serializeBinary = function() { + var writer = new jspb.BinaryWriter(); + proto.grpc.service.webservice.EnableProjectRequest.serializeBinaryToWriter(this, writer); + return writer.getResultBuffer(); +}; + + +/** + * Serializes the given message to binary data (in protobuf wire + * format), writing to the given BinaryWriter. + * @param {!proto.grpc.service.webservice.EnableProjectRequest} message + * @param {!jspb.BinaryWriter} writer + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.grpc.service.webservice.EnableProjectRequest.serializeBinaryToWriter = function(message, writer) { + var f = undefined; +}; + + + + + +if (jspb.Message.GENERATE_TO_OBJECT) { +/** + * Creates an object representation of this proto. + * Field names that are reserved in JavaScript and will be renamed to pb_name. + * Optional fields that are not set will be set to undefined. + * To access a reserved field use, foo.pb_, eg, foo.pb_default. + * For the list of reserved names please see: + * net/proto2/compiler/js/internal/generator.cc#kKeyword. + * @param {boolean=} opt_includeInstance Deprecated. whether to include the + * JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @return {!Object} + */ +proto.grpc.service.webservice.EnableProjectResponse.prototype.toObject = function(opt_includeInstance) { + return proto.grpc.service.webservice.EnableProjectResponse.toObject(opt_includeInstance, this); +}; + + +/** + * Static version of the {@see toObject} method. + * @param {boolean|undefined} includeInstance Deprecated. Whether to include + * the JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @param {!proto.grpc.service.webservice.EnableProjectResponse} msg The msg instance to transform. + * @return {!Object} + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.grpc.service.webservice.EnableProjectResponse.toObject = function(includeInstance, msg) { + var f, obj = { + + }; + + if (includeInstance) { + obj.$jspbMessageInstance = msg; + } + return obj; +}; +} + + +/** + * Deserializes binary data (in protobuf wire format). + * @param {jspb.ByteSource} bytes The bytes to deserialize. + * @return {!proto.grpc.service.webservice.EnableProjectResponse} + */ +proto.grpc.service.webservice.EnableProjectResponse.deserializeBinary = function(bytes) { + var reader = new jspb.BinaryReader(bytes); + var msg = new proto.grpc.service.webservice.EnableProjectResponse; + return proto.grpc.service.webservice.EnableProjectResponse.deserializeBinaryFromReader(msg, reader); +}; + + +/** + * Deserializes binary data (in protobuf wire format) from the + * given reader into the given message object. + * @param {!proto.grpc.service.webservice.EnableProjectResponse} msg The message object to deserialize into. + * @param {!jspb.BinaryReader} reader The BinaryReader to use. + * @return {!proto.grpc.service.webservice.EnableProjectResponse} + */ +proto.grpc.service.webservice.EnableProjectResponse.deserializeBinaryFromReader = function(msg, reader) { + while (reader.nextField()) { + if (reader.isEndGroup()) { + break; + } + var field = reader.getFieldNumber(); + switch (field) { + default: + reader.skipField(); + break; + } + } + return msg; +}; + + +/** + * Serializes the message to binary data (in protobuf wire format). + * @return {!Uint8Array} + */ +proto.grpc.service.webservice.EnableProjectResponse.prototype.serializeBinary = function() { + var writer = new jspb.BinaryWriter(); + proto.grpc.service.webservice.EnableProjectResponse.serializeBinaryToWriter(this, writer); + return writer.getResultBuffer(); +}; + + +/** + * Serializes the given message to binary data (in protobuf wire + * format), writing to the given BinaryWriter. + * @param {!proto.grpc.service.webservice.EnableProjectResponse} message + * @param {!jspb.BinaryWriter} writer + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.grpc.service.webservice.EnableProjectResponse.serializeBinaryToWriter = function(message, writer) { + var f = undefined; +}; + + + + + +if (jspb.Message.GENERATE_TO_OBJECT) { +/** + * Creates an object representation of this proto. + * Field names that are reserved in JavaScript and will be renamed to pb_name. + * Optional fields that are not set will be set to undefined. + * To access a reserved field use, foo.pb_, eg, foo.pb_default. + * For the list of reserved names please see: + * net/proto2/compiler/js/internal/generator.cc#kKeyword. + * @param {boolean=} opt_includeInstance Deprecated. whether to include the + * JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @return {!Object} + */ +proto.grpc.service.webservice.DisableProjectRequest.prototype.toObject = function(opt_includeInstance) { + return proto.grpc.service.webservice.DisableProjectRequest.toObject(opt_includeInstance, this); +}; + + +/** + * Static version of the {@see toObject} method. + * @param {boolean|undefined} includeInstance Deprecated. Whether to include + * the JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @param {!proto.grpc.service.webservice.DisableProjectRequest} msg The msg instance to transform. + * @return {!Object} + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.grpc.service.webservice.DisableProjectRequest.toObject = function(includeInstance, msg) { + var f, obj = { + + }; + + if (includeInstance) { + obj.$jspbMessageInstance = msg; + } + return obj; +}; +} + + +/** + * Deserializes binary data (in protobuf wire format). + * @param {jspb.ByteSource} bytes The bytes to deserialize. + * @return {!proto.grpc.service.webservice.DisableProjectRequest} + */ +proto.grpc.service.webservice.DisableProjectRequest.deserializeBinary = function(bytes) { + var reader = new jspb.BinaryReader(bytes); + var msg = new proto.grpc.service.webservice.DisableProjectRequest; + return proto.grpc.service.webservice.DisableProjectRequest.deserializeBinaryFromReader(msg, reader); +}; + + +/** + * Deserializes binary data (in protobuf wire format) from the + * given reader into the given message object. + * @param {!proto.grpc.service.webservice.DisableProjectRequest} msg The message object to deserialize into. + * @param {!jspb.BinaryReader} reader The BinaryReader to use. + * @return {!proto.grpc.service.webservice.DisableProjectRequest} + */ +proto.grpc.service.webservice.DisableProjectRequest.deserializeBinaryFromReader = function(msg, reader) { + while (reader.nextField()) { + if (reader.isEndGroup()) { + break; + } + var field = reader.getFieldNumber(); + switch (field) { + default: + reader.skipField(); + break; + } + } + return msg; +}; + + +/** + * Serializes the message to binary data (in protobuf wire format). + * @return {!Uint8Array} + */ +proto.grpc.service.webservice.DisableProjectRequest.prototype.serializeBinary = function() { + var writer = new jspb.BinaryWriter(); + proto.grpc.service.webservice.DisableProjectRequest.serializeBinaryToWriter(this, writer); + return writer.getResultBuffer(); +}; + + +/** + * Serializes the given message to binary data (in protobuf wire + * format), writing to the given BinaryWriter. + * @param {!proto.grpc.service.webservice.DisableProjectRequest} message + * @param {!jspb.BinaryWriter} writer + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.grpc.service.webservice.DisableProjectRequest.serializeBinaryToWriter = function(message, writer) { + var f = undefined; +}; + + + + + +if (jspb.Message.GENERATE_TO_OBJECT) { +/** + * Creates an object representation of this proto. + * Field names that are reserved in JavaScript and will be renamed to pb_name. + * Optional fields that are not set will be set to undefined. + * To access a reserved field use, foo.pb_, eg, foo.pb_default. + * For the list of reserved names please see: + * net/proto2/compiler/js/internal/generator.cc#kKeyword. + * @param {boolean=} opt_includeInstance Deprecated. whether to include the + * JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @return {!Object} + */ +proto.grpc.service.webservice.DisableProjectResponse.prototype.toObject = function(opt_includeInstance) { + return proto.grpc.service.webservice.DisableProjectResponse.toObject(opt_includeInstance, this); +}; + + +/** + * Static version of the {@see toObject} method. + * @param {boolean|undefined} includeInstance Deprecated. Whether to include + * the JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @param {!proto.grpc.service.webservice.DisableProjectResponse} msg The msg instance to transform. + * @return {!Object} + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.grpc.service.webservice.DisableProjectResponse.toObject = function(includeInstance, msg) { + var f, obj = { + + }; + + if (includeInstance) { + obj.$jspbMessageInstance = msg; + } + return obj; +}; +} + + +/** + * Deserializes binary data (in protobuf wire format). + * @param {jspb.ByteSource} bytes The bytes to deserialize. + * @return {!proto.grpc.service.webservice.DisableProjectResponse} + */ +proto.grpc.service.webservice.DisableProjectResponse.deserializeBinary = function(bytes) { + var reader = new jspb.BinaryReader(bytes); + var msg = new proto.grpc.service.webservice.DisableProjectResponse; + return proto.grpc.service.webservice.DisableProjectResponse.deserializeBinaryFromReader(msg, reader); +}; + + +/** + * Deserializes binary data (in protobuf wire format) from the + * given reader into the given message object. + * @param {!proto.grpc.service.webservice.DisableProjectResponse} msg The message object to deserialize into. + * @param {!jspb.BinaryReader} reader The BinaryReader to use. + * @return {!proto.grpc.service.webservice.DisableProjectResponse} + */ +proto.grpc.service.webservice.DisableProjectResponse.deserializeBinaryFromReader = function(msg, reader) { + while (reader.nextField()) { + if (reader.isEndGroup()) { + break; + } + var field = reader.getFieldNumber(); + switch (field) { + default: + reader.skipField(); + break; + } + } + return msg; +}; + + +/** + * Serializes the message to binary data (in protobuf wire format). + * @return {!Uint8Array} + */ +proto.grpc.service.webservice.DisableProjectResponse.prototype.serializeBinary = function() { + var writer = new jspb.BinaryWriter(); + proto.grpc.service.webservice.DisableProjectResponse.serializeBinaryToWriter(this, writer); + return writer.getResultBuffer(); +}; + + +/** + * Serializes the given message to binary data (in protobuf wire + * format), writing to the given BinaryWriter. + * @param {!proto.grpc.service.webservice.DisableProjectResponse} message + * @param {!jspb.BinaryWriter} writer + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.grpc.service.webservice.DisableProjectResponse.serializeBinaryToWriter = function(message, writer) { + var f = undefined; +}; + + + + + if (jspb.Message.GENERATE_TO_OBJECT) { /** * Creates an object representation of this proto. diff --git a/web/model/project_pb.d.ts b/web/model/project_pb.d.ts index d7767de1e6..6d85b06084 100644 --- a/web/model/project_pb.d.ts +++ b/web/model/project_pb.d.ts @@ -45,6 +45,9 @@ export class Project extends jspb.Message { clearUserGroupsList(): Project; addUserGroups(value?: ProjectUserGroup, index?: number): ProjectUserGroup; + getDisabled(): boolean; + setDisabled(value: boolean): Project; + getCreatedAt(): number; setCreatedAt(value: number): Project; @@ -71,6 +74,7 @@ export namespace Project { allowStrayAsViewer: boolean, rbacRolesList: Array, userGroupsList: Array, + disabled: boolean, createdAt: number, updatedAt: number, } diff --git a/web/model/project_pb.js b/web/model/project_pb.js index 1f888b6aee..4807a39d05 100644 --- a/web/model/project_pb.js +++ b/web/model/project_pb.js @@ -321,6 +321,7 @@ proto.model.Project.toObject = function(includeInstance, msg) { proto.model.ProjectRBACRole.toObject, includeInstance), userGroupsList: jspb.Message.toObjectList(msg.getUserGroupsList(), proto.model.ProjectUserGroup.toObject, includeInstance), + disabled: jspb.Message.getBooleanFieldWithDefault(msg, 11, false), createdAt: jspb.Message.getFieldWithDefault(msg, 14, 0), updatedAt: jspb.Message.getFieldWithDefault(msg, 15, 0) }; @@ -404,6 +405,10 @@ proto.model.Project.deserializeBinaryFromReader = function(msg, reader) { reader.readMessage(value,proto.model.ProjectUserGroup.deserializeBinaryFromReader); msg.addUserGroups(value); break; + case 11: + var value = /** @type {boolean} */ (reader.readBool()); + msg.setDisabled(value); + break; case 14: var value = /** @type {number} */ (reader.readInt64()); msg.setCreatedAt(value); @@ -516,6 +521,13 @@ proto.model.Project.serializeBinaryToWriter = function(message, writer) { proto.model.ProjectUserGroup.serializeBinaryToWriter ); } + f = message.getDisabled(); + if (f) { + writer.writeBool( + 11, + f + ); + } f = message.getCreatedAt(); if (f !== 0) { writer.writeInt64( @@ -810,6 +822,24 @@ proto.model.Project.prototype.clearUserGroupsList = function() { }; +/** + * optional bool disabled = 11; + * @return {boolean} + */ +proto.model.Project.prototype.getDisabled = function() { + return /** @type {boolean} */ (jspb.Message.getBooleanFieldWithDefault(this, 11, false)); +}; + + +/** + * @param {boolean} value + * @return {!proto.model.Project} returns this + */ +proto.model.Project.prototype.setDisabled = function(value) { + return jspb.Message.setProto3BooleanField(this, 11, value); +}; + + /** * optional int64 created_at = 14; * @return {number} diff --git a/web/src/api/project.ts b/web/src/api/project.ts index 919cbaaf8c..18df475781 100644 --- a/web/src/api/project.ts +++ b/web/src/api/project.ts @@ -21,6 +21,10 @@ import { DeleteProjectRBACRoleResponse, UpdateProjectRBACRoleRequest, UpdateProjectRBACRoleResponse, + EnableProjectRequest, + EnableProjectResponse, + DisableProjectRequest, + DisableProjectResponse, } from "pipecd/web/api_client/service_pb"; import { ProjectRBACConfig, @@ -158,3 +162,13 @@ export const updateRBACRole = ({ req.setPoliciesList(policies); return apiRequest(req, apiClient.updateProjectRBACRole); }; + +export const enableProject = (): Promise => { + const req = new EnableProjectRequest(); + return apiRequest(req, apiClient.enableProject); +}; + +export const disableProject = (): Promise => { + const req = new DisableProjectRequest(); + return apiRequest(req, apiClient.disableProject); +}; diff --git a/web/src/components/settings-page/project/components/github-sso-form/index.tsx b/web/src/components/settings-page/project/components/github-sso-form/index.tsx index ef9ceada67..3c54d02c0b 100644 --- a/web/src/components/settings-page/project/components/github-sso-form/index.tsx +++ b/web/src/components/settings-page/project/components/github-sso-form/index.tsx @@ -13,7 +13,7 @@ import { import EditIcon from "@mui/icons-material/Edit"; import * as React from "react"; -import { FC, memo, useState } from "react"; +import { FC, memo, useEffect, useState } from "react"; import { SSO_DESCRIPTION } from "~/constants/text"; import { UPDATE_SSO_SUCCESS } from "~/constants/toast-text"; import { UI_TEXT_CANCEL, UI_TEXT_SAVE } from "~/constants/ui-text"; @@ -51,6 +51,7 @@ export const GithubSSOForm: FC = memo(function GithubSSOForm() { const { data: projectDetail } = useGetProject(); const { github: sso, sharedSSO: sharedSSO } = projectDetail || {}; + const isProjectDisabled = projectDetail?.disabled ?? false; const { mutateAsync: updateGithubSso } = useUpdateGithubSso(); const { addToast } = useToast(); @@ -71,6 +72,12 @@ export const GithubSSOForm: FC = memo(function GithubSSOForm() { const isInvalid = clientId === "" || clientSecret === ""; + useEffect(() => { + if (isProjectDisabled) { + setIsEdit(false); + } + }, [isProjectDisabled]); + return ( <> @@ -79,7 +86,12 @@ export const GithubSSOForm: FC = memo(function GithubSSOForm() { {SSO_DESCRIPTION} - + {sso ? ( <> @@ -96,7 +108,11 @@ export const GithubSSOForm: FC = memo(function GithubSSOForm() {
- setIsEdit(true)} size="large"> + setIsEdit(true)} + disabled={isProjectDisabled} + size="large" + >
diff --git a/web/src/components/settings-page/project/components/project-status-form/index.tsx b/web/src/components/settings-page/project/components/project-status-form/index.tsx new file mode 100644 index 0000000000..656069a9ac --- /dev/null +++ b/web/src/components/settings-page/project/components/project-status-form/index.tsx @@ -0,0 +1,65 @@ +import { Alert, Switch } from "@mui/material"; +import { FC, memo, useCallback } from "react"; +import { + PROJECT_DISABLED_WARNING, + PROJECT_STATUS_DESCRIPTION, +} from "~/constants/text"; +import { + ProjectDescription, + ProjectTitle, + ProjectTitleWrap, +} from "~/styles/project-setting"; +import { useGetProject } from "~/queries/project/use-get-project"; +import { useToggleProjectAvailability } from "~/queries/project/use-toggle-project-availability"; +import { useToast } from "~/contexts/toast-context"; +import { + DISABLE_PROJECT_SUCCESS, + ENABLE_PROJECT_SUCCESS, +} from "~/constants/toast-text"; + +const SECTION_TITLE = "Project Status"; + +export const ProjectStatusForm: FC = memo(function ProjectStatusForm() { + const { data: projectDetail } = useGetProject(); + const isProjectDisabled = projectDetail?.disabled ?? false; + const hasProjectId = Boolean(projectDetail?.id); + + const { mutateAsync: toggleAvailability, isLoading } = + useToggleProjectAvailability(); + const { addToast } = useToast(); + + const handleToggle = useCallback(() => { + if (!hasProjectId || isLoading) { + return; + } + toggleAvailability({ enable: isProjectDisabled }).then(() => { + addToast({ + message: isProjectDisabled + ? ENABLE_PROJECT_SUCCESS + : DISABLE_PROJECT_SUCCESS, + severity: "success", + }); + }); + }, [addToast, hasProjectId, isLoading, isProjectDisabled, toggleAvailability]); + + return ( + <> + + {SECTION_TITLE} + + + + {PROJECT_STATUS_DESCRIPTION} + + {isProjectDisabled && ( + + {PROJECT_DISABLED_WARNING} + + )} + + ); +}); diff --git a/web/src/components/settings-page/project/components/rbac-form/components/add-user-group-dialog/index.test.tsx b/web/src/components/settings-page/project/components/rbac-form/components/add-user-group-dialog/index.test.tsx index 8279c1e38d..df4cdf8b4b 100644 --- a/web/src/components/settings-page/project/components/rbac-form/components/add-user-group-dialog/index.test.tsx +++ b/web/src/components/settings-page/project/components/rbac-form/components/add-user-group-dialog/index.test.tsx @@ -7,6 +7,7 @@ jest.mock("~/queries/project/use-get-project", () => ({ useGetProject: () => ({ data: { rbacRoles: [{ name: "Admin" }, { name: "Viewer" }], + disabled: false, }, }), })); diff --git a/web/src/components/settings-page/project/components/rbac-form/components/role-table-row/index.tsx b/web/src/components/settings-page/project/components/rbac-form/components/role-table-row/index.tsx index 4ec7860979..04b1a08745 100644 --- a/web/src/components/settings-page/project/components/rbac-form/components/role-table-row/index.tsx +++ b/web/src/components/settings-page/project/components/rbac-form/components/role-table-row/index.tsx @@ -10,6 +10,7 @@ interface Props { role: ProjectRBACRole.AsObject; onEdit: (role: ProjectRBACRole.AsObject) => void; onDelete: (roleName: string) => void; + disabled?: boolean; } const ITEM_HEIGHT = 48; @@ -18,6 +19,7 @@ export const RoleTableRow: FC = memo(function RoleTableRow({ role, onDelete, onEdit, + disabled = false, }) { const [anchorEl, setAnchorEl] = useState(null); @@ -60,7 +62,7 @@ export const RoleTableRow: FC = memo(function RoleTableRow({ edge="end" aria-label="open menu" onClick={handleMenuOpen} - disabled={role.isBuiltin} + disabled={role.isBuiltin || disabled} size="large" > @@ -70,7 +72,7 @@ export const RoleTableRow: FC = memo(function RoleTableRow({ = memo(function RoleTable({ + isProjectDisabled, +}) { const { data: projectDetail } = useGetProject(); const rbacRoles = projectDetail?.rbacRoles || []; @@ -48,6 +54,14 @@ export const RoleTable: FC = memo(function RoleTable() { null ); + useEffect(() => { + if (isProjectDisabled) { + setIsOpenAddForm(false); + setDeleteRoleName(null); + setEditRole(null); + } + }, [isProjectDisabled]); + const handleSubmit = useCallback( (values: { name: string; policies: string }) => { const params = { @@ -117,12 +131,17 @@ export const RoleTable: FC = memo(function RoleTable() { color="primary" startIcon={} onClick={() => setIsOpenAddForm(true)} + disabled={isProjectDisabled} > {UI_TEXT_ADD} - + @@ -138,6 +157,7 @@ export const RoleTable: FC = memo(function RoleTable() { role={role} onEdit={(role) => setEditRole(role)} onDelete={(role) => setDeleteRoleName(role)} + disabled={isProjectDisabled} /> ))} @@ -145,7 +165,7 @@ export const RoleTable: FC = memo(function RoleTable() { setIsOpenAddForm(false)} onSubmit={handleSubmit} /> @@ -157,7 +177,7 @@ export const RoleTable: FC = memo(function RoleTable() { /> diff --git a/web/src/components/settings-page/project/components/rbac-form/components/user-group/index.tsx b/web/src/components/settings-page/project/components/rbac-form/components/user-group/index.tsx index 00d4615107..da05941933 100644 --- a/web/src/components/settings-page/project/components/rbac-form/components/user-group/index.tsx +++ b/web/src/components/settings-page/project/components/rbac-form/components/user-group/index.tsx @@ -14,7 +14,7 @@ import { } from "@mui/material"; import * as React from "react"; import { Add as AddIcon, MoreVert as MenuIcon } from "@mui/icons-material"; -import { FC, memo, useCallback, useState } from "react"; +import { FC, memo, useCallback, useEffect, useState } from "react"; import { UI_TEXT_ADD } from "~/constants/ui-text"; import { AddUserGroupDialog } from "../add-user-group-dialog"; import { DeleteUserGroupConfirmDialog } from "../delete-user-group-confirm-dialog"; @@ -28,9 +28,15 @@ import { useGetProject } from "~/queries/project/use-get-project"; import { useAddUserGroup } from "~/queries/project/use-add-user-group"; import { useDeleteUserGroup } from "~/queries/project/use-delete-user-group"; +interface UserGroupTableProps { + isProjectDisabled: boolean; +} + const SUB_SECTION_TITLE = "User Group"; -export const UserGroupTable: FC = memo(function UserGroupTable() { +export const UserGroupTable: FC = memo(function UserGroupTable({ + isProjectDisabled, +}) { const [isOpenAddForm, setIsOpenAddForm] = useState(false); const [deleteSSOGroup, setDeleteSSOGroup] = useState(null); const [anchorEl, setAnchorEl] = React.useState( @@ -42,6 +48,14 @@ export const UserGroupTable: FC = memo(function UserGroupTable() { const { mutateAsync: deleteUserGroup } = useDeleteUserGroup(); const userGroups = projectDetail?.userGroups || []; + useEffect(() => { + if (isProjectDisabled) { + setIsOpenAddForm(false); + setAnchorEl(null); + setDeleteSSOGroup(null); + } + }, [isProjectDisabled]); + const handleSubmit = useCallback( (values: { ssoGroup: string; role: string }) => { addUserGroup(values).then(() => { @@ -98,11 +112,16 @@ export const UserGroupTable: FC = memo(function UserGroupTable() { color="primary" startIcon={} onClick={() => setIsOpenAddForm(true)} + disabled={isProjectDisabled} > {UI_TEXT_ADD} - +
@@ -121,6 +140,7 @@ export const UserGroupTable: FC = memo(function UserGroupTable() { data-id={group.ssoGroup} onClick={handleOpenMenu} size="large" + disabled={isProjectDisabled} > @@ -132,7 +152,7 @@ export const UserGroupTable: FC = memo(function UserGroupTable() { setIsOpenAddForm(false)} onSubmit={handleSubmit} /> diff --git a/web/src/components/settings-page/project/components/rbac-form/index.tsx b/web/src/components/settings-page/project/components/rbac-form/index.tsx index 0ba46a97b6..fb77d7a493 100644 --- a/web/src/components/settings-page/project/components/rbac-form/index.tsx +++ b/web/src/components/settings-page/project/components/rbac-form/index.tsx @@ -7,10 +7,14 @@ import { } from "~/styles/project-setting"; import { RoleTable } from "./components/role"; import { UserGroupTable } from "./components/user-group"; +import { useGetProject } from "~/queries/project/use-get-project"; const SECTION_TITLE = "Role-Based Access Control"; export const RBACForm: FC = memo(function RBACForm() { + const { data: projectDetail } = useGetProject(); + const isProjectDisabled = projectDetail?.disabled ?? false; + return ( <> @@ -21,9 +25,9 @@ export const RBACForm: FC = memo(function RBACForm() { {RBAC_DESCRIPTION} - + - + ); }); diff --git a/web/src/components/settings-page/project/components/static-admin-form/index.tsx b/web/src/components/settings-page/project/components/static-admin-form/index.tsx index c7124570ce..d47bb21bd8 100644 --- a/web/src/components/settings-page/project/components/static-admin-form/index.tsx +++ b/web/src/components/settings-page/project/components/static-admin-form/index.tsx @@ -12,7 +12,7 @@ import { import EditIcon from "@mui/icons-material/Edit"; import { useFormik } from "formik"; -import { FC, memo, useState } from "react"; +import { FC, memo, useEffect, useState } from "react"; import * as yup from "yup"; import { STATIC_ADMIN_DESCRIPTION } from "~/constants/text"; import { UPDATE_STATIC_ADMIN_INFO_SUCCESS } from "~/constants/toast-text"; @@ -112,6 +112,7 @@ export const StaticAdminForm: FC = memo(function StaticAdminForm() { const { data: project } = useGetProject(); const isEnabled = project?.staticAdminDisabled === false; + const isProjectDisabled = project?.disabled ?? false; const currentUsername = project?.username || null; const { mutateAsync: updateStaticAdmin } = useUpdateStaticAdmin(); @@ -120,6 +121,12 @@ export const StaticAdminForm: FC = memo(function StaticAdminForm() { } = useToggleAvailabilityStaticAdmin(); const { addToast } = useToast(); + useEffect(() => { + if (isProjectDisabled) { + setIsEdit(false); + } + }, [isProjectDisabled]); + const handleSubmit = (values: { username: string; password: string; @@ -138,6 +145,9 @@ export const StaticAdminForm: FC = memo(function StaticAdminForm() { }; const handleToggleAvailability = (): void => { + if (isProjectDisabled) { + return; + } toggleAvailability({ isEnabled: !isEnabled }); }; @@ -150,13 +160,18 @@ export const StaticAdminForm: FC = memo(function StaticAdminForm() { checked={isEnabled} color="primary" onClick={handleToggleAvailability} - disabled={currentUsername === null} + disabled={currentUsername === null || isProjectDisabled} /> {STATIC_ADMIN_DESCRIPTION} - + {currentUsername ? ( <> @@ -170,7 +185,7 @@ export const StaticAdminForm: FC = memo(function StaticAdminForm() { setIsEdit(true)} - disabled={isEnabled === false} + disabled={isEnabled === false || isProjectDisabled} size="large" > diff --git a/web/src/components/settings-page/project/index.tsx b/web/src/components/settings-page/project/index.tsx index 11450249bc..14a1279ffb 100644 --- a/web/src/components/settings-page/project/index.tsx +++ b/web/src/components/settings-page/project/index.tsx @@ -1,8 +1,9 @@ import { FC, memo } from "react"; +import { Box } from "@mui/material"; import { GithubSSOForm } from "./components/github-sso-form"; +import { ProjectStatusForm } from "./components/project-status-form"; import { RBACForm } from "./components/rbac-form"; import { StaticAdminForm } from "./components/static-admin-form"; -import { Box } from "@mui/material"; export const SettingsProjectPage: FC = memo(function SettingsProjectPage() { return ( @@ -14,7 +15,10 @@ export const SettingsProjectPage: FC = memo(function SettingsProjectPage() { flex: 1, })} > - + + + + diff --git a/web/src/constants/text.ts b/web/src/constants/text.ts index d959d5d00f..d838565401 100644 --- a/web/src/constants/text.ts +++ b/web/src/constants/text.ts @@ -2,3 +2,5 @@ export const STATIC_ADMIN_DESCRIPTION = `An admin account that was automatically export const SSO_DESCRIPTION = `Single sign-on (SSO) allows users to log in to PipeCD by relying on a trusted third party service. Currently, only GitHub is supported.`; export const RBAC_DESCRIPTION = `Role-based access control (RBAC) allows restricting the access on PipeCD web based on the roles of user groups within the project. Before using this feature, the SSO must be configured.`; export const WARNING_BREAKING_CHANGES = `New Releases Contains Breaking Changes`; +export const PROJECT_STATUS_DESCRIPTION = `Disabling a project prevents new logins, API key calls, and Piped connections. Re-enable it once maintenance completes to let your users access the control plane again.`; +export const PROJECT_DISABLED_WARNING = `This project is disabled. Existing sessions will soon lose access and no new logins or API calls are allowed until it is re-enabled.`; diff --git a/web/src/constants/toast-text.ts b/web/src/constants/toast-text.ts index 58a322ecde..680c6d84b0 100644 --- a/web/src/constants/toast-text.ts +++ b/web/src/constants/toast-text.ts @@ -28,3 +28,5 @@ export const DELETE_USER_GROUP_SUCCESS = "Successfully deleted User Group."; export const ADD_RBAC_ROLE_SUCCESS = "Successfully added RBAC Role."; export const DELETE_RBAC_ROLE_SUCCESS = "Successfully deleted RBAC Role."; export const UPDATE_RBAC_ROLE_SUCCESS = "Successfully updated RBAC Role."; +export const ENABLE_PROJECT_SUCCESS = "Project enabled."; +export const DISABLE_PROJECT_SUCCESS = "Project disabled."; diff --git a/web/src/queries/project/use-get-project.tsx b/web/src/queries/project/use-get-project.tsx index 1386672362..25e59b0253 100644 --- a/web/src/queries/project/use-get-project.tsx +++ b/web/src/queries/project/use-get-project.tsx @@ -24,6 +24,7 @@ type ProjectDetail = { github: GitHubSSO | null; userGroups: ProjectUserGroup.AsObject[] | []; rbacRoles: ProjectRBACRole.AsObject[] | []; + disabled: boolean; }; export const useGetProject = ( @@ -45,6 +46,7 @@ export const useGetProject = ( sharedSSO: null, userGroups: [], rbacRoles: [], + disabled: false, }; } @@ -58,6 +60,7 @@ export const useGetProject = ( sharedSSO: project.sharedSsoName, userGroups: project.userGroupsList, rbacRoles: project.rbacRolesList, + disabled: project.disabled, }; }, placeholderData: { @@ -70,6 +73,7 @@ export const useGetProject = ( sharedSSO: null, userGroups: [], rbacRoles: [], + disabled: false, }, retry: false, refetchOnMount: false, diff --git a/web/src/queries/project/use-toggle-project-availability.tsx b/web/src/queries/project/use-toggle-project-availability.tsx new file mode 100644 index 0000000000..073453a6be --- /dev/null +++ b/web/src/queries/project/use-toggle-project-availability.tsx @@ -0,0 +1,26 @@ +import { + useMutation, + UseMutationResult, + useQueryClient, +} from "@tanstack/react-query"; +import * as projectAPI from "~/api/project"; + +export const useToggleProjectAvailability = (): UseMutationResult< + void, + unknown, + { enable: boolean } +> => { + const queryClient = useQueryClient(); + return useMutation({ + mutationFn: async ({ enable }) => { + if (enable) { + await projectAPI.enableProject(); + } else { + await projectAPI.disableProject(); + } + }, + onSuccess: () => { + queryClient.invalidateQueries(["project", "detail"]); + }, + }); +}; From 604699ddc241a1583a4b5988733ae3f4ceedf1cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9Cniladrix719=E2=80=9D?= Date: Thu, 27 Nov 2025 02:36:51 +0530 Subject: [PATCH 2/9] fix: lint format MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: “niladrix719” --- pkg/app/helloworld/service/service.pb.go | 5 +- pkg/app/helloworld/service/service_grpc.pb.go | 1 + .../server/service/apiservice/service.pb.go | 5 +- .../service/apiservice/service_grpc.pb.go | 1 + .../server/service/pipedservice/service.pb.go | 5 +- .../service/pipedservice/service_grpc.pb.go | 1 + .../server/service/webservice/service.pb.go | 5 +- .../service/webservice/service_grpc.pb.go | 1 + pkg/model/analysis_result.pb.go | 5 +- pkg/model/apikey.pb.go | 5 +- pkg/model/application.pb.go | 5 +- pkg/model/application_live_state.pb.go | 5 +- pkg/model/command.pb.go | 5 +- pkg/model/common.pb.go | 5 +- pkg/model/deployment.pb.go | 5 +- pkg/model/deployment_chain.pb.go | 5 +- pkg/model/deployment_trace.pb.go | 5 +- pkg/model/event.pb.go | 5 +- pkg/model/insight.pb.go | 5 +- pkg/model/logblock.pb.go | 5 +- pkg/model/notificationevent.pb.go | 5 +- pkg/model/piped.pb.go | 5 +- pkg/model/piped_stat.pb.go | 5 +- pkg/model/planpreview.pb.go | 5 +- pkg/model/project.pb.go | 5 +- pkg/model/rbac.pb.go | 5 +- pkg/model/role.pb.go | 5 +- pkg/model/user.pb.go | 5 +- pkg/plugin/api/v1alpha1/common/common.pb.go | 5 +- pkg/plugin/api/v1alpha1/deployment/api.pb.go | 5 +- .../api/v1alpha1/deployment/api_grpc.pb.go | 1 + pkg/plugin/api/v1alpha1/livestate/api.pb.go | 5 +- .../api/v1alpha1/livestate/api_grpc.pb.go | 1 + pkg/plugin/api/v1alpha1/planpreview/api.pb.go | 5 +- .../api/v1alpha1/planpreview/api_grpc.pb.go | 1 + pkg/plugin/pipedservice/service.pb.go | 5 +- pkg/plugin/pipedservice/service_grpc.pb.go | 1 + web/src/__fixtures__/dummy-project.ts | 2 + .../components/project-status-form/index.tsx | 14 +- .../rbac-form/components/user-group/index.tsx | 274 +++++++++--------- 40 files changed, 245 insertions(+), 198 deletions(-) diff --git a/pkg/app/helloworld/service/service.pb.go b/pkg/app/helloworld/service/service.pb.go index 3975fa6078..bd7f450cd7 100644 --- a/pkg/app/helloworld/service/service.pb.go +++ b/pkg/app/helloworld/service/service.pb.go @@ -21,11 +21,12 @@ package service import ( + reflect "reflect" + sync "sync" + _ "github.com/envoyproxy/protoc-gen-validate/validate" protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" - reflect "reflect" - sync "sync" ) const ( diff --git a/pkg/app/helloworld/service/service_grpc.pb.go b/pkg/app/helloworld/service/service_grpc.pb.go index ae42e3b779..caea204bf6 100644 --- a/pkg/app/helloworld/service/service_grpc.pb.go +++ b/pkg/app/helloworld/service/service_grpc.pb.go @@ -8,6 +8,7 @@ package service import ( context "context" + grpc "google.golang.org/grpc" codes "google.golang.org/grpc/codes" status "google.golang.org/grpc/status" diff --git a/pkg/app/server/service/apiservice/service.pb.go b/pkg/app/server/service/apiservice/service.pb.go index ce59c23136..821be311dc 100644 --- a/pkg/app/server/service/apiservice/service.pb.go +++ b/pkg/app/server/service/apiservice/service.pb.go @@ -21,12 +21,13 @@ package apiservice import ( + reflect "reflect" + sync "sync" + _ "github.com/envoyproxy/protoc-gen-validate/validate" model "github.com/pipe-cd/pipecd/pkg/model" protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" - reflect "reflect" - sync "sync" ) const ( diff --git a/pkg/app/server/service/apiservice/service_grpc.pb.go b/pkg/app/server/service/apiservice/service_grpc.pb.go index 8193460074..8c2573ee17 100644 --- a/pkg/app/server/service/apiservice/service_grpc.pb.go +++ b/pkg/app/server/service/apiservice/service_grpc.pb.go @@ -8,6 +8,7 @@ package apiservice import ( context "context" + grpc "google.golang.org/grpc" codes "google.golang.org/grpc/codes" status "google.golang.org/grpc/status" diff --git a/pkg/app/server/service/pipedservice/service.pb.go b/pkg/app/server/service/pipedservice/service.pb.go index b34ff83335..8da1f543fa 100644 --- a/pkg/app/server/service/pipedservice/service.pb.go +++ b/pkg/app/server/service/pipedservice/service.pb.go @@ -21,12 +21,13 @@ package pipedservice import ( + reflect "reflect" + sync "sync" + _ "github.com/envoyproxy/protoc-gen-validate/validate" model "github.com/pipe-cd/pipecd/pkg/model" protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" - reflect "reflect" - sync "sync" ) const ( diff --git a/pkg/app/server/service/pipedservice/service_grpc.pb.go b/pkg/app/server/service/pipedservice/service_grpc.pb.go index 7d3079717d..9f82903921 100644 --- a/pkg/app/server/service/pipedservice/service_grpc.pb.go +++ b/pkg/app/server/service/pipedservice/service_grpc.pb.go @@ -8,6 +8,7 @@ package pipedservice import ( context "context" + grpc "google.golang.org/grpc" codes "google.golang.org/grpc/codes" status "google.golang.org/grpc/status" diff --git a/pkg/app/server/service/webservice/service.pb.go b/pkg/app/server/service/webservice/service.pb.go index 3d0b5baa58..d761a6fa62 100644 --- a/pkg/app/server/service/webservice/service.pb.go +++ b/pkg/app/server/service/webservice/service.pb.go @@ -21,14 +21,15 @@ package webservice import ( + reflect "reflect" + sync "sync" + _ "github.com/envoyproxy/protoc-gen-validate/validate" model "github.com/pipe-cd/pipecd/pkg/model" protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" _ "google.golang.org/protobuf/types/descriptorpb" wrapperspb "google.golang.org/protobuf/types/known/wrapperspb" - reflect "reflect" - sync "sync" ) const ( diff --git a/pkg/app/server/service/webservice/service_grpc.pb.go b/pkg/app/server/service/webservice/service_grpc.pb.go index 3ef9ff6e64..95c1ac8b24 100644 --- a/pkg/app/server/service/webservice/service_grpc.pb.go +++ b/pkg/app/server/service/webservice/service_grpc.pb.go @@ -8,6 +8,7 @@ package webservice import ( context "context" + grpc "google.golang.org/grpc" codes "google.golang.org/grpc/codes" status "google.golang.org/grpc/status" diff --git a/pkg/model/analysis_result.pb.go b/pkg/model/analysis_result.pb.go index 6c243805b7..1db8d275a6 100644 --- a/pkg/model/analysis_result.pb.go +++ b/pkg/model/analysis_result.pb.go @@ -21,11 +21,12 @@ package model import ( + reflect "reflect" + sync "sync" + _ "github.com/envoyproxy/protoc-gen-validate/validate" protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" - reflect "reflect" - sync "sync" ) const ( diff --git a/pkg/model/apikey.pb.go b/pkg/model/apikey.pb.go index 08c0af46d7..045df4eb97 100644 --- a/pkg/model/apikey.pb.go +++ b/pkg/model/apikey.pb.go @@ -21,11 +21,12 @@ package model import ( + reflect "reflect" + sync "sync" + _ "github.com/envoyproxy/protoc-gen-validate/validate" protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" - reflect "reflect" - sync "sync" ) const ( diff --git a/pkg/model/application.pb.go b/pkg/model/application.pb.go index b85be9b3cc..d3a88d05c6 100644 --- a/pkg/model/application.pb.go +++ b/pkg/model/application.pb.go @@ -21,11 +21,12 @@ package model import ( + reflect "reflect" + sync "sync" + _ "github.com/envoyproxy/protoc-gen-validate/validate" protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" - reflect "reflect" - sync "sync" ) const ( diff --git a/pkg/model/application_live_state.pb.go b/pkg/model/application_live_state.pb.go index 4aad111aad..ecab5709be 100644 --- a/pkg/model/application_live_state.pb.go +++ b/pkg/model/application_live_state.pb.go @@ -21,11 +21,12 @@ package model import ( + reflect "reflect" + sync "sync" + _ "github.com/envoyproxy/protoc-gen-validate/validate" protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" - reflect "reflect" - sync "sync" ) const ( diff --git a/pkg/model/command.pb.go b/pkg/model/command.pb.go index ce5d5b4c53..c5a1893548 100644 --- a/pkg/model/command.pb.go +++ b/pkg/model/command.pb.go @@ -21,11 +21,12 @@ package model import ( + reflect "reflect" + sync "sync" + _ "github.com/envoyproxy/protoc-gen-validate/validate" protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" - reflect "reflect" - sync "sync" ) const ( diff --git a/pkg/model/common.pb.go b/pkg/model/common.pb.go index 21de37ffa3..fea8b2f3d8 100644 --- a/pkg/model/common.pb.go +++ b/pkg/model/common.pb.go @@ -21,11 +21,12 @@ package model import ( + reflect "reflect" + sync "sync" + _ "github.com/envoyproxy/protoc-gen-validate/validate" protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" - reflect "reflect" - sync "sync" ) const ( diff --git a/pkg/model/deployment.pb.go b/pkg/model/deployment.pb.go index 5e31d35165..7fe61d18c6 100644 --- a/pkg/model/deployment.pb.go +++ b/pkg/model/deployment.pb.go @@ -21,11 +21,12 @@ package model import ( + reflect "reflect" + sync "sync" + _ "github.com/envoyproxy/protoc-gen-validate/validate" protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" - reflect "reflect" - sync "sync" ) const ( diff --git a/pkg/model/deployment_chain.pb.go b/pkg/model/deployment_chain.pb.go index 3e5630488a..0d427d09e1 100644 --- a/pkg/model/deployment_chain.pb.go +++ b/pkg/model/deployment_chain.pb.go @@ -21,11 +21,12 @@ package model import ( + reflect "reflect" + sync "sync" + _ "github.com/envoyproxy/protoc-gen-validate/validate" protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" - reflect "reflect" - sync "sync" ) const ( diff --git a/pkg/model/deployment_trace.pb.go b/pkg/model/deployment_trace.pb.go index ed159a140a..f4430c7267 100644 --- a/pkg/model/deployment_trace.pb.go +++ b/pkg/model/deployment_trace.pb.go @@ -21,11 +21,12 @@ package model import ( + reflect "reflect" + sync "sync" + _ "github.com/envoyproxy/protoc-gen-validate/validate" protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" - reflect "reflect" - sync "sync" ) const ( diff --git a/pkg/model/event.pb.go b/pkg/model/event.pb.go index 1c728f6009..0d4f40ea4d 100644 --- a/pkg/model/event.pb.go +++ b/pkg/model/event.pb.go @@ -21,11 +21,12 @@ package model import ( + reflect "reflect" + sync "sync" + _ "github.com/envoyproxy/protoc-gen-validate/validate" protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" - reflect "reflect" - sync "sync" ) const ( diff --git a/pkg/model/insight.pb.go b/pkg/model/insight.pb.go index d695aedcad..660986dc10 100644 --- a/pkg/model/insight.pb.go +++ b/pkg/model/insight.pb.go @@ -21,11 +21,12 @@ package model import ( + reflect "reflect" + sync "sync" + _ "github.com/envoyproxy/protoc-gen-validate/validate" protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" - reflect "reflect" - sync "sync" ) const ( diff --git a/pkg/model/logblock.pb.go b/pkg/model/logblock.pb.go index 0e9649867f..c86cecb901 100644 --- a/pkg/model/logblock.pb.go +++ b/pkg/model/logblock.pb.go @@ -21,11 +21,12 @@ package model import ( + reflect "reflect" + sync "sync" + _ "github.com/envoyproxy/protoc-gen-validate/validate" protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" - reflect "reflect" - sync "sync" ) const ( diff --git a/pkg/model/notificationevent.pb.go b/pkg/model/notificationevent.pb.go index 8b4bf96675..a75e875184 100644 --- a/pkg/model/notificationevent.pb.go +++ b/pkg/model/notificationevent.pb.go @@ -21,11 +21,12 @@ package model import ( + reflect "reflect" + sync "sync" + _ "github.com/envoyproxy/protoc-gen-validate/validate" protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" - reflect "reflect" - sync "sync" ) const ( diff --git a/pkg/model/piped.pb.go b/pkg/model/piped.pb.go index e1cc6bbf5f..bbf82f2e32 100644 --- a/pkg/model/piped.pb.go +++ b/pkg/model/piped.pb.go @@ -21,11 +21,12 @@ package model import ( + reflect "reflect" + sync "sync" + _ "github.com/envoyproxy/protoc-gen-validate/validate" protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" - reflect "reflect" - sync "sync" ) const ( diff --git a/pkg/model/piped_stat.pb.go b/pkg/model/piped_stat.pb.go index f80a449ff7..9e5faddda4 100644 --- a/pkg/model/piped_stat.pb.go +++ b/pkg/model/piped_stat.pb.go @@ -21,11 +21,12 @@ package model import ( + reflect "reflect" + sync "sync" + _ "github.com/envoyproxy/protoc-gen-validate/validate" protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" - reflect "reflect" - sync "sync" ) const ( diff --git a/pkg/model/planpreview.pb.go b/pkg/model/planpreview.pb.go index f0c49c1548..658f041772 100644 --- a/pkg/model/planpreview.pb.go +++ b/pkg/model/planpreview.pb.go @@ -21,11 +21,12 @@ package model import ( + reflect "reflect" + sync "sync" + _ "github.com/envoyproxy/protoc-gen-validate/validate" protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" - reflect "reflect" - sync "sync" ) const ( diff --git a/pkg/model/project.pb.go b/pkg/model/project.pb.go index ca46026a92..7e91fff8da 100644 --- a/pkg/model/project.pb.go +++ b/pkg/model/project.pb.go @@ -21,12 +21,13 @@ package model import ( + reflect "reflect" + sync "sync" + _ "github.com/envoyproxy/protoc-gen-validate/validate" protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" _ "google.golang.org/protobuf/types/descriptorpb" - reflect "reflect" - sync "sync" ) const ( diff --git a/pkg/model/rbac.pb.go b/pkg/model/rbac.pb.go index 049708fc04..02513aad79 100644 --- a/pkg/model/rbac.pb.go +++ b/pkg/model/rbac.pb.go @@ -21,11 +21,12 @@ package model import ( + reflect "reflect" + sync "sync" + protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" descriptorpb "google.golang.org/protobuf/types/descriptorpb" - reflect "reflect" - sync "sync" ) const ( diff --git a/pkg/model/role.pb.go b/pkg/model/role.pb.go index d8528d2e16..8d892f0020 100644 --- a/pkg/model/role.pb.go +++ b/pkg/model/role.pb.go @@ -21,11 +21,12 @@ package model import ( + reflect "reflect" + sync "sync" + protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" _ "google.golang.org/protobuf/types/descriptorpb" - reflect "reflect" - sync "sync" ) const ( diff --git a/pkg/model/user.pb.go b/pkg/model/user.pb.go index 4229732fe7..2b007c4bd2 100644 --- a/pkg/model/user.pb.go +++ b/pkg/model/user.pb.go @@ -21,11 +21,12 @@ package model import ( + reflect "reflect" + sync "sync" + _ "github.com/envoyproxy/protoc-gen-validate/validate" protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" - reflect "reflect" - sync "sync" ) const ( diff --git a/pkg/plugin/api/v1alpha1/common/common.pb.go b/pkg/plugin/api/v1alpha1/common/common.pb.go index 9f688acf8c..6fc88e64c6 100644 --- a/pkg/plugin/api/v1alpha1/common/common.pb.go +++ b/pkg/plugin/api/v1alpha1/common/common.pb.go @@ -23,10 +23,11 @@ package common import ( - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" reflect "reflect" sync "sync" + + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" ) const ( diff --git a/pkg/plugin/api/v1alpha1/deployment/api.pb.go b/pkg/plugin/api/v1alpha1/deployment/api.pb.go index ef11842b44..0daec9931e 100644 --- a/pkg/plugin/api/v1alpha1/deployment/api.pb.go +++ b/pkg/plugin/api/v1alpha1/deployment/api.pb.go @@ -21,13 +21,14 @@ package deployment import ( + reflect "reflect" + sync "sync" + _ "github.com/envoyproxy/protoc-gen-validate/validate" model "github.com/pipe-cd/pipecd/pkg/model" common "github.com/pipe-cd/pipecd/pkg/plugin/api/v1alpha1/common" protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" - reflect "reflect" - sync "sync" ) const ( diff --git a/pkg/plugin/api/v1alpha1/deployment/api_grpc.pb.go b/pkg/plugin/api/v1alpha1/deployment/api_grpc.pb.go index 8db550748e..e167ca3b3b 100644 --- a/pkg/plugin/api/v1alpha1/deployment/api_grpc.pb.go +++ b/pkg/plugin/api/v1alpha1/deployment/api_grpc.pb.go @@ -8,6 +8,7 @@ package deployment import ( context "context" + grpc "google.golang.org/grpc" codes "google.golang.org/grpc/codes" status "google.golang.org/grpc/status" diff --git a/pkg/plugin/api/v1alpha1/livestate/api.pb.go b/pkg/plugin/api/v1alpha1/livestate/api.pb.go index 967a70471b..c962fa9f1d 100644 --- a/pkg/plugin/api/v1alpha1/livestate/api.pb.go +++ b/pkg/plugin/api/v1alpha1/livestate/api.pb.go @@ -21,12 +21,13 @@ package livestate import ( + reflect "reflect" + sync "sync" + model "github.com/pipe-cd/pipecd/pkg/model" common "github.com/pipe-cd/pipecd/pkg/plugin/api/v1alpha1/common" protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" - reflect "reflect" - sync "sync" ) const ( diff --git a/pkg/plugin/api/v1alpha1/livestate/api_grpc.pb.go b/pkg/plugin/api/v1alpha1/livestate/api_grpc.pb.go index b724df262e..48e27d50bb 100644 --- a/pkg/plugin/api/v1alpha1/livestate/api_grpc.pb.go +++ b/pkg/plugin/api/v1alpha1/livestate/api_grpc.pb.go @@ -8,6 +8,7 @@ package livestate import ( context "context" + grpc "google.golang.org/grpc" codes "google.golang.org/grpc/codes" status "google.golang.org/grpc/status" diff --git a/pkg/plugin/api/v1alpha1/planpreview/api.pb.go b/pkg/plugin/api/v1alpha1/planpreview/api.pb.go index 5269379cac..25474819f7 100644 --- a/pkg/plugin/api/v1alpha1/planpreview/api.pb.go +++ b/pkg/plugin/api/v1alpha1/planpreview/api.pb.go @@ -21,11 +21,12 @@ package planpreview import ( + reflect "reflect" + sync "sync" + common "github.com/pipe-cd/pipecd/pkg/plugin/api/v1alpha1/common" protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" - reflect "reflect" - sync "sync" ) const ( diff --git a/pkg/plugin/api/v1alpha1/planpreview/api_grpc.pb.go b/pkg/plugin/api/v1alpha1/planpreview/api_grpc.pb.go index 73a044a059..8993d52c9c 100644 --- a/pkg/plugin/api/v1alpha1/planpreview/api_grpc.pb.go +++ b/pkg/plugin/api/v1alpha1/planpreview/api_grpc.pb.go @@ -8,6 +8,7 @@ package planpreview import ( context "context" + grpc "google.golang.org/grpc" codes "google.golang.org/grpc/codes" status "google.golang.org/grpc/status" diff --git a/pkg/plugin/pipedservice/service.pb.go b/pkg/plugin/pipedservice/service.pb.go index de61118540..9972500628 100644 --- a/pkg/plugin/pipedservice/service.pb.go +++ b/pkg/plugin/pipedservice/service.pb.go @@ -21,12 +21,13 @@ package pipedservice import ( + reflect "reflect" + sync "sync" + _ "github.com/envoyproxy/protoc-gen-validate/validate" model "github.com/pipe-cd/pipecd/pkg/model" protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" - reflect "reflect" - sync "sync" ) const ( diff --git a/pkg/plugin/pipedservice/service_grpc.pb.go b/pkg/plugin/pipedservice/service_grpc.pb.go index d3d61fbbff..ae9c435a2b 100644 --- a/pkg/plugin/pipedservice/service_grpc.pb.go +++ b/pkg/plugin/pipedservice/service_grpc.pb.go @@ -8,6 +8,7 @@ package pipedservice import ( context "context" + grpc "google.golang.org/grpc" codes "google.golang.org/grpc/codes" status "google.golang.org/grpc/status" diff --git a/web/src/__fixtures__/dummy-project.ts b/web/src/__fixtures__/dummy-project.ts index 6b34d70ba2..e0080545e0 100644 --- a/web/src/__fixtures__/dummy-project.ts +++ b/web/src/__fixtures__/dummy-project.ts @@ -50,6 +50,7 @@ export const dummyProject: Project.AsObject = { username: "static-admin-user", passwordHash: randomKeyHash(), }, + disabled: false, }; export function createProjectFromObject(o: Project.AsObject): Project { @@ -61,6 +62,7 @@ export function createProjectFromObject(o: Project.AsObject): Project { project.setUpdatedAt(o.updatedAt); project.setStaticAdminDisabled(o.staticAdminDisabled); project.setAllowStrayAsViewer(o.allowStrayAsViewer); + project.setDisabled(o.disabled); if (o.rbac) { const rbac = new ProjectRBACConfig(); rbac.setAdmin(o.rbac.admin); diff --git a/web/src/components/settings-page/project/components/project-status-form/index.tsx b/web/src/components/settings-page/project/components/project-status-form/index.tsx index 656069a9ac..517d471022 100644 --- a/web/src/components/settings-page/project/components/project-status-form/index.tsx +++ b/web/src/components/settings-page/project/components/project-status-form/index.tsx @@ -24,8 +24,10 @@ export const ProjectStatusForm: FC = memo(function ProjectStatusForm() { const isProjectDisabled = projectDetail?.disabled ?? false; const hasProjectId = Boolean(projectDetail?.id); - const { mutateAsync: toggleAvailability, isLoading } = - useToggleProjectAvailability(); + const { + mutateAsync: toggleAvailability, + isLoading, + } = useToggleProjectAvailability(); const { addToast } = useToast(); const handleToggle = useCallback(() => { @@ -40,7 +42,13 @@ export const ProjectStatusForm: FC = memo(function ProjectStatusForm() { severity: "success", }); }); - }, [addToast, hasProjectId, isLoading, isProjectDisabled, toggleAvailability]); + }, [ + addToast, + hasProjectId, + isLoading, + isProjectDisabled, + toggleAvailability, + ]); return ( <> diff --git a/web/src/components/settings-page/project/components/rbac-form/components/user-group/index.tsx b/web/src/components/settings-page/project/components/rbac-form/components/user-group/index.tsx index da05941933..138c783cf1 100644 --- a/web/src/components/settings-page/project/components/rbac-form/components/user-group/index.tsx +++ b/web/src/components/settings-page/project/components/rbac-form/components/user-group/index.tsx @@ -34,154 +34,154 @@ interface UserGroupTableProps { const SUB_SECTION_TITLE = "User Group"; -export const UserGroupTable: FC = memo(function UserGroupTable({ - isProjectDisabled, -}) { - const [isOpenAddForm, setIsOpenAddForm] = useState(false); - const [deleteSSOGroup, setDeleteSSOGroup] = useState(null); - const [anchorEl, setAnchorEl] = React.useState( - null - ); - const { addToast } = useToast(); - const { data: projectDetail } = useGetProject(); - const { mutateAsync: addUserGroup } = useAddUserGroup(); - const { mutateAsync: deleteUserGroup } = useDeleteUserGroup(); - const userGroups = projectDetail?.userGroups || []; +export const UserGroupTable: FC = memo( + function UserGroupTable({ isProjectDisabled }) { + const [isOpenAddForm, setIsOpenAddForm] = useState(false); + const [deleteSSOGroup, setDeleteSSOGroup] = useState(null); + const [anchorEl, setAnchorEl] = React.useState( + null + ); + const { addToast } = useToast(); + const { data: projectDetail } = useGetProject(); + const { mutateAsync: addUserGroup } = useAddUserGroup(); + const { mutateAsync: deleteUserGroup } = useDeleteUserGroup(); + const userGroups = projectDetail?.userGroups || []; - useEffect(() => { - if (isProjectDisabled) { - setIsOpenAddForm(false); - setAnchorEl(null); - setDeleteSSOGroup(null); - } - }, [isProjectDisabled]); + useEffect(() => { + if (isProjectDisabled) { + setIsOpenAddForm(false); + setAnchorEl(null); + setDeleteSSOGroup(null); + } + }, [isProjectDisabled]); - const handleSubmit = useCallback( - (values: { ssoGroup: string; role: string }) => { - addUserGroup(values).then(() => { - addToast({ - message: ADD_USER_GROUP_SUCCESS, - severity: "success", + const handleSubmit = useCallback( + (values: { ssoGroup: string; role: string }) => { + addUserGroup(values).then(() => { + addToast({ + message: ADD_USER_GROUP_SUCCESS, + severity: "success", + }); }); - }); - }, - [addToast, addUserGroup] - ); + }, + [addToast, addUserGroup] + ); - const handleOpenMenu = useCallback( - (e: React.MouseEvent) => { - setAnchorEl(e.currentTarget); - }, - [setAnchorEl] - ); + const handleOpenMenu = useCallback( + (e: React.MouseEvent) => { + setAnchorEl(e.currentTarget); + }, + [setAnchorEl] + ); - const handleCloseMenu = useCallback(() => { - setAnchorEl(null); - }, [setAnchorEl]); + const handleCloseMenu = useCallback(() => { + setAnchorEl(null); + }, [setAnchorEl]); - const handleCancelDeleting = useCallback(() => { - setDeleteSSOGroup(null); - }, [setDeleteSSOGroup]); + const handleCancelDeleting = useCallback(() => { + setDeleteSSOGroup(null); + }, [setDeleteSSOGroup]); - const handleDelete = useCallback( - (ssoGroup: string) => { - deleteUserGroup({ ssoGroup: ssoGroup }).then(() => { - addToast({ - message: DELETE_USER_GROUP_SUCCESS, - severity: "success", + const handleDelete = useCallback( + (ssoGroup: string) => { + deleteUserGroup({ ssoGroup: ssoGroup }).then(() => { + addToast({ + message: DELETE_USER_GROUP_SUCCESS, + severity: "success", + }); }); - }); - setDeleteSSOGroup(null); - }, - [addToast, deleteUserGroup] - ); + setDeleteSSOGroup(null); + }, + [addToast, deleteUserGroup] + ); - return ( - <> - - {SUB_SECTION_TITLE} + return ( + <> + + {SUB_SECTION_TITLE} - + + - {UI_TEXT_ADD} - - - -
- - - Team/Group - Role - - - - - {userGroups.map((group) => ( - - {group.ssoGroup} - {group.role} - - - - - +
+ + + Team/Group + Role + - ))} - -
-
- - { - if (anchorEl && anchorEl.dataset.id) { - setDeleteSSOGroup(anchorEl.dataset.id); - } - setAnchorEl(null); + + + {userGroups.map((group) => ( + + {group.ssoGroup} + {group.role} + + + + + + + ))} + + + + - Delete - - - setIsOpenAddForm(false)} - onSubmit={handleSubmit} - /> - - - ); -}); + { + if (anchorEl && anchorEl.dataset.id) { + setDeleteSSOGroup(anchorEl.dataset.id); + } + setAnchorEl(null); + }} + > + Delete + + + setIsOpenAddForm(false)} + onSubmit={handleSubmit} + /> + + + ); + } +); From 48c7ebce87561877a18f4f7496f7b8db9c0f9822 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9Cniladrix719=E2=80=9D?= Date: Thu, 27 Nov 2025 03:25:42 +0530 Subject: [PATCH 3/9] fix: lint and refactor MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: “niladrix719” --- .../grpcapi/api_disabled_project_test.go | 63 --- pkg/app/server/grpcapi/api_test.go | 51 +++ .../piped_api_disabled_project_test.go | 152 ------- pkg/app/server/grpcapi/piped_api_test.go | 140 +++++++ .../grpcapi/web_api_disabled_project_test.go | 374 ------------------ pkg/app/server/grpcapi/web_api_test.go | 362 +++++++++++++++++ .../service/webservice/service.pb.auth.go | 2 +- pkg/rpc/rpcauth/interceptor.go | 4 +- 8 files changed, 556 insertions(+), 592 deletions(-) delete mode 100644 pkg/app/server/grpcapi/api_disabled_project_test.go delete mode 100644 pkg/app/server/grpcapi/piped_api_disabled_project_test.go delete mode 100644 pkg/app/server/grpcapi/web_api_disabled_project_test.go diff --git a/pkg/app/server/grpcapi/api_disabled_project_test.go b/pkg/app/server/grpcapi/api_disabled_project_test.go deleted file mode 100644 index 361a6624cc..0000000000 --- a/pkg/app/server/grpcapi/api_disabled_project_test.go +++ /dev/null @@ -1,63 +0,0 @@ -package grpcapi - -import ( - "context" - "testing" - - "github.com/stretchr/testify/assert" - "go.uber.org/mock/gomock" - "go.uber.org/zap" - "google.golang.org/grpc/codes" - "google.golang.org/grpc/status" - - "github.com/pipe-cd/pipecd/pkg/app/server/service/apiservice" - "github.com/pipe-cd/pipecd/pkg/datastore/datastoretest" - "github.com/pipe-cd/pipecd/pkg/model" - "github.com/pipe-cd/pipecd/pkg/rpc/rpcauth" -) - -func TestAPISyncApplication_DisabledProject(t *testing.T) { - ctrl := gomock.NewController(t) - defer ctrl.Finish() - - projectID := "project-id" - appID := "app-id" - apiKeyID := "apikey-id" - - ctx := context.Background() - // Mock API key authentication - ctx = rpcauth.ContextWithAPIKey(ctx, &model.APIKey{ - Id: apiKeyID, - ProjectId: projectID, - Role: model.APIKey_READ_WRITE, - }) - - ps := datastoretest.NewMockProjectStore(ctrl) - ps.EXPECT().Get(gomock.Any(), projectID).Return(&model.Project{ - Id: projectID, - Disabled: true, - }, nil) - - as := datastoretest.NewMockApplicationStore(ctrl) - as.EXPECT().Get(gomock.Any(), appID).Return(&model.Application{ - Id: appID, - ProjectId: projectID, - }, nil) - - api := &API{ - projectStore: &mockProjectStore{MockProjectStore: ps}, - applicationStore: as, - logger: zap.NewNop(), - } - - resp, err := api.SyncApplication(ctx, &apiservice.SyncApplicationRequest{ - ApplicationId: appID, - }) - - assert.Error(t, err) - assert.Nil(t, resp) - st, ok := status.FromError(err) - assert.True(t, ok) - assert.Equal(t, codes.FailedPrecondition, st.Code()) - assert.Contains(t, st.Message(), "project is currently disabled") -} diff --git a/pkg/app/server/grpcapi/api_test.go b/pkg/app/server/grpcapi/api_test.go index 6443b331b4..03a95abfcc 100644 --- a/pkg/app/server/grpcapi/api_test.go +++ b/pkg/app/server/grpcapi/api_test.go @@ -19,8 +19,13 @@ import ( "testing" "github.com/stretchr/testify/assert" + "go.uber.org/mock/gomock" "go.uber.org/zap" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" + "github.com/pipe-cd/pipecd/pkg/app/server/service/apiservice" + "github.com/pipe-cd/pipecd/pkg/datastore/datastoretest" "github.com/pipe-cd/pipecd/pkg/model" "github.com/pipe-cd/pipecd/pkg/rpc/rpcauth" ) @@ -102,3 +107,49 @@ func TestRequireAPIKey(t *testing.T) { }) } } + +func TestAPISyncApplication_DisabledProject(t *testing.T) { + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + projectID := "project-id" + appID := "app-id" + apiKeyID := "apikey-id" + + ctx := context.Background() + // Mock API key authentication + ctx = rpcauth.ContextWithAPIKey(ctx, &model.APIKey{ + Id: apiKeyID, + ProjectId: projectID, + Role: model.APIKey_READ_WRITE, + }) + + ps := datastoretest.NewMockProjectStore(ctrl) + ps.EXPECT().Get(gomock.Any(), projectID).Return(&model.Project{ + Id: projectID, + Disabled: true, + }, nil) + + as := datastoretest.NewMockApplicationStore(ctrl) + as.EXPECT().Get(gomock.Any(), appID).Return(&model.Application{ + Id: appID, + ProjectId: projectID, + }, nil) + + api := &API{ + projectStore: &mockProjectStore{MockProjectStore: ps}, + applicationStore: as, + logger: zap.NewNop(), + } + + resp, err := api.SyncApplication(ctx, &apiservice.SyncApplicationRequest{ + ApplicationId: appID, + }) + + assert.Error(t, err) + assert.Nil(t, resp) + st, ok := status.FromError(err) + assert.True(t, ok) + assert.Equal(t, codes.FailedPrecondition, st.Code()) + assert.Contains(t, st.Message(), "project is currently disabled") +} diff --git a/pkg/app/server/grpcapi/piped_api_disabled_project_test.go b/pkg/app/server/grpcapi/piped_api_disabled_project_test.go deleted file mode 100644 index 8a78f24360..0000000000 --- a/pkg/app/server/grpcapi/piped_api_disabled_project_test.go +++ /dev/null @@ -1,152 +0,0 @@ -package grpcapi - -import ( - "context" - "testing" - - "github.com/stretchr/testify/assert" - "go.uber.org/mock/gomock" - "go.uber.org/zap" - "google.golang.org/grpc" - "google.golang.org/grpc/metadata" - - "github.com/pipe-cd/pipecd/pkg/app/server/service/pipedservice" - "github.com/pipe-cd/pipecd/pkg/datastore/datastoretest" - "github.com/pipe-cd/pipecd/pkg/model" - "github.com/pipe-cd/pipecd/pkg/rpc/rpcauth" -) - -type mockProjectStore struct { - *datastoretest.MockProjectStore -} - -func (m *mockProjectStore) DisableProject(ctx context.Context, id string) error { - return nil -} - -func (m *mockProjectStore) EnableProject(ctx context.Context, id string) error { - return nil -} - -type mockVerifier struct{} - -func (m *mockVerifier) Verify(ctx context.Context, projectID, pipedID, pipedKey string) error { - return nil -} - -func TestListApplications_DisabledProject(t *testing.T) { - ctrl := gomock.NewController(t) - defer ctrl.Finish() - - projectID := "project-id" - pipedID := "piped-id" - pipedKey := "piped-key" - - ctx := context.Background() - token := rpcauth.MakePipedToken(projectID, pipedID, pipedKey) - ctx = metadata.NewIncomingContext(ctx, metadata.MD{ - "authorization": []string{"PIPED-TOKEN " + token}, - }) - - ps := datastoretest.NewMockProjectStore(ctrl) - ps.EXPECT().Get(gomock.Any(), projectID).Return(&model.Project{ - Id: projectID, - Disabled: true, - }, nil) - - api := &PipedAPI{ - projectStore: &mockProjectStore{MockProjectStore: ps}, - logger: zap.NewNop(), - } - - verifier := &mockVerifier{} - interceptor := rpcauth.PipedTokenUnaryServerInterceptor(verifier, zap.NewNop()) - - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return api.ListApplications(ctx, req.(*pipedservice.ListApplicationsRequest)) - } - - resp, err := interceptor(ctx, &pipedservice.ListApplicationsRequest{}, &grpc.UnaryServerInfo{}, handler) - assert.NoError(t, err) - assert.Empty(t, resp.(*pipedservice.ListApplicationsResponse).Applications) -} - -func TestCreateDeployment_DisabledProject(t *testing.T) { - ctrl := gomock.NewController(t) - defer ctrl.Finish() - - projectID := "project-id" - pipedID := "piped-id" - pipedKey := "piped-key" - - ctx := context.Background() - token := rpcauth.MakePipedToken(projectID, pipedID, pipedKey) - ctx = metadata.NewIncomingContext(ctx, metadata.MD{ - "authorization": []string{"PIPED-TOKEN " + token}, - }) - - ps := datastoretest.NewMockProjectStore(ctrl) - ps.EXPECT().Get(gomock.Any(), projectID).Return(&model.Project{ - Id: projectID, - Disabled: true, - }, nil) - - api := &PipedAPI{ - projectStore: &mockProjectStore{MockProjectStore: ps}, - logger: zap.NewNop(), - } - - verifier := &mockVerifier{} - interceptor := rpcauth.PipedTokenUnaryServerInterceptor(verifier, zap.NewNop()) - - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return api.CreateDeployment(ctx, req.(*pipedservice.CreateDeploymentRequest)) - } - - resp, err := interceptor(ctx, &pipedservice.CreateDeploymentRequest{ - Deployment: &model.Deployment{ - ApplicationId: "app-id", - }, - }, &grpc.UnaryServerInfo{}, handler) - - assert.Error(t, err) - assert.Nil(t, resp) -} - -func TestListUnhandledCommands_DisabledProject(t *testing.T) { - ctrl := gomock.NewController(t) - defer ctrl.Finish() - - projectID := "project-id" - pipedID := "piped-id" - pipedKey := "piped-key" - - ctx := context.Background() - token := rpcauth.MakePipedToken(projectID, pipedID, pipedKey) - ctx = metadata.NewIncomingContext(ctx, metadata.MD{ - "authorization": []string{"PIPED-TOKEN " + token}, - }) - - ps := datastoretest.NewMockProjectStore(ctrl) - ps.EXPECT().Get(gomock.Any(), projectID).Return(&model.Project{ - Id: projectID, - Disabled: true, - }, nil) - - api := &PipedAPI{ - projectStore: &mockProjectStore{MockProjectStore: ps}, - logger: zap.NewNop(), - } - - verifier := &mockVerifier{} - interceptor := rpcauth.PipedTokenUnaryServerInterceptor(verifier, zap.NewNop()) - - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return api.ListUnhandledCommands(ctx, req.(*pipedservice.ListUnhandledCommandsRequest)) - } - - resp, err := interceptor(ctx, &pipedservice.ListUnhandledCommandsRequest{}, &grpc.UnaryServerInfo{}, handler) - - assert.NoError(t, err) - assert.Empty(t, resp.(*pipedservice.ListUnhandledCommandsResponse).Commands) -} diff --git a/pkg/app/server/grpcapi/piped_api_test.go b/pkg/app/server/grpcapi/piped_api_test.go index 0396468829..85fbca4091 100644 --- a/pkg/app/server/grpcapi/piped_api_test.go +++ b/pkg/app/server/grpcapi/piped_api_test.go @@ -21,12 +21,17 @@ import ( "github.com/stretchr/testify/assert" "go.uber.org/mock/gomock" + "go.uber.org/zap" + "google.golang.org/grpc" + "google.golang.org/grpc/metadata" + "github.com/pipe-cd/pipecd/pkg/app/server/service/pipedservice" "github.com/pipe-cd/pipecd/pkg/cache" "github.com/pipe-cd/pipecd/pkg/cache/cachetest" "github.com/pipe-cd/pipecd/pkg/datastore" "github.com/pipe-cd/pipecd/pkg/datastore/datastoretest" "github.com/pipe-cd/pipecd/pkg/model" + "github.com/pipe-cd/pipecd/pkg/rpc/rpcauth" ) func TestValidateAppBelongsToPiped(t *testing.T) { @@ -212,3 +217,138 @@ func TestValidateDeploymentBelongsToPiped(t *testing.T) { }) } } + +type mockProjectStore struct { + *datastoretest.MockProjectStore +} + +func (m *mockProjectStore) DisableProject(ctx context.Context, id string) error { + return nil +} + +func (m *mockProjectStore) EnableProject(ctx context.Context, id string) error { + return nil +} + +type mockVerifier struct{} + +func (m *mockVerifier) Verify(ctx context.Context, projectID, pipedID, pipedKey string) error { + return nil +} + +func TestListApplications_DisabledProject(t *testing.T) { + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + projectID := "project-id" + pipedID := "piped-id" + pipedKey := "piped-key" + + ctx := context.Background() + token := rpcauth.MakePipedToken(projectID, pipedID, pipedKey) + ctx = metadata.NewIncomingContext(ctx, metadata.MD{ + "authorization": []string{"PIPED-TOKEN " + token}, + }) + + ps := datastoretest.NewMockProjectStore(ctrl) + ps.EXPECT().Get(gomock.Any(), projectID).Return(&model.Project{ + Id: projectID, + Disabled: true, + }, nil) + + api := &PipedAPI{ + projectStore: &mockProjectStore{MockProjectStore: ps}, + logger: zap.NewNop(), + } + + verifier := &mockVerifier{} + interceptor := rpcauth.PipedTokenUnaryServerInterceptor(verifier, zap.NewNop()) + + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return api.ListApplications(ctx, req.(*pipedservice.ListApplicationsRequest)) + } + + resp, err := interceptor(ctx, &pipedservice.ListApplicationsRequest{}, &grpc.UnaryServerInfo{}, handler) + assert.NoError(t, err) + assert.Empty(t, resp.(*pipedservice.ListApplicationsResponse).Applications) +} + +func TestCreateDeployment_DisabledProject(t *testing.T) { + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + projectID := "project-id" + pipedID := "piped-id" + pipedKey := "piped-key" + + ctx := context.Background() + token := rpcauth.MakePipedToken(projectID, pipedID, pipedKey) + ctx = metadata.NewIncomingContext(ctx, metadata.MD{ + "authorization": []string{"PIPED-TOKEN " + token}, + }) + + ps := datastoretest.NewMockProjectStore(ctrl) + ps.EXPECT().Get(gomock.Any(), projectID).Return(&model.Project{ + Id: projectID, + Disabled: true, + }, nil) + + api := &PipedAPI{ + projectStore: &mockProjectStore{MockProjectStore: ps}, + logger: zap.NewNop(), + } + + verifier := &mockVerifier{} + interceptor := rpcauth.PipedTokenUnaryServerInterceptor(verifier, zap.NewNop()) + + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return api.CreateDeployment(ctx, req.(*pipedservice.CreateDeploymentRequest)) + } + + resp, err := interceptor(ctx, &pipedservice.CreateDeploymentRequest{ + Deployment: &model.Deployment{ + ApplicationId: "app-id", + }, + }, &grpc.UnaryServerInfo{}, handler) + + assert.Error(t, err) + assert.Nil(t, resp) +} + +func TestListUnhandledCommands_DisabledProject(t *testing.T) { + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + projectID := "project-id" + pipedID := "piped-id" + pipedKey := "piped-key" + + ctx := context.Background() + token := rpcauth.MakePipedToken(projectID, pipedID, pipedKey) + ctx = metadata.NewIncomingContext(ctx, metadata.MD{ + "authorization": []string{"PIPED-TOKEN " + token}, + }) + + ps := datastoretest.NewMockProjectStore(ctrl) + ps.EXPECT().Get(gomock.Any(), projectID).Return(&model.Project{ + Id: projectID, + Disabled: true, + }, nil) + + api := &PipedAPI{ + projectStore: &mockProjectStore{MockProjectStore: ps}, + logger: zap.NewNop(), + } + + verifier := &mockVerifier{} + interceptor := rpcauth.PipedTokenUnaryServerInterceptor(verifier, zap.NewNop()) + + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return api.ListUnhandledCommands(ctx, req.(*pipedservice.ListUnhandledCommandsRequest)) + } + + resp, err := interceptor(ctx, &pipedservice.ListUnhandledCommandsRequest{}, &grpc.UnaryServerInfo{}, handler) + + assert.NoError(t, err) + assert.Empty(t, resp.(*pipedservice.ListUnhandledCommandsResponse).Commands) +} diff --git a/pkg/app/server/grpcapi/web_api_disabled_project_test.go b/pkg/app/server/grpcapi/web_api_disabled_project_test.go deleted file mode 100644 index 2a86a0a8cd..0000000000 --- a/pkg/app/server/grpcapi/web_api_disabled_project_test.go +++ /dev/null @@ -1,374 +0,0 @@ -package grpcapi - -import ( - "context" - "testing" - "time" - - "github.com/stretchr/testify/assert" - "go.uber.org/mock/gomock" - "go.uber.org/zap" - "google.golang.org/grpc" - "google.golang.org/grpc/codes" - "google.golang.org/grpc/metadata" - "google.golang.org/grpc/status" - - "github.com/pipe-cd/pipecd/pkg/app/server/service/webservice" - "github.com/pipe-cd/pipecd/pkg/datastore/datastoretest" - "github.com/pipe-cd/pipecd/pkg/jwt" - "github.com/pipe-cd/pipecd/pkg/model" - "github.com/pipe-cd/pipecd/pkg/rpc/rpcauth" -) - -type mockJWTVerifier struct { - claims *jwt.Claims -} - -func (m *mockJWTVerifier) Verify(token string) (*jwt.Claims, error) { - return m.claims, nil -} - -type mockAuthorizer struct{} - -func (m *mockAuthorizer) Authorize(ctx context.Context, method string, role model.Role) bool { - return true -} - -func TestSyncApplication_DisabledProject(t *testing.T) { - ctrl := gomock.NewController(t) - defer ctrl.Finish() - - projectID := "project-id" - appID := "app-id" - - ctx := context.Background() - // Mock JWT token in cookie - ctx = metadata.NewIncomingContext(ctx, metadata.MD{ - "cookie": []string{"token=dummy-token"}, - }) - - ps := datastoretest.NewMockProjectStore(ctrl) - ps.EXPECT().Get(gomock.Any(), projectID).Return(&model.Project{ - Id: projectID, - Disabled: true, - }, nil) - - as := datastoretest.NewMockApplicationStore(ctrl) - as.EXPECT().Get(gomock.Any(), appID).Return(&model.Application{ - Id: appID, - ProjectId: projectID, - }, nil) - - api := &WebAPI{ - projectStore: &mockProjectStore{MockProjectStore: ps}, - applicationStore: as, - logger: zap.NewNop(), - } - - claims := jwt.NewClaims( - "sub", - "avatar-url", - 10*time.Minute, - &model.Role{ - ProjectId: projectID, - ProjectRbacRoles: []string{"ADMIN"}, - }, - ) - verifier := &mockJWTVerifier{claims: claims} - authorizer := &mockAuthorizer{} - interceptor := rpcauth.JWTUnaryServerInterceptor(verifier, authorizer, zap.NewNop()) - - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return api.SyncApplication(ctx, req.(*webservice.SyncApplicationRequest)) - } - - resp, err := interceptor(ctx, &webservice.SyncApplicationRequest{ - ApplicationId: appID, - }, &grpc.UnaryServerInfo{FullMethod: "/webservice.WebService/SyncApplication"}, handler) - - assert.Error(t, err) - assert.Nil(t, resp) - st, ok := status.FromError(err) - assert.True(t, ok) - assert.Equal(t, codes.FailedPrecondition, st.Code()) - assert.Contains(t, st.Message(), "project is currently disabled") -} - -func TestCancelDeployment_DisabledProject(t *testing.T) { - ctrl := gomock.NewController(t) - defer ctrl.Finish() - - projectID := "project-id" - deploymentID := "deployment-id" - - ctx := context.Background() - ctx = metadata.NewIncomingContext(ctx, metadata.MD{ - "cookie": []string{"token=dummy-token"}, - }) - - ps := datastoretest.NewMockProjectStore(ctrl) - ps.EXPECT().Get(gomock.Any(), projectID).Return(&model.Project{ - Id: projectID, - Disabled: true, - }, nil) - - ds := datastoretest.NewMockDeploymentStore(ctrl) - ds.EXPECT().Get(gomock.Any(), deploymentID).Return(&model.Deployment{ - Id: deploymentID, - ProjectId: projectID, - Status: model.DeploymentStatus_DEPLOYMENT_RUNNING, - }, nil) - - api := &WebAPI{ - projectStore: &mockProjectStore{MockProjectStore: ps}, - deploymentStore: ds, - logger: zap.NewNop(), - } - - claims := jwt.NewClaims( - "sub", - "avatar-url", - 10*time.Minute, - &model.Role{ - ProjectId: projectID, - ProjectRbacRoles: []string{"ADMIN"}, - }, - ) - verifier := &mockJWTVerifier{claims: claims} - authorizer := &mockAuthorizer{} - interceptor := rpcauth.JWTUnaryServerInterceptor(verifier, authorizer, zap.NewNop()) - - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return api.CancelDeployment(ctx, req.(*webservice.CancelDeploymentRequest)) - } - - resp, err := interceptor(ctx, &webservice.CancelDeploymentRequest{ - DeploymentId: deploymentID, - }, &grpc.UnaryServerInfo{FullMethod: "/webservice.WebService/CancelDeployment"}, handler) - - assert.Error(t, err) - assert.Nil(t, resp) - st, ok := status.FromError(err) - assert.True(t, ok) - assert.Equal(t, codes.FailedPrecondition, st.Code()) - assert.Contains(t, st.Message(), "project is currently disabled") -} - -func TestSkipStage_DisabledProject(t *testing.T) { - ctrl := gomock.NewController(t) - defer ctrl.Finish() - - projectID := "project-id" - deploymentID := "deployment-id" - stageID := "stage-id" - - ctx := context.Background() - ctx = metadata.NewIncomingContext(ctx, metadata.MD{ - "cookie": []string{"token=dummy-token"}, - }) - - ps := datastoretest.NewMockProjectStore(ctrl) - ps.EXPECT().Get(gomock.Any(), projectID).Return(&model.Project{ - Id: projectID, - Disabled: true, - }, nil) - - ds := datastoretest.NewMockDeploymentStore(ctrl) - ds.EXPECT().Get(gomock.Any(), deploymentID).Return(&model.Deployment{ - Id: deploymentID, - ProjectId: projectID, - Stages: []*model.PipelineStage{{ - Id: stageID, - Name: "K8S_SYNC", - Status: model.StageStatus_STAGE_RUNNING, - }}, - }, nil) - - api := &WebAPI{ - projectStore: &mockProjectStore{MockProjectStore: ps}, - deploymentStore: ds, - logger: zap.NewNop(), - } - - claims := jwt.NewClaims( - "sub", - "avatar-url", - 10*time.Minute, - &model.Role{ - ProjectId: projectID, - ProjectRbacRoles: []string{"ADMIN"}, - }, - ) - verifier := &mockJWTVerifier{claims: claims} - authorizer := &mockAuthorizer{} - interceptor := rpcauth.JWTUnaryServerInterceptor(verifier, authorizer, zap.NewNop()) - - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return api.SkipStage(ctx, req.(*webservice.SkipStageRequest)) - } - - resp, err := interceptor(ctx, &webservice.SkipStageRequest{ - DeploymentId: deploymentID, - StageId: stageID, - }, &grpc.UnaryServerInfo{FullMethod: "/webservice.WebService/SkipStage"}, handler) - - assert.Error(t, err) - assert.Nil(t, resp) - st, ok := status.FromError(err) - assert.True(t, ok) - assert.Equal(t, codes.FailedPrecondition, st.Code()) - assert.Contains(t, st.Message(), "project is currently disabled") -} - -func TestApproveStage_DisabledProject(t *testing.T) { - ctrl := gomock.NewController(t) - defer ctrl.Finish() - - userID := "user-id" - projectID := "project-id" - deploymentID := "deployment-id" - stageID := "stage-id" - - ctx := context.Background() - ctx = metadata.NewIncomingContext(ctx, metadata.MD{ - "cookie": []string{"token=dummy-token"}, - }) - - ps := datastoretest.NewMockProjectStore(ctrl) - ps.EXPECT().Get(gomock.Any(), projectID).Return(&model.Project{ - Id: projectID, - Disabled: true, - }, nil) - - ds := datastoretest.NewMockDeploymentStore(ctrl) - ds.EXPECT().Get(gomock.Any(), deploymentID).Return(&model.Deployment{ - Id: deploymentID, - ProjectId: projectID, - Stages: []*model.PipelineStage{{ - Id: stageID, - Name: "WAIT_APPROVAL", - Status: model.StageStatus_STAGE_RUNNING, - Metadata: map[string]string{ - "Approvers": userID, - }, - }}, - }, nil).Times(2) - - api := &WebAPI{ - projectStore: &mockProjectStore{MockProjectStore: ps}, - deploymentStore: ds, - deploymentProjectCache: newMockCache(), - logger: zap.NewNop(), - } - - claims := jwt.NewClaims( - userID, - "avatar-url", - 10*time.Minute, - &model.Role{ - ProjectId: projectID, - ProjectRbacRoles: []string{"ADMIN"}, - }, - ) - verifier := &mockJWTVerifier{claims: claims} - authorizer := &mockAuthorizer{} - interceptor := rpcauth.JWTUnaryServerInterceptor(verifier, authorizer, zap.NewNop()) - - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return api.ApproveStage(ctx, req.(*webservice.ApproveStageRequest)) - } - - resp, err := interceptor(ctx, &webservice.ApproveStageRequest{ - DeploymentId: deploymentID, - StageId: stageID, - }, &grpc.UnaryServerInfo{FullMethod: "/webservice.WebService/ApproveStage"}, handler) - - assert.Error(t, err) - assert.Nil(t, resp) - st, ok := status.FromError(err) - assert.True(t, ok) - assert.Equal(t, codes.FailedPrecondition, st.Code()) - assert.Contains(t, st.Message(), "project is currently disabled") -} - -func TestRestartPiped_DisabledProject(t *testing.T) { - ctrl := gomock.NewController(t) - defer ctrl.Finish() - - projectID := "project-id" - pipedID := "piped-id" - - ctx := context.Background() - ctx = metadata.NewIncomingContext(ctx, metadata.MD{ - "cookie": []string{"token=dummy-token"}, - }) - - ps := datastoretest.NewMockProjectStore(ctrl) - ps.EXPECT().Get(gomock.Any(), projectID).Return(&model.Project{ - Id: projectID, - Disabled: true, - }, nil) - - pips := datastoretest.NewMockPipedStore(ctrl) - pips.EXPECT().Get(gomock.Any(), pipedID).Return(&model.Piped{ - Id: pipedID, - ProjectId: projectID, - }, nil) - - api := &WebAPI{ - projectStore: &mockProjectStore{MockProjectStore: ps}, - pipedStore: pips, - logger: zap.NewNop(), - } - - claims := jwt.NewClaims( - "sub", - "avatar-url", - 10*time.Minute, - &model.Role{ - ProjectId: projectID, - ProjectRbacRoles: []string{"ADMIN"}, - }, - ) - verifier := &mockJWTVerifier{claims: claims} - authorizer := &mockAuthorizer{} - interceptor := rpcauth.JWTUnaryServerInterceptor(verifier, authorizer, zap.NewNop()) - - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return api.RestartPiped(ctx, req.(*webservice.RestartPipedRequest)) - } - - resp, err := interceptor(ctx, &webservice.RestartPipedRequest{ - PipedId: pipedID, - }, &grpc.UnaryServerInfo{FullMethod: "/webservice.WebService/RestartPiped"}, handler) - - assert.Error(t, err) - assert.Nil(t, resp) - st, ok := status.FromError(err) - assert.True(t, ok) - assert.Equal(t, codes.FailedPrecondition, st.Code()) - assert.Contains(t, st.Message(), "project is currently disabled") -} - -// mockCache is a simple mock implementation of cache.Cache for testing -type mockCache struct{} - -func newMockCache() *mockCache { - return &mockCache{} -} - -func (c *mockCache) Get(key string) (interface{}, error) { - return nil, assert.AnError -} - -func (c *mockCache) Put(key string, value interface{}) error { - return nil -} - -func (c *mockCache) Delete(key string) error { - return nil -} - -func (c *mockCache) GetAll() (map[string]interface{}, error) { - return nil, nil -} diff --git a/pkg/app/server/grpcapi/web_api_test.go b/pkg/app/server/grpcapi/web_api_test.go index 8c5884de12..a73c86c488 100644 --- a/pkg/app/server/grpcapi/web_api_test.go +++ b/pkg/app/server/grpcapi/web_api_test.go @@ -18,15 +18,24 @@ import ( "context" "errors" "testing" + "time" "github.com/stretchr/testify/assert" "go.uber.org/mock/gomock" + "go.uber.org/zap" + "google.golang.org/grpc" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/metadata" + "google.golang.org/grpc/status" + "github.com/pipe-cd/pipecd/pkg/app/server/service/webservice" "github.com/pipe-cd/pipecd/pkg/cache" "github.com/pipe-cd/pipecd/pkg/cache/cachetest" "github.com/pipe-cd/pipecd/pkg/datastore" "github.com/pipe-cd/pipecd/pkg/datastore/datastoretest" + "github.com/pipe-cd/pipecd/pkg/jwt" "github.com/pipe-cd/pipecd/pkg/model" + "github.com/pipe-cd/pipecd/pkg/rpc/rpcauth" ) func TestValidateAppBelongsToProject(t *testing.T) { @@ -390,3 +399,356 @@ func TestValidateApprover(t *testing.T) { }) } } + +type mockJWTVerifier struct { + claims *jwt.Claims +} + +func (m *mockJWTVerifier) Verify(token string) (*jwt.Claims, error) { + return m.claims, nil +} + +type mockAuthorizer struct{} + +func (m *mockAuthorizer) Authorize(ctx context.Context, method string, role *model.Role) bool { + return true +} + +func TestSyncApplication_DisabledProject(t *testing.T) { + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + projectID := "project-id" + appID := "app-id" + + ctx := context.Background() + // Mock JWT token in cookie + ctx = metadata.NewIncomingContext(ctx, metadata.MD{ + "cookie": []string{"token=dummy-token"}, + }) + + ps := datastoretest.NewMockProjectStore(ctrl) + ps.EXPECT().Get(gomock.Any(), projectID).Return(&model.Project{ + Id: projectID, + Disabled: true, + }, nil) + + as := datastoretest.NewMockApplicationStore(ctrl) + as.EXPECT().Get(gomock.Any(), appID).Return(&model.Application{ + Id: appID, + ProjectId: projectID, + }, nil) + + api := &WebAPI{ + projectStore: &mockProjectStore{MockProjectStore: ps}, + applicationStore: as, + logger: zap.NewNop(), + } + + claims := jwt.NewClaims( + "sub", + "avatar-url", + 10*time.Minute, + &model.Role{ + ProjectId: projectID, + ProjectRbacRoles: []string{"ADMIN"}, + }, + ) + verifier := &mockJWTVerifier{claims: claims} + authorizer := &mockAuthorizer{} + interceptor := rpcauth.JWTUnaryServerInterceptor(verifier, authorizer, zap.NewNop()) + + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return api.SyncApplication(ctx, req.(*webservice.SyncApplicationRequest)) + } + + resp, err := interceptor(ctx, &webservice.SyncApplicationRequest{ + ApplicationId: appID, + }, &grpc.UnaryServerInfo{FullMethod: "/webservice.WebService/SyncApplication"}, handler) + + assert.Error(t, err) + assert.Nil(t, resp) + st, ok := status.FromError(err) + assert.True(t, ok) + assert.Equal(t, codes.FailedPrecondition, st.Code()) + assert.Contains(t, st.Message(), "project is currently disabled") +} + +func TestCancelDeployment_DisabledProject(t *testing.T) { + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + projectID := "project-id" + deploymentID := "deployment-id" + + ctx := context.Background() + ctx = metadata.NewIncomingContext(ctx, metadata.MD{ + "cookie": []string{"token=dummy-token"}, + }) + + ps := datastoretest.NewMockProjectStore(ctrl) + ps.EXPECT().Get(gomock.Any(), projectID).Return(&model.Project{ + Id: projectID, + Disabled: true, + }, nil) + + ds := datastoretest.NewMockDeploymentStore(ctrl) + ds.EXPECT().Get(gomock.Any(), deploymentID).Return(&model.Deployment{ + Id: deploymentID, + ProjectId: projectID, + Status: model.DeploymentStatus_DEPLOYMENT_RUNNING, + }, nil) + + api := &WebAPI{ + projectStore: &mockProjectStore{MockProjectStore: ps}, + deploymentStore: ds, + logger: zap.NewNop(), + } + + claims := jwt.NewClaims( + "sub", + "avatar-url", + 10*time.Minute, + &model.Role{ + ProjectId: projectID, + ProjectRbacRoles: []string{"ADMIN"}, + }, + ) + verifier := &mockJWTVerifier{claims: claims} + authorizer := &mockAuthorizer{} + interceptor := rpcauth.JWTUnaryServerInterceptor(verifier, authorizer, zap.NewNop()) + + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return api.CancelDeployment(ctx, req.(*webservice.CancelDeploymentRequest)) + } + + resp, err := interceptor(ctx, &webservice.CancelDeploymentRequest{ + DeploymentId: deploymentID, + }, &grpc.UnaryServerInfo{FullMethod: "/webservice.WebService/CancelDeployment"}, handler) + + assert.Error(t, err) + assert.Nil(t, resp) + st, ok := status.FromError(err) + assert.True(t, ok) + assert.Equal(t, codes.FailedPrecondition, st.Code()) + assert.Contains(t, st.Message(), "project is currently disabled") +} + +func TestSkipStage_DisabledProject(t *testing.T) { + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + projectID := "project-id" + deploymentID := "deployment-id" + stageID := "stage-id" + + ctx := context.Background() + ctx = metadata.NewIncomingContext(ctx, metadata.MD{ + "cookie": []string{"token=dummy-token"}, + }) + + ps := datastoretest.NewMockProjectStore(ctrl) + ps.EXPECT().Get(gomock.Any(), projectID).Return(&model.Project{ + Id: projectID, + Disabled: true, + }, nil) + + ds := datastoretest.NewMockDeploymentStore(ctrl) + ds.EXPECT().Get(gomock.Any(), deploymentID).Return(&model.Deployment{ + Id: deploymentID, + ProjectId: projectID, + Stages: []*model.PipelineStage{{ + Id: stageID, + Name: "K8S_SYNC", + Status: model.StageStatus_STAGE_RUNNING, + }}, + }, nil) + + api := &WebAPI{ + projectStore: &mockProjectStore{MockProjectStore: ps}, + deploymentStore: ds, + logger: zap.NewNop(), + } + + claims := jwt.NewClaims( + "sub", + "avatar-url", + 10*time.Minute, + &model.Role{ + ProjectId: projectID, + ProjectRbacRoles: []string{"ADMIN"}, + }, + ) + verifier := &mockJWTVerifier{claims: claims} + authorizer := &mockAuthorizer{} + interceptor := rpcauth.JWTUnaryServerInterceptor(verifier, authorizer, zap.NewNop()) + + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return api.SkipStage(ctx, req.(*webservice.SkipStageRequest)) + } + + resp, err := interceptor(ctx, &webservice.SkipStageRequest{ + DeploymentId: deploymentID, + StageId: stageID, + }, &grpc.UnaryServerInfo{FullMethod: "/webservice.WebService/SkipStage"}, handler) + + assert.Error(t, err) + assert.Nil(t, resp) + st, ok := status.FromError(err) + assert.True(t, ok) + assert.Equal(t, codes.FailedPrecondition, st.Code()) + assert.Contains(t, st.Message(), "project is currently disabled") +} + +func TestApproveStage_DisabledProject(t *testing.T) { + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + userID := "user-id" + projectID := "project-id" + deploymentID := "deployment-id" + stageID := "stage-id" + + ctx := context.Background() + ctx = metadata.NewIncomingContext(ctx, metadata.MD{ + "cookie": []string{"token=dummy-token"}, + }) + + ps := datastoretest.NewMockProjectStore(ctrl) + ps.EXPECT().Get(gomock.Any(), projectID).Return(&model.Project{ + Id: projectID, + Disabled: true, + }, nil) + + ds := datastoretest.NewMockDeploymentStore(ctrl) + ds.EXPECT().Get(gomock.Any(), deploymentID).Return(&model.Deployment{ + Id: deploymentID, + ProjectId: projectID, + Stages: []*model.PipelineStage{{ + Id: stageID, + Name: "WAIT_APPROVAL", + Status: model.StageStatus_STAGE_RUNNING, + Metadata: map[string]string{ + "Approvers": userID, + }, + }}, + }, nil).Times(2) + + api := &WebAPI{ + projectStore: &mockProjectStore{MockProjectStore: ps}, + deploymentStore: ds, + deploymentProjectCache: newMockCache(), + logger: zap.NewNop(), + } + + claims := jwt.NewClaims( + userID, + "avatar-url", + 10*time.Minute, + &model.Role{ + ProjectId: projectID, + ProjectRbacRoles: []string{"ADMIN"}, + }, + ) + verifier := &mockJWTVerifier{claims: claims} + authorizer := &mockAuthorizer{} + interceptor := rpcauth.JWTUnaryServerInterceptor(verifier, authorizer, zap.NewNop()) + + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return api.ApproveStage(ctx, req.(*webservice.ApproveStageRequest)) + } + + resp, err := interceptor(ctx, &webservice.ApproveStageRequest{ + DeploymentId: deploymentID, + StageId: stageID, + }, &grpc.UnaryServerInfo{FullMethod: "/webservice.WebService/ApproveStage"}, handler) + + assert.Error(t, err) + assert.Nil(t, resp) + st, ok := status.FromError(err) + assert.True(t, ok) + assert.Equal(t, codes.FailedPrecondition, st.Code()) + assert.Contains(t, st.Message(), "project is currently disabled") +} + +func TestRestartPiped_DisabledProject(t *testing.T) { + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + projectID := "project-id" + pipedID := "piped-id" + + ctx := context.Background() + ctx = metadata.NewIncomingContext(ctx, metadata.MD{ + "cookie": []string{"token=dummy-token"}, + }) + + ps := datastoretest.NewMockProjectStore(ctrl) + ps.EXPECT().Get(gomock.Any(), projectID).Return(&model.Project{ + Id: projectID, + Disabled: true, + }, nil) + + pips := datastoretest.NewMockPipedStore(ctrl) + pips.EXPECT().Get(gomock.Any(), pipedID).Return(&model.Piped{ + Id: pipedID, + ProjectId: projectID, + }, nil) + + api := &WebAPI{ + projectStore: &mockProjectStore{MockProjectStore: ps}, + pipedStore: pips, + logger: zap.NewNop(), + } + + claims := jwt.NewClaims( + "sub", + "avatar-url", + 10*time.Minute, + &model.Role{ + ProjectId: projectID, + ProjectRbacRoles: []string{"ADMIN"}, + }, + ) + verifier := &mockJWTVerifier{claims: claims} + authorizer := &mockAuthorizer{} + interceptor := rpcauth.JWTUnaryServerInterceptor(verifier, authorizer, zap.NewNop()) + + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return api.RestartPiped(ctx, req.(*webservice.RestartPipedRequest)) + } + + resp, err := interceptor(ctx, &webservice.RestartPipedRequest{ + PipedId: pipedID, + }, &grpc.UnaryServerInfo{FullMethod: "/webservice.WebService/RestartPiped"}, handler) + + assert.Error(t, err) + assert.Nil(t, resp) + st, ok := status.FromError(err) + assert.True(t, ok) + assert.Equal(t, codes.FailedPrecondition, st.Code()) + assert.Contains(t, st.Message(), "project is currently disabled") +} + +// mockCache is a simple mock implementation of cache.Cache for testing +type mockCache struct{} + +func newMockCache() *mockCache { + return &mockCache{} +} + +func (c *mockCache) Get(key string) (interface{}, error) { + return nil, assert.AnError +} + +func (c *mockCache) Put(key string, value interface{}) error { + return nil +} + +func (c *mockCache) Delete(key string) error { + return nil +} + +func (c *mockCache) GetAll() (map[string]interface{}, error) { + return nil, nil +} diff --git a/pkg/app/server/service/webservice/service.pb.auth.go b/pkg/app/server/service/webservice/service.pb.auth.go index 50da1a9c41..4e4b68f4c6 100644 --- a/pkg/app/server/service/webservice/service.pb.auth.go +++ b/pkg/app/server/service/webservice/service.pb.auth.go @@ -92,7 +92,7 @@ func (a *authorizer) getAllProjectRBACRoles(ctx context.Context, projectID strin } // Authorize checks whether a role is enough for given gRPC method or not. -func (a *authorizer) Authorize(ctx context.Context, method string, r model.Role) bool { +func (a *authorizer) Authorize(ctx context.Context, method string, r *model.Role) bool { roles, err := a.getProjectRBACRoles(ctx, r.ProjectId, r.ProjectRbacRoles) if err != nil { a.logger.Error("failed to get rbac roles", diff --git a/pkg/rpc/rpcauth/interceptor.go b/pkg/rpc/rpcauth/interceptor.go index 08ff51ff2a..6dab8179c4 100644 --- a/pkg/rpc/rpcauth/interceptor.go +++ b/pkg/rpc/rpcauth/interceptor.go @@ -34,7 +34,7 @@ var ( // RBACAuthorizer defines a function to check required role for a specific RPC method. type RBACAuthorizer interface { - Authorize(context.Context, string, model.Role) bool + Authorize(context.Context, string, *model.Role) bool } // PipedTokenVerifier verifies the given piped token. @@ -201,7 +201,7 @@ func JWTUnaryServerInterceptor(verifier jwt.Verifier, authorizer RBACAuthorizer, logger.Warn("unable to verify token", zap.Error(err)) return nil, errUnauthenticated } - if !authorizer.Authorize(ctx, info.FullMethod, claims.Role) { + if !authorizer.Authorize(ctx, info.FullMethod, &claims.Role) { logger.Warn(fmt.Sprintf("unsufficient permission for method: %s", info.FullMethod), zap.Any("claims", claims), ) From e6f2cffabbfca961a7da7e1fdae603ea83079fee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9Cniladrix719=E2=80=9D?= Date: Thu, 27 Nov 2025 03:37:54 +0530 Subject: [PATCH 4/9] fix: gen/code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: “niladrix719” --- pkg/app/helloworld/service/service.pb.go | 5 ++-- pkg/app/helloworld/service/service_grpc.pb.go | 1 - .../server/service/apiservice/service.pb.go | 5 ++-- .../service/apiservice/service_grpc.pb.go | 1 - .../server/service/pipedservice/service.pb.go | 5 ++-- .../service/pipedservice/service_grpc.pb.go | 1 - .../service/webservice/service.pb.auth.go | 2 +- .../server/service/webservice/service.pb.go | 5 ++-- .../service/webservice/service_grpc.pb.go | 1 - pkg/datastore/datastoretest/datastore.mock.go | 28 +++++++++++++++++++ pkg/model/analysis_result.pb.go | 5 ++-- pkg/model/apikey.pb.go | 5 ++-- pkg/model/application.pb.go | 5 ++-- pkg/model/application_live_state.pb.go | 5 ++-- pkg/model/command.pb.go | 5 ++-- pkg/model/common.pb.go | 5 ++-- pkg/model/deployment.pb.go | 5 ++-- pkg/model/deployment_chain.pb.go | 5 ++-- pkg/model/deployment_trace.pb.go | 5 ++-- pkg/model/event.pb.go | 5 ++-- pkg/model/insight.pb.go | 5 ++-- pkg/model/logblock.pb.go | 5 ++-- pkg/model/notificationevent.pb.go | 5 ++-- pkg/model/piped.pb.go | 5 ++-- pkg/model/piped_stat.pb.go | 5 ++-- pkg/model/planpreview.pb.go | 5 ++-- pkg/model/project.pb.go | 5 ++-- pkg/model/rbac.pb.go | 5 ++-- pkg/model/role.pb.go | 5 ++-- pkg/model/user.pb.go | 5 ++-- pkg/plugin/api/v1alpha1/common/common.pb.go | 5 ++-- pkg/plugin/api/v1alpha1/deployment/api.pb.go | 5 ++-- .../api/v1alpha1/deployment/api_grpc.pb.go | 1 - pkg/plugin/api/v1alpha1/livestate/api.pb.go | 5 ++-- .../api/v1alpha1/livestate/api_grpc.pb.go | 1 - pkg/plugin/api/v1alpha1/planpreview/api.pb.go | 5 ++-- .../api/v1alpha1/planpreview/api_grpc.pb.go | 1 - pkg/plugin/pipedservice/service.pb.go | 5 ++-- pkg/plugin/pipedservice/service_grpc.pb.go | 1 - tool/codegen/protoc-gen-auth/file.go | 2 +- 40 files changed, 88 insertions(+), 97 deletions(-) diff --git a/pkg/app/helloworld/service/service.pb.go b/pkg/app/helloworld/service/service.pb.go index bd7f450cd7..3975fa6078 100644 --- a/pkg/app/helloworld/service/service.pb.go +++ b/pkg/app/helloworld/service/service.pb.go @@ -21,12 +21,11 @@ package service import ( - reflect "reflect" - sync "sync" - _ "github.com/envoyproxy/protoc-gen-validate/validate" protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" ) const ( diff --git a/pkg/app/helloworld/service/service_grpc.pb.go b/pkg/app/helloworld/service/service_grpc.pb.go index caea204bf6..ae42e3b779 100644 --- a/pkg/app/helloworld/service/service_grpc.pb.go +++ b/pkg/app/helloworld/service/service_grpc.pb.go @@ -8,7 +8,6 @@ package service import ( context "context" - grpc "google.golang.org/grpc" codes "google.golang.org/grpc/codes" status "google.golang.org/grpc/status" diff --git a/pkg/app/server/service/apiservice/service.pb.go b/pkg/app/server/service/apiservice/service.pb.go index 821be311dc..ce59c23136 100644 --- a/pkg/app/server/service/apiservice/service.pb.go +++ b/pkg/app/server/service/apiservice/service.pb.go @@ -21,13 +21,12 @@ package apiservice import ( - reflect "reflect" - sync "sync" - _ "github.com/envoyproxy/protoc-gen-validate/validate" model "github.com/pipe-cd/pipecd/pkg/model" protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" ) const ( diff --git a/pkg/app/server/service/apiservice/service_grpc.pb.go b/pkg/app/server/service/apiservice/service_grpc.pb.go index 8c2573ee17..8193460074 100644 --- a/pkg/app/server/service/apiservice/service_grpc.pb.go +++ b/pkg/app/server/service/apiservice/service_grpc.pb.go @@ -8,7 +8,6 @@ package apiservice import ( context "context" - grpc "google.golang.org/grpc" codes "google.golang.org/grpc/codes" status "google.golang.org/grpc/status" diff --git a/pkg/app/server/service/pipedservice/service.pb.go b/pkg/app/server/service/pipedservice/service.pb.go index 8da1f543fa..b34ff83335 100644 --- a/pkg/app/server/service/pipedservice/service.pb.go +++ b/pkg/app/server/service/pipedservice/service.pb.go @@ -21,13 +21,12 @@ package pipedservice import ( - reflect "reflect" - sync "sync" - _ "github.com/envoyproxy/protoc-gen-validate/validate" model "github.com/pipe-cd/pipecd/pkg/model" protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" ) const ( diff --git a/pkg/app/server/service/pipedservice/service_grpc.pb.go b/pkg/app/server/service/pipedservice/service_grpc.pb.go index 9f82903921..7d3079717d 100644 --- a/pkg/app/server/service/pipedservice/service_grpc.pb.go +++ b/pkg/app/server/service/pipedservice/service_grpc.pb.go @@ -8,7 +8,6 @@ package pipedservice import ( context "context" - grpc "google.golang.org/grpc" codes "google.golang.org/grpc/codes" status "google.golang.org/grpc/status" diff --git a/pkg/app/server/service/webservice/service.pb.auth.go b/pkg/app/server/service/webservice/service.pb.auth.go index 4e4b68f4c6..50da1a9c41 100644 --- a/pkg/app/server/service/webservice/service.pb.auth.go +++ b/pkg/app/server/service/webservice/service.pb.auth.go @@ -92,7 +92,7 @@ func (a *authorizer) getAllProjectRBACRoles(ctx context.Context, projectID strin } // Authorize checks whether a role is enough for given gRPC method or not. -func (a *authorizer) Authorize(ctx context.Context, method string, r *model.Role) bool { +func (a *authorizer) Authorize(ctx context.Context, method string, r model.Role) bool { roles, err := a.getProjectRBACRoles(ctx, r.ProjectId, r.ProjectRbacRoles) if err != nil { a.logger.Error("failed to get rbac roles", diff --git a/pkg/app/server/service/webservice/service.pb.go b/pkg/app/server/service/webservice/service.pb.go index d761a6fa62..3d0b5baa58 100644 --- a/pkg/app/server/service/webservice/service.pb.go +++ b/pkg/app/server/service/webservice/service.pb.go @@ -21,15 +21,14 @@ package webservice import ( - reflect "reflect" - sync "sync" - _ "github.com/envoyproxy/protoc-gen-validate/validate" model "github.com/pipe-cd/pipecd/pkg/model" protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" _ "google.golang.org/protobuf/types/descriptorpb" wrapperspb "google.golang.org/protobuf/types/known/wrapperspb" + reflect "reflect" + sync "sync" ) const ( diff --git a/pkg/app/server/service/webservice/service_grpc.pb.go b/pkg/app/server/service/webservice/service_grpc.pb.go index 95c1ac8b24..3ef9ff6e64 100644 --- a/pkg/app/server/service/webservice/service_grpc.pb.go +++ b/pkg/app/server/service/webservice/service_grpc.pb.go @@ -8,7 +8,6 @@ package webservice import ( context "context" - grpc "google.golang.org/grpc" codes "google.golang.org/grpc/codes" status "google.golang.org/grpc/status" diff --git a/pkg/datastore/datastoretest/datastore.mock.go b/pkg/datastore/datastoretest/datastore.mock.go index 555929b409..913205918e 100644 --- a/pkg/datastore/datastoretest/datastore.mock.go +++ b/pkg/datastore/datastoretest/datastore.mock.go @@ -113,6 +113,20 @@ func (mr *MockProjectStoreMockRecorder) DeleteProjectUserGroup(ctx, id, sso any) return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteProjectUserGroup", reflect.TypeOf((*MockProjectStore)(nil).DeleteProjectUserGroup), ctx, id, sso) } +// DisableProject mocks base method. +func (m *MockProjectStore) DisableProject(ctx context.Context, id string) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "DisableProject", ctx, id) + ret0, _ := ret[0].(error) + return ret0 +} + +// DisableProject indicates an expected call of DisableProject. +func (mr *MockProjectStoreMockRecorder) DisableProject(ctx, id any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DisableProject", reflect.TypeOf((*MockProjectStore)(nil).DisableProject), ctx, id) +} + // DisableStaticAdmin mocks base method. func (m *MockProjectStore) DisableStaticAdmin(ctx context.Context, id string) error { m.ctrl.T.Helper() @@ -127,6 +141,20 @@ func (mr *MockProjectStoreMockRecorder) DisableStaticAdmin(ctx, id any) *gomock. return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DisableStaticAdmin", reflect.TypeOf((*MockProjectStore)(nil).DisableStaticAdmin), ctx, id) } +// EnableProject mocks base method. +func (m *MockProjectStore) EnableProject(ctx context.Context, id string) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "EnableProject", ctx, id) + ret0, _ := ret[0].(error) + return ret0 +} + +// EnableProject indicates an expected call of EnableProject. +func (mr *MockProjectStoreMockRecorder) EnableProject(ctx, id any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "EnableProject", reflect.TypeOf((*MockProjectStore)(nil).EnableProject), ctx, id) +} + // EnableStaticAdmin mocks base method. func (m *MockProjectStore) EnableStaticAdmin(ctx context.Context, id string) error { m.ctrl.T.Helper() diff --git a/pkg/model/analysis_result.pb.go b/pkg/model/analysis_result.pb.go index 1db8d275a6..6c243805b7 100644 --- a/pkg/model/analysis_result.pb.go +++ b/pkg/model/analysis_result.pb.go @@ -21,12 +21,11 @@ package model import ( - reflect "reflect" - sync "sync" - _ "github.com/envoyproxy/protoc-gen-validate/validate" protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" ) const ( diff --git a/pkg/model/apikey.pb.go b/pkg/model/apikey.pb.go index 045df4eb97..08c0af46d7 100644 --- a/pkg/model/apikey.pb.go +++ b/pkg/model/apikey.pb.go @@ -21,12 +21,11 @@ package model import ( - reflect "reflect" - sync "sync" - _ "github.com/envoyproxy/protoc-gen-validate/validate" protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" ) const ( diff --git a/pkg/model/application.pb.go b/pkg/model/application.pb.go index d3a88d05c6..b85be9b3cc 100644 --- a/pkg/model/application.pb.go +++ b/pkg/model/application.pb.go @@ -21,12 +21,11 @@ package model import ( - reflect "reflect" - sync "sync" - _ "github.com/envoyproxy/protoc-gen-validate/validate" protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" ) const ( diff --git a/pkg/model/application_live_state.pb.go b/pkg/model/application_live_state.pb.go index ecab5709be..4aad111aad 100644 --- a/pkg/model/application_live_state.pb.go +++ b/pkg/model/application_live_state.pb.go @@ -21,12 +21,11 @@ package model import ( - reflect "reflect" - sync "sync" - _ "github.com/envoyproxy/protoc-gen-validate/validate" protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" ) const ( diff --git a/pkg/model/command.pb.go b/pkg/model/command.pb.go index c5a1893548..ce5d5b4c53 100644 --- a/pkg/model/command.pb.go +++ b/pkg/model/command.pb.go @@ -21,12 +21,11 @@ package model import ( - reflect "reflect" - sync "sync" - _ "github.com/envoyproxy/protoc-gen-validate/validate" protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" ) const ( diff --git a/pkg/model/common.pb.go b/pkg/model/common.pb.go index fea8b2f3d8..21de37ffa3 100644 --- a/pkg/model/common.pb.go +++ b/pkg/model/common.pb.go @@ -21,12 +21,11 @@ package model import ( - reflect "reflect" - sync "sync" - _ "github.com/envoyproxy/protoc-gen-validate/validate" protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" ) const ( diff --git a/pkg/model/deployment.pb.go b/pkg/model/deployment.pb.go index 7fe61d18c6..5e31d35165 100644 --- a/pkg/model/deployment.pb.go +++ b/pkg/model/deployment.pb.go @@ -21,12 +21,11 @@ package model import ( - reflect "reflect" - sync "sync" - _ "github.com/envoyproxy/protoc-gen-validate/validate" protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" ) const ( diff --git a/pkg/model/deployment_chain.pb.go b/pkg/model/deployment_chain.pb.go index 0d427d09e1..3e5630488a 100644 --- a/pkg/model/deployment_chain.pb.go +++ b/pkg/model/deployment_chain.pb.go @@ -21,12 +21,11 @@ package model import ( - reflect "reflect" - sync "sync" - _ "github.com/envoyproxy/protoc-gen-validate/validate" protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" ) const ( diff --git a/pkg/model/deployment_trace.pb.go b/pkg/model/deployment_trace.pb.go index f4430c7267..ed159a140a 100644 --- a/pkg/model/deployment_trace.pb.go +++ b/pkg/model/deployment_trace.pb.go @@ -21,12 +21,11 @@ package model import ( - reflect "reflect" - sync "sync" - _ "github.com/envoyproxy/protoc-gen-validate/validate" protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" ) const ( diff --git a/pkg/model/event.pb.go b/pkg/model/event.pb.go index 0d4f40ea4d..1c728f6009 100644 --- a/pkg/model/event.pb.go +++ b/pkg/model/event.pb.go @@ -21,12 +21,11 @@ package model import ( - reflect "reflect" - sync "sync" - _ "github.com/envoyproxy/protoc-gen-validate/validate" protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" ) const ( diff --git a/pkg/model/insight.pb.go b/pkg/model/insight.pb.go index 660986dc10..d695aedcad 100644 --- a/pkg/model/insight.pb.go +++ b/pkg/model/insight.pb.go @@ -21,12 +21,11 @@ package model import ( - reflect "reflect" - sync "sync" - _ "github.com/envoyproxy/protoc-gen-validate/validate" protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" ) const ( diff --git a/pkg/model/logblock.pb.go b/pkg/model/logblock.pb.go index c86cecb901..0e9649867f 100644 --- a/pkg/model/logblock.pb.go +++ b/pkg/model/logblock.pb.go @@ -21,12 +21,11 @@ package model import ( - reflect "reflect" - sync "sync" - _ "github.com/envoyproxy/protoc-gen-validate/validate" protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" ) const ( diff --git a/pkg/model/notificationevent.pb.go b/pkg/model/notificationevent.pb.go index a75e875184..8b4bf96675 100644 --- a/pkg/model/notificationevent.pb.go +++ b/pkg/model/notificationevent.pb.go @@ -21,12 +21,11 @@ package model import ( - reflect "reflect" - sync "sync" - _ "github.com/envoyproxy/protoc-gen-validate/validate" protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" ) const ( diff --git a/pkg/model/piped.pb.go b/pkg/model/piped.pb.go index bbf82f2e32..e1cc6bbf5f 100644 --- a/pkg/model/piped.pb.go +++ b/pkg/model/piped.pb.go @@ -21,12 +21,11 @@ package model import ( - reflect "reflect" - sync "sync" - _ "github.com/envoyproxy/protoc-gen-validate/validate" protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" ) const ( diff --git a/pkg/model/piped_stat.pb.go b/pkg/model/piped_stat.pb.go index 9e5faddda4..f80a449ff7 100644 --- a/pkg/model/piped_stat.pb.go +++ b/pkg/model/piped_stat.pb.go @@ -21,12 +21,11 @@ package model import ( - reflect "reflect" - sync "sync" - _ "github.com/envoyproxy/protoc-gen-validate/validate" protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" ) const ( diff --git a/pkg/model/planpreview.pb.go b/pkg/model/planpreview.pb.go index 658f041772..f0c49c1548 100644 --- a/pkg/model/planpreview.pb.go +++ b/pkg/model/planpreview.pb.go @@ -21,12 +21,11 @@ package model import ( - reflect "reflect" - sync "sync" - _ "github.com/envoyproxy/protoc-gen-validate/validate" protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" ) const ( diff --git a/pkg/model/project.pb.go b/pkg/model/project.pb.go index 7e91fff8da..ca46026a92 100644 --- a/pkg/model/project.pb.go +++ b/pkg/model/project.pb.go @@ -21,13 +21,12 @@ package model import ( - reflect "reflect" - sync "sync" - _ "github.com/envoyproxy/protoc-gen-validate/validate" protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" _ "google.golang.org/protobuf/types/descriptorpb" + reflect "reflect" + sync "sync" ) const ( diff --git a/pkg/model/rbac.pb.go b/pkg/model/rbac.pb.go index 02513aad79..049708fc04 100644 --- a/pkg/model/rbac.pb.go +++ b/pkg/model/rbac.pb.go @@ -21,12 +21,11 @@ package model import ( - reflect "reflect" - sync "sync" - protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" descriptorpb "google.golang.org/protobuf/types/descriptorpb" + reflect "reflect" + sync "sync" ) const ( diff --git a/pkg/model/role.pb.go b/pkg/model/role.pb.go index 8d892f0020..d8528d2e16 100644 --- a/pkg/model/role.pb.go +++ b/pkg/model/role.pb.go @@ -21,12 +21,11 @@ package model import ( - reflect "reflect" - sync "sync" - protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" _ "google.golang.org/protobuf/types/descriptorpb" + reflect "reflect" + sync "sync" ) const ( diff --git a/pkg/model/user.pb.go b/pkg/model/user.pb.go index 2b007c4bd2..4229732fe7 100644 --- a/pkg/model/user.pb.go +++ b/pkg/model/user.pb.go @@ -21,12 +21,11 @@ package model import ( - reflect "reflect" - sync "sync" - _ "github.com/envoyproxy/protoc-gen-validate/validate" protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" ) const ( diff --git a/pkg/plugin/api/v1alpha1/common/common.pb.go b/pkg/plugin/api/v1alpha1/common/common.pb.go index 6fc88e64c6..9f688acf8c 100644 --- a/pkg/plugin/api/v1alpha1/common/common.pb.go +++ b/pkg/plugin/api/v1alpha1/common/common.pb.go @@ -23,11 +23,10 @@ package common import ( - reflect "reflect" - sync "sync" - protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" ) const ( diff --git a/pkg/plugin/api/v1alpha1/deployment/api.pb.go b/pkg/plugin/api/v1alpha1/deployment/api.pb.go index 0daec9931e..ef11842b44 100644 --- a/pkg/plugin/api/v1alpha1/deployment/api.pb.go +++ b/pkg/plugin/api/v1alpha1/deployment/api.pb.go @@ -21,14 +21,13 @@ package deployment import ( - reflect "reflect" - sync "sync" - _ "github.com/envoyproxy/protoc-gen-validate/validate" model "github.com/pipe-cd/pipecd/pkg/model" common "github.com/pipe-cd/pipecd/pkg/plugin/api/v1alpha1/common" protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" ) const ( diff --git a/pkg/plugin/api/v1alpha1/deployment/api_grpc.pb.go b/pkg/plugin/api/v1alpha1/deployment/api_grpc.pb.go index e167ca3b3b..8db550748e 100644 --- a/pkg/plugin/api/v1alpha1/deployment/api_grpc.pb.go +++ b/pkg/plugin/api/v1alpha1/deployment/api_grpc.pb.go @@ -8,7 +8,6 @@ package deployment import ( context "context" - grpc "google.golang.org/grpc" codes "google.golang.org/grpc/codes" status "google.golang.org/grpc/status" diff --git a/pkg/plugin/api/v1alpha1/livestate/api.pb.go b/pkg/plugin/api/v1alpha1/livestate/api.pb.go index c962fa9f1d..967a70471b 100644 --- a/pkg/plugin/api/v1alpha1/livestate/api.pb.go +++ b/pkg/plugin/api/v1alpha1/livestate/api.pb.go @@ -21,13 +21,12 @@ package livestate import ( - reflect "reflect" - sync "sync" - model "github.com/pipe-cd/pipecd/pkg/model" common "github.com/pipe-cd/pipecd/pkg/plugin/api/v1alpha1/common" protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" ) const ( diff --git a/pkg/plugin/api/v1alpha1/livestate/api_grpc.pb.go b/pkg/plugin/api/v1alpha1/livestate/api_grpc.pb.go index 48e27d50bb..b724df262e 100644 --- a/pkg/plugin/api/v1alpha1/livestate/api_grpc.pb.go +++ b/pkg/plugin/api/v1alpha1/livestate/api_grpc.pb.go @@ -8,7 +8,6 @@ package livestate import ( context "context" - grpc "google.golang.org/grpc" codes "google.golang.org/grpc/codes" status "google.golang.org/grpc/status" diff --git a/pkg/plugin/api/v1alpha1/planpreview/api.pb.go b/pkg/plugin/api/v1alpha1/planpreview/api.pb.go index 25474819f7..5269379cac 100644 --- a/pkg/plugin/api/v1alpha1/planpreview/api.pb.go +++ b/pkg/plugin/api/v1alpha1/planpreview/api.pb.go @@ -21,12 +21,11 @@ package planpreview import ( - reflect "reflect" - sync "sync" - common "github.com/pipe-cd/pipecd/pkg/plugin/api/v1alpha1/common" protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" ) const ( diff --git a/pkg/plugin/api/v1alpha1/planpreview/api_grpc.pb.go b/pkg/plugin/api/v1alpha1/planpreview/api_grpc.pb.go index 8993d52c9c..73a044a059 100644 --- a/pkg/plugin/api/v1alpha1/planpreview/api_grpc.pb.go +++ b/pkg/plugin/api/v1alpha1/planpreview/api_grpc.pb.go @@ -8,7 +8,6 @@ package planpreview import ( context "context" - grpc "google.golang.org/grpc" codes "google.golang.org/grpc/codes" status "google.golang.org/grpc/status" diff --git a/pkg/plugin/pipedservice/service.pb.go b/pkg/plugin/pipedservice/service.pb.go index 9972500628..de61118540 100644 --- a/pkg/plugin/pipedservice/service.pb.go +++ b/pkg/plugin/pipedservice/service.pb.go @@ -21,13 +21,12 @@ package pipedservice import ( - reflect "reflect" - sync "sync" - _ "github.com/envoyproxy/protoc-gen-validate/validate" model "github.com/pipe-cd/pipecd/pkg/model" protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" ) const ( diff --git a/pkg/plugin/pipedservice/service_grpc.pb.go b/pkg/plugin/pipedservice/service_grpc.pb.go index ae9c435a2b..d3d61fbbff 100644 --- a/pkg/plugin/pipedservice/service_grpc.pb.go +++ b/pkg/plugin/pipedservice/service_grpc.pb.go @@ -8,7 +8,6 @@ package pipedservice import ( context "context" - grpc "google.golang.org/grpc" codes "google.golang.org/grpc/codes" status "google.golang.org/grpc/status" diff --git a/tool/codegen/protoc-gen-auth/file.go b/tool/codegen/protoc-gen-auth/file.go index ea7063087f..113821ba72 100644 --- a/tool/codegen/protoc-gen-auth/file.go +++ b/tool/codegen/protoc-gen-auth/file.go @@ -116,7 +116,7 @@ func (a *authorizer) getAllProjectRBACRoles(ctx context.Context, projectID strin } // Authorize checks whether a role is enough for given gRPC method or not. -func (a *authorizer) Authorize(ctx context.Context, method string, r model.Role) bool { +func (a *authorizer) Authorize(ctx context.Context, method string, r *model.Role) bool { roles, err := a.getProjectRBACRoles(ctx, r.ProjectId, r.ProjectRbacRoles) if err != nil { a.logger.Error("failed to get rbac roles", From eaef937f9d0d489a7dd13d5dbd7d86f2252c7dfc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9Cniladrix719=E2=80=9D?= Date: Thu, 27 Nov 2025 03:50:51 +0530 Subject: [PATCH 5/9] fix: gen/code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: “niladrix719” --- pkg/app/server/service/webservice/service.pb.auth.go | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/pkg/app/server/service/webservice/service.pb.auth.go b/pkg/app/server/service/webservice/service.pb.auth.go index 50da1a9c41..694cd5ed09 100644 --- a/pkg/app/server/service/webservice/service.pb.auth.go +++ b/pkg/app/server/service/webservice/service.pb.auth.go @@ -5,6 +5,7 @@ package webservice import ( "context" + "fmt" "time" "go.uber.org/zap" @@ -82,6 +83,13 @@ func (a *authorizer) getAllProjectRBACRoles(ctx context.Context, projectID strin return nil, err } + if p.Disabled { + a.logger.Warn("project is disabled", + zap.String("project", projectID), + ) + return nil, fmt.Errorf("project %s is disabled", projectID) + } + if err = a.rbacCache.Put(projectID, p.RbacRoles); err != nil { a.logger.Warn("unable to store the rbac in memory cache", zap.String("project", projectID), @@ -92,7 +100,7 @@ func (a *authorizer) getAllProjectRBACRoles(ctx context.Context, projectID strin } // Authorize checks whether a role is enough for given gRPC method or not. -func (a *authorizer) Authorize(ctx context.Context, method string, r model.Role) bool { +func (a *authorizer) Authorize(ctx context.Context, method string, r *model.Role) bool { roles, err := a.getProjectRBACRoles(ctx, r.ProjectId, r.ProjectRbacRoles) if err != nil { a.logger.Error("failed to get rbac roles", From a24f93fc456a9f9a3522008ea949d0713dc930d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9Cniladrix719=E2=80=9D?= Date: Tue, 9 Dec 2025 21:57:10 +0530 Subject: [PATCH 6/9] update gen code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: “niladrix719” --- pkg/app/server/grpcapi/web_api_test.go | 2 +- pkg/app/server/service/webservice/service.pb.auth.go | 2 +- pkg/rpc/rpcauth/interceptor.go | 4 ++-- tool/codegen/protoc-gen-auth/file.go | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/pkg/app/server/grpcapi/web_api_test.go b/pkg/app/server/grpcapi/web_api_test.go index a73c86c488..dc99c3862d 100644 --- a/pkg/app/server/grpcapi/web_api_test.go +++ b/pkg/app/server/grpcapi/web_api_test.go @@ -410,7 +410,7 @@ func (m *mockJWTVerifier) Verify(token string) (*jwt.Claims, error) { type mockAuthorizer struct{} -func (m *mockAuthorizer) Authorize(ctx context.Context, method string, role *model.Role) bool { +func (m *mockAuthorizer) Authorize(ctx context.Context, method string, role model.Role) bool { return true } diff --git a/pkg/app/server/service/webservice/service.pb.auth.go b/pkg/app/server/service/webservice/service.pb.auth.go index 694cd5ed09..09ccc4c2e2 100644 --- a/pkg/app/server/service/webservice/service.pb.auth.go +++ b/pkg/app/server/service/webservice/service.pb.auth.go @@ -100,7 +100,7 @@ func (a *authorizer) getAllProjectRBACRoles(ctx context.Context, projectID strin } // Authorize checks whether a role is enough for given gRPC method or not. -func (a *authorizer) Authorize(ctx context.Context, method string, r *model.Role) bool { +func (a *authorizer) Authorize(ctx context.Context, method string, r model.Role) bool { roles, err := a.getProjectRBACRoles(ctx, r.ProjectId, r.ProjectRbacRoles) if err != nil { a.logger.Error("failed to get rbac roles", diff --git a/pkg/rpc/rpcauth/interceptor.go b/pkg/rpc/rpcauth/interceptor.go index 6dab8179c4..08ff51ff2a 100644 --- a/pkg/rpc/rpcauth/interceptor.go +++ b/pkg/rpc/rpcauth/interceptor.go @@ -34,7 +34,7 @@ var ( // RBACAuthorizer defines a function to check required role for a specific RPC method. type RBACAuthorizer interface { - Authorize(context.Context, string, *model.Role) bool + Authorize(context.Context, string, model.Role) bool } // PipedTokenVerifier verifies the given piped token. @@ -201,7 +201,7 @@ func JWTUnaryServerInterceptor(verifier jwt.Verifier, authorizer RBACAuthorizer, logger.Warn("unable to verify token", zap.Error(err)) return nil, errUnauthenticated } - if !authorizer.Authorize(ctx, info.FullMethod, &claims.Role) { + if !authorizer.Authorize(ctx, info.FullMethod, claims.Role) { logger.Warn(fmt.Sprintf("unsufficient permission for method: %s", info.FullMethod), zap.Any("claims", claims), ) diff --git a/tool/codegen/protoc-gen-auth/file.go b/tool/codegen/protoc-gen-auth/file.go index 113821ba72..ea7063087f 100644 --- a/tool/codegen/protoc-gen-auth/file.go +++ b/tool/codegen/protoc-gen-auth/file.go @@ -116,7 +116,7 @@ func (a *authorizer) getAllProjectRBACRoles(ctx context.Context, projectID strin } // Authorize checks whether a role is enough for given gRPC method or not. -func (a *authorizer) Authorize(ctx context.Context, method string, r *model.Role) bool { +func (a *authorizer) Authorize(ctx context.Context, method string, r model.Role) bool { roles, err := a.getProjectRBACRoles(ctx, r.ProjectId, r.ProjectRbacRoles) if err != nil { a.logger.Error("failed to get rbac roles", From 61bf7d2afdafa34c07abb6a04ad1586dc2e8a86b Mon Sep 17 00:00:00 2001 From: Niladri Adhikary <91966855+niladrix719@users.noreply.github.com> Date: Wed, 14 Jan 2026 11:57:04 +0530 Subject: [PATCH 7/9] Remove handling for disabled projects Removed logging and error handling for disabled projects. Signed-off-by: Niladri Adhikary <91966855+niladrix719@users.noreply.github.com> --- tool/codegen/protoc-gen-auth/file.go | 8 -------- 1 file changed, 8 deletions(-) diff --git a/tool/codegen/protoc-gen-auth/file.go b/tool/codegen/protoc-gen-auth/file.go index ea7063087f..415ce3e91a 100644 --- a/tool/codegen/protoc-gen-auth/file.go +++ b/tool/codegen/protoc-gen-auth/file.go @@ -21,7 +21,6 @@ package webservice import ( "context" - "fmt" "time" "go.uber.org/zap" @@ -99,13 +98,6 @@ func (a *authorizer) getAllProjectRBACRoles(ctx context.Context, projectID strin return nil, err } - if p.Disabled { - a.logger.Warn("project is disabled", - zap.String("project", projectID), - ) - return nil, fmt.Errorf("project %s is disabled", projectID) - } - if err = a.rbacCache.Put(projectID, p.RbacRoles); err != nil { a.logger.Warn("unable to store the rbac in memory cache", zap.String("project", projectID), From 17a2a58b44bf116e038f60cd036ffec9b2b6eedd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9Cniladrix719=E2=80=9D?= Date: Thu, 15 Jan 2026 13:00:55 +0530 Subject: [PATCH 8/9] fix: gen issue MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: “niladrix719” --- pkg/app/server/service/webservice/service.pb.auth.go | 8 -------- 1 file changed, 8 deletions(-) diff --git a/pkg/app/server/service/webservice/service.pb.auth.go b/pkg/app/server/service/webservice/service.pb.auth.go index 09ccc4c2e2..50da1a9c41 100644 --- a/pkg/app/server/service/webservice/service.pb.auth.go +++ b/pkg/app/server/service/webservice/service.pb.auth.go @@ -5,7 +5,6 @@ package webservice import ( "context" - "fmt" "time" "go.uber.org/zap" @@ -83,13 +82,6 @@ func (a *authorizer) getAllProjectRBACRoles(ctx context.Context, projectID strin return nil, err } - if p.Disabled { - a.logger.Warn("project is disabled", - zap.String("project", projectID), - ) - return nil, fmt.Errorf("project %s is disabled", projectID) - } - if err = a.rbacCache.Put(projectID, p.RbacRoles); err != nil { a.logger.Warn("unable to store the rbac in memory cache", zap.String("project", projectID), From a0578e60853d0c7019728cec4e8024056faf335e Mon Sep 17 00:00:00 2001 From: Niladri Adhikary Date: Thu, 19 Feb 2026 21:07:18 +0530 Subject: [PATCH 9/9] revert: the pointer change Signed-off-by: Niladri Adhikary --- pkg/app/server/grpcapi/web_api_test.go | 10 +++++----- pkg/app/server/httpapi/callback.go | 2 +- pkg/app/server/httpapi/login.go | 2 +- pkg/jwt/jwt.go | 8 ++------ pkg/jwt/signer_test.go | 2 +- pkg/jwt/verifier_test.go | 4 ++-- 6 files changed, 12 insertions(+), 16 deletions(-) diff --git a/pkg/app/server/grpcapi/web_api_test.go b/pkg/app/server/grpcapi/web_api_test.go index dc99c3862d..b99dce49d3 100644 --- a/pkg/app/server/grpcapi/web_api_test.go +++ b/pkg/app/server/grpcapi/web_api_test.go @@ -449,7 +449,7 @@ func TestSyncApplication_DisabledProject(t *testing.T) { "sub", "avatar-url", 10*time.Minute, - &model.Role{ + model.Role{ ProjectId: projectID, ProjectRbacRoles: []string{"ADMIN"}, }, @@ -509,7 +509,7 @@ func TestCancelDeployment_DisabledProject(t *testing.T) { "sub", "avatar-url", 10*time.Minute, - &model.Role{ + model.Role{ ProjectId: projectID, ProjectRbacRoles: []string{"ADMIN"}, }, @@ -574,7 +574,7 @@ func TestSkipStage_DisabledProject(t *testing.T) { "sub", "avatar-url", 10*time.Minute, - &model.Role{ + model.Role{ ProjectId: projectID, ProjectRbacRoles: []string{"ADMIN"}, }, @@ -645,7 +645,7 @@ func TestApproveStage_DisabledProject(t *testing.T) { userID, "avatar-url", 10*time.Minute, - &model.Role{ + model.Role{ ProjectId: projectID, ProjectRbacRoles: []string{"ADMIN"}, }, @@ -705,7 +705,7 @@ func TestRestartPiped_DisabledProject(t *testing.T) { "sub", "avatar-url", 10*time.Minute, - &model.Role{ + model.Role{ ProjectId: projectID, ProjectRbacRoles: []string{"ADMIN"}, }, diff --git a/pkg/app/server/httpapi/callback.go b/pkg/app/server/httpapi/callback.go index e10b095405..555fdbba4c 100644 --- a/pkg/app/server/httpapi/callback.go +++ b/pkg/app/server/httpapi/callback.go @@ -103,7 +103,7 @@ func (h *authHandler) handleCallback(w http.ResponseWriter, r *http.Request) { user.Username, user.AvatarUrl, tokenTTL, - user.Role, + *user.Role, //nolint:govet ) signedToken, err := h.signer.Sign(claims) if err != nil { diff --git a/pkg/app/server/httpapi/login.go b/pkg/app/server/httpapi/login.go index 7550616e13..1e94b02533 100644 --- a/pkg/app/server/httpapi/login.go +++ b/pkg/app/server/httpapi/login.go @@ -143,7 +143,7 @@ func (h *authHandler) handleStaticAdminLogin(w http.ResponseWriter, r *http.Requ admin.Username, "", defaultTokenTTL, - &model.Role{ + model.Role{ ProjectId: projectID, ProjectRbacRoles: []string{model.BuiltinRBACRoleAdmin.String()}, }, diff --git a/pkg/jwt/jwt.go b/pkg/jwt/jwt.go index 152bdb2074..ffd2cc3f6f 100644 --- a/pkg/jwt/jwt.go +++ b/pkg/jwt/jwt.go @@ -39,12 +39,8 @@ type Claims struct { } // NewClaims creates a new claims for a given github user. -func NewClaims(githubUserID, avatarURL string, ttl time.Duration, role *model.Role) *Claims { +func NewClaims(githubUserID, avatarURL string, ttl time.Duration, role model.Role) *Claims { now := time.Now().UTC() - var roleValue model.Role - if role != nil { - roleValue = *role //nolint:govet // Copying proto role into the token snapshot is intentional. - } return &Claims{ RegisteredClaims: jwtgo.RegisteredClaims{ Subject: githubUserID, @@ -54,7 +50,7 @@ func NewClaims(githubUserID, avatarURL string, ttl time.Duration, role *model.Ro ExpiresAt: jwtgo.NewNumericDate(now.Add(ttl)), }, AvatarURL: avatarURL, - Role: roleValue, + Role: role, } } diff --git a/pkg/jwt/signer_test.go b/pkg/jwt/signer_test.go index a8b8917238..e60287dc58 100644 --- a/pkg/jwt/signer_test.go +++ b/pkg/jwt/signer_test.go @@ -25,7 +25,7 @@ import ( ) func TestSign(t *testing.T) { - claims := NewClaims("user-1", "avatar-url", time.Hour, &model.Role{ + claims := NewClaims("user-1", "avatar-url", time.Hour, model.Role{ ProjectId: "project-1", }) diff --git a/pkg/jwt/verifier_test.go b/pkg/jwt/verifier_test.go index 5a949b730f..a12eb4e409 100644 --- a/pkg/jwt/verifier_test.go +++ b/pkg/jwt/verifier_test.go @@ -40,7 +40,7 @@ func TestVerify(t *testing.T) { }{ { name: "ok", - claims: NewClaims("user-1", "avatar-url", time.Hour, &model.Role{ + claims: NewClaims("user-1", "avatar-url", time.Hour, model.Role{ ProjectId: "project-1", }), fail: false, @@ -129,7 +129,7 @@ func TestVerify(t *testing.T) { testFunc(hsS, hsV) - c := NewClaims("user", "avatar-url", time.Hour, &model.Role{ + c := NewClaims("user", "avatar-url", time.Hour, model.Role{ ProjectId: "project", })