From 262d4e221ff34010aa5074501a3d422c7fa7fd45 Mon Sep 17 00:00:00 2001 From: jlandowner Date: Sun, 2 Jun 2024 16:45:07 +0900 Subject: [PATCH 1/3] Add EventWatcher on dashboard - Add EventWatcher on dashboard - Update event and user proto --- charts/cosmo/templates/dashboard/roles.yaml | 35 +- internal/cmd/user/get_events.go | 21 +- internal/dashboard/auth_handler.go | 2 +- internal/dashboard/auth_middleware.go | 54 +- internal/dashboard/event_watcher.go | 169 ++++++ internal/dashboard/root.go | 10 + internal/dashboard/server.go | 7 +- internal/dashboard/template_handler.go | 4 +- internal/dashboard/user_handler.go | 31 +- internal/dashboard/util.go | 4 + internal/dashboard/webauthn_handler.go | 2 +- internal/dashboard/workspace_handler.go | 4 +- pkg/apiconv/user.go | 65 ++- pkg/apiconv/user_test.go | 40 +- pkg/apiconv/workspace.go | 10 + pkg/cli/client.go | 2 +- pkg/kosmo/event.go | 29 +- .../event_service.connect.go | 105 ++++ .../user_service.connect.go | 26 + proto/gen/dashboard/v1alpha1/event.pb.go | 86 ++- .../dashboard/v1alpha1/event.pb.validate.go | 50 +- .../dashboard/v1alpha1/event_service.pb.go | 100 ++++ .../v1alpha1/event_service.pb.validate.go | 36 ++ proto/gen/dashboard/v1alpha1/user.pb.go | 87 ++- .../dashboard/v1alpha1/user.pb.validate.go | 34 -- .../gen/dashboard/v1alpha1/user_service.pb.go | 520 ++++++++++++------ .../v1alpha1/user_service.pb.validate.go | 273 +++++++++ proto/gen/dashboard/v1alpha1/workspace.pb.go | 165 +++--- .../v1alpha1/workspace.pb.validate.go | 29 + proto/gen/index.md | 367 +++++++----- .../dashboard/v1alpha1/event.proto | 17 +- .../dashboard/v1alpha1/event_service.proto | 16 + .../dashboard/v1alpha1/user.proto | 2 - .../dashboard/v1alpha1/user_service.proto | 15 + .../dashboard/v1alpha1/workspace.proto | 2 + 35 files changed, 1759 insertions(+), 660 deletions(-) create mode 100644 internal/dashboard/event_watcher.go create mode 100644 proto/gen/dashboard/v1alpha1/dashboardv1alpha1connect/event_service.connect.go create mode 100644 proto/gen/dashboard/v1alpha1/event_service.pb.go create mode 100644 proto/gen/dashboard/v1alpha1/event_service.pb.validate.go create mode 100644 proto/proto/dashboard-apis/dashboard/v1alpha1/event_service.proto diff --git a/charts/cosmo/templates/dashboard/roles.yaml b/charts/cosmo/templates/dashboard/roles.yaml index f1523e54..b9d4e2af 100644 --- a/charts/cosmo/templates/dashboard/roles.yaml +++ b/charts/cosmo/templates/dashboard/roles.yaml @@ -37,26 +37,6 @@ rules: resources: - workspaces - users - verbs: - - create - - delete - - patch - - update - - get - - list - - watch -- apiGroups: - - cosmo-workspace.github.io - resources: - - workspaces/status - - users/status - verbs: - - get - - list - - watch -- apiGroups: - - cosmo-workspace.github.io - resources: - instances - templates - clusterinstances @@ -70,27 +50,28 @@ rules: - list - watch - apiGroups: - - cosmo-workspace.github.io + - events.k8s.io resources: - - instances/status + - events verbs: - get - list - watch + - update - apiGroups: - - events.k8s.io + - authentication.k8s.io resources: - - events + - tokenreviews verbs: + - create - get - list - watch - apiGroups: - - authentication.k8s.io + - '*' resources: - - tokenreviews + - '*' verbs: - - create - get - list - watch diff --git a/internal/cmd/user/get_events.go b/internal/cmd/user/get_events.go index 9381bf1a..64b67459 100644 --- a/internal/cmd/user/get_events.go +++ b/internal/cmd/user/get_events.go @@ -7,8 +7,6 @@ import ( "time" "github.com/spf13/cobra" - "google.golang.org/protobuf/types/known/timestamppb" - "k8s.io/utils/ptr" "github.com/cosmo-workspace/cosmo/api/v1alpha1" "github.com/cosmo-workspace/cosmo/pkg/apiconv" @@ -88,35 +86,34 @@ func (o *GetEventsOption) RunE(cmd *cobra.Command, args []string) error { } func (o *GetEventsOption) GetEventsWithDashClient(ctx context.Context) ([]*dashv1alpha1.Event, error) { - req := &dashv1alpha1.GetUserRequest{ + req := &dashv1alpha1.GetEventsRequest{ UserName: o.UserName, - WithRaw: ptr.To(true), } c := o.CosmoDashClient - res, err := c.UserServiceClient.GetUser(ctx, cli.NewRequestWithToken(req, o.CliConfig)) + res, err := c.UserServiceClient.GetEvents(ctx, cli.NewRequestWithToken(req, o.CliConfig)) if err != nil { - return nil, fmt.Errorf("failed to get user: %w", err) + return nil, fmt.Errorf("failed to get events: %w", err) } o.Logr.DebugAll().Info("UserServiceClient.GetUser", "res", res) - return res.Msg.User.Events, nil + return res.Msg.Items, nil } func (o *GetEventsOption) OutputTable(w io.Writer, events []*dashv1alpha1.Event) { data := [][]string{} for _, v := range events { - data = append(data, []string{lastSeen(v.EventTime, v.Series), v.Type, v.Reason, regarding(v.Regarding), v.ReportingController, v.Note}) + data = append(data, []string{lastSeen(v.Series), v.Type, v.Reason, regarding(v.Regarding), v.ReportingController, v.Note}) } cli.OutputTable(w, []string{"LAST SEEN", "TYPE", "REASON", "OBJECT", "REPORTER", "MESSAGE"}, data) } -func lastSeen(t *timestamppb.Timestamp, series *dashv1alpha1.EventSeries) string { - if series != nil { - return fmt.Sprintf("%s (%vx)", time.Since(t.AsTime()).Round(time.Second), series.Count) +func lastSeen(series *dashv1alpha1.EventSeries) string { + if series.Count > 0 { + return fmt.Sprintf("%s (%vx)", time.Since(series.LastObservedTime.AsTime()).Round(time.Second), series.Count) } - return time.Since(t.AsTime()).Round(time.Second).String() + return time.Since(series.LastObservedTime.AsTime()).Round(time.Second).String() } func regarding(v *dashv1alpha1.ObjectReference) string { diff --git a/internal/dashboard/auth_handler.go b/internal/dashboard/auth_handler.go index 7c7fc455..b526d486 100644 --- a/internal/dashboard/auth_handler.go +++ b/internal/dashboard/auth_handler.go @@ -21,7 +21,7 @@ import ( func (s *Server) AuthServiceHandler(mux *http.ServeMux) { path, handler := dashboardv1alpha1connect.NewAuthServiceHandler(s) - mux.Handle(path, s.contextMiddleware(handler)) + mux.Handle(path, s.timeoutHandler(s.contextMiddleware(handler))) } func (s *Server) CreateSession(w http.ResponseWriter, r *http.Request, sesInfo session.Info) error { diff --git a/internal/dashboard/auth_middleware.go b/internal/dashboard/auth_middleware.go index db202685..32c45bff 100644 --- a/internal/dashboard/auth_middleware.go +++ b/internal/dashboard/auth_middleware.go @@ -7,7 +7,7 @@ import ( "net/http" "time" - "github.com/bufbuild/connect-go" + connect_go "github.com/bufbuild/connect-go" apierrs "k8s.io/apimachinery/pkg/api/errors" cosmov1alpha1 "github.com/cosmo-workspace/cosmo/api/v1alpha1" @@ -52,25 +52,47 @@ func (s *Server) contextMiddleware(next http.Handler) http.Handler { }) } -func (s *Server) authorizationInterceptor() connect.UnaryInterceptorFunc { - interceptor := func(next connect.UnaryFunc) connect.UnaryFunc { - return connect.UnaryFunc(func(ctx context.Context, req connect.AnyRequest) (connect.AnyResponse, error) { +type authorizationInterceptorFunc func(ctx context.Context) (loginUser *cosmov1alpha1.User, deadline time.Time, err error) - log := clog.FromContext(ctx).WithName("authorization") +// WrapUnary implements [Interceptor] with an authorization. +func (f authorizationInterceptorFunc) WrapUnary(next connect_go.UnaryFunc) connect_go.UnaryFunc { + return connect_go.UnaryFunc(func(ctx context.Context, req connect_go.AnyRequest) (connect_go.AnyResponse, error) { + log := clog.FromContext(ctx).WithName("unary authorization") - loginUser, deadline, err := s.verifyAndGetLoginUser(ctx) - if err != nil { - return nil, ErrResponse(log, err) - } + loginUser, deadline, err := f(ctx) + if err != nil { + return nil, ErrResponse(log, err) + } - ctx = newContextWithCaller(ctx, loginUser) - ctx, cancel := context.WithDeadline(ctx, deadline) - defer cancel() + ctx = newContextWithCaller(ctx, loginUser) + ctx, cancel := context.WithDeadline(ctx, deadline) + defer cancel() - return next(ctx, req) - }) - } - return connect.UnaryInterceptorFunc(interceptor) + return next(ctx, req) + }) +} + +// WrapStreamingClient implements [Interceptor] with a no-op. +func (f authorizationInterceptorFunc) WrapStreamingClient(next connect_go.StreamingClientFunc) connect_go.StreamingClientFunc { + return next +} + +// WrapStreamingHandler implements [Interceptor] with an authorization. +func (f authorizationInterceptorFunc) WrapStreamingHandler(next connect_go.StreamingHandlerFunc) connect_go.StreamingHandlerFunc { + return connect_go.StreamingHandlerFunc(func(ctx context.Context, conn connect_go.StreamingHandlerConn) error { + log := clog.FromContext(ctx).WithName("streaming handler authorization") + + loginUser, deadline, err := f(ctx) + if err != nil { + return ErrResponse(log, err) + } + + ctx = newContextWithCaller(ctx, loginUser) + ctx, cancel := context.WithDeadline(ctx, deadline) + defer cancel() + + return next(ctx, conn) + }) } func (s *Server) verifyAndGetLoginUser(ctx context.Context) (loginUser *cosmov1alpha1.User, deadline time.Time, err error) { diff --git a/internal/dashboard/event_watcher.go b/internal/dashboard/event_watcher.go new file mode 100644 index 00000000..72bef383 --- /dev/null +++ b/internal/dashboard/event_watcher.go @@ -0,0 +1,169 @@ +package dashboard + +import ( + "context" + "crypto/sha256" + "fmt" + "net/http" + "sync" + "time" + + eventv1 "k8s.io/api/events/v1" + ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/reconcile" + + connect_go "github.com/bufbuild/connect-go" + + cosmov1alpha1 "github.com/cosmo-workspace/cosmo/api/v1alpha1" + "github.com/cosmo-workspace/cosmo/pkg/apiconv" + "github.com/cosmo-workspace/cosmo/pkg/clog" + "github.com/cosmo-workspace/cosmo/pkg/kosmo" + dashv1alpha1 "github.com/cosmo-workspace/cosmo/proto/gen/dashboard/v1alpha1" + "github.com/cosmo-workspace/cosmo/proto/gen/dashboard/v1alpha1/dashboardv1alpha1connect" +) + +func (s *Server) StreamServiceHandler(mux *http.ServeMux) { + path, handler := dashboardv1alpha1connect.NewStreamServiceHandler(s, + connect_go.WithInterceptors(authorizationInterceptorFunc(s.verifyAndGetLoginUser)), + ) + mux.Handle(path, s.contextMiddleware(handler)) +} + +// StreamingEvents implements dashboardv1alpha1connect.UserServiceHandler. +func (s *Server) StreamingEvents(ctx context.Context, req *connect_go.Request[dashv1alpha1.GetEventsRequest], stream *connect_go.ServerStream[dashv1alpha1.GetEventsResponse]) error { + log := clog.FromContext(ctx).WithCaller() + log.Info("request", "req", req) + + if err := userAuthentication(ctx, req.Msg.UserName); err != nil { + return err + } + key := sha256.Sum256([]byte(stream.Conn().RequestHeader().Get("Cookie"))) + + ctx, cancel := context.WithTimeout(ctx, time.Second*300) + defer cancel() + + events, err := s.Klient.ListEvents(ctx, cosmov1alpha1.UserNamespace(req.Msg.UserName)) + if err != nil { + return ErrResponse(log, err) + } + + for _, v := range events { + if req.Msg.From != nil { + events := make([]eventv1.Event, 0) + if _, last := apiconv.EventObservedTime(v); last.After(req.Msg.From.AsTime()) { + events = append(events, v) + } + if len(events) > 0 { + res := &dashv1alpha1.GetEventsResponse{ + Items: apiconv.K2D_Events([]eventv1.Event{v}), + } + if err := stream.Send(res); err != nil { + log.Error(err, "send error") + return err + } + } + } + } + + eventCh := s.watcher.subscribe(ctx, fmt.Sprintf("%x", key)) + if eventCh == nil { + return fmt.Errorf("channel already exists") + } + + for { + select { + case <-ctx.Done(): + log.Debug().Info("ctx done") + return nil + case event, ok := <-eventCh: + if ok { + log.Debug().Info("delegating event", "user", req.Msg.UserName) + if event.Namespace != cosmov1alpha1.UserNamespace(req.Msg.UserName) { + continue + } + res := &dashv1alpha1.GetEventsResponse{ + Items: apiconv.K2D_Events([]eventv1.Event{event}), + } + log.Info("sending event", "event", event) + if err := stream.Send(res); err != nil { + log.Error(err, "send error") + return err + } + } else { + log.Debug().Info("event channel closed") + return nil + } + } + } +} + +type watcher struct { + Klient kosmo.Client + Log *clog.Logger + subscribers sync.Map + cancelSubscribe sync.Map + sendingLock sync.Mutex +} + +func (r *watcher) subscribe(ctx context.Context, key string) <-chan eventv1.Event { + log := r.Log.WithValues("key", key) + log.Debug().Info("create new channel") + + ctx, cancel := context.WithCancel(ctx) + preCancel, ok := r.cancelSubscribe.Load(key) + if ok { + preCancel.(context.CancelFunc)() + } + + ch := make(chan eventv1.Event) + r.subscribers.Store(key, ch) + r.cancelSubscribe.Store(key, cancel) + + go func(ch chan eventv1.Event) { + log.Debug().Info("wait channel closed...") + <-ctx.Done() + log.Debug().Info("close channel") + r.sendingLock.Lock() + defer r.sendingLock.Unlock() + r.subscribers.Delete(key) + r.cancelSubscribe.Delete(key) + close(ch) + }(ch) + + return ch +} + +func (r *watcher) Reconcile(ctx context.Context, req reconcile.Request) (reconcile.Result, error) { + log := r.Log.WithValues("req", req) + log.Debug().Info("start reconcile") + + var event eventv1.Event + if err := r.Klient.Get(ctx, req.NamespacedName, &event); err != nil { + return ctrl.Result{}, client.IgnoreNotFound(err) + } + if err := r.Klient.UpdateEventAnnotations(ctx, &event); err != nil { + log.Error(err, "failed to set regaining instance on event annotation") + } + + r.sendingLock.Lock() + defer r.sendingLock.Unlock() + r.subscribers.Range(func(key, value any) bool { + log.Debug().Info("send event to channel", "key", key, "event", event) + ch := value.(chan eventv1.Event) + ch <- event + return true + }) + log.Debug().Info("finish reconcile") + return reconcile.Result{}, nil +} + +func (r *watcher) SetupWithManager(mgr ctrl.Manager) error { + _, err := ctrl.NewControllerManagedBy(mgr). + For(&eventv1.Event{}). + Build(r) + if err != nil { + return err + } + return nil +} diff --git a/internal/dashboard/root.go b/internal/dashboard/root.go index 20280a22..69100ab8 100644 --- a/internal/dashboard/root.go +++ b/internal/dashboard/root.go @@ -253,6 +253,15 @@ func (o *options) RunE(cmd *cobra.Command, args []string) error { return fmt.Errorf("failed to create webauthn instance: %w", err) } + eventWatcher := &watcher{ + Log: clog.NewLogger(ctrl.Log.WithName("eventwatcher")), + Klient: kosmo.NewClient(mgr.GetClient()), + } + if err := eventWatcher.SetupWithManager(mgr); err != nil { + setupLog.Error(err, "unable to event watcher") + os.Exit(1) + } + serv := &Server{ Log: clog.NewLogger(ctrl.Log.WithName("dashboard")), Klient: klient, @@ -272,6 +281,7 @@ func (o *options) RunE(cmd *cobra.Command, args []string) error { http: &http.Server{Addr: fmt.Sprintf(":%d", o.ServerPort)}, sessionStore: nil, webauthn: wa, + watcher: eventWatcher, } if err := mgr.Add(serv); err != nil { diff --git a/internal/dashboard/server.go b/internal/dashboard/server.go index eaa2648c..7fb04b34 100644 --- a/internal/dashboard/server.go +++ b/internal/dashboard/server.go @@ -43,6 +43,8 @@ type Server struct { webauthn *webauthn.WebAuthn webauthnSessionMap sync.Map + + watcher *watcher } func (s *Server) setupRouter() { @@ -55,6 +57,7 @@ func (s *Server) setupRouter() { s.UserServiceHandler(mux) s.TemplateServiceHandler(mux) s.WorkspaceServiceHandler(mux) + s.StreamServiceHandler(mux) // setup serving static files mux.Handle("/", http.StripPrefix("/", http.FileServer(http.Dir(s.StaticFileDir)))) @@ -62,7 +65,7 @@ func (s *Server) setupRouter() { // setup middlewares for all routers to use HTTPRequestLogger and TimeoutHandler. // deadline of the Timeout handler takes precedence over any subsequent deadlines reqLogr := NewHTTPRequestLogger(s.Log) - s.http.Handler = reqLogr.Middleware(s.timeoutHandler(mux)) + s.http.Handler = reqLogr.Middleware(mux) } func (s *Server) setupSessionStore() { @@ -86,7 +89,7 @@ func (s *Server) timeoutHandler(next http.Handler) http.Handler { return http.TimeoutHandler(next, s.ResponseTimeout, "") } -// Start run server +// Start implements manager.Runnable func (s *Server) Start(ctx context.Context) error { s.http = &http.Server{ Addr: fmt.Sprintf(":%d", s.Port), diff --git a/internal/dashboard/template_handler.go b/internal/dashboard/template_handler.go index 8568f3d5..74cf8258 100644 --- a/internal/dashboard/template_handler.go +++ b/internal/dashboard/template_handler.go @@ -15,10 +15,10 @@ import ( func (s *Server) TemplateServiceHandler(mux *http.ServeMux) { path, handler := dashboardv1alpha1connect.NewTemplateServiceHandler(s, - connect_go.WithInterceptors(s.authorizationInterceptor()), + connect_go.WithInterceptors(authorizationInterceptorFunc(s.verifyAndGetLoginUser)), connect_go.WithInterceptors(s.validatorInterceptor()), ) - mux.Handle(path, s.contextMiddleware(handler)) + mux.Handle(path, s.timeoutHandler(s.contextMiddleware(handler))) } func (s *Server) GetWorkspaceTemplates(ctx context.Context, req *connect_go.Request[dashv1alpha1.GetWorkspaceTemplatesRequest]) (*connect_go.Response[dashv1alpha1.GetWorkspaceTemplatesResponse], error) { diff --git a/internal/dashboard/user_handler.go b/internal/dashboard/user_handler.go index 883216c7..31ddcc8a 100644 --- a/internal/dashboard/user_handler.go +++ b/internal/dashboard/user_handler.go @@ -17,10 +17,10 @@ import ( func (s *Server) UserServiceHandler(mux *http.ServeMux) { path, handler := dashboardv1alpha1connect.NewUserServiceHandler(s, - connect_go.WithInterceptors(s.authorizationInterceptor()), + connect_go.WithInterceptors(authorizationInterceptorFunc(s.verifyAndGetLoginUser)), connect_go.WithInterceptors(s.validatorInterceptor()), ) - mux.Handle(path, s.contextMiddleware(handler)) + mux.Handle(path, s.timeoutHandler(s.contextMiddleware(handler))) } func (s *Server) CreateUser(ctx context.Context, req *connect_go.Request[dashv1alpha1.CreateUserRequest]) (*connect_go.Response[dashv1alpha1.CreateUserResponse], error) { @@ -101,19 +101,36 @@ func (s *Server) GetUser(ctx context.Context, req *connect_go.Request[dashv1alph if err != nil { return nil, ErrResponse(log, err) } - events, err := s.Klient.ListEvents(ctx, cosmov1alpha1.UserNamespace(user.Name)) - if err != nil { - log.Error(err, "failed to list events", "user", user.Name) - } res := &dashv1alpha1.GetUserResponse{ User: apiconv.C2D_User(*user, apiconv.WithUserRaw(req.Msg.WithRaw)), } - res.User.Events = apiconv.K2D_Events(events) return connect_go.NewResponse(res), nil } +func (s *Server) GetEvents(ctx context.Context, req *connect_go.Request[dashv1alpha1.GetEventsRequest]) (*connect_go.Response[dashv1alpha1.GetEventsResponse], error) { + log := clog.FromContext(ctx).WithCaller() + log.Debug().Info("request", "req", req) + + if err := userAuthentication(ctx, req.Msg.UserName); err != nil { + return nil, ErrResponse(log, err) + } + + events, err := s.Klient.ListEvents(ctx, cosmov1alpha1.UserNamespace(req.Msg.UserName)) + if err != nil { + return nil, ErrResponse(log, err) + } + + res := &dashv1alpha1.GetEventsResponse{ + Items: apiconv.K2D_Events(events), + } + if len(res.Items) == 0 { + res.Message = "No items found" + } + return connect_go.NewResponse(res), nil +} + func (s *Server) DeleteUser(ctx context.Context, req *connect_go.Request[dashv1alpha1.DeleteUserRequest]) (*connect_go.Response[dashv1alpha1.DeleteUserResponse], error) { log := clog.FromContext(ctx).WithCaller() log.Debug().Info("request", "req", req) diff --git a/internal/dashboard/util.go b/internal/dashboard/util.go index 31c8ee01..78a9eee8 100644 --- a/internal/dashboard/util.go +++ b/internal/dashboard/util.go @@ -23,6 +23,10 @@ func (w *StoreStatusResponseWriter) StatusCode() int { return w.statusCode } +func (w *StoreStatusResponseWriter) Flush() { + w.ResponseWriter.(http.Flusher).Flush() +} + func (w *StoreStatusResponseWriter) WriteHeader(statusCode int) { w.statusCode = statusCode w.ResponseWriter.WriteHeader(statusCode) diff --git a/internal/dashboard/webauthn_handler.go b/internal/dashboard/webauthn_handler.go index 263cc19d..5ea94a8b 100644 --- a/internal/dashboard/webauthn_handler.go +++ b/internal/dashboard/webauthn_handler.go @@ -24,7 +24,7 @@ import ( func (s *Server) WebAuthnServiceHandler(mux *http.ServeMux) { path, handler := dashboardv1alpha1connect.NewWebAuthnServiceHandler(s, connect_go.WithInterceptors(s.validatorInterceptor())) - mux.Handle(path, s.contextMiddleware(handler)) + mux.Handle(path, s.timeoutHandler(s.contextMiddleware(handler))) } func (s *Server) storeWebAuthnSession(sess *webauthn.SessionData) { diff --git a/internal/dashboard/workspace_handler.go b/internal/dashboard/workspace_handler.go index 25b217bc..d2aebf62 100644 --- a/internal/dashboard/workspace_handler.go +++ b/internal/dashboard/workspace_handler.go @@ -15,10 +15,10 @@ import ( func (s *Server) WorkspaceServiceHandler(mux *http.ServeMux) { path, handler := dashboardv1alpha1connect.NewWorkspaceServiceHandler(s, - connect_go.WithInterceptors(s.authorizationInterceptor()), + connect_go.WithInterceptors(authorizationInterceptorFunc(s.verifyAndGetLoginUser)), connect_go.WithInterceptors(s.validatorInterceptor()), ) - mux.Handle(path, s.contextMiddleware(handler)) + mux.Handle(path, s.timeoutHandler(s.contextMiddleware(handler))) } func (s *Server) CreateWorkspace(ctx context.Context, req *connect_go.Request[dashv1alpha1.CreateWorkspaceRequest]) (*connect_go.Response[dashv1alpha1.CreateWorkspaceResponse], error) { diff --git a/pkg/apiconv/user.go b/pkg/apiconv/user.go index 69788f81..8fd1df44 100644 --- a/pkg/apiconv/user.go +++ b/pkg/apiconv/user.go @@ -5,11 +5,13 @@ import ( "regexp" "sort" "strings" + "time" "google.golang.org/protobuf/types/known/timestamppb" eventsv1 "k8s.io/api/events/v1" cosmov1alpha1 "github.com/cosmo-workspace/cosmo/api/v1alpha1" + "github.com/cosmo-workspace/cosmo/pkg/kubeutil" dashv1alpha1 "github.com/cosmo-workspace/cosmo/proto/gen/dashboard/v1alpha1" ) @@ -153,29 +155,22 @@ func D2S_UserAddons(addons []*dashv1alpha1.UserAddon) []string { func K2D_Events(events []eventsv1.Event) []*dashv1alpha1.Event { es := make([]*dashv1alpha1.Event, len(events)) for i, v := range events { - var eventTime *timestamppb.Timestamp - if v.EventTime.Year() != 1 { - eventTime = timestamppb.New(v.EventTime.Time) - } else { - eventTime = timestamppb.New(v.DeprecatedLastTimestamp.Time) - } + first, last := EventObservedTime(v) - var count int32 - if v.Series != nil { - count = v.Series.Count - } else { - count = v.DeprecatedCount + userName := kubeutil.GetAnnotation(&v, cosmov1alpha1.EventAnnKeyUserName) + if userName == "" { + userName = cosmov1alpha1.UserNameByNamespace(v.Namespace) } - var lastTime *timestamppb.Timestamp - if v.Series != nil { - lastTime = timestamppb.New(v.Series.LastObservedTime.Time) - } else { - lastTime = timestamppb.New(v.DeprecatedLastTimestamp.Time) + var wsName *string + if instName := kubeutil.GetAnnotation(&v, cosmov1alpha1.EventAnnKeyInstanceName); instName != "" { + wsName = &instName } e := &dashv1alpha1.Event{ - EventTime: eventTime, + Id: v.Name, + User: userName, + EventTime: timestamppb.New(first), Reason: v.Reason, Note: v.Note, Type: v.Type, @@ -186,14 +181,38 @@ func K2D_Events(events []eventsv1.Event) []*dashv1alpha1.Event { Namespace: v.Regarding.Namespace, }, ReportingController: v.ReportingController, - } - if count > 1 { - e.Series = &dashv1alpha1.EventSeries{ - Count: count, - LastObservedTime: lastTime, - } + RegardingWorkspace: wsName, + Series: &dashv1alpha1.EventSeries{ + Count: EventCount(v), + LastObservedTime: timestamppb.New(last), + }, } es[i] = e } return es } + +func EventCount(v eventsv1.Event) int32 { + if v.Series != nil { + return v.Series.Count + } else { + return v.DeprecatedCount + } +} + +func EventObservedTime(v eventsv1.Event) (first time.Time, last time.Time) { + if v.EventTime.Year() != 1 { + first = v.EventTime.Time + } else { + first = v.DeprecatedFirstTimestamp.Time + } + if v.Series != nil { + last = v.Series.LastObservedTime.Time + } else { + last = v.DeprecatedLastTimestamp.Time + } + if last.Before(first) { + return first, first + } + return first, last +} diff --git a/pkg/apiconv/user_test.go b/pkg/apiconv/user_test.go index 197e84b4..4fe114fc 100644 --- a/pkg/apiconv/user_test.go +++ b/pkg/apiconv/user_test.go @@ -734,6 +734,10 @@ func TestK2D_Events(t *testing.T) { Namespace: "cosmo-user-tom", ResourceVersion: "1043545", UID: "d2f21050-ae78-4894-b6b1-19fe3918b7c2", + Annotations: map[string]string{ + cosmov1alpha1.EventAnnKeyInstanceName: "aaa", + cosmov1alpha1.EventAnnKeyUserName: "bbb", + }, }, Note: "Stopping container code-server", Reason: "Killing", @@ -754,6 +758,8 @@ func TestK2D_Events(t *testing.T) { }, want: []*dashv1alpha1.Event{ { + Id: "ws1.17d13738ea85aac8", + User: "tom", EventTime: timestamppb.New(timeParse("2024-05-20T14:00:50Z").Time), Type: "Normal", Note: "successfully reconciled. instance synced", @@ -765,8 +771,14 @@ func TestK2D_Events(t *testing.T) { Namespace: "cosmo-user-tom", }, ReportingController: "cosmo-workspace-controller", + Series: &dashv1alpha1.EventSeries{ + Count: 1, + LastObservedTime: timestamppb.New(timeParse("2024-05-20T14:00:50Z").Time), + }, }, { + Id: "ws1.17d13738ecc558d0", + User: "tom", EventTime: timestamppb.New(timeParse("2024-05-20T14:00:50Z").Time), Type: "Normal", Note: "Deployment ws1-workspace is not desired state, synced", @@ -777,9 +789,15 @@ func TestK2D_Events(t *testing.T) { Name: "ws1", Namespace: "cosmo-user-tom", }, + Series: &dashv1alpha1.EventSeries{ + Count: 1, + LastObservedTime: timestamppb.New(timeParse("2024-05-20T14:00:50Z").Time), + }, ReportingController: "cosmo-instance-controller", }, { + Id: "ws1-workspace.17d13738edffd9f0", + User: "tom", EventTime: timestamppb.New(timeParse("2024-05-20T14:00:50Z").Time), Type: "Normal", Note: "Scaled down replica set ws1-workspace-66b8cd6764 to 0 from 1", @@ -790,9 +808,16 @@ func TestK2D_Events(t *testing.T) { Name: "ws1-workspace", Namespace: "cosmo-user-tom", }, + Series: &dashv1alpha1.EventSeries{ + Count: 1, + LastObservedTime: timestamppb.New(timeParse("2024-05-20T14:00:50Z").Time), + }, + ReportingController: "deployment-controller", }, { + Id: "ws1-workspace-66b8cd6764.17d13738ef8a33c4", + User: "tom", EventTime: timestamppb.New(timeParse("2024-05-20T14:00:50Z").Time), Type: "Normal", Note: "Deleted pod: ws1-workspace-66b8cd6764-fz2k7", @@ -803,9 +828,14 @@ func TestK2D_Events(t *testing.T) { Name: "ws1-workspace-66b8cd6764", Namespace: "cosmo-user-tom", }, + Series: &dashv1alpha1.EventSeries{ + Count: 1, + LastObservedTime: timestamppb.New(timeParse("2024-05-20T14:00:50Z").Time), + }, ReportingController: "replicaset-controller", }, { + Id: "ws1-workspace-66b8cd6764-fz2k7.17d13738efcc7a13", EventTime: timestamppb.New(timeParse("2024-05-20T14:00:50Z").Time), Type: "Normal", Note: "Stopping container code-server", @@ -816,7 +846,13 @@ func TestK2D_Events(t *testing.T) { Name: "ws1-workspace-66b8cd6764-fz2k7", Namespace: "cosmo-user-tom", }, + Series: &dashv1alpha1.EventSeries{ + Count: 1, + LastObservedTime: timestamppb.New(timeParse("2024-05-20T14:00:50Z").Time), + }, ReportingController: "kubelet", + RegardingWorkspace: ptr.To("aaa"), + User: "bbb", }, }, }, @@ -838,7 +874,7 @@ func TestK2D_Events(t *testing.T) { ReportingController: "cosmo-workspace-controller", Series: &eventsv1.EventSeries{ Count: 3, - LastObservedTime: metav1.MicroTime(timeParse("2024-05-20T13:59:50Z")), + LastObservedTime: metav1.MicroTime(timeParse("2024-05-20T14:30:50Z")), }, }, }, @@ -858,7 +894,7 @@ func TestK2D_Events(t *testing.T) { ReportingController: "cosmo-workspace-controller", Series: &dashv1alpha1.EventSeries{ Count: 3, - LastObservedTime: timestamppb.New(timeParse("2024-05-20T13:59:50Z").Time), + LastObservedTime: timestamppb.New(timeParse("2024-05-20T14:30:50Z").Time), }, }, }, diff --git a/pkg/apiconv/workspace.go b/pkg/apiconv/workspace.go index 550c1ff2..7d5b35ef 100644 --- a/pkg/apiconv/workspace.go +++ b/pkg/apiconv/workspace.go @@ -1,9 +1,13 @@ package apiconv import ( + "time" + + "google.golang.org/protobuf/types/known/timestamppb" "k8s.io/utils/ptr" cosmov1alpha1 "github.com/cosmo-workspace/cosmo/api/v1alpha1" + "github.com/cosmo-workspace/cosmo/pkg/kubeutil" dashv1alpha1 "github.com/cosmo-workspace/cosmo/proto/gen/dashboard/v1alpha1" ) @@ -45,6 +49,12 @@ func C2D_Workspace(ws cosmov1alpha1.Workspace, opts ...WorkspaceConvertOptions) MainUrl: ws.Status.URLs[cosmov1alpha1.MainRuleKey(ws.Status.Config)], }, } + + t, err := time.Parse(time.RFC3339, kubeutil.GetAnnotation(&ws, cosmov1alpha1.WorkspaceAnnKeyLastStartedAt)) + if err == nil { + d.Status.LastStartedAt = timestamppb.New(t) + } + for _, opt := range opts { opt(&ws, d) } diff --git a/pkg/cli/client.go b/pkg/cli/client.go index c3e52ca8..3264b82f 100644 --- a/pkg/cli/client.go +++ b/pkg/cli/client.go @@ -70,7 +70,7 @@ func ConnectErrorHandler(rcmd RunCommand) func(*cobra.Command, []string) error { rcmd.Logger().Debug().Info("connectErr", "code", connectErr.Code(), "message", connectErr.Message()) if connectErr.Code() == connect.CodeUnknown { if strings.Index(connectErr.Message(), fmt.Sprintf("%d", http.StatusFound)) > 0 { - return fmt.Errorf("session has been expired: please login again") + return fmt.Errorf("session has been expired: please login again by \"cosmoctl login --again\"") } return fmt.Errorf("%w: session might have been expired", err) } diff --git a/pkg/kosmo/event.go b/pkg/kosmo/event.go index 0f238f74..08288707 100644 --- a/pkg/kosmo/event.go +++ b/pkg/kosmo/event.go @@ -16,6 +16,7 @@ import ( cosmov1alpha1 "github.com/cosmo-workspace/cosmo/api/v1alpha1" "github.com/cosmo-workspace/cosmo/pkg/clog" + "github.com/cosmo-workspace/cosmo/pkg/kubeutil" ) func (c *Client) ListEvents(ctx context.Context, namespace string) ([]eventsv1.Event, error) { @@ -26,7 +27,7 @@ func (c *Client) ListEvents(ctx context.Context, namespace string) ([]eventsv1.E return nil, apierrs.NewInternalError(fmt.Errorf("failed to list Event: %w", err)) } for _, v := range events.Items { - err := c.SetRegardingInstanceOnAnnotation(ctx, v.DeepCopy()) + err := c.UpdateEventAnnotations(ctx, v.DeepCopy()) if err != nil { log.Debug().Info("failed to cache instance name on event annotation", "error", err, "namespace", namespace, "event", v.Name) } @@ -36,14 +37,15 @@ func (c *Client) ListEvents(ctx context.Context, namespace string) ([]eventsv1.E return events.Items, nil } -func (c *Client) SetRegardingInstanceOnAnnotation(ctx context.Context, event *eventsv1.Event) error { +func (c *Client) UpdateEventAnnotations(ctx context.Context, event *eventsv1.Event) error { log := clog.FromContext(ctx).WithCaller() ann := event.GetAnnotations() if ann != nil { - v := ann[cosmov1alpha1.EventAnnKeyInstanceName] - if v != "" { - // found instane name cached on event annotation + instName := ann[cosmov1alpha1.EventAnnKeyInstanceName] + userName := ann[cosmov1alpha1.EventAnnKeyUserName] + if instName != "" && userName != "" { + // annotation is expected return nil } } else { @@ -62,23 +64,14 @@ func (c *Client) SetRegardingInstanceOnAnnotation(ctx context.Context, event *ev return fmt.Errorf("failed to fetch regarding object: %w", err) } - label := obj.GetLabels() - if label == nil { - return nil // regarding object has no label - } - v := label[cosmov1alpha1.LabelKeyInstanceName] - if v == "" { - return nil // label has no instance name - } - - // found instance name on label. so we cache it on event annotation - ann[cosmov1alpha1.EventAnnKeyInstanceName] = v + ann[cosmov1alpha1.EventAnnKeyInstanceName] = kubeutil.GetLabel(&obj, cosmov1alpha1.LabelKeyInstanceName) + ann[cosmov1alpha1.EventAnnKeyUserName] = cosmov1alpha1.UserNameByNamespace(event.Namespace) event.SetAnnotations(ann) if err := c.Update(ctx, event); err != nil { - return fmt.Errorf("failed to cache instance name on event annotation: %w", err) + return fmt.Errorf("failed to cache on event annotation: %w", err) } - log.Info("cached instance name on event annotation", "event", event) + log.Info("cached on event annotation", "event", event) return nil } diff --git a/proto/gen/dashboard/v1alpha1/dashboardv1alpha1connect/event_service.connect.go b/proto/gen/dashboard/v1alpha1/dashboardv1alpha1connect/event_service.connect.go new file mode 100644 index 00000000..45f34475 --- /dev/null +++ b/proto/gen/dashboard/v1alpha1/dashboardv1alpha1connect/event_service.connect.go @@ -0,0 +1,105 @@ +// +//Cosmo Dashboard API +//Manipulate cosmo dashboard resource API + +// Code generated by protoc-gen-connect-go. DO NOT EDIT. +// +// Source: dashboard/v1alpha1/event_service.proto + +package dashboardv1alpha1connect + +import ( + context "context" + errors "errors" + connect_go "github.com/bufbuild/connect-go" + v1alpha1 "github.com/cosmo-workspace/cosmo/proto/gen/dashboard/v1alpha1" + http "net/http" + strings "strings" +) + +// This is a compile-time assertion to ensure that this generated file and the connect package are +// compatible. If you get a compiler error that this constant is not defined, this code was +// generated with a version of connect newer than the one compiled into your binary. You can fix the +// problem by either regenerating this code with an older version of connect or updating the connect +// version compiled into your binary. +const _ = connect_go.IsAtLeastVersion0_1_0 + +const ( + // StreamServiceName is the fully-qualified name of the StreamService service. + StreamServiceName = "dashboard.v1alpha1.StreamService" +) + +// These constants are the fully-qualified names of the RPCs defined in this package. They're +// exposed at runtime as Spec.Procedure and as the final two segments of the HTTP route. +// +// Note that these are different from the fully-qualified method names used by +// google.golang.org/protobuf/reflect/protoreflect. To convert from these constants to +// reflection-formatted method names, remove the leading slash and convert the remaining slash to a +// period. +const ( + // StreamServiceStreamingEventsProcedure is the fully-qualified name of the StreamService's + // StreamingEvents RPC. + StreamServiceStreamingEventsProcedure = "/dashboard.v1alpha1.StreamService/StreamingEvents" +) + +// StreamServiceClient is a client for the dashboard.v1alpha1.StreamService service. +type StreamServiceClient interface { + // Streaming new events for user + StreamingEvents(context.Context, *connect_go.Request[v1alpha1.GetEventsRequest]) (*connect_go.ServerStreamForClient[v1alpha1.GetEventsResponse], error) +} + +// NewStreamServiceClient constructs a client for the dashboard.v1alpha1.StreamService service. By +// default, it uses the Connect protocol with the binary Protobuf Codec, asks for gzipped responses, +// and sends uncompressed requests. To use the gRPC or gRPC-Web protocols, supply the +// connect.WithGRPC() or connect.WithGRPCWeb() options. +// +// The URL supplied here should be the base URL for the Connect or gRPC server (for example, +// http://api.acme.com or https://acme.com/grpc). +func NewStreamServiceClient(httpClient connect_go.HTTPClient, baseURL string, opts ...connect_go.ClientOption) StreamServiceClient { + baseURL = strings.TrimRight(baseURL, "/") + return &streamServiceClient{ + streamingEvents: connect_go.NewClient[v1alpha1.GetEventsRequest, v1alpha1.GetEventsResponse]( + httpClient, + baseURL+StreamServiceStreamingEventsProcedure, + opts..., + ), + } +} + +// streamServiceClient implements StreamServiceClient. +type streamServiceClient struct { + streamingEvents *connect_go.Client[v1alpha1.GetEventsRequest, v1alpha1.GetEventsResponse] +} + +// StreamingEvents calls dashboard.v1alpha1.StreamService.StreamingEvents. +func (c *streamServiceClient) StreamingEvents(ctx context.Context, req *connect_go.Request[v1alpha1.GetEventsRequest]) (*connect_go.ServerStreamForClient[v1alpha1.GetEventsResponse], error) { + return c.streamingEvents.CallServerStream(ctx, req) +} + +// StreamServiceHandler is an implementation of the dashboard.v1alpha1.StreamService service. +type StreamServiceHandler interface { + // Streaming new events for user + StreamingEvents(context.Context, *connect_go.Request[v1alpha1.GetEventsRequest], *connect_go.ServerStream[v1alpha1.GetEventsResponse]) error +} + +// NewStreamServiceHandler builds an HTTP handler from the service implementation. It returns the +// path on which to mount the handler and the handler itself. +// +// By default, handlers support the Connect, gRPC, and gRPC-Web protocols with the binary Protobuf +// and JSON codecs. They also support gzip compression. +func NewStreamServiceHandler(svc StreamServiceHandler, opts ...connect_go.HandlerOption) (string, http.Handler) { + mux := http.NewServeMux() + mux.Handle(StreamServiceStreamingEventsProcedure, connect_go.NewServerStreamHandler( + StreamServiceStreamingEventsProcedure, + svc.StreamingEvents, + opts..., + )) + return "/dashboard.v1alpha1.StreamService/", mux +} + +// UnimplementedStreamServiceHandler returns CodeUnimplemented from all methods. +type UnimplementedStreamServiceHandler struct{} + +func (UnimplementedStreamServiceHandler) StreamingEvents(context.Context, *connect_go.Request[v1alpha1.GetEventsRequest], *connect_go.ServerStream[v1alpha1.GetEventsResponse]) error { + return connect_go.NewError(connect_go.CodeUnimplemented, errors.New("dashboard.v1alpha1.StreamService.StreamingEvents is not implemented")) +} diff --git a/proto/gen/dashboard/v1alpha1/dashboardv1alpha1connect/user_service.connect.go b/proto/gen/dashboard/v1alpha1/dashboardv1alpha1connect/user_service.connect.go index 5bbf7cda..59ab8051 100644 --- a/proto/gen/dashboard/v1alpha1/dashboardv1alpha1connect/user_service.connect.go +++ b/proto/gen/dashboard/v1alpha1/dashboardv1alpha1connect/user_service.connect.go @@ -43,6 +43,8 @@ const ( UserServiceGetUserProcedure = "/dashboard.v1alpha1.UserService/GetUser" // UserServiceGetUsersProcedure is the fully-qualified name of the UserService's GetUsers RPC. UserServiceGetUsersProcedure = "/dashboard.v1alpha1.UserService/GetUsers" + // UserServiceGetEventsProcedure is the fully-qualified name of the UserService's GetEvents RPC. + UserServiceGetEventsProcedure = "/dashboard.v1alpha1.UserService/GetEvents" // UserServiceCreateUserProcedure is the fully-qualified name of the UserService's CreateUser RPC. UserServiceCreateUserProcedure = "/dashboard.v1alpha1.UserService/CreateUser" // UserServiceUpdateUserDisplayNameProcedure is the fully-qualified name of the UserService's @@ -67,6 +69,8 @@ type UserServiceClient interface { GetUser(context.Context, *connect_go.Request[v1alpha1.GetUserRequest]) (*connect_go.Response[v1alpha1.GetUserResponse], error) // Returns an array of User model GetUsers(context.Context, *connect_go.Request[v1alpha1.GetUsersRequest]) (*connect_go.Response[v1alpha1.GetUsersResponse], error) + // Returns events for User + GetEvents(context.Context, *connect_go.Request[v1alpha1.GetEventsRequest]) (*connect_go.Response[v1alpha1.GetEventsResponse], error) // Create a new User CreateUser(context.Context, *connect_go.Request[v1alpha1.CreateUserRequest]) (*connect_go.Response[v1alpha1.CreateUserResponse], error) // Update user display name @@ -104,6 +108,11 @@ func NewUserServiceClient(httpClient connect_go.HTTPClient, baseURL string, opts baseURL+UserServiceGetUsersProcedure, opts..., ), + getEvents: connect_go.NewClient[v1alpha1.GetEventsRequest, v1alpha1.GetEventsResponse]( + httpClient, + baseURL+UserServiceGetEventsProcedure, + opts..., + ), createUser: connect_go.NewClient[v1alpha1.CreateUserRequest, v1alpha1.CreateUserResponse]( httpClient, baseURL+UserServiceCreateUserProcedure, @@ -137,6 +146,7 @@ type userServiceClient struct { deleteUser *connect_go.Client[v1alpha1.DeleteUserRequest, v1alpha1.DeleteUserResponse] getUser *connect_go.Client[v1alpha1.GetUserRequest, v1alpha1.GetUserResponse] getUsers *connect_go.Client[v1alpha1.GetUsersRequest, v1alpha1.GetUsersResponse] + getEvents *connect_go.Client[v1alpha1.GetEventsRequest, v1alpha1.GetEventsResponse] createUser *connect_go.Client[v1alpha1.CreateUserRequest, v1alpha1.CreateUserResponse] updateUserDisplayName *connect_go.Client[v1alpha1.UpdateUserDisplayNameRequest, v1alpha1.UpdateUserDisplayNameResponse] updateUserPassword *connect_go.Client[v1alpha1.UpdateUserPasswordRequest, v1alpha1.UpdateUserPasswordResponse] @@ -159,6 +169,11 @@ func (c *userServiceClient) GetUsers(ctx context.Context, req *connect_go.Reques return c.getUsers.CallUnary(ctx, req) } +// GetEvents calls dashboard.v1alpha1.UserService.GetEvents. +func (c *userServiceClient) GetEvents(ctx context.Context, req *connect_go.Request[v1alpha1.GetEventsRequest]) (*connect_go.Response[v1alpha1.GetEventsResponse], error) { + return c.getEvents.CallUnary(ctx, req) +} + // CreateUser calls dashboard.v1alpha1.UserService.CreateUser. func (c *userServiceClient) CreateUser(ctx context.Context, req *connect_go.Request[v1alpha1.CreateUserRequest]) (*connect_go.Response[v1alpha1.CreateUserResponse], error) { return c.createUser.CallUnary(ctx, req) @@ -192,6 +207,8 @@ type UserServiceHandler interface { GetUser(context.Context, *connect_go.Request[v1alpha1.GetUserRequest]) (*connect_go.Response[v1alpha1.GetUserResponse], error) // Returns an array of User model GetUsers(context.Context, *connect_go.Request[v1alpha1.GetUsersRequest]) (*connect_go.Response[v1alpha1.GetUsersResponse], error) + // Returns events for User + GetEvents(context.Context, *connect_go.Request[v1alpha1.GetEventsRequest]) (*connect_go.Response[v1alpha1.GetEventsResponse], error) // Create a new User CreateUser(context.Context, *connect_go.Request[v1alpha1.CreateUserRequest]) (*connect_go.Response[v1alpha1.CreateUserResponse], error) // Update user display name @@ -226,6 +243,11 @@ func NewUserServiceHandler(svc UserServiceHandler, opts ...connect_go.HandlerOpt svc.GetUsers, opts..., )) + mux.Handle(UserServiceGetEventsProcedure, connect_go.NewUnaryHandler( + UserServiceGetEventsProcedure, + svc.GetEvents, + opts..., + )) mux.Handle(UserServiceCreateUserProcedure, connect_go.NewUnaryHandler( UserServiceCreateUserProcedure, svc.CreateUser, @@ -269,6 +291,10 @@ func (UnimplementedUserServiceHandler) GetUsers(context.Context, *connect_go.Req return nil, connect_go.NewError(connect_go.CodeUnimplemented, errors.New("dashboard.v1alpha1.UserService.GetUsers is not implemented")) } +func (UnimplementedUserServiceHandler) GetEvents(context.Context, *connect_go.Request[v1alpha1.GetEventsRequest]) (*connect_go.Response[v1alpha1.GetEventsResponse], error) { + return nil, connect_go.NewError(connect_go.CodeUnimplemented, errors.New("dashboard.v1alpha1.UserService.GetEvents is not implemented")) +} + func (UnimplementedUserServiceHandler) CreateUser(context.Context, *connect_go.Request[v1alpha1.CreateUserRequest]) (*connect_go.Response[v1alpha1.CreateUserResponse], error) { return nil, connect_go.NewError(connect_go.CodeUnimplemented, errors.New("dashboard.v1alpha1.UserService.CreateUser is not implemented")) } diff --git a/proto/gen/dashboard/v1alpha1/event.pb.go b/proto/gen/dashboard/v1alpha1/event.pb.go index 1d1ff0d7..10a682e2 100644 --- a/proto/gen/dashboard/v1alpha1/event.pb.go +++ b/proto/gen/dashboard/v1alpha1/event.pb.go @@ -30,13 +30,16 @@ type Event struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - EventTime *timestamppb.Timestamp `protobuf:"bytes,1,opt,name=eventTime,proto3" json:"eventTime,omitempty"` - Type string `protobuf:"bytes,2,opt,name=type,proto3" json:"type,omitempty"` - Note string `protobuf:"bytes,3,opt,name=note,proto3" json:"note,omitempty"` - Reason string `protobuf:"bytes,4,opt,name=reason,proto3" json:"reason,omitempty"` - Regarding *ObjectReference `protobuf:"bytes,5,opt,name=regarding,proto3" json:"regarding,omitempty"` - ReportingController string `protobuf:"bytes,6,opt,name=reportingController,proto3" json:"reportingController,omitempty"` - Series *EventSeries `protobuf:"bytes,7,opt,name=series,proto3,oneof" json:"series,omitempty"` + Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` + User string `protobuf:"bytes,2,opt,name=user,proto3" json:"user,omitempty"` + EventTime *timestamppb.Timestamp `protobuf:"bytes,3,opt,name=eventTime,proto3" json:"eventTime,omitempty"` + Type string `protobuf:"bytes,4,opt,name=type,proto3" json:"type,omitempty"` + Note string `protobuf:"bytes,5,opt,name=note,proto3" json:"note,omitempty"` + Reason string `protobuf:"bytes,6,opt,name=reason,proto3" json:"reason,omitempty"` + Regarding *ObjectReference `protobuf:"bytes,7,opt,name=regarding,proto3" json:"regarding,omitempty"` + ReportingController string `protobuf:"bytes,8,opt,name=reportingController,proto3" json:"reportingController,omitempty"` + Series *EventSeries `protobuf:"bytes,9,opt,name=series,proto3" json:"series,omitempty"` + RegardingWorkspace *string `protobuf:"bytes,10,opt,name=regardingWorkspace,proto3,oneof" json:"regardingWorkspace,omitempty"` } func (x *Event) Reset() { @@ -71,6 +74,20 @@ func (*Event) Descriptor() ([]byte, []int) { return file_dashboard_v1alpha1_event_proto_rawDescGZIP(), []int{0} } +func (x *Event) GetId() string { + if x != nil { + return x.Id + } + return "" +} + +func (x *Event) GetUser() string { + if x != nil { + return x.User + } + return "" +} + func (x *Event) GetEventTime() *timestamppb.Timestamp { if x != nil { return x.EventTime @@ -120,6 +137,13 @@ func (x *Event) GetSeries() *EventSeries { return nil } +func (x *Event) GetRegardingWorkspace() string { + if x != nil && x.RegardingWorkspace != nil { + return *x.RegardingWorkspace + } + return "" +} + type EventSeries struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -254,27 +278,33 @@ var file_dashboard_v1alpha1_event_proto_rawDesc = []byte{ 0x12, 0x12, 0x64, 0x61, 0x73, 0x68, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x1a, 0x1f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xbf, 0x02, 0x0a, 0x05, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, - 0x38, 0x0a, 0x09, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x54, 0x69, 0x6d, 0x65, 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, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, - 0x65, 0x76, 0x65, 0x6e, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, - 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x12, 0x0a, - 0x04, 0x6e, 0x6f, 0x74, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x6f, 0x74, - 0x65, 0x12, 0x16, 0x0a, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x12, 0x41, 0x0a, 0x09, 0x72, 0x65, 0x67, - 0x61, 0x72, 0x64, 0x69, 0x6e, 0x67, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x64, - 0x61, 0x73, 0x68, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, - 0x31, 0x2e, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x52, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, - 0x65, 0x52, 0x09, 0x72, 0x65, 0x67, 0x61, 0x72, 0x64, 0x69, 0x6e, 0x67, 0x12, 0x30, 0x0a, 0x13, - 0x72, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, - 0x6c, 0x65, 0x72, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x13, 0x72, 0x65, 0x70, 0x6f, 0x72, - 0x74, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x12, 0x3c, - 0x0a, 0x06, 0x73, 0x65, 0x72, 0x69, 0x65, 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, - 0x2e, 0x64, 0x61, 0x73, 0x68, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, - 0x68, 0x61, 0x31, 0x2e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x53, 0x65, 0x72, 0x69, 0x65, 0x73, 0x48, - 0x00, 0x52, 0x06, 0x73, 0x65, 0x72, 0x69, 0x65, 0x73, 0x88, 0x01, 0x01, 0x42, 0x09, 0x0a, 0x07, - 0x5f, 0x73, 0x65, 0x72, 0x69, 0x65, 0x73, 0x22, 0x6b, 0x0a, 0x0b, 0x45, 0x76, 0x65, 0x6e, 0x74, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x9f, 0x03, 0x0a, 0x05, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, + 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, + 0x12, 0x0a, 0x04, 0x75, 0x73, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x75, + 0x73, 0x65, 0x72, 0x12, 0x38, 0x0a, 0x09, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x54, 0x69, 0x6d, 0x65, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, + 0x6d, 0x70, 0x52, 0x09, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x12, 0x0a, + 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, 0x70, + 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x6f, 0x74, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x04, 0x6e, 0x6f, 0x74, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x18, + 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x12, 0x41, 0x0a, + 0x09, 0x72, 0x65, 0x67, 0x61, 0x72, 0x64, 0x69, 0x6e, 0x67, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x23, 0x2e, 0x64, 0x61, 0x73, 0x68, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x2e, 0x76, 0x31, 0x61, + 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x52, 0x65, 0x66, 0x65, + 0x72, 0x65, 0x6e, 0x63, 0x65, 0x52, 0x09, 0x72, 0x65, 0x67, 0x61, 0x72, 0x64, 0x69, 0x6e, 0x67, + 0x12, 0x30, 0x0a, 0x13, 0x72, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, + 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x13, 0x72, + 0x65, 0x70, 0x6f, 0x72, 0x74, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, + 0x65, 0x72, 0x12, 0x37, 0x0a, 0x06, 0x73, 0x65, 0x72, 0x69, 0x65, 0x73, 0x18, 0x09, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x64, 0x61, 0x73, 0x68, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x2e, 0x76, + 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x53, 0x65, 0x72, + 0x69, 0x65, 0x73, 0x52, 0x06, 0x73, 0x65, 0x72, 0x69, 0x65, 0x73, 0x12, 0x33, 0x0a, 0x12, 0x72, + 0x65, 0x67, 0x61, 0x72, 0x64, 0x69, 0x6e, 0x67, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, + 0x65, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x12, 0x72, 0x65, 0x67, 0x61, 0x72, + 0x64, 0x69, 0x6e, 0x67, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x88, 0x01, 0x01, + 0x42, 0x15, 0x0a, 0x13, 0x5f, 0x72, 0x65, 0x67, 0x61, 0x72, 0x64, 0x69, 0x6e, 0x67, 0x57, 0x6f, + 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x22, 0x6b, 0x0a, 0x0b, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x53, 0x65, 0x72, 0x69, 0x65, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x46, 0x0a, 0x10, 0x6c, 0x61, 0x73, 0x74, 0x4f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x54, 0x69, 0x6d, 0x65, diff --git a/proto/gen/dashboard/v1alpha1/event.pb.validate.go b/proto/gen/dashboard/v1alpha1/event.pb.validate.go index f7fd46c6..0c4bb27f 100644 --- a/proto/gen/dashboard/v1alpha1/event.pb.validate.go +++ b/proto/gen/dashboard/v1alpha1/event.pb.validate.go @@ -56,6 +56,10 @@ func (m *Event) validate(all bool) error { var errors []error + // no validation rules for Id + + // no validation rules for User + if all { switch v := interface{}(m.GetEventTime()).(type) { case interface{ ValidateAll() error }: @@ -122,37 +126,37 @@ func (m *Event) validate(all bool) error { // no validation rules for ReportingController - if m.Series != nil { - - if all { - switch v := interface{}(m.GetSeries()).(type) { - case interface{ ValidateAll() error }: - if err := v.ValidateAll(); err != nil { - errors = append(errors, EventValidationError{ - field: "Series", - reason: "embedded message failed validation", - cause: err, - }) - } - case interface{ Validate() error }: - if err := v.Validate(); err != nil { - errors = append(errors, EventValidationError{ - field: "Series", - reason: "embedded message failed validation", - cause: err, - }) - } + if all { + switch v := interface{}(m.GetSeries()).(type) { + case interface{ ValidateAll() error }: + if err := v.ValidateAll(); err != nil { + errors = append(errors, EventValidationError{ + field: "Series", + reason: "embedded message failed validation", + cause: err, + }) } - } else if v, ok := interface{}(m.GetSeries()).(interface{ Validate() error }); ok { + case interface{ Validate() error }: if err := v.Validate(); err != nil { - return EventValidationError{ + errors = append(errors, EventValidationError{ field: "Series", reason: "embedded message failed validation", cause: err, - } + }) + } + } + } else if v, ok := interface{}(m.GetSeries()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return EventValidationError{ + field: "Series", + reason: "embedded message failed validation", + cause: err, } } + } + if m.RegardingWorkspace != nil { + // no validation rules for RegardingWorkspace } if len(errors) > 0 { diff --git a/proto/gen/dashboard/v1alpha1/event_service.pb.go b/proto/gen/dashboard/v1alpha1/event_service.pb.go new file mode 100644 index 00000000..c04dd81e --- /dev/null +++ b/proto/gen/dashboard/v1alpha1/event_service.pb.go @@ -0,0 +1,100 @@ +// +//Cosmo Dashboard API +//Manipulate cosmo dashboard resource API + +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.30.0 +// protoc (unknown) +// source: dashboard/v1alpha1/event_service.proto + +package dashboardv1alpha1 + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +var File_dashboard_v1alpha1_event_service_proto protoreflect.FileDescriptor + +var file_dashboard_v1alpha1_event_service_proto_rawDesc = []byte{ + 0x0a, 0x26, 0x64, 0x61, 0x73, 0x68, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x2f, 0x76, 0x31, 0x61, 0x6c, + 0x70, 0x68, 0x61, 0x31, 0x2f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, + 0x63, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x12, 0x64, 0x61, 0x73, 0x68, 0x62, 0x6f, + 0x61, 0x72, 0x64, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x1a, 0x1e, 0x64, 0x61, + 0x73, 0x68, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, + 0x2f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x25, 0x64, 0x61, + 0x73, 0x68, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, + 0x2f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x32, 0x71, 0x0a, 0x0d, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x53, 0x65, 0x72, + 0x76, 0x69, 0x63, 0x65, 0x12, 0x60, 0x0a, 0x0f, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x69, 0x6e, + 0x67, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x24, 0x2e, 0x64, 0x61, 0x73, 0x68, 0x62, 0x6f, + 0x61, 0x72, 0x64, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x47, 0x65, 0x74, + 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x25, 0x2e, + 0x64, 0x61, 0x73, 0x68, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, + 0x61, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x30, 0x01, 0x42, 0xe5, 0x01, 0x0a, 0x16, 0x63, 0x6f, 0x6d, 0x2e, 0x64, + 0x61, 0x73, 0x68, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, + 0x31, 0x42, 0x11, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x50, + 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x4f, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, + 0x6f, 0x6d, 0x2f, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2d, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, + 0x63, 0x65, 0x2f, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x67, + 0x65, 0x6e, 0x2f, 0x64, 0x61, 0x73, 0x68, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x2f, 0x76, 0x31, 0x61, + 0x6c, 0x70, 0x68, 0x61, 0x31, 0x3b, 0x64, 0x61, 0x73, 0x68, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x76, + 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0xa2, 0x02, 0x03, 0x44, 0x58, 0x58, 0xaa, 0x02, 0x12, + 0x44, 0x61, 0x73, 0x68, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x2e, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, + 0x61, 0x31, 0xca, 0x02, 0x12, 0x44, 0x61, 0x73, 0x68, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x5c, 0x56, + 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0xe2, 0x02, 0x1e, 0x44, 0x61, 0x73, 0x68, 0x62, 0x6f, + 0x61, 0x72, 0x64, 0x5c, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x5c, 0x47, 0x50, 0x42, + 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x13, 0x44, 0x61, 0x73, 0x68, 0x62, + 0x6f, 0x61, 0x72, 0x64, 0x3a, 0x3a, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x62, 0x06, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, +} + +var file_dashboard_v1alpha1_event_service_proto_goTypes = []interface{}{ + (*GetEventsRequest)(nil), // 0: dashboard.v1alpha1.GetEventsRequest + (*GetEventsResponse)(nil), // 1: dashboard.v1alpha1.GetEventsResponse +} +var file_dashboard_v1alpha1_event_service_proto_depIdxs = []int32{ + 0, // 0: dashboard.v1alpha1.StreamService.StreamingEvents:input_type -> dashboard.v1alpha1.GetEventsRequest + 1, // 1: dashboard.v1alpha1.StreamService.StreamingEvents:output_type -> dashboard.v1alpha1.GetEventsResponse + 1, // [1:2] is the sub-list for method output_type + 0, // [0:1] is the sub-list for method input_type + 0, // [0:0] is the sub-list for extension type_name + 0, // [0:0] is the sub-list for extension extendee + 0, // [0:0] is the sub-list for field type_name +} + +func init() { file_dashboard_v1alpha1_event_service_proto_init() } +func file_dashboard_v1alpha1_event_service_proto_init() { + if File_dashboard_v1alpha1_event_service_proto != nil { + return + } + file_dashboard_v1alpha1_event_proto_init() + file_dashboard_v1alpha1_user_service_proto_init() + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_dashboard_v1alpha1_event_service_proto_rawDesc, + NumEnums: 0, + NumMessages: 0, + NumExtensions: 0, + NumServices: 1, + }, + GoTypes: file_dashboard_v1alpha1_event_service_proto_goTypes, + DependencyIndexes: file_dashboard_v1alpha1_event_service_proto_depIdxs, + }.Build() + File_dashboard_v1alpha1_event_service_proto = out.File + file_dashboard_v1alpha1_event_service_proto_rawDesc = nil + file_dashboard_v1alpha1_event_service_proto_goTypes = nil + file_dashboard_v1alpha1_event_service_proto_depIdxs = nil +} diff --git a/proto/gen/dashboard/v1alpha1/event_service.pb.validate.go b/proto/gen/dashboard/v1alpha1/event_service.pb.validate.go new file mode 100644 index 00000000..5c94f7e7 --- /dev/null +++ b/proto/gen/dashboard/v1alpha1/event_service.pb.validate.go @@ -0,0 +1,36 @@ +// Code generated by protoc-gen-validate. DO NOT EDIT. +// source: dashboard/v1alpha1/event_service.proto + +package dashboardv1alpha1 + +import ( + "bytes" + "errors" + "fmt" + "net" + "net/mail" + "net/url" + "regexp" + "sort" + "strings" + "time" + "unicode/utf8" + + "google.golang.org/protobuf/types/known/anypb" +) + +// ensure the imports are used +var ( + _ = bytes.MinRead + _ = errors.New("") + _ = fmt.Print + _ = utf8.UTFMax + _ = (*regexp.Regexp)(nil) + _ = (*strings.Reader)(nil) + _ = net.IPv4len + _ = time.Duration(0) + _ = (*url.URL)(nil) + _ = (*mail.Address)(nil) + _ = anypb.Any{} + _ = sort.Sort +) diff --git a/proto/gen/dashboard/v1alpha1/user.pb.go b/proto/gen/dashboard/v1alpha1/user.pb.go index 37176641..7a27ef23 100644 --- a/proto/gen/dashboard/v1alpha1/user.pb.go +++ b/proto/gen/dashboard/v1alpha1/user.pb.go @@ -38,7 +38,6 @@ type User struct { DefaultPassword string `protobuf:"bytes,6,opt,name=default_password,json=defaultPassword,proto3" json:"default_password,omitempty"` Status string `protobuf:"bytes,7,opt,name=status,proto3" json:"status,omitempty"` Raw *string `protobuf:"bytes,8,opt,name=raw,proto3,oneof" json:"raw,omitempty"` - Events []*Event `protobuf:"bytes,9,rep,name=events,proto3" json:"events,omitempty"` } func (x *User) Reset() { @@ -129,13 +128,6 @@ func (x *User) GetRaw() string { return "" } -func (x *User) GetEvents() []*Event { - if x != nil { - return x.Events - } - return nil -} - type UserAddon struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -206,9 +198,7 @@ var file_dashboard_v1alpha1_user_proto_rawDesc = []byte{ 0x70, 0x68, 0x61, 0x31, 0x2f, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x12, 0x64, 0x61, 0x73, 0x68, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 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, 0x1e, 0x64, 0x61, - 0x73, 0x68, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, - 0x2f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xbc, 0x02, 0x0a, + 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x89, 0x02, 0x0a, 0x04, 0x55, 0x73, 0x65, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, @@ -225,38 +215,34 @@ var file_dashboard_v1alpha1_user_proto_rawDesc = []byte{ 0x64, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x15, 0x0a, 0x03, 0x72, 0x61, 0x77, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x03, 0x72, 0x61, 0x77, 0x88, 0x01, 0x01, - 0x12, 0x31, 0x0a, 0x06, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x09, 0x20, 0x03, 0x28, 0x0b, - 0x32, 0x19, 0x2e, 0x64, 0x61, 0x73, 0x68, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x2e, 0x76, 0x31, 0x61, - 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x52, 0x06, 0x65, 0x76, 0x65, - 0x6e, 0x74, 0x73, 0x42, 0x06, 0x0a, 0x04, 0x5f, 0x72, 0x61, 0x77, 0x22, 0xcd, 0x01, 0x0a, 0x09, - 0x55, 0x73, 0x65, 0x72, 0x41, 0x64, 0x64, 0x6f, 0x6e, 0x12, 0x23, 0x0a, 0x08, 0x74, 0x65, 0x6d, - 0x70, 0x6c, 0x61, 0x74, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xfa, 0x42, 0x04, - 0x72, 0x02, 0x10, 0x01, 0x52, 0x08, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x12, 0x25, - 0x0a, 0x0e, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x64, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0d, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x53, - 0x63, 0x6f, 0x70, 0x65, 0x64, 0x12, 0x3b, 0x0a, 0x04, 0x76, 0x61, 0x72, 0x73, 0x18, 0x03, 0x20, - 0x03, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x64, 0x61, 0x73, 0x68, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x2e, - 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x41, 0x64, 0x64, - 0x6f, 0x6e, 0x2e, 0x56, 0x61, 0x72, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x04, 0x76, 0x61, - 0x72, 0x73, 0x1a, 0x37, 0x0a, 0x09, 0x56, 0x61, 0x72, 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, 0x42, 0xdd, 0x01, 0x0a, 0x16, - 0x63, 0x6f, 0x6d, 0x2e, 0x64, 0x61, 0x73, 0x68, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x2e, 0x76, 0x31, - 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x42, 0x09, 0x55, 0x73, 0x65, 0x72, 0x50, 0x72, 0x6f, 0x74, - 0x6f, 0x50, 0x01, 0x5a, 0x4f, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, - 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2d, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x2f, - 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x67, 0x65, 0x6e, 0x2f, - 0x64, 0x61, 0x73, 0x68, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, - 0x61, 0x31, 0x3b, 0x64, 0x61, 0x73, 0x68, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x76, 0x31, 0x61, 0x6c, - 0x70, 0x68, 0x61, 0x31, 0xa2, 0x02, 0x03, 0x44, 0x58, 0x58, 0xaa, 0x02, 0x12, 0x44, 0x61, 0x73, - 0x68, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x2e, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0xca, - 0x02, 0x12, 0x44, 0x61, 0x73, 0x68, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x5c, 0x56, 0x31, 0x61, 0x6c, - 0x70, 0x68, 0x61, 0x31, 0xe2, 0x02, 0x1e, 0x44, 0x61, 0x73, 0x68, 0x62, 0x6f, 0x61, 0x72, 0x64, - 0x5c, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, - 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x13, 0x44, 0x61, 0x73, 0x68, 0x62, 0x6f, 0x61, 0x72, - 0x64, 0x3a, 0x3a, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x33, + 0x42, 0x06, 0x0a, 0x04, 0x5f, 0x72, 0x61, 0x77, 0x22, 0xcd, 0x01, 0x0a, 0x09, 0x55, 0x73, 0x65, + 0x72, 0x41, 0x64, 0x64, 0x6f, 0x6e, 0x12, 0x23, 0x0a, 0x08, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, + 0x74, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xfa, 0x42, 0x04, 0x72, 0x02, 0x10, + 0x01, 0x52, 0x08, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x12, 0x25, 0x0a, 0x0e, 0x63, + 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x64, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x08, 0x52, 0x0d, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x53, 0x63, 0x6f, 0x70, + 0x65, 0x64, 0x12, 0x3b, 0x0a, 0x04, 0x76, 0x61, 0x72, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, + 0x32, 0x27, 0x2e, 0x64, 0x61, 0x73, 0x68, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x2e, 0x76, 0x31, 0x61, + 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x41, 0x64, 0x64, 0x6f, 0x6e, 0x2e, + 0x56, 0x61, 0x72, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x04, 0x76, 0x61, 0x72, 0x73, 0x1a, + 0x37, 0x0a, 0x09, 0x56, 0x61, 0x72, 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, 0x42, 0xdd, 0x01, 0x0a, 0x16, 0x63, 0x6f, 0x6d, + 0x2e, 0x64, 0x61, 0x73, 0x68, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, + 0x68, 0x61, 0x31, 0x42, 0x09, 0x55, 0x73, 0x65, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, + 0x5a, 0x4f, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x63, 0x6f, 0x73, + 0x6d, 0x6f, 0x2d, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x2f, 0x63, 0x6f, 0x73, + 0x6d, 0x6f, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x64, 0x61, 0x73, + 0x68, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x3b, + 0x64, 0x61, 0x73, 0x68, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, + 0x31, 0xa2, 0x02, 0x03, 0x44, 0x58, 0x58, 0xaa, 0x02, 0x12, 0x44, 0x61, 0x73, 0x68, 0x62, 0x6f, + 0x61, 0x72, 0x64, 0x2e, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0xca, 0x02, 0x12, 0x44, + 0x61, 0x73, 0x68, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x5c, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, + 0x31, 0xe2, 0x02, 0x1e, 0x44, 0x61, 0x73, 0x68, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x5c, 0x56, 0x31, + 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, + 0x74, 0x61, 0xea, 0x02, 0x13, 0x44, 0x61, 0x73, 0x68, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x3a, 0x3a, + 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -276,17 +262,15 @@ var file_dashboard_v1alpha1_user_proto_goTypes = []interface{}{ (*User)(nil), // 0: dashboard.v1alpha1.User (*UserAddon)(nil), // 1: dashboard.v1alpha1.UserAddon nil, // 2: dashboard.v1alpha1.UserAddon.VarsEntry - (*Event)(nil), // 3: dashboard.v1alpha1.Event } var file_dashboard_v1alpha1_user_proto_depIdxs = []int32{ 1, // 0: dashboard.v1alpha1.User.addons:type_name -> dashboard.v1alpha1.UserAddon - 3, // 1: dashboard.v1alpha1.User.events:type_name -> dashboard.v1alpha1.Event - 2, // 2: dashboard.v1alpha1.UserAddon.vars:type_name -> dashboard.v1alpha1.UserAddon.VarsEntry - 3, // [3:3] is the sub-list for method output_type - 3, // [3:3] is the sub-list for method input_type - 3, // [3:3] is the sub-list for extension type_name - 3, // [3:3] is the sub-list for extension extendee - 0, // [0:3] is the sub-list for field type_name + 2, // 1: dashboard.v1alpha1.UserAddon.vars:type_name -> dashboard.v1alpha1.UserAddon.VarsEntry + 2, // [2:2] is the sub-list for method output_type + 2, // [2:2] is the sub-list for method input_type + 2, // [2:2] is the sub-list for extension type_name + 2, // [2:2] is the sub-list for extension extendee + 0, // [0:2] is the sub-list for field type_name } func init() { file_dashboard_v1alpha1_user_proto_init() } @@ -294,7 +278,6 @@ func file_dashboard_v1alpha1_user_proto_init() { if File_dashboard_v1alpha1_user_proto != nil { return } - file_dashboard_v1alpha1_event_proto_init() if !protoimpl.UnsafeEnabled { file_dashboard_v1alpha1_user_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*User); i { diff --git a/proto/gen/dashboard/v1alpha1/user.pb.validate.go b/proto/gen/dashboard/v1alpha1/user.pb.validate.go index c986fcc2..3f12de0b 100644 --- a/proto/gen/dashboard/v1alpha1/user.pb.validate.go +++ b/proto/gen/dashboard/v1alpha1/user.pb.validate.go @@ -100,40 +100,6 @@ func (m *User) validate(all bool) error { // no validation rules for Status - for idx, item := range m.GetEvents() { - _, _ = idx, item - - if all { - switch v := interface{}(item).(type) { - case interface{ ValidateAll() error }: - if err := v.ValidateAll(); err != nil { - errors = append(errors, UserValidationError{ - field: fmt.Sprintf("Events[%v]", idx), - reason: "embedded message failed validation", - cause: err, - }) - } - case interface{ Validate() error }: - if err := v.Validate(); err != nil { - errors = append(errors, UserValidationError{ - field: fmt.Sprintf("Events[%v]", idx), - reason: "embedded message failed validation", - cause: err, - }) - } - } - } else if v, ok := interface{}(item).(interface{ Validate() error }); ok { - if err := v.Validate(); err != nil { - return UserValidationError{ - field: fmt.Sprintf("Events[%v]", idx), - reason: "embedded message failed validation", - cause: err, - } - } - } - - } - if m.Raw != nil { // no validation rules for Raw } diff --git a/proto/gen/dashboard/v1alpha1/user_service.pb.go b/proto/gen/dashboard/v1alpha1/user_service.pb.go index 9251b685..bf9d498c 100644 --- a/proto/gen/dashboard/v1alpha1/user_service.pb.go +++ b/proto/gen/dashboard/v1alpha1/user_service.pb.go @@ -14,6 +14,7 @@ import ( _ "github.com/envoyproxy/protoc-gen-validate/validate" protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" + timestamppb "google.golang.org/protobuf/types/known/timestamppb" reflect "reflect" sync "sync" ) @@ -905,6 +906,116 @@ func (x *UpdateUserAddonsResponse) GetUser() *User { return nil } +type GetEventsRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + UserName string `protobuf:"bytes,1,opt,name=user_name,json=userName,proto3" json:"user_name,omitempty"` + From *timestamppb.Timestamp `protobuf:"bytes,2,opt,name=from,proto3,oneof" json:"from,omitempty"` +} + +func (x *GetEventsRequest) Reset() { + *x = GetEventsRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_dashboard_v1alpha1_user_service_proto_msgTypes[16] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetEventsRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetEventsRequest) ProtoMessage() {} + +func (x *GetEventsRequest) ProtoReflect() protoreflect.Message { + mi := &file_dashboard_v1alpha1_user_service_proto_msgTypes[16] + 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 GetEventsRequest.ProtoReflect.Descriptor instead. +func (*GetEventsRequest) Descriptor() ([]byte, []int) { + return file_dashboard_v1alpha1_user_service_proto_rawDescGZIP(), []int{16} +} + +func (x *GetEventsRequest) GetUserName() string { + if x != nil { + return x.UserName + } + return "" +} + +func (x *GetEventsRequest) GetFrom() *timestamppb.Timestamp { + if x != nil { + return x.From + } + return nil +} + +type GetEventsResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Message string `protobuf:"bytes,1,opt,name=message,proto3" json:"message,omitempty"` + Items []*Event `protobuf:"bytes,2,rep,name=items,proto3" json:"items,omitempty"` +} + +func (x *GetEventsResponse) Reset() { + *x = GetEventsResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_dashboard_v1alpha1_user_service_proto_msgTypes[17] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetEventsResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetEventsResponse) ProtoMessage() {} + +func (x *GetEventsResponse) ProtoReflect() protoreflect.Message { + mi := &file_dashboard_v1alpha1_user_service_proto_msgTypes[17] + 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 GetEventsResponse.ProtoReflect.Descriptor instead. +func (*GetEventsResponse) Descriptor() ([]byte, []int) { + return file_dashboard_v1alpha1_user_service_proto_rawDescGZIP(), []int{17} +} + +func (x *GetEventsResponse) GetMessage() string { + if x != nil { + return x.Message + } + return "" +} + +func (x *GetEventsResponse) GetItems() []*Event { + if x != nil { + return x.Items + } + return nil +} + var File_dashboard_v1alpha1_user_service_proto protoreflect.FileDescriptor var file_dashboard_v1alpha1_user_service_proto_rawDesc = []byte{ @@ -913,111 +1024,128 @@ var file_dashboard_v1alpha1_user_service_proto_rawDesc = []byte{ 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x12, 0x64, 0x61, 0x73, 0x68, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x1a, 0x1d, 0x64, 0x61, 0x73, 0x68, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, - 0x75, 0x73, 0x65, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x17, 0x76, 0x61, 0x6c, 0x69, + 0x75, 0x73, 0x65, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1e, 0x64, 0x61, 0x73, 0x68, + 0x62, 0x6f, 0x61, 0x72, 0x64, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x65, + 0x76, 0x65, 0x6e, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 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, 0x22, 0x39, 0x0a, 0x11, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x55, 0x73, 0x65, - 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x24, 0x0a, 0x09, 0x75, 0x73, 0x65, 0x72, - 0x5f, 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, 0x4e, 0x61, 0x6d, 0x65, 0x22, 0x5c, - 0x0a, 0x12, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x74, 0x6f, 0x1a, 0x1f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x39, 0x0a, 0x11, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x55, 0x73, + 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x24, 0x0a, 0x09, 0x75, 0x73, 0x65, + 0x72, 0x5f, 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, 0x4e, 0x61, 0x6d, 0x65, 0x22, + 0x5c, 0x0a, 0x12, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, + 0x2c, 0x0a, 0x04, 0x75, 0x73, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, + 0x64, 0x61, 0x73, 0x68, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, + 0x61, 0x31, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x52, 0x04, 0x75, 0x73, 0x65, 0x72, 0x22, 0x3e, 0x0a, + 0x0f, 0x47, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x12, 0x1e, 0x0a, 0x08, 0x77, 0x69, 0x74, 0x68, 0x5f, 0x72, 0x61, 0x77, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x08, 0x48, 0x00, 0x52, 0x07, 0x77, 0x69, 0x74, 0x68, 0x52, 0x61, 0x77, 0x88, 0x01, 0x01, + 0x42, 0x0b, 0x0a, 0x09, 0x5f, 0x77, 0x69, 0x74, 0x68, 0x5f, 0x72, 0x61, 0x77, 0x22, 0x5c, 0x0a, + 0x10, 0x47, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x2e, 0x0a, 0x05, 0x69, + 0x74, 0x65, 0x6d, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x64, 0x61, 0x73, + 0x68, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, + 0x55, 0x73, 0x65, 0x72, 0x52, 0x05, 0x69, 0x74, 0x65, 0x6d, 0x73, 0x22, 0x5a, 0x0a, 0x0e, 0x47, + 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1b, 0x0a, + 0x09, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x08, 0x75, 0x73, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1e, 0x0a, 0x08, 0x77, 0x69, + 0x74, 0x68, 0x5f, 0x72, 0x61, 0x77, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x48, 0x00, 0x52, 0x07, + 0x77, 0x69, 0x74, 0x68, 0x52, 0x61, 0x77, 0x88, 0x01, 0x01, 0x42, 0x0b, 0x0a, 0x09, 0x5f, 0x77, + 0x69, 0x74, 0x68, 0x5f, 0x72, 0x61, 0x77, 0x22, 0x3f, 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x55, 0x73, + 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2c, 0x0a, 0x04, 0x75, 0x73, + 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x64, 0x61, 0x73, 0x68, 0x62, + 0x6f, 0x61, 0x72, 0x64, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x55, 0x73, + 0x65, 0x72, 0x52, 0x04, 0x75, 0x73, 0x65, 0x72, 0x22, 0xf1, 0x01, 0x0a, 0x11, 0x43, 0x72, 0x65, + 0x61, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x26, + 0x0a, 0x09, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x42, 0x09, 0xfa, 0x42, 0x06, 0x72, 0x04, 0x10, 0x01, 0x18, 0x32, 0x52, 0x08, 0x75, 0x73, + 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x2a, 0x0a, 0x0c, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, + 0x79, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xfa, 0x42, + 0x04, 0x72, 0x02, 0x18, 0x3f, 0x52, 0x0b, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x4e, 0x61, + 0x6d, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x72, 0x6f, 0x6c, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, + 0x09, 0x52, 0x05, 0x72, 0x6f, 0x6c, 0x65, 0x73, 0x12, 0x3b, 0x0a, 0x09, 0x61, 0x75, 0x74, 0x68, + 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x42, 0x1e, 0xfa, 0x42, 0x1b, + 0x72, 0x19, 0x52, 0x00, 0x52, 0x0f, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x2d, 0x73, + 0x65, 0x63, 0x72, 0x65, 0x74, 0x52, 0x04, 0x6c, 0x64, 0x61, 0x70, 0x52, 0x08, 0x61, 0x75, 0x74, + 0x68, 0x54, 0x79, 0x70, 0x65, 0x12, 0x35, 0x0a, 0x06, 0x61, 0x64, 0x64, 0x6f, 0x6e, 0x73, 0x18, + 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x64, 0x61, 0x73, 0x68, 0x62, 0x6f, 0x61, 0x72, + 0x64, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x41, + 0x64, 0x64, 0x6f, 0x6e, 0x52, 0x06, 0x61, 0x64, 0x64, 0x6f, 0x6e, 0x73, 0x22, 0x5c, 0x0a, 0x12, + 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x2c, 0x0a, 0x04, + 0x75, 0x73, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x64, 0x61, 0x73, + 0x68, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, + 0x55, 0x73, 0x65, 0x72, 0x52, 0x04, 0x75, 0x73, 0x65, 0x72, 0x22, 0x67, 0x0a, 0x1c, 0x55, 0x70, + 0x64, 0x61, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x44, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x4e, + 0x61, 0x6d, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x24, 0x0a, 0x09, 0x75, 0x73, + 0x65, 0x72, 0x5f, 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, 0x4e, 0x61, 0x6d, 0x65, + 0x12, 0x21, 0x0a, 0x0c, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x5f, 0x6e, 0x61, 0x6d, 0x65, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x4e, + 0x61, 0x6d, 0x65, 0x22, 0x67, 0x0a, 0x1d, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x55, 0x73, 0x65, + 0x72, 0x44, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x4e, 0x61, 0x6d, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x2c, 0x0a, 0x04, 0x75, 0x73, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x64, 0x61, 0x73, 0x68, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, - 0x31, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x52, 0x04, 0x75, 0x73, 0x65, 0x72, 0x22, 0x3e, 0x0a, 0x0f, - 0x47, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, - 0x1e, 0x0a, 0x08, 0x77, 0x69, 0x74, 0x68, 0x5f, 0x72, 0x61, 0x77, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x08, 0x48, 0x00, 0x52, 0x07, 0x77, 0x69, 0x74, 0x68, 0x52, 0x61, 0x77, 0x88, 0x01, 0x01, 0x42, - 0x0b, 0x0a, 0x09, 0x5f, 0x77, 0x69, 0x74, 0x68, 0x5f, 0x72, 0x61, 0x77, 0x22, 0x5c, 0x0a, 0x10, - 0x47, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x2e, 0x0a, 0x05, 0x69, 0x74, - 0x65, 0x6d, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x64, 0x61, 0x73, 0x68, - 0x62, 0x6f, 0x61, 0x72, 0x64, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x55, - 0x73, 0x65, 0x72, 0x52, 0x05, 0x69, 0x74, 0x65, 0x6d, 0x73, 0x22, 0x5a, 0x0a, 0x0e, 0x47, 0x65, - 0x74, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1b, 0x0a, 0x09, - 0x75, 0x73, 0x65, 0x72, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x08, 0x75, 0x73, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1e, 0x0a, 0x08, 0x77, 0x69, 0x74, - 0x68, 0x5f, 0x72, 0x61, 0x77, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x48, 0x00, 0x52, 0x07, 0x77, - 0x69, 0x74, 0x68, 0x52, 0x61, 0x77, 0x88, 0x01, 0x01, 0x42, 0x0b, 0x0a, 0x09, 0x5f, 0x77, 0x69, - 0x74, 0x68, 0x5f, 0x72, 0x61, 0x77, 0x22, 0x3f, 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x55, 0x73, 0x65, - 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2c, 0x0a, 0x04, 0x75, 0x73, 0x65, - 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x64, 0x61, 0x73, 0x68, 0x62, 0x6f, - 0x61, 0x72, 0x64, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x55, 0x73, 0x65, - 0x72, 0x52, 0x04, 0x75, 0x73, 0x65, 0x72, 0x22, 0xf1, 0x01, 0x0a, 0x11, 0x43, 0x72, 0x65, 0x61, - 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x26, 0x0a, - 0x09, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x42, 0x09, 0xfa, 0x42, 0x06, 0x72, 0x04, 0x10, 0x01, 0x18, 0x32, 0x52, 0x08, 0x75, 0x73, 0x65, - 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x2a, 0x0a, 0x0c, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, - 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xfa, 0x42, 0x04, - 0x72, 0x02, 0x18, 0x3f, 0x52, 0x0b, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x4e, 0x61, 0x6d, - 0x65, 0x12, 0x14, 0x0a, 0x05, 0x72, 0x6f, 0x6c, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, - 0x52, 0x05, 0x72, 0x6f, 0x6c, 0x65, 0x73, 0x12, 0x3b, 0x0a, 0x09, 0x61, 0x75, 0x74, 0x68, 0x5f, - 0x74, 0x79, 0x70, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x42, 0x1e, 0xfa, 0x42, 0x1b, 0x72, - 0x19, 0x52, 0x00, 0x52, 0x0f, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x2d, 0x73, 0x65, - 0x63, 0x72, 0x65, 0x74, 0x52, 0x04, 0x6c, 0x64, 0x61, 0x70, 0x52, 0x08, 0x61, 0x75, 0x74, 0x68, - 0x54, 0x79, 0x70, 0x65, 0x12, 0x35, 0x0a, 0x06, 0x61, 0x64, 0x64, 0x6f, 0x6e, 0x73, 0x18, 0x05, - 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x64, 0x61, 0x73, 0x68, 0x62, 0x6f, 0x61, 0x72, 0x64, - 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x41, 0x64, - 0x64, 0x6f, 0x6e, 0x52, 0x06, 0x61, 0x64, 0x64, 0x6f, 0x6e, 0x73, 0x22, 0x5c, 0x0a, 0x12, 0x43, - 0x72, 0x65, 0x61, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x2c, 0x0a, 0x04, 0x75, - 0x73, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x64, 0x61, 0x73, 0x68, - 0x62, 0x6f, 0x61, 0x72, 0x64, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x55, - 0x73, 0x65, 0x72, 0x52, 0x04, 0x75, 0x73, 0x65, 0x72, 0x22, 0x67, 0x0a, 0x1c, 0x55, 0x70, 0x64, - 0x61, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x44, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x4e, 0x61, - 0x6d, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x24, 0x0a, 0x09, 0x75, 0x73, 0x65, - 0x72, 0x5f, 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, 0x4e, 0x61, 0x6d, 0x65, 0x12, - 0x21, 0x0a, 0x0c, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x4e, 0x61, - 0x6d, 0x65, 0x22, 0x67, 0x0a, 0x1d, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, - 0x44, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x4e, 0x61, 0x6d, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x31, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x52, 0x04, 0x75, 0x73, 0x65, 0x72, 0x22, 0xa1, 0x01, 0x0a, + 0x19, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x50, 0x61, 0x73, 0x73, 0x77, + 0x6f, 0x72, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x24, 0x0a, 0x09, 0x75, 0x73, + 0x65, 0x72, 0x5f, 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, 0x4e, 0x61, 0x6d, 0x65, + 0x12, 0x32, 0x0a, 0x10, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x70, 0x61, 0x73, 0x73, + 0x77, 0x6f, 0x72, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xfa, 0x42, 0x04, 0x72, + 0x02, 0x10, 0x01, 0x52, 0x0f, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x50, 0x61, 0x73, 0x73, + 0x77, 0x6f, 0x72, 0x64, 0x12, 0x2a, 0x0a, 0x0c, 0x6e, 0x65, 0x77, 0x5f, 0x70, 0x61, 0x73, 0x73, + 0x77, 0x6f, 0x72, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xfa, 0x42, 0x04, 0x72, + 0x02, 0x10, 0x01, 0x52, 0x0b, 0x6e, 0x65, 0x77, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, + 0x22, 0x36, 0x0a, 0x1a, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x50, 0x61, + 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x18, + 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x53, 0x0a, 0x15, 0x55, 0x70, 0x64, 0x61, + 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x52, 0x6f, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x12, 0x24, 0x0a, 0x09, 0x75, 0x73, 0x65, 0x72, 0x5f, 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, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x72, 0x6f, 0x6c, 0x65, 0x73, + 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x05, 0x72, 0x6f, 0x6c, 0x65, 0x73, 0x22, 0x60, 0x0a, + 0x16, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x52, 0x6f, 0x6c, 0x65, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, + 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, + 0x65, 0x12, 0x2c, 0x0a, 0x04, 0x75, 0x73, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x18, 0x2e, 0x64, 0x61, 0x73, 0x68, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x2e, 0x76, 0x31, 0x61, 0x6c, + 0x70, 0x68, 0x61, 0x31, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x52, 0x04, 0x75, 0x73, 0x65, 0x72, 0x22, + 0x76, 0x0a, 0x17, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x41, 0x64, 0x64, + 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x24, 0x0a, 0x09, 0x75, 0x73, + 0x65, 0x72, 0x5f, 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, 0x4e, 0x61, 0x6d, 0x65, + 0x12, 0x35, 0x0a, 0x06, 0x61, 0x64, 0x64, 0x6f, 0x6e, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, + 0x32, 0x1d, 0x2e, 0x64, 0x61, 0x73, 0x68, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x2e, 0x76, 0x31, 0x61, + 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x41, 0x64, 0x64, 0x6f, 0x6e, 0x52, + 0x06, 0x61, 0x64, 0x64, 0x6f, 0x6e, 0x73, 0x22, 0x62, 0x0a, 0x18, 0x55, 0x70, 0x64, 0x61, 0x74, + 0x65, 0x55, 0x73, 0x65, 0x72, 0x41, 0x64, 0x64, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x2c, 0x0a, 0x04, 0x75, 0x73, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x64, 0x61, 0x73, 0x68, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, - 0x2e, 0x55, 0x73, 0x65, 0x72, 0x52, 0x04, 0x75, 0x73, 0x65, 0x72, 0x22, 0xa1, 0x01, 0x0a, 0x19, - 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, - 0x72, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x24, 0x0a, 0x09, 0x75, 0x73, 0x65, - 0x72, 0x5f, 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, 0x4e, 0x61, 0x6d, 0x65, 0x12, - 0x32, 0x0a, 0x10, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x70, 0x61, 0x73, 0x73, 0x77, - 0x6f, 0x72, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xfa, 0x42, 0x04, 0x72, 0x02, - 0x10, 0x01, 0x52, 0x0f, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x50, 0x61, 0x73, 0x73, 0x77, - 0x6f, 0x72, 0x64, 0x12, 0x2a, 0x0a, 0x0c, 0x6e, 0x65, 0x77, 0x5f, 0x70, 0x61, 0x73, 0x73, 0x77, - 0x6f, 0x72, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xfa, 0x42, 0x04, 0x72, 0x02, - 0x10, 0x01, 0x52, 0x0b, 0x6e, 0x65, 0x77, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x22, - 0x36, 0x0a, 0x1a, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x50, 0x61, 0x73, - 0x73, 0x77, 0x6f, 0x72, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x18, 0x0a, - 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, - 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x53, 0x0a, 0x15, 0x55, 0x70, 0x64, 0x61, 0x74, - 0x65, 0x55, 0x73, 0x65, 0x72, 0x52, 0x6f, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x12, 0x24, 0x0a, 0x09, 0x75, 0x73, 0x65, 0x72, 0x5f, 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, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x72, 0x6f, 0x6c, 0x65, 0x73, 0x18, - 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x05, 0x72, 0x6f, 0x6c, 0x65, 0x73, 0x22, 0x60, 0x0a, 0x16, - 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x52, 0x6f, 0x6c, 0x65, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, - 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, - 0x12, 0x2c, 0x0a, 0x04, 0x75, 0x73, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, - 0x2e, 0x64, 0x61, 0x73, 0x68, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, - 0x68, 0x61, 0x31, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x52, 0x04, 0x75, 0x73, 0x65, 0x72, 0x22, 0x76, - 0x0a, 0x17, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x41, 0x64, 0x64, 0x6f, - 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x24, 0x0a, 0x09, 0x75, 0x73, 0x65, - 0x72, 0x5f, 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, 0x4e, 0x61, 0x6d, 0x65, 0x12, - 0x35, 0x0a, 0x06, 0x61, 0x64, 0x64, 0x6f, 0x6e, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, - 0x1d, 0x2e, 0x64, 0x61, 0x73, 0x68, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x2e, 0x76, 0x31, 0x61, 0x6c, - 0x70, 0x68, 0x61, 0x31, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x41, 0x64, 0x64, 0x6f, 0x6e, 0x52, 0x06, - 0x61, 0x64, 0x64, 0x6f, 0x6e, 0x73, 0x22, 0x62, 0x0a, 0x18, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, - 0x55, 0x73, 0x65, 0x72, 0x41, 0x64, 0x64, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x2c, 0x0a, 0x04, - 0x75, 0x73, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x64, 0x61, 0x73, - 0x68, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, - 0x55, 0x73, 0x65, 0x72, 0x52, 0x04, 0x75, 0x73, 0x65, 0x72, 0x32, 0xbd, 0x06, 0x0a, 0x0b, 0x55, + 0x2e, 0x55, 0x73, 0x65, 0x72, 0x52, 0x04, 0x75, 0x73, 0x65, 0x72, 0x22, 0x6d, 0x0a, 0x10, 0x47, + 0x65, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, + 0x1b, 0x0a, 0x09, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x08, 0x75, 0x73, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x33, 0x0a, 0x04, + 0x66, 0x72, 0x6f, 0x6d, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, + 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, + 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x48, 0x00, 0x52, 0x04, 0x66, 0x72, 0x6f, 0x6d, 0x88, 0x01, + 0x01, 0x42, 0x07, 0x0a, 0x05, 0x5f, 0x66, 0x72, 0x6f, 0x6d, 0x22, 0x5e, 0x0a, 0x11, 0x47, 0x65, + 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x2f, 0x0a, 0x05, 0x69, 0x74, 0x65, + 0x6d, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x64, 0x61, 0x73, 0x68, 0x62, + 0x6f, 0x61, 0x72, 0x64, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x45, 0x76, + 0x65, 0x6e, 0x74, 0x52, 0x05, 0x69, 0x74, 0x65, 0x6d, 0x73, 0x32, 0x97, 0x07, 0x0a, 0x0b, 0x55, 0x73, 0x65, 0x72, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x5b, 0x0a, 0x0a, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x12, 0x25, 0x2e, 0x64, 0x61, 0x73, 0x68, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x44, 0x65, @@ -1035,56 +1163,62 @@ var file_dashboard_v1alpha1_user_service_proto_rawDesc = []byte{ 0x55, 0x73, 0x65, 0x72, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x64, 0x61, 0x73, 0x68, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x5b, 0x0a, 0x0a, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, - 0x12, 0x25, 0x2e, 0x64, 0x61, 0x73, 0x68, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x2e, 0x76, 0x31, 0x61, - 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x26, 0x2e, 0x64, 0x61, 0x73, 0x68, 0x62, 0x6f, - 0x61, 0x72, 0x64, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x43, 0x72, 0x65, - 0x61, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x7c, 0x0a, 0x15, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x44, 0x69, 0x73, - 0x70, 0x6c, 0x61, 0x79, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x30, 0x2e, 0x64, 0x61, 0x73, 0x68, 0x62, - 0x6f, 0x61, 0x72, 0x64, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x55, 0x70, - 0x64, 0x61, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x44, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x4e, - 0x61, 0x6d, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x31, 0x2e, 0x64, 0x61, 0x73, + 0x73, 0x65, 0x12, 0x58, 0x0a, 0x09, 0x47, 0x65, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x12, + 0x24, 0x2e, 0x64, 0x61, 0x73, 0x68, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x2e, 0x76, 0x31, 0x61, 0x6c, + 0x70, 0x68, 0x61, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x25, 0x2e, 0x64, 0x61, 0x73, 0x68, 0x62, 0x6f, 0x61, 0x72, + 0x64, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x45, 0x76, + 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x5b, 0x0a, 0x0a, + 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x12, 0x25, 0x2e, 0x64, 0x61, 0x73, 0x68, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, - 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x44, 0x69, 0x73, 0x70, 0x6c, 0x61, - 0x79, 0x4e, 0x61, 0x6d, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x73, 0x0a, - 0x12, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x50, 0x61, 0x73, 0x73, 0x77, - 0x6f, 0x72, 0x64, 0x12, 0x2d, 0x2e, 0x64, 0x61, 0x73, 0x68, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x2e, - 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x55, - 0x73, 0x65, 0x72, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x2e, 0x2e, 0x64, 0x61, 0x73, 0x68, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x2e, 0x76, + 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x26, 0x2e, 0x64, 0x61, 0x73, 0x68, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x2e, 0x76, 0x31, + 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x55, 0x73, 0x65, + 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x7c, 0x0a, 0x15, 0x55, 0x70, 0x64, + 0x61, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x44, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x4e, 0x61, + 0x6d, 0x65, 0x12, 0x30, 0x2e, 0x64, 0x61, 0x73, 0x68, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x55, 0x73, - 0x65, 0x72, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x67, 0x0a, 0x0e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, - 0x52, 0x6f, 0x6c, 0x65, 0x12, 0x29, 0x2e, 0x64, 0x61, 0x73, 0x68, 0x62, 0x6f, 0x61, 0x72, 0x64, + 0x65, 0x72, 0x44, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x4e, 0x61, 0x6d, 0x65, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x31, 0x2e, 0x64, 0x61, 0x73, 0x68, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, - 0x55, 0x73, 0x65, 0x72, 0x52, 0x6f, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x2a, 0x2e, 0x64, 0x61, 0x73, 0x68, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x2e, 0x76, 0x31, 0x61, 0x6c, - 0x70, 0x68, 0x61, 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x52, - 0x6f, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6d, 0x0a, 0x10, 0x55, - 0x70, 0x64, 0x61, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x41, 0x64, 0x64, 0x6f, 0x6e, 0x73, 0x12, - 0x2b, 0x2e, 0x64, 0x61, 0x73, 0x68, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x2e, 0x76, 0x31, 0x61, 0x6c, - 0x70, 0x68, 0x61, 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x41, - 0x64, 0x64, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2c, 0x2e, 0x64, + 0x55, 0x73, 0x65, 0x72, 0x44, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x4e, 0x61, 0x6d, 0x65, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x73, 0x0a, 0x12, 0x55, 0x70, 0x64, 0x61, 0x74, + 0x65, 0x55, 0x73, 0x65, 0x72, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x12, 0x2d, 0x2e, + 0x64, 0x61, 0x73, 0x68, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, + 0x61, 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x50, 0x61, 0x73, + 0x73, 0x77, 0x6f, 0x72, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2e, 0x2e, 0x64, 0x61, 0x73, 0x68, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, - 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x41, 0x64, 0x64, 0x6f, - 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0xe4, 0x01, 0x0a, 0x16, 0x63, - 0x6f, 0x6d, 0x2e, 0x64, 0x61, 0x73, 0x68, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x2e, 0x76, 0x31, 0x61, - 0x6c, 0x70, 0x68, 0x61, 0x31, 0x42, 0x10, 0x55, 0x73, 0x65, 0x72, 0x53, 0x65, 0x72, 0x76, 0x69, - 0x63, 0x65, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x4f, 0x67, 0x69, 0x74, 0x68, 0x75, - 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2d, 0x77, 0x6f, 0x72, 0x6b, - 0x73, 0x70, 0x61, 0x63, 0x65, 0x2f, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2f, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x64, 0x61, 0x73, 0x68, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x2f, - 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x3b, 0x64, 0x61, 0x73, 0x68, 0x62, 0x6f, 0x61, - 0x72, 0x64, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0xa2, 0x02, 0x03, 0x44, 0x58, 0x58, - 0xaa, 0x02, 0x12, 0x44, 0x61, 0x73, 0x68, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x2e, 0x56, 0x31, 0x61, - 0x6c, 0x70, 0x68, 0x61, 0x31, 0xca, 0x02, 0x12, 0x44, 0x61, 0x73, 0x68, 0x62, 0x6f, 0x61, 0x72, - 0x64, 0x5c, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0xe2, 0x02, 0x1e, 0x44, 0x61, 0x73, - 0x68, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x5c, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x5c, - 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x13, 0x44, 0x61, - 0x73, 0x68, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x3a, 0x3a, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, - 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x50, 0x61, 0x73, 0x73, + 0x77, 0x6f, 0x72, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x67, 0x0a, 0x0e, + 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x52, 0x6f, 0x6c, 0x65, 0x12, 0x29, + 0x2e, 0x64, 0x61, 0x73, 0x68, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, + 0x68, 0x61, 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x52, 0x6f, + 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x64, 0x61, 0x73, 0x68, + 0x62, 0x6f, 0x61, 0x72, 0x64, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x55, + 0x70, 0x64, 0x61, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x52, 0x6f, 0x6c, 0x65, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6d, 0x0a, 0x10, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x55, + 0x73, 0x65, 0x72, 0x41, 0x64, 0x64, 0x6f, 0x6e, 0x73, 0x12, 0x2b, 0x2e, 0x64, 0x61, 0x73, 0x68, + 0x62, 0x6f, 0x61, 0x72, 0x64, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x55, + 0x70, 0x64, 0x61, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x41, 0x64, 0x64, 0x6f, 0x6e, 0x73, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2c, 0x2e, 0x64, 0x61, 0x73, 0x68, 0x62, 0x6f, 0x61, + 0x72, 0x64, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, + 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x41, 0x64, 0x64, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x42, 0xe4, 0x01, 0x0a, 0x16, 0x63, 0x6f, 0x6d, 0x2e, 0x64, 0x61, 0x73, + 0x68, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x42, + 0x10, 0x55, 0x73, 0x65, 0x72, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x50, 0x72, 0x6f, 0x74, + 0x6f, 0x50, 0x01, 0x5a, 0x4f, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, + 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2d, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x2f, + 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x67, 0x65, 0x6e, 0x2f, + 0x64, 0x61, 0x73, 0x68, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, + 0x61, 0x31, 0x3b, 0x64, 0x61, 0x73, 0x68, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x76, 0x31, 0x61, 0x6c, + 0x70, 0x68, 0x61, 0x31, 0xa2, 0x02, 0x03, 0x44, 0x58, 0x58, 0xaa, 0x02, 0x12, 0x44, 0x61, 0x73, + 0x68, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x2e, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0xca, + 0x02, 0x12, 0x44, 0x61, 0x73, 0x68, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x5c, 0x56, 0x31, 0x61, 0x6c, + 0x70, 0x68, 0x61, 0x31, 0xe2, 0x02, 0x1e, 0x44, 0x61, 0x73, 0x68, 0x62, 0x6f, 0x61, 0x72, 0x64, + 0x5c, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, + 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x13, 0x44, 0x61, 0x73, 0x68, 0x62, 0x6f, 0x61, 0x72, + 0x64, 0x3a, 0x3a, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x33, } var ( @@ -1099,7 +1233,7 @@ func file_dashboard_v1alpha1_user_service_proto_rawDescGZIP() []byte { return file_dashboard_v1alpha1_user_service_proto_rawDescData } -var file_dashboard_v1alpha1_user_service_proto_msgTypes = make([]protoimpl.MessageInfo, 16) +var file_dashboard_v1alpha1_user_service_proto_msgTypes = make([]protoimpl.MessageInfo, 18) var file_dashboard_v1alpha1_user_service_proto_goTypes = []interface{}{ (*DeleteUserRequest)(nil), // 0: dashboard.v1alpha1.DeleteUserRequest (*DeleteUserResponse)(nil), // 1: dashboard.v1alpha1.DeleteUserResponse @@ -1117,40 +1251,48 @@ var file_dashboard_v1alpha1_user_service_proto_goTypes = []interface{}{ (*UpdateUserRoleResponse)(nil), // 13: dashboard.v1alpha1.UpdateUserRoleResponse (*UpdateUserAddonsRequest)(nil), // 14: dashboard.v1alpha1.UpdateUserAddonsRequest (*UpdateUserAddonsResponse)(nil), // 15: dashboard.v1alpha1.UpdateUserAddonsResponse - (*User)(nil), // 16: dashboard.v1alpha1.User - (*UserAddon)(nil), // 17: dashboard.v1alpha1.UserAddon + (*GetEventsRequest)(nil), // 16: dashboard.v1alpha1.GetEventsRequest + (*GetEventsResponse)(nil), // 17: dashboard.v1alpha1.GetEventsResponse + (*User)(nil), // 18: dashboard.v1alpha1.User + (*UserAddon)(nil), // 19: dashboard.v1alpha1.UserAddon + (*timestamppb.Timestamp)(nil), // 20: google.protobuf.Timestamp + (*Event)(nil), // 21: dashboard.v1alpha1.Event } var file_dashboard_v1alpha1_user_service_proto_depIdxs = []int32{ - 16, // 0: dashboard.v1alpha1.DeleteUserResponse.user:type_name -> dashboard.v1alpha1.User - 16, // 1: dashboard.v1alpha1.GetUsersResponse.items:type_name -> dashboard.v1alpha1.User - 16, // 2: dashboard.v1alpha1.GetUserResponse.user:type_name -> dashboard.v1alpha1.User - 17, // 3: dashboard.v1alpha1.CreateUserRequest.addons:type_name -> dashboard.v1alpha1.UserAddon - 16, // 4: dashboard.v1alpha1.CreateUserResponse.user:type_name -> dashboard.v1alpha1.User - 16, // 5: dashboard.v1alpha1.UpdateUserDisplayNameResponse.user:type_name -> dashboard.v1alpha1.User - 16, // 6: dashboard.v1alpha1.UpdateUserRoleResponse.user:type_name -> dashboard.v1alpha1.User - 17, // 7: dashboard.v1alpha1.UpdateUserAddonsRequest.addons:type_name -> dashboard.v1alpha1.UserAddon - 16, // 8: dashboard.v1alpha1.UpdateUserAddonsResponse.user:type_name -> dashboard.v1alpha1.User - 0, // 9: dashboard.v1alpha1.UserService.DeleteUser:input_type -> dashboard.v1alpha1.DeleteUserRequest - 4, // 10: dashboard.v1alpha1.UserService.GetUser:input_type -> dashboard.v1alpha1.GetUserRequest - 2, // 11: dashboard.v1alpha1.UserService.GetUsers:input_type -> dashboard.v1alpha1.GetUsersRequest - 6, // 12: dashboard.v1alpha1.UserService.CreateUser:input_type -> dashboard.v1alpha1.CreateUserRequest - 8, // 13: dashboard.v1alpha1.UserService.UpdateUserDisplayName:input_type -> dashboard.v1alpha1.UpdateUserDisplayNameRequest - 10, // 14: dashboard.v1alpha1.UserService.UpdateUserPassword:input_type -> dashboard.v1alpha1.UpdateUserPasswordRequest - 12, // 15: dashboard.v1alpha1.UserService.UpdateUserRole:input_type -> dashboard.v1alpha1.UpdateUserRoleRequest - 14, // 16: dashboard.v1alpha1.UserService.UpdateUserAddons:input_type -> dashboard.v1alpha1.UpdateUserAddonsRequest - 1, // 17: dashboard.v1alpha1.UserService.DeleteUser:output_type -> dashboard.v1alpha1.DeleteUserResponse - 5, // 18: dashboard.v1alpha1.UserService.GetUser:output_type -> dashboard.v1alpha1.GetUserResponse - 3, // 19: dashboard.v1alpha1.UserService.GetUsers:output_type -> dashboard.v1alpha1.GetUsersResponse - 7, // 20: dashboard.v1alpha1.UserService.CreateUser:output_type -> dashboard.v1alpha1.CreateUserResponse - 9, // 21: dashboard.v1alpha1.UserService.UpdateUserDisplayName:output_type -> dashboard.v1alpha1.UpdateUserDisplayNameResponse - 11, // 22: dashboard.v1alpha1.UserService.UpdateUserPassword:output_type -> dashboard.v1alpha1.UpdateUserPasswordResponse - 13, // 23: dashboard.v1alpha1.UserService.UpdateUserRole:output_type -> dashboard.v1alpha1.UpdateUserRoleResponse - 15, // 24: dashboard.v1alpha1.UserService.UpdateUserAddons:output_type -> dashboard.v1alpha1.UpdateUserAddonsResponse - 17, // [17:25] is the sub-list for method output_type - 9, // [9:17] is the sub-list for method input_type - 9, // [9:9] is the sub-list for extension type_name - 9, // [9:9] is the sub-list for extension extendee - 0, // [0:9] is the sub-list for field type_name + 18, // 0: dashboard.v1alpha1.DeleteUserResponse.user:type_name -> dashboard.v1alpha1.User + 18, // 1: dashboard.v1alpha1.GetUsersResponse.items:type_name -> dashboard.v1alpha1.User + 18, // 2: dashboard.v1alpha1.GetUserResponse.user:type_name -> dashboard.v1alpha1.User + 19, // 3: dashboard.v1alpha1.CreateUserRequest.addons:type_name -> dashboard.v1alpha1.UserAddon + 18, // 4: dashboard.v1alpha1.CreateUserResponse.user:type_name -> dashboard.v1alpha1.User + 18, // 5: dashboard.v1alpha1.UpdateUserDisplayNameResponse.user:type_name -> dashboard.v1alpha1.User + 18, // 6: dashboard.v1alpha1.UpdateUserRoleResponse.user:type_name -> dashboard.v1alpha1.User + 19, // 7: dashboard.v1alpha1.UpdateUserAddonsRequest.addons:type_name -> dashboard.v1alpha1.UserAddon + 18, // 8: dashboard.v1alpha1.UpdateUserAddonsResponse.user:type_name -> dashboard.v1alpha1.User + 20, // 9: dashboard.v1alpha1.GetEventsRequest.from:type_name -> google.protobuf.Timestamp + 21, // 10: dashboard.v1alpha1.GetEventsResponse.items:type_name -> dashboard.v1alpha1.Event + 0, // 11: dashboard.v1alpha1.UserService.DeleteUser:input_type -> dashboard.v1alpha1.DeleteUserRequest + 4, // 12: dashboard.v1alpha1.UserService.GetUser:input_type -> dashboard.v1alpha1.GetUserRequest + 2, // 13: dashboard.v1alpha1.UserService.GetUsers:input_type -> dashboard.v1alpha1.GetUsersRequest + 16, // 14: dashboard.v1alpha1.UserService.GetEvents:input_type -> dashboard.v1alpha1.GetEventsRequest + 6, // 15: dashboard.v1alpha1.UserService.CreateUser:input_type -> dashboard.v1alpha1.CreateUserRequest + 8, // 16: dashboard.v1alpha1.UserService.UpdateUserDisplayName:input_type -> dashboard.v1alpha1.UpdateUserDisplayNameRequest + 10, // 17: dashboard.v1alpha1.UserService.UpdateUserPassword:input_type -> dashboard.v1alpha1.UpdateUserPasswordRequest + 12, // 18: dashboard.v1alpha1.UserService.UpdateUserRole:input_type -> dashboard.v1alpha1.UpdateUserRoleRequest + 14, // 19: dashboard.v1alpha1.UserService.UpdateUserAddons:input_type -> dashboard.v1alpha1.UpdateUserAddonsRequest + 1, // 20: dashboard.v1alpha1.UserService.DeleteUser:output_type -> dashboard.v1alpha1.DeleteUserResponse + 5, // 21: dashboard.v1alpha1.UserService.GetUser:output_type -> dashboard.v1alpha1.GetUserResponse + 3, // 22: dashboard.v1alpha1.UserService.GetUsers:output_type -> dashboard.v1alpha1.GetUsersResponse + 17, // 23: dashboard.v1alpha1.UserService.GetEvents:output_type -> dashboard.v1alpha1.GetEventsResponse + 7, // 24: dashboard.v1alpha1.UserService.CreateUser:output_type -> dashboard.v1alpha1.CreateUserResponse + 9, // 25: dashboard.v1alpha1.UserService.UpdateUserDisplayName:output_type -> dashboard.v1alpha1.UpdateUserDisplayNameResponse + 11, // 26: dashboard.v1alpha1.UserService.UpdateUserPassword:output_type -> dashboard.v1alpha1.UpdateUserPasswordResponse + 13, // 27: dashboard.v1alpha1.UserService.UpdateUserRole:output_type -> dashboard.v1alpha1.UpdateUserRoleResponse + 15, // 28: dashboard.v1alpha1.UserService.UpdateUserAddons:output_type -> dashboard.v1alpha1.UpdateUserAddonsResponse + 20, // [20:29] is the sub-list for method output_type + 11, // [11:20] is the sub-list for method input_type + 11, // [11:11] is the sub-list for extension type_name + 11, // [11:11] is the sub-list for extension extendee + 0, // [0:11] is the sub-list for field type_name } func init() { file_dashboard_v1alpha1_user_service_proto_init() } @@ -1159,6 +1301,7 @@ func file_dashboard_v1alpha1_user_service_proto_init() { return } file_dashboard_v1alpha1_user_proto_init() + file_dashboard_v1alpha1_event_proto_init() if !protoimpl.UnsafeEnabled { file_dashboard_v1alpha1_user_service_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*DeleteUserRequest); i { @@ -1352,16 +1495,41 @@ func file_dashboard_v1alpha1_user_service_proto_init() { return nil } } + file_dashboard_v1alpha1_user_service_proto_msgTypes[16].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GetEventsRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_dashboard_v1alpha1_user_service_proto_msgTypes[17].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GetEventsResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } } file_dashboard_v1alpha1_user_service_proto_msgTypes[2].OneofWrappers = []interface{}{} file_dashboard_v1alpha1_user_service_proto_msgTypes[4].OneofWrappers = []interface{}{} + file_dashboard_v1alpha1_user_service_proto_msgTypes[16].OneofWrappers = []interface{}{} type x struct{} out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_dashboard_v1alpha1_user_service_proto_rawDesc, NumEnums: 0, - NumMessages: 16, + NumMessages: 18, NumExtensions: 0, NumServices: 1, }, diff --git a/proto/gen/dashboard/v1alpha1/user_service.pb.validate.go b/proto/gen/dashboard/v1alpha1/user_service.pb.validate.go index 0d43bdd4..0a290abf 100644 --- a/proto/gen/dashboard/v1alpha1/user_service.pb.validate.go +++ b/proto/gen/dashboard/v1alpha1/user_service.pb.validate.go @@ -2078,3 +2078,276 @@ var _ interface { Cause() error ErrorName() string } = UpdateUserAddonsResponseValidationError{} + +// Validate checks the field values on GetEventsRequest 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 *GetEventsRequest) Validate() error { + return m.validate(false) +} + +// ValidateAll checks the field values on GetEventsRequest 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 +// GetEventsRequestMultiError, or nil if none found. +func (m *GetEventsRequest) ValidateAll() error { + return m.validate(true) +} + +func (m *GetEventsRequest) validate(all bool) error { + if m == nil { + return nil + } + + var errors []error + + // no validation rules for UserName + + if m.From != nil { + + if all { + switch v := interface{}(m.GetFrom()).(type) { + case interface{ ValidateAll() error }: + if err := v.ValidateAll(); err != nil { + errors = append(errors, GetEventsRequestValidationError{ + field: "From", + reason: "embedded message failed validation", + cause: err, + }) + } + case interface{ Validate() error }: + if err := v.Validate(); err != nil { + errors = append(errors, GetEventsRequestValidationError{ + field: "From", + reason: "embedded message failed validation", + cause: err, + }) + } + } + } else if v, ok := interface{}(m.GetFrom()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return GetEventsRequestValidationError{ + field: "From", + reason: "embedded message failed validation", + cause: err, + } + } + } + + } + + if len(errors) > 0 { + return GetEventsRequestMultiError(errors) + } + + return nil +} + +// GetEventsRequestMultiError is an error wrapping multiple validation errors +// returned by GetEventsRequest.ValidateAll() if the designated constraints +// aren't met. +type GetEventsRequestMultiError []error + +// Error returns a concatenation of all the error messages it wraps. +func (m GetEventsRequestMultiError) 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 GetEventsRequestMultiError) AllErrors() []error { return m } + +// GetEventsRequestValidationError is the validation error returned by +// GetEventsRequest.Validate if the designated constraints aren't met. +type GetEventsRequestValidationError struct { + field string + reason string + cause error + key bool +} + +// Field function returns field value. +func (e GetEventsRequestValidationError) Field() string { return e.field } + +// Reason function returns reason value. +func (e GetEventsRequestValidationError) Reason() string { return e.reason } + +// Cause function returns cause value. +func (e GetEventsRequestValidationError) Cause() error { return e.cause } + +// Key function returns key value. +func (e GetEventsRequestValidationError) Key() bool { return e.key } + +// ErrorName returns error name. +func (e GetEventsRequestValidationError) ErrorName() string { return "GetEventsRequestValidationError" } + +// Error satisfies the builtin error interface +func (e GetEventsRequestValidationError) 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 %sGetEventsRequest.%s: %s%s", + key, + e.field, + e.reason, + cause) +} + +var _ error = GetEventsRequestValidationError{} + +var _ interface { + Field() string + Reason() string + Key() bool + Cause() error + ErrorName() string +} = GetEventsRequestValidationError{} + +// Validate checks the field values on GetEventsResponse 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 *GetEventsResponse) Validate() error { + return m.validate(false) +} + +// ValidateAll checks the field values on GetEventsResponse 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 +// GetEventsResponseMultiError, or nil if none found. +func (m *GetEventsResponse) ValidateAll() error { + return m.validate(true) +} + +func (m *GetEventsResponse) validate(all bool) error { + if m == nil { + return nil + } + + var errors []error + + // no validation rules for Message + + for idx, item := range m.GetItems() { + _, _ = idx, item + + if all { + switch v := interface{}(item).(type) { + case interface{ ValidateAll() error }: + if err := v.ValidateAll(); err != nil { + errors = append(errors, GetEventsResponseValidationError{ + field: fmt.Sprintf("Items[%v]", idx), + reason: "embedded message failed validation", + cause: err, + }) + } + case interface{ Validate() error }: + if err := v.Validate(); err != nil { + errors = append(errors, GetEventsResponseValidationError{ + field: fmt.Sprintf("Items[%v]", idx), + reason: "embedded message failed validation", + cause: err, + }) + } + } + } else if v, ok := interface{}(item).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return GetEventsResponseValidationError{ + field: fmt.Sprintf("Items[%v]", idx), + reason: "embedded message failed validation", + cause: err, + } + } + } + + } + + if len(errors) > 0 { + return GetEventsResponseMultiError(errors) + } + + return nil +} + +// GetEventsResponseMultiError is an error wrapping multiple validation errors +// returned by GetEventsResponse.ValidateAll() if the designated constraints +// aren't met. +type GetEventsResponseMultiError []error + +// Error returns a concatenation of all the error messages it wraps. +func (m GetEventsResponseMultiError) 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 GetEventsResponseMultiError) AllErrors() []error { return m } + +// GetEventsResponseValidationError is the validation error returned by +// GetEventsResponse.Validate if the designated constraints aren't met. +type GetEventsResponseValidationError struct { + field string + reason string + cause error + key bool +} + +// Field function returns field value. +func (e GetEventsResponseValidationError) Field() string { return e.field } + +// Reason function returns reason value. +func (e GetEventsResponseValidationError) Reason() string { return e.reason } + +// Cause function returns cause value. +func (e GetEventsResponseValidationError) Cause() error { return e.cause } + +// Key function returns key value. +func (e GetEventsResponseValidationError) Key() bool { return e.key } + +// ErrorName returns error name. +func (e GetEventsResponseValidationError) ErrorName() string { + return "GetEventsResponseValidationError" +} + +// Error satisfies the builtin error interface +func (e GetEventsResponseValidationError) 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 %sGetEventsResponse.%s: %s%s", + key, + e.field, + e.reason, + cause) +} + +var _ error = GetEventsResponseValidationError{} + +var _ interface { + Field() string + Reason() string + Key() bool + Cause() error + ErrorName() string +} = GetEventsResponseValidationError{} diff --git a/proto/gen/dashboard/v1alpha1/workspace.pb.go b/proto/gen/dashboard/v1alpha1/workspace.pb.go index 16c2d874..a071e6ea 100644 --- a/proto/gen/dashboard/v1alpha1/workspace.pb.go +++ b/proto/gen/dashboard/v1alpha1/workspace.pb.go @@ -14,6 +14,7 @@ import ( _ "github.com/envoyproxy/protoc-gen-validate/validate" protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" + timestamppb "google.golang.org/protobuf/types/known/timestamppb" reflect "reflect" sync "sync" ) @@ -180,8 +181,9 @@ type WorkspaceStatus struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Phase string `protobuf:"bytes,1,opt,name=phase,proto3" json:"phase,omitempty"` - MainUrl string `protobuf:"bytes,2,opt,name=main_url,json=mainUrl,proto3" json:"main_url,omitempty"` + Phase string `protobuf:"bytes,1,opt,name=phase,proto3" json:"phase,omitempty"` + MainUrl string `protobuf:"bytes,2,opt,name=main_url,json=mainUrl,proto3" json:"main_url,omitempty"` + LastStartedAt *timestamppb.Timestamp `protobuf:"bytes,3,opt,name=lastStartedAt,proto3" json:"lastStartedAt,omitempty"` } func (x *WorkspaceStatus) Reset() { @@ -230,6 +232,13 @@ func (x *WorkspaceStatus) GetMainUrl() string { return "" } +func (x *WorkspaceStatus) GetLastStartedAt() *timestamppb.Timestamp { + if x != nil { + return x.LastStartedAt + } + return nil +} + type Workspace struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -317,66 +326,72 @@ var file_dashboard_v1alpha1_workspace_proto_rawDesc = []byte{ 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x12, 0x64, 0x61, 0x73, 0x68, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 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, 0x22, 0xb0, 0x01, 0x0a, 0x0b, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x52, 0x75, 0x6c, - 0x65, 0x12, 0x2c, 0x0a, 0x0b, 0x70, 0x6f, 0x72, 0x74, 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x42, 0x0b, 0xfa, 0x42, 0x08, 0x1a, 0x06, 0x10, 0x80, 0x80, - 0x04, 0x20, 0x00, 0x52, 0x0a, 0x70, 0x6f, 0x72, 0x74, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x12, - 0x2c, 0x0a, 0x12, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x5f, 0x68, 0x6f, 0x73, 0x74, 0x5f, 0x70, - 0x72, 0x65, 0x66, 0x69, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x63, 0x75, 0x73, - 0x74, 0x6f, 0x6d, 0x48, 0x6f, 0x73, 0x74, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x12, 0x1b, 0x0a, - 0x09, 0x68, 0x74, 0x74, 0x70, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x08, 0x68, 0x74, 0x74, 0x70, 0x50, 0x61, 0x74, 0x68, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x72, - 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x75, 0x72, 0x6c, 0x12, 0x16, 0x0a, 0x06, - 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x70, 0x75, - 0x62, 0x6c, 0x69, 0x63, 0x22, 0xfc, 0x01, 0x0a, 0x0d, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, - 0x63, 0x65, 0x53, 0x70, 0x65, 0x63, 0x12, 0x1a, 0x0a, 0x08, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, - 0x74, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, - 0x74, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x72, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x73, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x72, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x73, 0x12, 0x3f, - 0x0a, 0x04, 0x76, 0x61, 0x72, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x64, - 0x61, 0x73, 0x68, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, - 0x31, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x53, 0x70, 0x65, 0x63, 0x2e, - 0x56, 0x61, 0x72, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x04, 0x76, 0x61, 0x72, 0x73, 0x12, - 0x39, 0x0a, 0x07, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, - 0x32, 0x1f, 0x2e, 0x64, 0x61, 0x73, 0x68, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x2e, 0x76, 0x31, 0x61, - 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x52, 0x75, 0x6c, - 0x65, 0x52, 0x07, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x1a, 0x37, 0x0a, 0x09, 0x56, 0x61, - 0x72, 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, 0x42, 0x0a, 0x0f, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, - 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x70, 0x68, 0x61, 0x73, 0x65, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x70, 0x68, 0x61, 0x73, 0x65, 0x12, 0x19, 0x0a, 0x08, - 0x6d, 0x61, 0x69, 0x6e, 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, - 0x6d, 0x61, 0x69, 0x6e, 0x55, 0x72, 0x6c, 0x22, 0xd1, 0x01, 0x0a, 0x09, 0x57, 0x6f, 0x72, 0x6b, - 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x6f, 0x77, 0x6e, - 0x65, 0x72, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6f, - 0x77, 0x6e, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x35, 0x0a, 0x04, 0x73, 0x70, 0x65, 0x63, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x64, 0x61, 0x73, 0x68, 0x62, 0x6f, 0x61, - 0x72, 0x64, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x57, 0x6f, 0x72, 0x6b, - 0x73, 0x70, 0x61, 0x63, 0x65, 0x53, 0x70, 0x65, 0x63, 0x52, 0x04, 0x73, 0x70, 0x65, 0x63, 0x12, - 0x3b, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x23, 0x2e, 0x64, 0x61, 0x73, 0x68, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x2e, 0x76, 0x31, 0x61, 0x6c, - 0x70, 0x68, 0x61, 0x31, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x53, 0x74, - 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x15, 0x0a, 0x03, - 0x72, 0x61, 0x77, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x03, 0x72, 0x61, 0x77, - 0x88, 0x01, 0x01, 0x42, 0x06, 0x0a, 0x04, 0x5f, 0x72, 0x61, 0x77, 0x42, 0xe2, 0x01, 0x0a, 0x16, - 0x63, 0x6f, 0x6d, 0x2e, 0x64, 0x61, 0x73, 0x68, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x2e, 0x76, 0x31, - 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x42, 0x0e, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, - 0x65, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x4f, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, - 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2d, 0x77, 0x6f, 0x72, 0x6b, 0x73, - 0x70, 0x61, 0x63, 0x65, 0x2f, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x64, 0x61, 0x73, 0x68, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x2f, 0x76, - 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x3b, 0x64, 0x61, 0x73, 0x68, 0x62, 0x6f, 0x61, 0x72, - 0x64, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0xa2, 0x02, 0x03, 0x44, 0x58, 0x58, 0xaa, - 0x02, 0x12, 0x44, 0x61, 0x73, 0x68, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x2e, 0x56, 0x31, 0x61, 0x6c, - 0x70, 0x68, 0x61, 0x31, 0xca, 0x02, 0x12, 0x44, 0x61, 0x73, 0x68, 0x62, 0x6f, 0x61, 0x72, 0x64, - 0x5c, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0xe2, 0x02, 0x1e, 0x44, 0x61, 0x73, 0x68, - 0x62, 0x6f, 0x61, 0x72, 0x64, 0x5c, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x5c, 0x47, - 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x13, 0x44, 0x61, 0x73, - 0x68, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x3a, 0x3a, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, - 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x6f, 0x1a, 0x1f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, + 0x75, 0x66, 0x2f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x22, 0xb0, 0x01, 0x0a, 0x0b, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x52, 0x75, + 0x6c, 0x65, 0x12, 0x2c, 0x0a, 0x0b, 0x70, 0x6f, 0x72, 0x74, 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, + 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x42, 0x0b, 0xfa, 0x42, 0x08, 0x1a, 0x06, 0x10, 0x80, + 0x80, 0x04, 0x20, 0x00, 0x52, 0x0a, 0x70, 0x6f, 0x72, 0x74, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, + 0x12, 0x2c, 0x0a, 0x12, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x5f, 0x68, 0x6f, 0x73, 0x74, 0x5f, + 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x63, 0x75, + 0x73, 0x74, 0x6f, 0x6d, 0x48, 0x6f, 0x73, 0x74, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x12, 0x1b, + 0x0a, 0x09, 0x68, 0x74, 0x74, 0x70, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x18, 0x03, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x08, 0x68, 0x74, 0x74, 0x70, 0x50, 0x61, 0x74, 0x68, 0x12, 0x10, 0x0a, 0x03, 0x75, + 0x72, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x75, 0x72, 0x6c, 0x12, 0x16, 0x0a, + 0x06, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x70, + 0x75, 0x62, 0x6c, 0x69, 0x63, 0x22, 0xfc, 0x01, 0x0a, 0x0d, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, + 0x61, 0x63, 0x65, 0x53, 0x70, 0x65, 0x63, 0x12, 0x1a, 0x0a, 0x08, 0x74, 0x65, 0x6d, 0x70, 0x6c, + 0x61, 0x74, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x74, 0x65, 0x6d, 0x70, 0x6c, + 0x61, 0x74, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x72, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x73, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x72, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x73, 0x12, + 0x3f, 0x0a, 0x04, 0x76, 0x61, 0x72, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2b, 0x2e, + 0x64, 0x61, 0x73, 0x68, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, + 0x61, 0x31, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x53, 0x70, 0x65, 0x63, + 0x2e, 0x56, 0x61, 0x72, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x04, 0x76, 0x61, 0x72, 0x73, + 0x12, 0x39, 0x0a, 0x07, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x18, 0x04, 0x20, 0x03, 0x28, + 0x0b, 0x32, 0x1f, 0x2e, 0x64, 0x61, 0x73, 0x68, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x2e, 0x76, 0x31, + 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x52, 0x75, + 0x6c, 0x65, 0x52, 0x07, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x1a, 0x37, 0x0a, 0x09, 0x56, + 0x61, 0x72, 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, 0x84, 0x01, 0x0a, 0x0f, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, + 0x63, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x70, 0x68, 0x61, 0x73, + 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x70, 0x68, 0x61, 0x73, 0x65, 0x12, 0x19, + 0x0a, 0x08, 0x6d, 0x61, 0x69, 0x6e, 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x07, 0x6d, 0x61, 0x69, 0x6e, 0x55, 0x72, 0x6c, 0x12, 0x40, 0x0a, 0x0d, 0x6c, 0x61, 0x73, + 0x74, 0x53, 0x74, 0x61, 0x72, 0x74, 0x65, 0x64, 0x41, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, + 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0d, 0x6c, 0x61, + 0x73, 0x74, 0x53, 0x74, 0x61, 0x72, 0x74, 0x65, 0x64, 0x41, 0x74, 0x22, 0xd1, 0x01, 0x0a, 0x09, + 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, + 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1d, 0x0a, + 0x0a, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x09, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x35, 0x0a, 0x04, + 0x73, 0x70, 0x65, 0x63, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x64, 0x61, 0x73, + 0x68, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, + 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x53, 0x70, 0x65, 0x63, 0x52, 0x04, 0x73, + 0x70, 0x65, 0x63, 0x12, 0x3b, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x04, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x64, 0x61, 0x73, 0x68, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x2e, + 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, + 0x63, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, + 0x12, 0x15, 0x0a, 0x03, 0x72, 0x61, 0x77, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, + 0x03, 0x72, 0x61, 0x77, 0x88, 0x01, 0x01, 0x42, 0x06, 0x0a, 0x04, 0x5f, 0x72, 0x61, 0x77, 0x42, + 0xe2, 0x01, 0x0a, 0x16, 0x63, 0x6f, 0x6d, 0x2e, 0x64, 0x61, 0x73, 0x68, 0x62, 0x6f, 0x61, 0x72, + 0x64, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x42, 0x0e, 0x57, 0x6f, 0x72, 0x6b, + 0x73, 0x70, 0x61, 0x63, 0x65, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x4f, 0x67, 0x69, + 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2d, 0x77, + 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x2f, 0x63, 0x6f, 0x73, 0x6d, 0x6f, 0x2f, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x64, 0x61, 0x73, 0x68, 0x62, 0x6f, 0x61, + 0x72, 0x64, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x3b, 0x64, 0x61, 0x73, 0x68, + 0x62, 0x6f, 0x61, 0x72, 0x64, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0xa2, 0x02, 0x03, + 0x44, 0x58, 0x58, 0xaa, 0x02, 0x12, 0x44, 0x61, 0x73, 0x68, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x2e, + 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0xca, 0x02, 0x12, 0x44, 0x61, 0x73, 0x68, 0x62, + 0x6f, 0x61, 0x72, 0x64, 0x5c, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0xe2, 0x02, 0x1e, + 0x44, 0x61, 0x73, 0x68, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x5c, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, + 0x61, 0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, + 0x13, 0x44, 0x61, 0x73, 0x68, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x3a, 0x3a, 0x56, 0x31, 0x61, 0x6c, + 0x70, 0x68, 0x61, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -393,22 +408,24 @@ func file_dashboard_v1alpha1_workspace_proto_rawDescGZIP() []byte { var file_dashboard_v1alpha1_workspace_proto_msgTypes = make([]protoimpl.MessageInfo, 5) var file_dashboard_v1alpha1_workspace_proto_goTypes = []interface{}{ - (*NetworkRule)(nil), // 0: dashboard.v1alpha1.NetworkRule - (*WorkspaceSpec)(nil), // 1: dashboard.v1alpha1.WorkspaceSpec - (*WorkspaceStatus)(nil), // 2: dashboard.v1alpha1.WorkspaceStatus - (*Workspace)(nil), // 3: dashboard.v1alpha1.Workspace - nil, // 4: dashboard.v1alpha1.WorkspaceSpec.VarsEntry + (*NetworkRule)(nil), // 0: dashboard.v1alpha1.NetworkRule + (*WorkspaceSpec)(nil), // 1: dashboard.v1alpha1.WorkspaceSpec + (*WorkspaceStatus)(nil), // 2: dashboard.v1alpha1.WorkspaceStatus + (*Workspace)(nil), // 3: dashboard.v1alpha1.Workspace + nil, // 4: dashboard.v1alpha1.WorkspaceSpec.VarsEntry + (*timestamppb.Timestamp)(nil), // 5: google.protobuf.Timestamp } var file_dashboard_v1alpha1_workspace_proto_depIdxs = []int32{ 4, // 0: dashboard.v1alpha1.WorkspaceSpec.vars:type_name -> dashboard.v1alpha1.WorkspaceSpec.VarsEntry 0, // 1: dashboard.v1alpha1.WorkspaceSpec.network:type_name -> dashboard.v1alpha1.NetworkRule - 1, // 2: dashboard.v1alpha1.Workspace.spec:type_name -> dashboard.v1alpha1.WorkspaceSpec - 2, // 3: dashboard.v1alpha1.Workspace.status:type_name -> dashboard.v1alpha1.WorkspaceStatus - 4, // [4:4] is the sub-list for method output_type - 4, // [4:4] is the sub-list for method input_type - 4, // [4:4] is the sub-list for extension type_name - 4, // [4:4] is the sub-list for extension extendee - 0, // [0:4] is the sub-list for field type_name + 5, // 2: dashboard.v1alpha1.WorkspaceStatus.lastStartedAt:type_name -> google.protobuf.Timestamp + 1, // 3: dashboard.v1alpha1.Workspace.spec:type_name -> dashboard.v1alpha1.WorkspaceSpec + 2, // 4: dashboard.v1alpha1.Workspace.status:type_name -> dashboard.v1alpha1.WorkspaceStatus + 5, // [5:5] is the sub-list for method output_type + 5, // [5:5] is the sub-list for method input_type + 5, // [5:5] is the sub-list for extension type_name + 5, // [5:5] is the sub-list for extension extendee + 0, // [0:5] is the sub-list for field type_name } func init() { file_dashboard_v1alpha1_workspace_proto_init() } diff --git a/proto/gen/dashboard/v1alpha1/workspace.pb.validate.go b/proto/gen/dashboard/v1alpha1/workspace.pb.validate.go index 92c0b724..60f8fa6e 100644 --- a/proto/gen/dashboard/v1alpha1/workspace.pb.validate.go +++ b/proto/gen/dashboard/v1alpha1/workspace.pb.validate.go @@ -319,6 +319,35 @@ func (m *WorkspaceStatus) validate(all bool) error { // no validation rules for MainUrl + if all { + switch v := interface{}(m.GetLastStartedAt()).(type) { + case interface{ ValidateAll() error }: + if err := v.ValidateAll(); err != nil { + errors = append(errors, WorkspaceStatusValidationError{ + field: "LastStartedAt", + reason: "embedded message failed validation", + cause: err, + }) + } + case interface{ Validate() error }: + if err := v.Validate(); err != nil { + errors = append(errors, WorkspaceStatusValidationError{ + field: "LastStartedAt", + reason: "embedded message failed validation", + cause: err, + }) + } + } + } else if v, ok := interface{}(m.GetLastStartedAt()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return WorkspaceStatusValidationError{ + field: "LastStartedAt", + reason: "embedded message failed validation", + cause: err, + } + } + } + if len(errors) > 0 { return WorkspaceStatusMultiError(errors) } diff --git a/proto/gen/index.md b/proto/gen/index.md index 4068643d..9b4be009 100644 --- a/proto/gen/index.md +++ b/proto/gen/index.md @@ -16,18 +16,6 @@ - [EventSeries](#dashboard-v1alpha1-EventSeries) - [ObjectReference](#dashboard-v1alpha1-ObjectReference) -- [dashboard/v1alpha1/template.proto](#dashboard_v1alpha1_template-proto) - - [Template](#dashboard-v1alpha1-Template) - - [TemplateRequiredVars](#dashboard-v1alpha1-TemplateRequiredVars) - -- [dashboard/v1alpha1/template_service.proto](#dashboard_v1alpha1_template_service-proto) - - [GetUserAddonTemplatesRequest](#dashboard-v1alpha1-GetUserAddonTemplatesRequest) - - [GetUserAddonTemplatesResponse](#dashboard-v1alpha1-GetUserAddonTemplatesResponse) - - [GetWorkspaceTemplatesRequest](#dashboard-v1alpha1-GetWorkspaceTemplatesRequest) - - [GetWorkspaceTemplatesResponse](#dashboard-v1alpha1-GetWorkspaceTemplatesResponse) - - - [TemplateService](#dashboard-v1alpha1-TemplateService) - - [dashboard/v1alpha1/user.proto](#dashboard_v1alpha1_user-proto) - [User](#dashboard-v1alpha1-User) - [UserAddon](#dashboard-v1alpha1-UserAddon) @@ -38,6 +26,8 @@ - [CreateUserResponse](#dashboard-v1alpha1-CreateUserResponse) - [DeleteUserRequest](#dashboard-v1alpha1-DeleteUserRequest) - [DeleteUserResponse](#dashboard-v1alpha1-DeleteUserResponse) + - [GetEventsRequest](#dashboard-v1alpha1-GetEventsRequest) + - [GetEventsResponse](#dashboard-v1alpha1-GetEventsResponse) - [GetUserRequest](#dashboard-v1alpha1-GetUserRequest) - [GetUserResponse](#dashboard-v1alpha1-GetUserResponse) - [GetUsersRequest](#dashboard-v1alpha1-GetUsersRequest) @@ -53,6 +43,21 @@ - [UserService](#dashboard-v1alpha1-UserService) +- [dashboard/v1alpha1/event_service.proto](#dashboard_v1alpha1_event_service-proto) + - [StreamService](#dashboard-v1alpha1-StreamService) + +- [dashboard/v1alpha1/template.proto](#dashboard_v1alpha1_template-proto) + - [Template](#dashboard-v1alpha1-Template) + - [TemplateRequiredVars](#dashboard-v1alpha1-TemplateRequiredVars) + +- [dashboard/v1alpha1/template_service.proto](#dashboard_v1alpha1_template_service-proto) + - [GetUserAddonTemplatesRequest](#dashboard-v1alpha1-GetUserAddonTemplatesRequest) + - [GetUserAddonTemplatesResponse](#dashboard-v1alpha1-GetUserAddonTemplatesResponse) + - [GetWorkspaceTemplatesRequest](#dashboard-v1alpha1-GetWorkspaceTemplatesRequest) + - [GetWorkspaceTemplatesResponse](#dashboard-v1alpha1-GetWorkspaceTemplatesResponse) + + - [TemplateService](#dashboard-v1alpha1-TemplateService) + - [dashboard/v1alpha1/webauthn.proto](#dashboard_v1alpha1_webauthn-proto) - [BeginLoginRequest](#dashboard-v1alpha1-BeginLoginRequest) - [BeginLoginResponse](#dashboard-v1alpha1-BeginLoginResponse) @@ -212,13 +217,16 @@ | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | +| id | [string](#string) | | | +| user | [string](#string) | | | | eventTime | [google.protobuf.Timestamp](#google-protobuf-Timestamp) | | | | type | [string](#string) | | | | note | [string](#string) | | | | reason | [string](#string) | | | | regarding | [ObjectReference](#dashboard-v1alpha1-ObjectReference) | | | | reportingController | [string](#string) | | | -| series | [EventSeries](#dashboard-v1alpha1-EventSeries) | optional | | +| series | [EventSeries](#dashboard-v1alpha1-EventSeries) | | | +| regardingWorkspace | [string](#string) | optional | | @@ -268,28 +276,28 @@ - +

Top

-## dashboard/v1alpha1/template.proto +## dashboard/v1alpha1/user.proto - + -### Template +### User | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | | name | [string](#string) | | | -| description | [string](#string) | | | -| required_vars | [TemplateRequiredVars](#dashboard-v1alpha1-TemplateRequiredVars) | repeated | | -| is_default_user_addon | [bool](#bool) | optional | | -| is_cluster_scope | [bool](#bool) | | | -| required_useraddons | [string](#string) | repeated | | -| userroles | [string](#string) | repeated | | +| display_name | [string](#string) | | | +| roles | [string](#string) | repeated | | +| auth_type | [string](#string) | | | +| addons | [UserAddon](#dashboard-v1alpha1-UserAddon) | repeated | | +| default_password | [string](#string) | | | +| status | [string](#string) | | | | raw | [string](#string) | optional | | @@ -297,16 +305,33 @@ - + -### TemplateRequiredVars +### UserAddon | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| var_name | [string](#string) | | | -| default_value | [string](#string) | | | +| template | [string](#string) | | | +| cluster_scoped | [bool](#bool) | | | +| vars | [UserAddon.VarsEntry](#dashboard-v1alpha1-UserAddon-VarsEntry) | repeated | | + + + + + + + + +### UserAddon.VarsEntry + + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| key | [string](#string) | | | +| value | [string](#string) | | | @@ -322,188 +347,182 @@ - +

Top

-## dashboard/v1alpha1/template_service.proto +## dashboard/v1alpha1/user_service.proto - + -### GetUserAddonTemplatesRequest +### CreateUserRequest | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| use_role_filter | [bool](#bool) | optional | | -| with_raw | [bool](#bool) | optional | | +| user_name | [string](#string) | | | +| display_name | [string](#string) | | | +| roles | [string](#string) | repeated | | +| auth_type | [string](#string) | | | +| addons | [UserAddon](#dashboard-v1alpha1-UserAddon) | repeated | | - + -### GetUserAddonTemplatesResponse +### CreateUserResponse | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | | message | [string](#string) | | | -| items | [Template](#dashboard-v1alpha1-Template) | repeated | | +| user | [User](#dashboard-v1alpha1-User) | | | - + -### GetWorkspaceTemplatesRequest +### DeleteUserRequest | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| use_role_filter | [bool](#bool) | optional | | -| with_raw | [bool](#bool) | optional | | +| user_name | [string](#string) | | | - + -### GetWorkspaceTemplatesResponse +### DeleteUserResponse | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | | message | [string](#string) | | | -| items | [Template](#dashboard-v1alpha1-Template) | repeated | | +| user | [User](#dashboard-v1alpha1-User) | | | - - + - +### GetEventsRequest - -### TemplateService +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| user_name | [string](#string) | | | +| from | [google.protobuf.Timestamp](#google-protobuf-Timestamp) | optional | | -| Method Name | Request Type | Response Type | Description | -| ----------- | ------------ | ------------- | ------------| -| GetUserAddonTemplates | [GetUserAddonTemplatesRequest](#dashboard-v1alpha1-GetUserAddonTemplatesRequest) | [GetUserAddonTemplatesResponse](#dashboard-v1alpha1-GetUserAddonTemplatesResponse) | List templates typed useraddon | -| GetWorkspaceTemplates | [GetWorkspaceTemplatesRequest](#dashboard-v1alpha1-GetWorkspaceTemplatesRequest) | [GetWorkspaceTemplatesResponse](#dashboard-v1alpha1-GetWorkspaceTemplatesResponse) | List templates typed workspace | - - -

Top

+ + +### GetEventsResponse + + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| message | [string](#string) | | | +| items | [Event](#dashboard-v1alpha1-Event) | repeated | | -## dashboard/v1alpha1/user.proto - -### User + + + +### GetUserRequest | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| name | [string](#string) | | | -| display_name | [string](#string) | | | -| roles | [string](#string) | repeated | | -| auth_type | [string](#string) | | | -| addons | [UserAddon](#dashboard-v1alpha1-UserAddon) | repeated | | -| default_password | [string](#string) | | | -| status | [string](#string) | | | -| raw | [string](#string) | optional | | -| events | [Event](#dashboard-v1alpha1-Event) | repeated | | +| user_name | [string](#string) | | | +| with_raw | [bool](#bool) | optional | | - + -### UserAddon +### GetUserResponse | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| template | [string](#string) | | | -| cluster_scoped | [bool](#bool) | | | -| vars | [UserAddon.VarsEntry](#dashboard-v1alpha1-UserAddon-VarsEntry) | repeated | | +| user | [User](#dashboard-v1alpha1-User) | | | - + -### UserAddon.VarsEntry +### GetUsersRequest | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| key | [string](#string) | | | -| value | [string](#string) | | | +| with_raw | [bool](#bool) | optional | | - - + - +### GetUsersResponse - +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| message | [string](#string) | | | +| items | [User](#dashboard-v1alpha1-User) | repeated | | - -

Top

-## dashboard/v1alpha1/user_service.proto - -### CreateUserRequest + + +### UpdateUserAddonsRequest | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | | user_name | [string](#string) | | | -| display_name | [string](#string) | | | -| roles | [string](#string) | repeated | | -| auth_type | [string](#string) | | | | addons | [UserAddon](#dashboard-v1alpha1-UserAddon) | repeated | | @@ -511,9 +530,9 @@ - + -### CreateUserResponse +### UpdateUserAddonsResponse @@ -527,24 +546,25 @@ - + -### DeleteUserRequest +### UpdateUserDisplayNameRequest | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | | user_name | [string](#string) | | | +| display_name | [string](#string) | | | - + -### DeleteUserResponse +### UpdateUserDisplayNameResponse @@ -558,190 +578,242 @@ - + -### GetUserRequest +### UpdateUserPasswordRequest | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | | user_name | [string](#string) | | | -| with_raw | [bool](#bool) | optional | | +| current_password | [string](#string) | | | +| new_password | [string](#string) | | | - + -### GetUserResponse +### UpdateUserPasswordResponse | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| user | [User](#dashboard-v1alpha1-User) | | | +| message | [string](#string) | | | - + -### GetUsersRequest +### UpdateUserRoleRequest | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| with_raw | [bool](#bool) | optional | | +| user_name | [string](#string) | | | +| roles | [string](#string) | repeated | | - + -### GetUsersResponse +### UpdateUserRoleResponse | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | | message | [string](#string) | | | -| items | [User](#dashboard-v1alpha1-User) | repeated | | +| user | [User](#dashboard-v1alpha1-User) | | | + - + -### UpdateUserAddonsRequest + + -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| user_name | [string](#string) | | | -| addons | [UserAddon](#dashboard-v1alpha1-UserAddon) | repeated | | +### UserService +| Method Name | Request Type | Response Type | Description | +| ----------- | ------------ | ------------- | ------------| +| DeleteUser | [DeleteUserRequest](#dashboard-v1alpha1-DeleteUserRequest) | [DeleteUserResponse](#dashboard-v1alpha1-DeleteUserResponse) | Delete user by ID | +| GetUser | [GetUserRequest](#dashboard-v1alpha1-GetUserRequest) | [GetUserResponse](#dashboard-v1alpha1-GetUserResponse) | Returns a single User model | +| GetUsers | [GetUsersRequest](#dashboard-v1alpha1-GetUsersRequest) | [GetUsersResponse](#dashboard-v1alpha1-GetUsersResponse) | Returns an array of User model | +| GetEvents | [GetEventsRequest](#dashboard-v1alpha1-GetEventsRequest) | [GetEventsResponse](#dashboard-v1alpha1-GetEventsResponse) | Returns events for User | +| CreateUser | [CreateUserRequest](#dashboard-v1alpha1-CreateUserRequest) | [CreateUserResponse](#dashboard-v1alpha1-CreateUserResponse) | Create a new User | +| UpdateUserDisplayName | [UpdateUserDisplayNameRequest](#dashboard-v1alpha1-UpdateUserDisplayNameRequest) | [UpdateUserDisplayNameResponse](#dashboard-v1alpha1-UpdateUserDisplayNameResponse) | Update user display name | +| UpdateUserPassword | [UpdateUserPasswordRequest](#dashboard-v1alpha1-UpdateUserPasswordRequest) | [UpdateUserPasswordResponse](#dashboard-v1alpha1-UpdateUserPasswordResponse) | Update a single User password | +| UpdateUserRole | [UpdateUserRoleRequest](#dashboard-v1alpha1-UpdateUserRoleRequest) | [UpdateUserRoleResponse](#dashboard-v1alpha1-UpdateUserRoleResponse) | Update a single User role | +| UpdateUserAddons | [UpdateUserAddonsRequest](#dashboard-v1alpha1-UpdateUserAddonsRequest) | [UpdateUserAddonsResponse](#dashboard-v1alpha1-UpdateUserAddonsResponse) | Update a single User role | + - + +

Top

-### UpdateUserAddonsResponse +## dashboard/v1alpha1/event_service.proto + -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| message | [string](#string) | | | -| user | [User](#dashboard-v1alpha1-User) | | | + + + +### StreamService - +| Method Name | Request Type | Response Type | Description | +| ----------- | ------------ | ------------- | ------------| +| StreamingEvents | [GetEventsRequest](#dashboard-v1alpha1-GetEventsRequest) | [GetEventsResponse](#dashboard-v1alpha1-GetEventsResponse) stream | Streaming new events for user | + + + + + + +

Top

+ +## dashboard/v1alpha1/template.proto -### UpdateUserDisplayNameRequest + + + + +### Template | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| user_name | [string](#string) | | | -| display_name | [string](#string) | | | +| name | [string](#string) | | | +| description | [string](#string) | | | +| required_vars | [TemplateRequiredVars](#dashboard-v1alpha1-TemplateRequiredVars) | repeated | | +| is_default_user_addon | [bool](#bool) | optional | | +| is_cluster_scope | [bool](#bool) | | | +| required_useraddons | [string](#string) | repeated | | +| userroles | [string](#string) | repeated | | +| raw | [string](#string) | optional | | - + -### UpdateUserDisplayNameResponse +### TemplateRequiredVars | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| message | [string](#string) | | | -| user | [User](#dashboard-v1alpha1-User) | | | +| var_name | [string](#string) | | | +| default_value | [string](#string) | | | + - + + + + + + + + + +

Top

+ +## dashboard/v1alpha1/template_service.proto -### UpdateUserPasswordRequest + + + + +### GetUserAddonTemplatesRequest | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| user_name | [string](#string) | | | -| current_password | [string](#string) | | | -| new_password | [string](#string) | | | +| use_role_filter | [bool](#bool) | optional | | +| with_raw | [bool](#bool) | optional | | - + -### UpdateUserPasswordResponse +### GetUserAddonTemplatesResponse | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | | message | [string](#string) | | | +| items | [Template](#dashboard-v1alpha1-Template) | repeated | | - + -### UpdateUserRoleRequest +### GetWorkspaceTemplatesRequest | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | -| user_name | [string](#string) | | | -| roles | [string](#string) | repeated | | +| use_role_filter | [bool](#bool) | optional | | +| with_raw | [bool](#bool) | optional | | - + -### UpdateUserRoleResponse +### GetWorkspaceTemplatesResponse | Field | Type | Label | Description | | ----- | ---- | ----- | ----------- | | message | [string](#string) | | | -| user | [User](#dashboard-v1alpha1-User) | | | +| items | [Template](#dashboard-v1alpha1-Template) | repeated | | @@ -754,21 +826,15 @@ - + -### UserService +### TemplateService | Method Name | Request Type | Response Type | Description | | ----------- | ------------ | ------------- | ------------| -| DeleteUser | [DeleteUserRequest](#dashboard-v1alpha1-DeleteUserRequest) | [DeleteUserResponse](#dashboard-v1alpha1-DeleteUserResponse) | Delete user by ID | -| GetUser | [GetUserRequest](#dashboard-v1alpha1-GetUserRequest) | [GetUserResponse](#dashboard-v1alpha1-GetUserResponse) | Returns a single User model | -| GetUsers | [GetUsersRequest](#dashboard-v1alpha1-GetUsersRequest) | [GetUsersResponse](#dashboard-v1alpha1-GetUsersResponse) | Returns an array of User model | -| CreateUser | [CreateUserRequest](#dashboard-v1alpha1-CreateUserRequest) | [CreateUserResponse](#dashboard-v1alpha1-CreateUserResponse) | Create a new User | -| UpdateUserDisplayName | [UpdateUserDisplayNameRequest](#dashboard-v1alpha1-UpdateUserDisplayNameRequest) | [UpdateUserDisplayNameResponse](#dashboard-v1alpha1-UpdateUserDisplayNameResponse) | Update user display name | -| UpdateUserPassword | [UpdateUserPasswordRequest](#dashboard-v1alpha1-UpdateUserPasswordRequest) | [UpdateUserPasswordResponse](#dashboard-v1alpha1-UpdateUserPasswordResponse) | Update a single User password | -| UpdateUserRole | [UpdateUserRoleRequest](#dashboard-v1alpha1-UpdateUserRoleRequest) | [UpdateUserRoleResponse](#dashboard-v1alpha1-UpdateUserRoleResponse) | Update a single User role | -| UpdateUserAddons | [UpdateUserAddonsRequest](#dashboard-v1alpha1-UpdateUserAddonsRequest) | [UpdateUserAddonsResponse](#dashboard-v1alpha1-UpdateUserAddonsResponse) | Update a single User role | +| GetUserAddonTemplates | [GetUserAddonTemplatesRequest](#dashboard-v1alpha1-GetUserAddonTemplatesRequest) | [GetUserAddonTemplatesResponse](#dashboard-v1alpha1-GetUserAddonTemplatesResponse) | List templates typed useraddon | +| GetWorkspaceTemplates | [GetWorkspaceTemplatesRequest](#dashboard-v1alpha1-GetWorkspaceTemplatesRequest) | [GetWorkspaceTemplatesResponse](#dashboard-v1alpha1-GetWorkspaceTemplatesResponse) | List templates typed workspace | @@ -1129,6 +1195,7 @@ | ----- | ---- | ----- | ----------- | | phase | [string](#string) | | | | main_url | [string](#string) | | | +| lastStartedAt | [google.protobuf.Timestamp](#google-protobuf-Timestamp) | | | diff --git a/proto/proto/dashboard-apis/dashboard/v1alpha1/event.proto b/proto/proto/dashboard-apis/dashboard/v1alpha1/event.proto index 5e36bc50..d8420df9 100644 --- a/proto/proto/dashboard-apis/dashboard/v1alpha1/event.proto +++ b/proto/proto/dashboard-apis/dashboard/v1alpha1/event.proto @@ -10,13 +10,16 @@ package dashboard.v1alpha1; import "google/protobuf/timestamp.proto"; message Event { - google.protobuf.Timestamp eventTime = 1; - string type = 2; - string note = 3; - string reason = 4; - ObjectReference regarding = 5; - string reportingController = 6; - optional EventSeries series = 7; + string id = 1; + string user = 2; + google.protobuf.Timestamp eventTime = 3; + string type = 4; + string note = 5; + string reason = 6; + ObjectReference regarding = 7; + string reportingController = 8; + EventSeries series = 9; + optional string regardingWorkspace = 10; } message EventSeries { diff --git a/proto/proto/dashboard-apis/dashboard/v1alpha1/event_service.proto b/proto/proto/dashboard-apis/dashboard/v1alpha1/event_service.proto new file mode 100644 index 00000000..a2693d69 --- /dev/null +++ b/proto/proto/dashboard-apis/dashboard/v1alpha1/event_service.proto @@ -0,0 +1,16 @@ +/* + Cosmo Dashboard API + Manipulate cosmo dashboard resource API +*/ + +syntax = "proto3"; + +package dashboard.v1alpha1; + +import "dashboard/v1alpha1/event.proto"; +import "dashboard/v1alpha1/user_service.proto"; + +service StreamService { + // Streaming new events for user + rpc StreamingEvents(GetEventsRequest) returns (stream GetEventsResponse); +} diff --git a/proto/proto/dashboard-apis/dashboard/v1alpha1/user.proto b/proto/proto/dashboard-apis/dashboard/v1alpha1/user.proto index 2c2b73e3..8fe41fbc 100644 --- a/proto/proto/dashboard-apis/dashboard/v1alpha1/user.proto +++ b/proto/proto/dashboard-apis/dashboard/v1alpha1/user.proto @@ -8,7 +8,6 @@ syntax = "proto3"; package dashboard.v1alpha1; import "validate/validate.proto"; -import "dashboard/v1alpha1/event.proto"; message User { string name = 1; @@ -19,7 +18,6 @@ message User { string default_password = 6; string status = 7; optional string raw = 8; - repeated Event events = 9; } message UserAddon { diff --git a/proto/proto/dashboard-apis/dashboard/v1alpha1/user_service.proto b/proto/proto/dashboard-apis/dashboard/v1alpha1/user_service.proto index ae2e2bce..ccac148a 100644 --- a/proto/proto/dashboard-apis/dashboard/v1alpha1/user_service.proto +++ b/proto/proto/dashboard-apis/dashboard/v1alpha1/user_service.proto @@ -8,8 +8,11 @@ syntax = "proto3"; package dashboard.v1alpha1; import "dashboard/v1alpha1/user.proto"; +import "dashboard/v1alpha1/event.proto"; import "validate/validate.proto"; +import "google/protobuf/timestamp.proto"; + service UserService { // Delete user by ID rpc DeleteUser(DeleteUserRequest) returns (DeleteUserResponse); @@ -17,6 +20,8 @@ service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); // Returns an array of User model rpc GetUsers(GetUsersRequest) returns (GetUsersResponse); + // Returns events for User + rpc GetEvents(GetEventsRequest) returns (GetEventsResponse); // Create a new User rpc CreateUser(CreateUserRequest) returns (CreateUserResponse); // Update user display name @@ -110,3 +115,13 @@ message UpdateUserAddonsResponse { string message = 1; User user = 2; } + +message GetEventsRequest { + string user_name = 1; + optional google.protobuf.Timestamp from = 2; +} + +message GetEventsResponse { + string message = 1; + repeated Event items = 2; +} \ No newline at end of file diff --git a/proto/proto/dashboard-apis/dashboard/v1alpha1/workspace.proto b/proto/proto/dashboard-apis/dashboard/v1alpha1/workspace.proto index 811953a5..3dc13b25 100644 --- a/proto/proto/dashboard-apis/dashboard/v1alpha1/workspace.proto +++ b/proto/proto/dashboard-apis/dashboard/v1alpha1/workspace.proto @@ -7,6 +7,7 @@ syntax = "proto3"; package dashboard.v1alpha1; import "validate/validate.proto"; +import "google/protobuf/timestamp.proto"; message NetworkRule { int32 port_number = 1 [(validate.rules).int32 = { gt: 0, lt: 65536 }]; @@ -26,6 +27,7 @@ message WorkspaceSpec { message WorkspaceStatus { string phase = 1; string main_url = 2; + google.protobuf.Timestamp lastStartedAt = 3; } message Workspace { From 82a1e3b3e928f7fe2cf1d68e41655594ae1764c1 Mon Sep 17 00:00:00 2001 From: jlandowner Date: Sun, 2 Jun 2024 16:46:53 +0900 Subject: [PATCH 2/3] Update UI for support Events - Add EventPage - Add Event notifications icon on app bar - Refactoring WorkspaceList --- web/dashboard-ui/package.json | 3 +- web/dashboard-ui/src/App.tsx | 103 ++- .../src/components/LoginProvider.tsx | 324 +++++-- .../proto/gen/dashboard/v1alpha1/event_pb.ts | 46 +- .../v1alpha1/event_service_connectweb.ts | 32 + .../proto/gen/dashboard/v1alpha1/user_pb.ts | 7 - .../v1alpha1/user_service_connectweb.ts | 13 +- .../gen/dashboard/v1alpha1/user_service_pb.ts | 89 +- .../gen/dashboard/v1alpha1/workspace_pb.ts | 8 +- .../src/services/DashboardServices.ts | 4 + .../src/views/atoms/EventsDataGrid.tsx | 100 +++ .../src/views/organisms/EventDetailDialog.tsx | 175 ++++ .../src/views/organisms/EventModule.tsx | 75 ++ .../src/views/organisms/UserModule.tsx | 47 +- .../views/organisms/WorkspaceActionDialog.tsx | 4 +- .../src/views/organisms/WorkspaceModule.tsx | 432 ++++++--- .../src/views/pages/EventPage.tsx | 159 ++++ .../src/views/pages/WorkspacePage.tsx | 819 ++++++++++++------ .../src/views/templates/PageTemplate.tsx | 479 +++++++--- web/dashboard-ui/yarn.lock | 79 +- 20 files changed, 2312 insertions(+), 686 deletions(-) create mode 100644 web/dashboard-ui/src/proto/gen/dashboard/v1alpha1/event_service_connectweb.ts create mode 100644 web/dashboard-ui/src/views/atoms/EventsDataGrid.tsx create mode 100644 web/dashboard-ui/src/views/organisms/EventDetailDialog.tsx create mode 100644 web/dashboard-ui/src/views/organisms/EventModule.tsx create mode 100644 web/dashboard-ui/src/views/pages/EventPage.tsx diff --git a/web/dashboard-ui/package.json b/web/dashboard-ui/package.json index 1c9941db..d9010cca 100644 --- a/web/dashboard-ui/package.json +++ b/web/dashboard-ui/package.json @@ -20,6 +20,7 @@ "@emotion/styled": "11.11.0", "@mui/icons-material": "5.15.7", "@mui/material": "5.15.7", + "@mui/x-data-grid": "^7.5.1", "@types/node": "20.11.15", "base64url": "^3.0.1", "copy-to-clipboard": "3.3.3", @@ -48,4 +49,4 @@ "vite": "5.0.12", "vitest": "1.2.2" } -} \ No newline at end of file +} diff --git a/web/dashboard-ui/src/App.tsx b/web/dashboard-ui/src/App.tsx index fa3b4470..6aa11dfa 100644 --- a/web/dashboard-ui/src/App.tsx +++ b/web/dashboard-ui/src/App.tsx @@ -1,71 +1,90 @@ -import { CircularProgress } from '@mui/material'; -import { SnackbarProvider } from 'notistack'; -import React, { Suspense } from 'react'; -import { HashRouter, Navigate, Route, Routes } from 'react-router-dom'; -import './App.css'; -import { AuthRoute } from './components/AuthRoute'; -import { LoginProvider } from './components/LoginProvider'; -import { MyThemeProvider } from './components/MyThemeProvider'; -import { PageSettingsProvider } from './components/PageSettingsProvider'; -import { ProgressProvider } from './components/ProgressProvider'; -import { AuthenticatorManageDialogContext } from './views/organisms/AuthenticatorManageDialog'; -import { PasswordChangeDialogContext } from './views/organisms/PasswordChangeDialog'; -import { UserInfoDialogContext } from './views/organisms/UserActionDialog'; -import { UserAddonChangeDialogContext } from './views/organisms/UserAddonsChangeDialog'; -import { UserContext } from './views/organisms/UserModule'; -import { UserNameChangeDialogContext } from './views/organisms/UserNameChangeDialog'; -import { SignIn } from './views/pages/SignIn'; -import { UserPage } from './views/pages/UserPage'; -import { WorkspacePage } from './views/pages/WorkspacePage'; - -// const WorkspacePage = lazy( -// () => import('./views/pages/WorkspacePage').then(module => ({ default: module.WorkspacePage })) -// ); -// const UserPage = lazy( -// () => import('./views/pages/UserPage').then(module => ({ default: module.UserPage })) -// ); +import { CircularProgress } from "@mui/material"; +import { SnackbarProvider } from "notistack"; +import React, { Suspense } from "react"; +import { HashRouter, Navigate, Route, Routes } from "react-router-dom"; +import "./App.css"; +import { AuthRoute } from "./components/AuthRoute"; +import { LoginProvider } from "./components/LoginProvider"; +import { MyThemeProvider } from "./components/MyThemeProvider"; +import { PageSettingsProvider } from "./components/PageSettingsProvider"; +import { ProgressProvider } from "./components/ProgressProvider"; +import { AuthenticatorManageDialogContext } from "./views/organisms/AuthenticatorManageDialog"; +import { EventDetailDialogContext } from "./views/organisms/EventDetailDialog"; +import { PasswordChangeDialogContext } from "./views/organisms/PasswordChangeDialog"; +import { UserInfoDialogContext } from "./views/organisms/UserActionDialog"; +import { UserAddonChangeDialogContext } from "./views/organisms/UserAddonsChangeDialog"; +import { UserContext } from "./views/organisms/UserModule"; +import { UserNameChangeDialogContext } from "./views/organisms/UserNameChangeDialog"; +import { EventPage } from "./views/pages/EventPage"; +import { SignIn } from "./views/pages/SignIn"; +import { UserPage } from "./views/pages/UserPage"; +import { WorkspacePage } from "./views/pages/WorkspacePage"; const Loading: React.VFC = () => { return (
- ) -} + ); +}; function SwitchApp() { return ( } /> - } /> - } /> - } /> + + + + } + /> + + + + } + /> + + + + } + /> + } /> ); } - function App() { - console.log('App'); + console.log("App"); return ( }>
- + - + @@ -73,7 +92,9 @@ function App() { - + + + @@ -81,7 +102,7 @@ function App() { - + diff --git a/web/dashboard-ui/src/components/LoginProvider.tsx b/web/dashboard-ui/src/components/LoginProvider.tsx index d923f92c..ee3fbbe0 100644 --- a/web/dashboard-ui/src/components/LoginProvider.tsx +++ b/web/dashboard-ui/src/components/LoginProvider.tsx @@ -1,17 +1,33 @@ -import { Box, CircularProgress, CssBaseline, Stack, Typography } from '@mui/material'; -import { useSnackbar } from 'notistack'; -import React, { createContext, useContext, useEffect, useState } from 'react'; -import { User } from '../proto/gen/dashboard/v1alpha1/user_pb'; -import { useAuthService, useUserService, useWebAuthnService } from '../services/DashboardServices'; -import { base64url } from './Base64'; -import { useProgress } from './ProgressProvider'; - +import { Code, ConnectError } from "@bufbuild/connect"; +import { + Box, + CircularProgress, + CssBaseline, + Stack, + Typography, +} from "@mui/material"; +import { useSnackbar } from "notistack"; +import React, { createContext, useContext, useEffect, useState } from "react"; +import { useNavigate } from "react-router-dom"; +import { Event } from "../proto/gen/dashboard/v1alpha1/event_pb"; +import { User } from "../proto/gen/dashboard/v1alpha1/user_pb"; +import { + useAuthService, + useStreamService, + useUserService, + useWebAuthnService, +} from "../services/DashboardServices"; +import { latestTime } from "../views/organisms/EventModule"; +import { base64url } from "./Base64"; +import { useProgress } from "./ProgressProvider"; /** * context * ref: https://github.com/DefinitelyTyped/DefinitelyTyped/pull/24509#issuecomment-774430643 */ -const Context = createContext>(undefined as any); +const Context = createContext>( + undefined as any, +); /** * hooks @@ -21,48 +37,124 @@ export function useLogin() { } const useLoginModule = () => { - console.log('useLoginModule'); + console.log("useLoginModule"); const [loginUser, setLoginUser] = useState(); + const isSignIn = Boolean(loginUser); + const { enqueueSnackbar } = useSnackbar(); const { setMask, releaseMask } = useProgress(); const userService = useUserService(); const authService = useAuthService(); const webauthnService = useWebAuthnService(); + const [myEvents, setMyEvents] = useState([]); + const [newEventsCount, setNewEventsCount] = useState(0); + const [clock, setClock] = useState(new Date()); + + const streamService = useStreamService(); + const [isWatching, setIsWatching] = React.useState(false); + + const updateClock = () => setClock(new Date()); + + const handleMyEvents = (events: Event[]) => { + for (const event of events) { + const index = myEvents.findIndex((e) => (e.id === event.id)); + if (index >= 0) { + // replace event + console.log("!!! replace", event.id, index); + myEvents[index] = event; + myEvents.sort((a, b) => latestTime(b) - latestTime(a)); + setMyEvents(myEvents); + } else { + // put event on the top of event list + console.log("!!! new", event.id); + myEvents.push(event); + myEvents.sort((a, b) => latestTime(b) - latestTime(a)); + setMyEvents(myEvents); + } + } + }; + + const watchMyEvents = async () => { + if (isSignIn) { + const watchEvents = async (retryCount: number) => { + console.log("Start watching events...", loginUser?.name, retryCount); + try { + const result = await streamService.streamingEvents({ + userName: loginUser?.name, + }, {}); + for await (const event of result) { + updateClock(); + setNewEventsCount((v) => v + 1); + handleMyEvents(event.items); + retryCount = 0; + } + } catch (error) { + console.log("watch failed", error, "retryCount", retryCount); + if (retryCount < 10) { + retryCount += 1; + const waitTime = Math.floor(Math.random() * 5 + 1) * 1000; + console.log("watch re-conntect after milisec", waitTime); + setTimeout(() => watchEvents(retryCount), waitTime); + } else { + console.log("Reached retry limit for watching events"); + } + } + }; + if (!isWatching) { + setIsWatching(true); + watchEvents(0); + setIsWatching(false); + } + } + }; + /** * loginWithWebAuthn */ const loginWithWebAuthn = async (userName: string) => { - console.log('loginWithWebAuthn start'); + console.log("loginWithWebAuthn start"); try { const credId = localStorage.getItem(`credId`); if (credId === null) { - throw Error('credId is null'); + throw Error("credId is null"); } - const beginResp = await webauthnService.beginLogin({ userName: userName }); + const beginResp = await webauthnService.beginLogin({ + userName: userName, + }); const options = JSON.parse(beginResp.credentialRequestOptions); const opt: CredentialRequestOptions = JSON.parse(JSON.stringify(options)); if (options.publicKey?.challenge) { - opt.publicKey!.challenge = base64url.decode(options.publicKey?.challenge); + opt.publicKey!.challenge = base64url.decode( + options.publicKey?.challenge, + ); } let allowed = false; - for (let index = 0; index < options.publicKey?.allowCredentials.length; index++) { - if (options.publicKey?.allowCredentials[index].id === credId) { allowed = true }; + for ( + let index = 0; + index < options.publicKey?.allowCredentials.length; + index++ + ) { + if (options.publicKey?.allowCredentials[index].id === credId) { + allowed = true; + } if (options.publicKey?.allowCredentials) { - opt.publicKey!.allowCredentials![index].id = base64url.decode(options.publicKey?.allowCredentials[index].id); + opt.publicKey!.allowCredentials![index].id = base64url.decode( + options.publicKey?.allowCredentials[index].id, + ); } } - if (!allowed) { throw Error('invalid credentials'); } + if (!allowed) throw Error("invalid credentials"); // Credential is allowed to access only id and type so use any. const cred: any = await navigator.credentials.get(opt); if (cred === null) { console.log("cred is null"); - throw Error('credential is null'); + throw Error("credential is null"); } const credential = { @@ -77,136 +169,158 @@ const useLoginModule = () => { }, }; - const finResp = await webauthnService.finishLogin({ userName: userName, credentialRequestResult: JSON.stringify(credential) }); + const finResp = await webauthnService.finishLogin({ + userName: userName, + credentialRequestResult: JSON.stringify(credential), + }); await getMyUserInfo(userName); - console.log('loginWithWebAuthn end', finResp); + console.log("loginWithWebAuthn end", finResp); return; - } - catch (error) { + } catch (error) { setLoginUser(undefined); error instanceof DOMException || handleError(error); throw error; } - } - + }; /** * verifyLogin */ const verifyLogin = async () => { - console.log('verify start'); + console.log("verify start"); try { const resp = await authService.verify({}); if (resp.userName) { await getMyUserInfo(resp.userName); } - } - catch (error) { + } catch (error) { setLoginUser(undefined); //handleError(error); + } finally { + console.log("verify end"); } - finally { - console.log('verify end'); - } - } - + }; /** - * login: SignIn + * login: SignIn */ const login = async (userName: string, password: string) => { - console.log('login'); + console.log("login"); try { - const res = await authService.login({ userName: userName, password: password }); + const res = await authService.login({ + userName: userName, + password: password, + }); await getMyUserInfo(userName); - console.log('login end'); + console.log("login end"); return res; - } - catch (error) { + } catch (error) { setLoginUser(undefined); - console.log('login error'); + console.log("login error"); handleError(error); throw error; } - } - + }; /** * login: MyUserInfo */ const getMyUserInfo = async (userName: string) => { - console.log('getMyUserInfo', userName); + console.log("getMyUserInfo", userName); // if (loginUser || !username) { // console.log('getMyUserInfo cancel', loginUser, username); // return; // } try { const responseUser = await userService.getUser({ userName: userName }); - setLoginUser(prev => { console.log('setLoginUser', prev, responseUser.user); return responseUser.user! }); - } - catch (error) { - console.log('getMyUserInfo error'); + setLoginUser((prev) => { + console.log("setLoginUser", prev, responseUser.user); + return responseUser.user!; + }); + } catch (error) { + console.log("getMyUserInfo error"); handleError(error); throw error; } - } + }; /** * login: MyUserInfo */ const refreshUserInfo = async () => { - console.log('refreshUserInfo'); + console.log("refreshUserInfo"); if (loginUser) { getMyUserInfo(loginUser.name); } - } + }; /** - * logout: Pagetemplate + * logout: Pagetemplate */ const logout = async () => { - console.log('logout'); + console.log("logout"); try { await authService.logout({}); - } - catch (error) { - console.log('logout error'); + } catch (error) { + console.log("logout error"); handleError(error); throw error; + } finally { + console.log("logout end"); + setLoginUser((prev) => { + console.log("setLoginUser", `${prev} -> undefined`); + return undefined; + }); } - finally { - console.log('logout end'); - setLoginUser(prev => { console.log('setLoginUser', `${prev} -> undefined`); return undefined }); - } - } + }; /** * updataPassword */ - const updataPassword = async (currentPassword: string, newPassword: string) => { - console.log('updataPassword', loginUser?.name); + const updataPassword = async ( + currentPassword: string, + newPassword: string, + ) => { + console.log("updataPassword", loginUser?.name); setMask(); try { try { - return await userService.updateUserPassword({ userName: loginUser!.name, currentPassword, newPassword }); - } - catch (error) { + return await userService.updateUserPassword({ + userName: loginUser!.name, + currentPassword, + newPassword, + }); + } catch (error) { handleError(error); throw error; } - } - finally { - console.log('updataPassword end'); + } finally { + console.log("updataPassword end"); releaseMask(); } - } + }; /** - * clearLoginUser + * clearLoginUser */ const clearLoginUser = async () => { setLoginUser(undefined); - } + }; + + const getMyEvents = async () => { + if (loginUser) { + try { + const result = await userService.getEvents({ + userName: loginUser?.name, + }); + handleMyEvents(result.items); + } catch (error) { + handleError(error); + } + } else { + console.error("getEvents called before login"); + } + }; /** * error handler @@ -214,8 +328,8 @@ const useLoginModule = () => { const handleError = (error: any) => { console.log(error); const msg = error?.message; - msg && enqueueSnackbar(msg, { variant: 'error' }); - } + msg && enqueueSnackbar(msg, { variant: "error" }); + }; return { loginUser, @@ -226,14 +340,23 @@ const useLoginModule = () => { refreshUserInfo, updataPassword, clearLoginUser, + myEvents, + getMyEvents, + watchMyEvents, + newEventsCount, + setNewEventsCount, + clock, + updateClock, }; -} +}; /** * Provider */ -export const LoginProvider: React.FC> = ({ children }) => { - console.log('LoginProvider'); +export const LoginProvider: React.FC> = ( + { children }, +) => { + console.log("LoginProvider"); const loginModule = useLoginModule(); const [isVerified, setIsVerified] = useState(false); @@ -244,23 +367,48 @@ export const LoginProvider: React.FC> = ({ chil return ( - {isVerified ? children : + {isVerified ? children : (
- - + + - verifying session... + verifying session... -
} -
- ) -} +
+ )} + + ); +}; /** - * export private member. (for test) + * error handler */ -// export const __local__ = { -// useLoginModule, -// }; +export function useHandleError() { + const { enqueueSnackbar } = useSnackbar(); + const navigate = useNavigate(); + const { clearLoginUser } = useLogin(); + + const handleError = (error: any) => { + console.log("handleError", error, "metadata", error?.metadata); + + if ( + error instanceof ConnectError && + (error.code === Code.Unauthenticated || + (error.message.includes("302") && error.code === Code.Unknown)) + ) { + clearLoginUser(); + navigate("/signin"); + const msg = error.message.includes("302") + ? "session expired" + : error?.message; + msg && enqueueSnackbar(msg, { variant: "error" }); + } else { + const msg = error?.message; + msg && enqueueSnackbar(msg, { variant: "error" }); + } + throw error; + }; + return { handleError }; +} diff --git a/web/dashboard-ui/src/proto/gen/dashboard/v1alpha1/event_pb.ts b/web/dashboard-ui/src/proto/gen/dashboard/v1alpha1/event_pb.ts index ca67dad8..e7ec2a44 100644 --- a/web/dashboard-ui/src/proto/gen/dashboard/v1alpha1/event_pb.ts +++ b/web/dashboard-ui/src/proto/gen/dashboard/v1alpha1/event_pb.ts @@ -15,40 +15,55 @@ import { Message, proto3, Timestamp } from "@bufbuild/protobuf"; */ export class Event extends Message { /** - * @generated from field: google.protobuf.Timestamp eventTime = 1; + * @generated from field: string id = 1; + */ + id = ""; + + /** + * @generated from field: string user = 2; + */ + user = ""; + + /** + * @generated from field: google.protobuf.Timestamp eventTime = 3; */ eventTime?: Timestamp; /** - * @generated from field: string type = 2; + * @generated from field: string type = 4; */ type = ""; /** - * @generated from field: string note = 3; + * @generated from field: string note = 5; */ note = ""; /** - * @generated from field: string reason = 4; + * @generated from field: string reason = 6; */ reason = ""; /** - * @generated from field: dashboard.v1alpha1.ObjectReference regarding = 5; + * @generated from field: dashboard.v1alpha1.ObjectReference regarding = 7; */ regarding?: ObjectReference; /** - * @generated from field: string reportingController = 6; + * @generated from field: string reportingController = 8; */ reportingController = ""; /** - * @generated from field: optional dashboard.v1alpha1.EventSeries series = 7; + * @generated from field: dashboard.v1alpha1.EventSeries series = 9; */ series?: EventSeries; + /** + * @generated from field: optional string regardingWorkspace = 10; + */ + regardingWorkspace?: string; + constructor(data?: PartialMessage) { super(); proto3.util.initPartial(data, this); @@ -57,13 +72,16 @@ export class Event extends Message { static readonly runtime: typeof proto3 = proto3; static readonly typeName = "dashboard.v1alpha1.Event"; static readonly fields: FieldList = proto3.util.newFieldList(() => [ - { no: 1, name: "eventTime", kind: "message", T: Timestamp }, - { no: 2, name: "type", kind: "scalar", T: 9 /* ScalarType.STRING */ }, - { no: 3, name: "note", kind: "scalar", T: 9 /* ScalarType.STRING */ }, - { no: 4, name: "reason", kind: "scalar", T: 9 /* ScalarType.STRING */ }, - { no: 5, name: "regarding", kind: "message", T: ObjectReference }, - { no: 6, name: "reportingController", kind: "scalar", T: 9 /* ScalarType.STRING */ }, - { no: 7, name: "series", kind: "message", T: EventSeries, opt: true }, + { no: 1, name: "id", kind: "scalar", T: 9 /* ScalarType.STRING */ }, + { no: 2, name: "user", kind: "scalar", T: 9 /* ScalarType.STRING */ }, + { no: 3, name: "eventTime", kind: "message", T: Timestamp }, + { no: 4, name: "type", kind: "scalar", T: 9 /* ScalarType.STRING */ }, + { no: 5, name: "note", kind: "scalar", T: 9 /* ScalarType.STRING */ }, + { no: 6, name: "reason", kind: "scalar", T: 9 /* ScalarType.STRING */ }, + { no: 7, name: "regarding", kind: "message", T: ObjectReference }, + { no: 8, name: "reportingController", kind: "scalar", T: 9 /* ScalarType.STRING */ }, + { no: 9, name: "series", kind: "message", T: EventSeries }, + { no: 10, name: "regardingWorkspace", kind: "scalar", T: 9 /* ScalarType.STRING */, opt: true }, ]); static fromBinary(bytes: Uint8Array, options?: Partial): Event { diff --git a/web/dashboard-ui/src/proto/gen/dashboard/v1alpha1/event_service_connectweb.ts b/web/dashboard-ui/src/proto/gen/dashboard/v1alpha1/event_service_connectweb.ts new file mode 100644 index 00000000..4e49cef4 --- /dev/null +++ b/web/dashboard-ui/src/proto/gen/dashboard/v1alpha1/event_service_connectweb.ts @@ -0,0 +1,32 @@ +// +//Cosmo Dashboard API +//Manipulate cosmo dashboard resource API + +// @generated by protoc-gen-connect-web v0.8.6 with parameter "target=ts" +// @generated from file dashboard/v1alpha1/event_service.proto (package dashboard.v1alpha1, syntax proto3) +/* eslint-disable */ +// @ts-nocheck + +import { GetEventsRequest, GetEventsResponse } from "./user_service_pb.js"; +import { MethodKind } from "@bufbuild/protobuf"; + +/** + * @generated from service dashboard.v1alpha1.StreamService + */ +export const StreamService = { + typeName: "dashboard.v1alpha1.StreamService", + methods: { + /** + * Streaming new events for user + * + * @generated from rpc dashboard.v1alpha1.StreamService.StreamingEvents + */ + streamingEvents: { + name: "StreamingEvents", + I: GetEventsRequest, + O: GetEventsResponse, + kind: MethodKind.ServerStreaming, + }, + } +} as const; + diff --git a/web/dashboard-ui/src/proto/gen/dashboard/v1alpha1/user_pb.ts b/web/dashboard-ui/src/proto/gen/dashboard/v1alpha1/user_pb.ts index ddc98c45..ae35cd2c 100644 --- a/web/dashboard-ui/src/proto/gen/dashboard/v1alpha1/user_pb.ts +++ b/web/dashboard-ui/src/proto/gen/dashboard/v1alpha1/user_pb.ts @@ -9,7 +9,6 @@ import type { BinaryReadOptions, FieldList, JsonReadOptions, JsonValue, PartialMessage, PlainMessage } from "@bufbuild/protobuf"; import { Message, proto3 } from "@bufbuild/protobuf"; -import { Event } from "./event_pb.js"; /** * @generated from message dashboard.v1alpha1.User @@ -55,11 +54,6 @@ export class User extends Message { */ raw?: string; - /** - * @generated from field: repeated dashboard.v1alpha1.Event events = 9; - */ - events: Event[] = []; - constructor(data?: PartialMessage) { super(); proto3.util.initPartial(data, this); @@ -76,7 +70,6 @@ export class User extends Message { { no: 6, name: "default_password", kind: "scalar", T: 9 /* ScalarType.STRING */ }, { no: 7, name: "status", kind: "scalar", T: 9 /* ScalarType.STRING */ }, { no: 8, name: "raw", kind: "scalar", T: 9 /* ScalarType.STRING */, opt: true }, - { no: 9, name: "events", kind: "message", T: Event, repeated: true }, ]); static fromBinary(bytes: Uint8Array, options?: Partial): User { diff --git a/web/dashboard-ui/src/proto/gen/dashboard/v1alpha1/user_service_connectweb.ts b/web/dashboard-ui/src/proto/gen/dashboard/v1alpha1/user_service_connectweb.ts index 69f03fa6..a782ca39 100644 --- a/web/dashboard-ui/src/proto/gen/dashboard/v1alpha1/user_service_connectweb.ts +++ b/web/dashboard-ui/src/proto/gen/dashboard/v1alpha1/user_service_connectweb.ts @@ -7,7 +7,7 @@ /* eslint-disable */ // @ts-nocheck -import { CreateUserRequest, CreateUserResponse, DeleteUserRequest, DeleteUserResponse, GetUserRequest, GetUserResponse, GetUsersRequest, GetUsersResponse, UpdateUserAddonsRequest, UpdateUserAddonsResponse, UpdateUserDisplayNameRequest, UpdateUserDisplayNameResponse, UpdateUserPasswordRequest, UpdateUserPasswordResponse, UpdateUserRoleRequest, UpdateUserRoleResponse } from "./user_service_pb.js"; +import { CreateUserRequest, CreateUserResponse, DeleteUserRequest, DeleteUserResponse, GetEventsRequest, GetEventsResponse, GetUserRequest, GetUserResponse, GetUsersRequest, GetUsersResponse, UpdateUserAddonsRequest, UpdateUserAddonsResponse, UpdateUserDisplayNameRequest, UpdateUserDisplayNameResponse, UpdateUserPasswordRequest, UpdateUserPasswordResponse, UpdateUserRoleRequest, UpdateUserRoleResponse } from "./user_service_pb.js"; import { MethodKind } from "@bufbuild/protobuf"; /** @@ -49,6 +49,17 @@ export const UserService = { O: GetUsersResponse, kind: MethodKind.Unary, }, + /** + * Returns events for User + * + * @generated from rpc dashboard.v1alpha1.UserService.GetEvents + */ + getEvents: { + name: "GetEvents", + I: GetEventsRequest, + O: GetEventsResponse, + kind: MethodKind.Unary, + }, /** * Create a new User * diff --git a/web/dashboard-ui/src/proto/gen/dashboard/v1alpha1/user_service_pb.ts b/web/dashboard-ui/src/proto/gen/dashboard/v1alpha1/user_service_pb.ts index 20448704..d9b7a47f 100644 --- a/web/dashboard-ui/src/proto/gen/dashboard/v1alpha1/user_service_pb.ts +++ b/web/dashboard-ui/src/proto/gen/dashboard/v1alpha1/user_service_pb.ts @@ -8,8 +8,9 @@ // @ts-nocheck import type { BinaryReadOptions, FieldList, JsonReadOptions, JsonValue, PartialMessage, PlainMessage } from "@bufbuild/protobuf"; -import { Message, proto3 } from "@bufbuild/protobuf"; +import { Message, proto3, Timestamp } from "@bufbuild/protobuf"; import { User, UserAddon } from "./user_pb.js"; +import { Event } from "./event_pb.js"; /** * @generated from message dashboard.v1alpha1.DeleteUserRequest @@ -699,3 +700,89 @@ export class UpdateUserAddonsResponse extends Message } } +/** + * @generated from message dashboard.v1alpha1.GetEventsRequest + */ +export class GetEventsRequest extends Message { + /** + * @generated from field: string user_name = 1; + */ + userName = ""; + + /** + * @generated from field: optional google.protobuf.Timestamp from = 2; + */ + from?: Timestamp; + + constructor(data?: PartialMessage) { + super(); + proto3.util.initPartial(data, this); + } + + static readonly runtime: typeof proto3 = proto3; + static readonly typeName = "dashboard.v1alpha1.GetEventsRequest"; + static readonly fields: FieldList = proto3.util.newFieldList(() => [ + { no: 1, name: "user_name", kind: "scalar", T: 9 /* ScalarType.STRING */ }, + { no: 2, name: "from", kind: "message", T: Timestamp, opt: true }, + ]); + + static fromBinary(bytes: Uint8Array, options?: Partial): GetEventsRequest { + return new GetEventsRequest().fromBinary(bytes, options); + } + + static fromJson(jsonValue: JsonValue, options?: Partial): GetEventsRequest { + return new GetEventsRequest().fromJson(jsonValue, options); + } + + static fromJsonString(jsonString: string, options?: Partial): GetEventsRequest { + return new GetEventsRequest().fromJsonString(jsonString, options); + } + + static equals(a: GetEventsRequest | PlainMessage | undefined, b: GetEventsRequest | PlainMessage | undefined): boolean { + return proto3.util.equals(GetEventsRequest, a, b); + } +} + +/** + * @generated from message dashboard.v1alpha1.GetEventsResponse + */ +export class GetEventsResponse extends Message { + /** + * @generated from field: string message = 1; + */ + message = ""; + + /** + * @generated from field: repeated dashboard.v1alpha1.Event items = 2; + */ + items: Event[] = []; + + constructor(data?: PartialMessage) { + super(); + proto3.util.initPartial(data, this); + } + + static readonly runtime: typeof proto3 = proto3; + static readonly typeName = "dashboard.v1alpha1.GetEventsResponse"; + static readonly fields: FieldList = proto3.util.newFieldList(() => [ + { no: 1, name: "message", kind: "scalar", T: 9 /* ScalarType.STRING */ }, + { no: 2, name: "items", kind: "message", T: Event, repeated: true }, + ]); + + static fromBinary(bytes: Uint8Array, options?: Partial): GetEventsResponse { + return new GetEventsResponse().fromBinary(bytes, options); + } + + static fromJson(jsonValue: JsonValue, options?: Partial): GetEventsResponse { + return new GetEventsResponse().fromJson(jsonValue, options); + } + + static fromJsonString(jsonString: string, options?: Partial): GetEventsResponse { + return new GetEventsResponse().fromJsonString(jsonString, options); + } + + static equals(a: GetEventsResponse | PlainMessage | undefined, b: GetEventsResponse | PlainMessage | undefined): boolean { + return proto3.util.equals(GetEventsResponse, a, b); + } +} + diff --git a/web/dashboard-ui/src/proto/gen/dashboard/v1alpha1/workspace_pb.ts b/web/dashboard-ui/src/proto/gen/dashboard/v1alpha1/workspace_pb.ts index 9d53179f..a57af150 100644 --- a/web/dashboard-ui/src/proto/gen/dashboard/v1alpha1/workspace_pb.ts +++ b/web/dashboard-ui/src/proto/gen/dashboard/v1alpha1/workspace_pb.ts @@ -8,7 +8,7 @@ // @ts-nocheck import type { BinaryReadOptions, FieldList, JsonReadOptions, JsonValue, PartialMessage, PlainMessage } from "@bufbuild/protobuf"; -import { Message, proto3, protoInt64 } from "@bufbuild/protobuf"; +import { Message, proto3, protoInt64, Timestamp } from "@bufbuild/protobuf"; /** * @generated from message dashboard.v1alpha1.NetworkRule @@ -140,6 +140,11 @@ export class WorkspaceStatus extends Message { */ mainUrl = ""; + /** + * @generated from field: google.protobuf.Timestamp lastStartedAt = 3; + */ + lastStartedAt?: Timestamp; + constructor(data?: PartialMessage) { super(); proto3.util.initPartial(data, this); @@ -150,6 +155,7 @@ export class WorkspaceStatus extends Message { static readonly fields: FieldList = proto3.util.newFieldList(() => [ { no: 1, name: "phase", kind: "scalar", T: 9 /* ScalarType.STRING */ }, { no: 2, name: "main_url", kind: "scalar", T: 9 /* ScalarType.STRING */ }, + { no: 3, name: "lastStartedAt", kind: "message", T: Timestamp }, ]); static fromBinary(bytes: Uint8Array, options?: Partial): WorkspaceStatus { diff --git a/web/dashboard-ui/src/services/DashboardServices.ts b/web/dashboard-ui/src/services/DashboardServices.ts index a1e70f46..0a5f1eab 100644 --- a/web/dashboard-ui/src/services/DashboardServices.ts +++ b/web/dashboard-ui/src/services/DashboardServices.ts @@ -2,6 +2,7 @@ import { createPromiseClient } from "@bufbuild/connect"; import { createConnectTransport, createGrpcWebTransport } from "@bufbuild/connect-web"; import { useMemo } from "react"; import { AuthService } from "../proto/gen/dashboard/v1alpha1/auth_service_connectweb"; +import { StreamService } from "../proto/gen/dashboard/v1alpha1/event_service_connectweb"; import { TemplateService } from "../proto/gen/dashboard/v1alpha1/template_service_connectweb"; import { UserService } from "../proto/gen/dashboard/v1alpha1/user_service_connectweb"; import { WebAuthnService } from "../proto/gen/dashboard/v1alpha1/webauthn_connectweb"; @@ -29,4 +30,7 @@ export function useWorkspaceService() { } export function useWebAuthnService() { return useMemo(() => createPromiseClient(WebAuthnService, transport), [WebAuthnService]); +} +export function useStreamService() { + return useMemo(() => createPromiseClient(StreamService, transport), [StreamService]); } \ No newline at end of file diff --git a/web/dashboard-ui/src/views/atoms/EventsDataGrid.tsx b/web/dashboard-ui/src/views/atoms/EventsDataGrid.tsx new file mode 100644 index 00000000..dac2e91f --- /dev/null +++ b/web/dashboard-ui/src/views/atoms/EventsDataGrid.tsx @@ -0,0 +1,100 @@ +import { Info, Warning } from "@mui/icons-material"; +import { Chip, SxProps } from "@mui/material"; +import { + DataGrid, + DataGridProps, + gridClasses, + GridColDef, +} from "@mui/x-data-grid"; +import React from "react"; +import { Event } from "../../proto/gen/dashboard/v1alpha1/event_pb"; +import { EventDetailDialogContext } from "../organisms/EventDetailDialog"; + +export type EventsDataGridProp = { + events: Event[]; + maxHeight?: number; + sx?: SxProps; + dataGridProps?: Omit; + clock: Date; +}; + +export const EventsDataGrid: React.FC = ( + { events, maxHeight, sx, dataGridProps, clock }, +) => { + const eventDetailDialogDispatch = EventDetailDialogContext.useDispatch(); + + const columns: GridColDef[] = [ + { field: "type", headerName: "Type", width: 50 }, + { + field: "eventTime", + headerName: "LastSeen", + valueGetter: (value, row: Event) => + (row.series?.lastObservedTime || row.eventTime)?.toDate(), + valueFormatter: (value: Date) => + formatTime(clock.getTime() - value.getTime()), + flex: 0.2, + minWidth: 80, + }, + { + field: "reason", + headerName: "Reason", + flex: 0.25, + renderCell: (params) => ( + + : } + label={params.value} + /> + ), + }, + { field: "regardingWorkspace", headerName: "Workspace" }, + { + field: "regarding", + headerName: "Object", + valueGetter: (value, row) => + row.regarding?.kind + "/" + row.regarding?.name, + flex: 0.3, + }, + { field: "reportingController", headerName: "Reporter" }, + { + field: "series", + headerName: "Count", + valueGetter: (value, row) => row.series?.count || 1, + }, + { field: "note", headerName: "Message", flex: 1 }, + ]; + + return ( + <> +
+ "auto"} + sx={{ + [`& .${gridClasses.cell}`]: { + py: 1, + }, + ...sx, + }} + onRowClick={(params) => { + eventDetailDialogDispatch(true, { event: params.row }); + }} + hideFooter + {...dataGridProps} + /> +
+ + ); +}; + +export function formatTime(milisec: number): string { + const sec = Math.floor(milisec / 1000) % 60; + const min = Math.floor(milisec / 1000 / 60) % 60; + const hours = Math.floor(milisec / 1000 / 60 / 60) % 24; + if (hours > 0) return `${hours}h${min}m${sec}s`; + if (min > 0) return `${min}m${sec}s`; + return `${sec}s`; +} diff --git a/web/dashboard-ui/src/views/organisms/EventDetailDialog.tsx b/web/dashboard-ui/src/views/organisms/EventDetailDialog.tsx new file mode 100644 index 00000000..b95bdd91 --- /dev/null +++ b/web/dashboard-ui/src/views/organisms/EventDetailDialog.tsx @@ -0,0 +1,175 @@ +import { ContentCopy, Info, Warning } from "@mui/icons-material"; +import { + Box, + Button, + Dialog, + DialogActions, + DialogContent, + DialogTitle, + Divider, + IconButton, + InputAdornment, + Stack, + TextField, + TextFieldProps, +} from "@mui/material"; +import copy from "copy-to-clipboard"; +import { useSnackbar } from "notistack"; +import React, { useState } from "react"; +import { UseFormRegisterReturn } from "react-hook-form"; +import { DialogContext } from "../../components/ContextProvider"; +import { Event } from "../../proto/gen/dashboard/v1alpha1/event_pb"; + +const registerMui = ({ ref, ...rest }: UseFormRegisterReturn) => ({ + inputRef: ref, + ...rest, +}); + +const ClipboardTextField = (props: TextFieldProps) => { + const [focused, setFocused] = useState(false); + const { enqueueSnackbar } = useSnackbar(); + + const onCopy = (text) => { // eslint-disable-line + copy(text); + enqueueSnackbar("Copied!", { variant: "success" }); + }; + + return ( + setFocused(true)} + onMouseLeave={() => setFocused(false)} + InputProps={focused + ? { + endAdornment: ( + + { + onCopy(props.value); + }} + > + + + + ), + } + : undefined} + /> + ); +}; + +export const EventDetailDialog: React.FC< + { onClose: () => void; event: Event } +> = ({ onClose, event }) => { + console.log("EventDetailDialog"); + + return ( + onClose()} fullWidth> + + + {event.type == "Normal" + ? + : } + {event.reason} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ); +}; + +/** + * Context + */ +export const EventDetailDialogContext = DialogContext<{ event: Event }>( + (props) => , +); diff --git a/web/dashboard-ui/src/views/organisms/EventModule.tsx b/web/dashboard-ui/src/views/organisms/EventModule.tsx new file mode 100644 index 00000000..41ea012c --- /dev/null +++ b/web/dashboard-ui/src/views/organisms/EventModule.tsx @@ -0,0 +1,75 @@ +import { Timestamp } from "@bufbuild/protobuf"; +import { useState } from "react"; +import { ModuleContext } from "../../components/ContextProvider"; +import { useHandleError, useLogin } from "../../components/LoginProvider"; +import { Event } from "../../proto/gen/dashboard/v1alpha1/event_pb"; +import { User } from "../../proto/gen/dashboard/v1alpha1/user_pb"; +import { useUserService } from "../../services/DashboardServices"; +import { setUserStateFuncFilteredByLoginUserRole } from "./UserModule"; +/** + * hooks + */ +const useEvent = () => { + console.log("useEvent"); + const { handleError } = useHandleError(); + + const [events, setEvents] = useState([]); + const userService = useUserService(); + + const { loginUser, updateClock } = useLogin(); + const [user, setUser] = useState(loginUser || new User()); + const [users, setUsers] = useState([loginUser || new User()]); + + const getUsers = async () => { + console.log("useEvent:getUsers"); + try { + const result = await userService.getUsers({}); + setUsers( + setUserStateFuncFilteredByLoginUserRole(result.items, loginUser), + ); + } catch (error) { + handleError(error); + } + }; + + const getEvents = async () => { + console.log("useEvent:getEvents"); + try { + const result = await userService.getEvents({ userName: user.name }); + setEvents(result.items); + updateClock(); + } catch (error) { + handleError(error); + } + }; + + return ({ + user, + setUser, + users, + setUsers, + events, + setEvents, + getEvents, + getUsers, + }); +}; + +export function getTime(timestamp?: Timestamp): number { + if (!timestamp) { + return 0; + } + return timestamp.toDate().getTime(); +} + +export function latestTime(event?: Event): number { + if (!event) { + return 0; + } + const t1 = getTime(event.series?.lastObservedTime); + const t2 = getTime(event.eventTime); + return t1 > t2 ? t1 : t2; +} + +export const EventContext = ModuleContext(useEvent); +export const useEventModule = EventContext.useContext; diff --git a/web/dashboard-ui/src/views/organisms/UserModule.tsx b/web/dashboard-ui/src/views/organisms/UserModule.tsx index 2bb6ee36..e656cdac 100644 --- a/web/dashboard-ui/src/views/organisms/UserModule.tsx +++ b/web/dashboard-ui/src/views/organisms/UserModule.tsx @@ -1,9 +1,7 @@ -import { Code, ConnectError } from "@bufbuild/connect"; import { useSnackbar } from "notistack"; import { useState } from "react"; -import { useNavigate } from "react-router-dom"; import { ModuleContext } from "../../components/ContextProvider"; -import { useLogin } from "../../components/LoginProvider"; +import { useHandleError } from "../../components/LoginProvider"; import { useProgress } from "../../components/ProgressProvider"; import { Template } from "../../proto/gen/dashboard/v1alpha1/template_pb"; import { User, UserAddon } from "../../proto/gen/dashboard/v1alpha1/user_pb"; @@ -56,6 +54,26 @@ export const hasAdminForRole = (myRoles: string[], userrole: string) => { return false } +function filterUsersByRoles(users: User[], myRoles: string[]) { + return hasPrivilegedRole(myRoles) ? users : users.filter((u) => { + for (const userRole of u.roles) { + if (hasAdminForRole(myRoles, userRole)) { + return true + } + } + return false + }) +} + +export function setUserStateFuncFilteredByLoginUserRole(users: User[], loginUser?: User) { + const f = (prev: User[]) => { + const newUsers = users.sort((a, b) => (a.name < b.name) ? -1 : 1); + const roleFilteredNewUsers = filterUsersByRoles(newUsers, (loginUser?.roles || [])) + return JSON.stringify(prev) === JSON.stringify(roleFilteredNewUsers) ? prev : roleFilteredNewUsers; + } + return f +} + /** * hooks */ @@ -243,29 +261,6 @@ export const useTemplates = () => { }); } -/** -* error handler -*/ -const useHandleError = () => { - const { enqueueSnackbar } = useSnackbar(); - const navigate = useNavigate(); - const { clearLoginUser } = useLogin(); - - const handleError = (error: any) => { - console.log('handleError', error); - - if (error instanceof ConnectError && - error.code === Code.Unauthenticated) { - clearLoginUser(); - navigate('/signin'); - } - const msg = error?.message; - msg && enqueueSnackbar(msg, { variant: 'error' }); - throw error; - } - return { handleError } -} - /** * UserProvider */ diff --git a/web/dashboard-ui/src/views/organisms/WorkspaceActionDialog.tsx b/web/dashboard-ui/src/views/organisms/WorkspaceActionDialog.tsx index 6a39ed52..740ac9b9 100644 --- a/web/dashboard-ui/src/views/organisms/WorkspaceActionDialog.tsx +++ b/web/dashboard-ui/src/views/organisms/WorkspaceActionDialog.tsx @@ -9,7 +9,7 @@ import { DialogContext } from "../../components/ContextProvider"; import { Template } from "../../proto/gen/dashboard/v1alpha1/template_pb"; import { Workspace } from "../../proto/gen/dashboard/v1alpha1/workspace_pb"; import { TextFieldLabel } from "../atoms/TextFieldLabel"; -import { useTemplates, useWorkspaceModule, useWorkspaceUsersModule } from "./WorkspaceModule"; +import { useTemplates, useWorkspaceModule } from "./WorkspaceModule"; const registerMui = ({ ref, ...rest }: UseFormRegisterReturn) => ({ @@ -108,7 +108,7 @@ export const WorkspaceCreateDialog: React.VFC<{ onClose: () => void }> = ({ onCl console.log('WorkspaceCreateDialog'); const hooks = useWorkspaceModule(); - const { user } = useWorkspaceUsersModule(); + const { user } = useWorkspaceModule(); const [template, setTemplate] = useState