From c4e4618551bebefc7c1c365a604e01e6f9f26417 Mon Sep 17 00:00:00 2001 From: Julio Garcia <11684004+juligasa@users.noreply.github.com> Date: Wed, 24 Apr 2024 00:19:22 +0200 Subject: [PATCH] Delete Entities Delete entities. List deleted and undo deletion --- .../daemon/api/documents/v1alpha/comments.go | 3 +- .../daemon/api/documents/v1alpha/documents.go | 15 - .../documents/v1alpha/documents_bugs_test.go | 38 - .../api/documents/v1alpha/documents_test.go | 36 - .../daemon/api/entities/v1alpha/entities.go | 128 ++- backend/daemon/daemon_e2e_test.go | 189 +++- backend/daemon/storage/migrations.go | 12 + backend/daemon/storage/schema.gen.go | 22 + backend/daemon/storage/schema.gensum | 4 +- backend/daemon/storage/schema.sql | 13 + .../documents/v1alpha/documents.pb.go | 623 +++++++------ .../documents/v1alpha/documents_grpc.pb.go | 38 - .../genproto/entities/v1alpha/entities.pb.go | 871 +++++++++++++----- .../entities/v1alpha/entities_grpc.pb.go | 117 +++ backend/hyper/entity.go | 7 +- backend/hyper/hyper.go | 15 +- backend/hyper/hypersql/queries.gen.go | 190 ++++ backend/hyper/hypersql/queries.gensum | 4 +- backend/hyper/hypersql/queries.go | 61 +- backend/hyper/indexing.go | 20 +- .../packages/app/components/delete-dialog.tsx | 109 ++- frontend/packages/app/components/forms.tsx | 16 +- .../app/components/titlebar-common.tsx | 61 ++ frontend/packages/app/models/accounts.ts | 2 +- frontend/packages/app/models/documents.ts | 17 - frontend/packages/app/models/entities.ts | 47 + frontend/packages/app/models/query-keys.ts | 3 - .../app/pages/account-content-page.tsx | 5 +- frontend/packages/app/pages/contacts-page.tsx | 26 +- frontend/packages/app/pages/groups.tsx | 46 +- .../app/pages/publication-list-page.tsx | 17 +- .../documents/v1alpha/documents_connect.ts | 13 +- .../documents/v1alpha/documents_pb.ts | 107 ++- .../entities/v1alpha/entities_connect.ts | 38 +- .../entities/v1alpha/entities_pb.ts | 260 +++++- .../packages/shared/src/client/grpc-types.ts | 2 +- proto/documents/v1alpha/documents.proto | 25 +- proto/documents/v1alpha/go.gensum | 4 +- proto/documents/v1alpha/js.gensum | 4 +- proto/entities/v1alpha/entities.proto | 62 ++ proto/entities/v1alpha/go.gensum | 4 +- proto/entities/v1alpha/js.gensum | 4 +- 42 files changed, 2450 insertions(+), 828 deletions(-) create mode 100644 frontend/packages/app/models/entities.ts diff --git a/backend/daemon/api/documents/v1alpha/comments.go b/backend/daemon/api/documents/v1alpha/comments.go index 01e6e34da0..39ff7fbbdb 100644 --- a/backend/daemon/api/documents/v1alpha/comments.go +++ b/backend/daemon/api/documents/v1alpha/comments.go @@ -10,6 +10,7 @@ import ( "net/url" "strings" + "crawshaw.io/sqlite" "github.com/ipfs/go-cid" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" @@ -133,7 +134,7 @@ func (srv *Server) ListComments(ctx context.Context, in *documents.ListCommentsR } resp := &documents.ListCommentsResponse{} - if err := srv.blobs.ForEachComment(ctx, in.Target, func(c cid.Cid, cmt hyper.Comment) error { + if err := srv.blobs.ForEachComment(ctx, in.Target, func(c cid.Cid, cmt hyper.Comment, _ *sqlite.Conn) error { pb, err := commentToProto(ctx, srv.blobs, c, cmt) if err != nil { return fmt.Errorf("failed to convert comment %s to proto", c.String()) diff --git a/backend/daemon/api/documents/v1alpha/documents.go b/backend/daemon/api/documents/v1alpha/documents.go index ea19dc399a..0c564b3050 100644 --- a/backend/daemon/api/documents/v1alpha/documents.go +++ b/backend/daemon/api/documents/v1alpha/documents.go @@ -630,21 +630,6 @@ func (api *Server) loadPublication(ctx context.Context, docid hyper.EntityID, ve }, nil } -// DeletePublication implements the corresponding gRPC method. -func (api *Server) DeletePublication(ctx context.Context, in *documents.DeletePublicationRequest) (*emptypb.Empty, error) { - if in.DocumentId == "" { - return nil, status.Errorf(codes.InvalidArgument, "must specify publication ID to delete") - } - - eid := hyper.EntityID(in.DocumentId) - - if err := api.blobs.DeleteEntity(ctx, eid); err != nil { - return nil, err - } - - return &emptypb.Empty{}, nil -} - // PushPublication implements the corresponding gRPC method. func (api *Server) PushPublication(ctx context.Context, in *documents.PushPublicationRequest) (*emptypb.Empty, error) { if in.DocumentId == "" { diff --git a/backend/daemon/api/documents/v1alpha/documents_bugs_test.go b/backend/daemon/api/documents/v1alpha/documents_bugs_test.go index d4f8c0ea89..f1b84e0289 100644 --- a/backend/daemon/api/documents/v1alpha/documents_bugs_test.go +++ b/backend/daemon/api/documents/v1alpha/documents_bugs_test.go @@ -254,44 +254,6 @@ func TestBug_MoveBockWithoutReplacement(t *testing.T) { require.Len(t, dlist.Documents, 1) } -func TestBug_MissingLinkTarget(t *testing.T) { - t.Parallel() - - api := newTestDocsAPI(t, "alice") - ctx := context.Background() - - draft, err := api.CreateDraft(ctx, &CreateDraftRequest{}) - require.NoError(t, err) - updated := updateDraft(ctx, t, api, draft.Id, []*DocumentChange{ - {Op: &DocumentChange_SetTitle{SetTitle: "My new document title"}}, - {Op: &DocumentChange_MoveBlock_{MoveBlock: &DocumentChange_MoveBlock{BlockId: "b1"}}}, - {Op: &DocumentChange_ReplaceBlock{ReplaceBlock: &Block{ - Id: "b1", - Type: "statement", - Text: "Hello world!", - Annotations: []*Annotation{ - { - Type: "link", - Attributes: map[string]string{ - "url": "mtt://bafy2bzaceaemtzyq7gj6fa5jn4xhfq6yp657j5dpoqvh6bio4kk4bi2wmoroy/baeaxdiheaiqfsiervpfvbohhvjgnkcto3f5p4alwe4k46fr334vlw4n5jaknnqa/MIWneLC1", - }, - Starts: []int32{0}, - Ends: []int32{5}, - }, - }, - }}}, - }) - require.NoError(t, err) - require.NotNil(t, updated) - published, err := api.PublishDraft(ctx, &PublishDraftRequest{DocumentId: draft.Id}) - require.NoError(t, err) - require.NotNil(t, published) - - linked, err := api.GetPublication(ctx, &GetPublicationRequest{DocumentId: "bafy2bzaceaemtzyq7gj6fa5jn4xhfq6yp657j5dpoqvh6bio4kk4bi2wmoroy"}) - require.Error(t, err) - require.Nil(t, linked) -} - func TestBug_BlockRevisionMustUpdate(t *testing.T) { t.Parallel() diff --git a/backend/daemon/api/documents/v1alpha/documents_test.go b/backend/daemon/api/documents/v1alpha/documents_test.go index 99ce56026a..9e92652489 100644 --- a/backend/daemon/api/documents/v1alpha/documents_test.go +++ b/backend/daemon/api/documents/v1alpha/documents_test.go @@ -742,42 +742,6 @@ func TestGetPublicationWithDraftID(t *testing.T) { require.Nil(t, published, "draft is not a publication") } -func TestAPIDeletePublication(t *testing.T) { - api := newTestDocsAPI(t, "alice") - ctx := context.Background() - - doc, err := api.CreateDraft(ctx, &documents.CreateDraftRequest{}) - require.NoError(t, err) - doc = updateDraft(ctx, t, api, doc.Id, []*documents.DocumentChange{ - {Op: &documents.DocumentChange_SetTitle{SetTitle: "My new document title"}}}, - ) - - _, err = api.PublishDraft(ctx, &documents.PublishDraftRequest{DocumentId: doc.Id}) - require.NoError(t, err) - - list, err := api.ListPublications(ctx, &documents.ListPublicationsRequest{}) - require.NoError(t, err) - require.Len(t, list.Publications, 1) - - deleted, err := api.DeletePublication(ctx, &documents.DeletePublicationRequest{DocumentId: doc.Id}) - require.NoError(t, err) - require.NotNil(t, deleted) - - list, err = api.ListPublications(ctx, &documents.ListPublicationsRequest{}) - require.NoError(t, err) - require.Len(t, list.Publications, 0) - - pub, err := api.GetPublication(ctx, &documents.GetPublicationRequest{DocumentId: doc.Id}) - require.Error(t, err, "must fail to get deleted publication") - _ = pub - - // TODO: fix status codes. - // s, ok := status.FromError(err) - // require.True(t, ok) - // require.Nil(t, pub) - // require.Equal(t, codes.NotFound, s.Code()) -} - func TestPublisherAndEditors(t *testing.T) { t.Parallel() diff --git a/backend/daemon/api/entities/v1alpha/entities.go b/backend/daemon/api/entities/v1alpha/entities.go index eda0e66f78..ec068749b0 100644 --- a/backend/daemon/api/entities/v1alpha/entities.go +++ b/backend/daemon/api/entities/v1alpha/entities.go @@ -5,6 +5,7 @@ import ( "context" "encoding/base64" "encoding/json" + "errors" "fmt" "math" "mintter/backend/core" @@ -27,6 +28,7 @@ import ( "golang.org/x/exp/slices" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" + "google.golang.org/protobuf/types/known/emptypb" "google.golang.org/protobuf/types/known/timestamppb" ) @@ -369,17 +371,13 @@ func (api *Server) SearchEntities(ctx context.Context, in *entities.SearchEntiti var owners []string const limit = 30 if err := api.blobs.Query(ctx, func(conn *sqlite.Conn) error { - err := sqlitex.Exec(conn, qGetEntityTitles(), func(stmt *sqlite.Stmt) error { + return sqlitex.Exec(conn, qGetEntityTitles(), func(stmt *sqlite.Stmt) error { titles = append(titles, stmt.ColumnText(0)) iris = append(iris, stmt.ColumnText(1)) ownerID := core.Principal(stmt.ColumnBytes(2)).String() owners = append(owners, ownerID) return nil }) - if err != nil { - return err - } - return nil }); err != nil { return nil, err } @@ -400,6 +398,126 @@ func (api *Server) SearchEntities(ctx context.Context, in *entities.SearchEntiti return &entities.SearchEntitiesResponse{Entities: matchingEntities}, nil } +// DeleteEntity implements the corresponding gRPC method. +func (api *Server) DeleteEntity(ctx context.Context, in *entities.DeleteEntityRequest) (*emptypb.Empty, error) { + var meta string + var qGetResourceMetadata = dqb.Str(` + SELECT meta from meta_view + WHERE iri = :eid + `) + + if in.Id == "" { + return nil, status.Errorf(codes.InvalidArgument, "must specify entity ID to delete") + } + + eid := hyper.EntityID(in.Id) + + err := api.blobs.Query(ctx, func(conn *sqlite.Conn) error { + return sqlitex.Exec(conn, qGetResourceMetadata(), func(stmt *sqlite.Stmt) error { + meta = stmt.ColumnText(0) + return nil + }, in.Id) + }) + if err != nil { + return nil, err + } + err = api.blobs.ForEachComment(ctx, eid.String(), func(c cid.Cid, cmt hyper.Comment, conn *sqlite.Conn) error { + referencedDocument := strings.Split(cmt.Target, "?v=")[0] + if referencedDocument == eid.String() { + _, err = hypersql.BlobsDelete(conn, c.Hash()) + if err != nil { + if err = hypersql.BlobsEmptyByHash(conn, c.Hash()); err != nil { + return err + } + } + if cmt.RepliedComment.String() != "" { + _, err = hypersql.BlobsDelete(conn, cmt.RepliedComment.Hash()) + if err != nil { + if err = hypersql.BlobsEmptyByHash(conn, cmt.RepliedComment.Hash()); err != nil { + return err + } + } + } + + return nil + } + return nil + }) + + err = api.blobs.DeleteEntity(ctx, eid) + if err != nil { + if errors.Is(err, hyper.ErrEntityNotFound) { + return nil, err + } + + _, err = &emptypb.Empty{}, api.blobs.Query(ctx, func(conn *sqlite.Conn) error { + return hypersql.BlobsEmptyByEID(conn, in.Id) + }) + if err != nil { + return &emptypb.Empty{}, err + } + + _, err = &emptypb.Empty{}, api.blobs.Query(ctx, func(conn *sqlite.Conn) error { + return hypersql.BlobsStructuralDelete(conn, in.Id) + }) + if err != nil { + return &emptypb.Empty{}, err + } + } + _, err = &emptypb.Empty{}, api.blobs.Query(ctx, func(conn *sqlite.Conn) error { + return sqlitex.WithTx(conn, func() error { + res, err := hypersql.EntitiesInsertRemovedRecord(conn, eid.String(), in.Reason, meta) + if err != nil { + return err + } + if res.ResourceEID != eid.String() { + return fmt.Errorf("%w: %s", hyper.ErrEntityNotFound, eid) + } + + return nil + }) + }) + return &emptypb.Empty{}, err +} + +// UndeleteEntity implements the corresponding gRPC method. +func (api *Server) UndeleteEntity(ctx context.Context, in *entities.UndeleteEntityRequest) (*emptypb.Empty, error) { + if in.Id == "" { + return nil, status.Errorf(codes.InvalidArgument, "must specify entity ID to restore") + } + + eid := hyper.EntityID(in.Id) + + return &emptypb.Empty{}, api.blobs.Query(ctx, func(conn *sqlite.Conn) error { + return hypersql.EntitiesDeleteRemovedRecord(conn, eid.String()) + }) +} + +// ListDeletedEntities implements the corresponding gRPC method. +func (api *Server) ListDeletedEntities(ctx context.Context, _ *entities.ListDeletedEntitiesRequest) (*entities.ListDeletedEntitiesResponse, error) { + resp := &entities.ListDeletedEntitiesResponse{ + DeletedEntities: make([]*entities.DeletedEntity, 0), + } + + err := api.blobs.Query(ctx, func(conn *sqlite.Conn) error { + list, err := hypersql.EntitiesListRemovedRecords(conn) + if err != nil { + return err + } + for _, entity := range list { + resp.DeletedEntities = append(resp.DeletedEntities, &entities.DeletedEntity{ + Id: entity.DeletedResourcesIRI, + DeleteTime: ×tamppb.Timestamp{Seconds: entity.DeletedResourcesDeleteTime}, + DeletedReason: entity.DeletedResourcesReason, + Metadata: entity.DeletedResourcesMeta, + }) + } + return nil + }) + + return resp, err +} + var qGetEntityTitles = dqb.Str(` SELECT meta, iri, principal FROM meta_view;`) diff --git a/backend/daemon/daemon_e2e_test.go b/backend/daemon/daemon_e2e_test.go index 24bc605de6..2e680e0162 100644 --- a/backend/daemon/daemon_e2e_test.go +++ b/backend/daemon/daemon_e2e_test.go @@ -127,7 +127,7 @@ func TestDaemonPushPublication(t *testing.T) { alice := makeTestApp(t, "alice", cfg, true) ctx := context.Background() - pub := publishDocument(t, ctx, alice) + pub := publishDocument(t, ctx, alice, "") _, err := alice.RPC.Documents.PushPublication(ctx, &documents.PushPublicationRequest{ DocumentId: pub.Document.Id, Url: ipfs.TestGateway, @@ -168,7 +168,7 @@ func TestAPIGetRemotePublication(t *testing.T) { require.NoError(t, alice.Net.MustGet().Libp2p().Network().ClosePeer(bob.Storage.Device().ID())) alice.Net.MustGet().Libp2p().Peerstore().RemovePeer(bob.Storage.Device().ID()) - pub := publishDocument(t, ctx, alice) + pub := publishDocument(t, ctx, alice, "") time.Sleep(time.Second) @@ -178,6 +178,170 @@ func TestAPIGetRemotePublication(t *testing.T) { testutil.ProtoEqual(t, pub, remotePub, "remote publication doesn't match") } +func TestAPIDeleteAndRestoreEntity(t *testing.T) { + t.Parallel() + + aliceCfg := makeTestConfig(t) + bobCfg := makeTestConfig(t) + + aliceCfg.Syncing.WarmupDuration = 100 * time.Millisecond + bobCfg.Syncing.WarmupDuration = 100 * time.Millisecond + + alice := makeTestApp(t, "alice", aliceCfg, true) + bob := makeTestApp(t, "bob", bobCfg, true) + ctx := context.Background() + + _, err := alice.RPC.Networking.Connect(ctx, &networking.ConnectRequest{ + Addrs: getAddrs(t, bob), + }) + require.NoError(t, err) + + require.NoError(t, alice.Blobs.SetAccountTrust(ctx, bob.Storage.Identity().MustGet().Account().Principal())) + require.NoError(t, bob.Blobs.SetAccountTrust(ctx, alice.Storage.Identity().MustGet().Account().Principal())) + + pub := publishDocument(t, ctx, alice, "") + linkedDoc := publishDocument(t, ctx, alice, pub.Document.Id+"?v="+pub.Version+"#"+pub.Document.Children[0].Block.Id) + comment, err := bob.RPC.Documents.CreateComment(ctx, &documents.CreateCommentRequest{ + Target: pub.Document.Id + "?v=" + pub.Version, + RepliedComment: "", + Content: []*documents.BlockNode{{Block: &documents.Block{ + Id: "c1", + Type: "paragraph", + Text: "Bob's comment", + }}}, + }) + + require.NoError(t, err) + time.Sleep(200 * time.Millisecond) + + // so alice gets Bob's comment + _, err = alice.RPC.Daemon.ForceSync(ctx, &daemon.ForceSyncRequest{}) + require.NoError(t, err) + time.Sleep(200 * time.Millisecond) + + comm, err := alice.RPC.Documents.GetComment(ctx, &documents.GetCommentRequest{ + Id: comment.Id, + }) + require.NoError(t, err) + require.Equal(t, comment.Id, comm.Id, "Alice should have Bob's comment") + require.Equal(t, comment.Content, comm.Content, "Comment's content should not have been deleted") + + reply, err := alice.RPC.Documents.CreateComment(ctx, &documents.CreateCommentRequest{ + Target: pub.Document.Id + "?v=" + pub.Version, + RepliedComment: comment.Id, + Content: []*documents.BlockNode{{Block: &documents.Block{ + Id: "c2", + Type: "paragraph", + Text: "Alice's reply", + }}}, + }) + require.NoError(t, err) + + // so bob gets Alice's document + comment reply + _, err = bob.RPC.Daemon.ForceSync(ctx, &daemon.ForceSyncRequest{}) + require.NoError(t, err) + time.Sleep(200 * time.Millisecond) + + doc, err := bob.RPC.Documents.GetPublication(ctx, &documents.GetPublicationRequest{ + DocumentId: pub.Document.Id, + LocalOnly: true, + }) + require.NoError(t, err) + require.Equal(t, pub.Document.Id, doc.Document.Id, "Bob should have synced the document") + + _, err = bob.RPC.Documents.GetComment(ctx, &documents.GetCommentRequest{ + Id: reply.Id, + }) + require.NoError(t, err, "Bob should have synced Alice's reply") + + // Now Alice removes de document + const reason = "I don't want it anymore" + _, err = alice.RPC.Entities.DeleteEntity(ctx, &entities.DeleteEntityRequest{ + Id: doc.Document.Id, + Reason: reason, + }) + require.NoError(t, err) + lst, err := alice.RPC.Entities.ListDeletedEntities(ctx, &entities.ListDeletedEntitiesRequest{}) + require.NoError(t, err) + require.Len(t, lst.DeletedEntities, 1) + require.Equal(t, doc.Document.Id, lst.DeletedEntities[0].Id) + require.Equal(t, reason, lst.DeletedEntities[0].DeletedReason) + + // bob creates another document that should get to Alice + BobsPub := publishDocument(t, ctx, bob, "") + // Even if we sync we shouldn't get the document back + _, err = alice.RPC.Daemon.ForceSync(ctx, &daemon.ForceSyncRequest{}) + require.NoError(t, err) + time.Sleep(200 * time.Millisecond) + + _, err = alice.RPC.Documents.GetPublication(ctx, &documents.GetPublicationRequest{ + DocumentId: pub.Document.Id, + LocalOnly: true, + }) + require.Error(t, err) + + pubList, err := alice.RPC.Documents.ListPublications(ctx, &documents.ListPublicationsRequest{}) + require.NoError(t, err) + require.Len(t, pubList.Publications, 2) + require.Equal(t, pubList.Publications[1].Document.Id, linkedDoc.Document.Id, "Alice Should see the document linking the deleted one") + + _, err = alice.RPC.Documents.GetComment(ctx, &documents.GetCommentRequest{ + Id: reply.Id, + }) + require.Error(t, err) + _, err = alice.RPC.Documents.GetComment(ctx, &documents.GetCommentRequest{ + Id: comment.Id, + }) + require.Error(t, err) + + // But she should get Bob's document + _, err = alice.RPC.Documents.GetPublication(ctx, &documents.GetPublicationRequest{ + DocumentId: BobsPub.Document.Id, + LocalOnly: true, + }) + require.NoError(t, err) + + // Only after restoring the document we should get it back. + _, err = alice.RPC.Entities.UndeleteEntity(ctx, &entities.UndeleteEntityRequest{ + Id: doc.Document.Id, + }) + require.NoError(t, err) + + lst, err = alice.RPC.Entities.ListDeletedEntities(ctx, &entities.ListDeletedEntitiesRequest{}) + require.NoError(t, err) + require.Len(t, lst.DeletedEntities, 0) + + _, err = alice.RPC.Daemon.ForceSync(ctx, &daemon.ForceSyncRequest{}) + require.NoError(t, err) + time.Sleep(200 * time.Millisecond) + + doc, err = alice.RPC.Documents.GetPublication(ctx, &documents.GetPublicationRequest{ + DocumentId: pub.Document.Id, + LocalOnly: true, + }) + require.NoError(t, err) + require.Equal(t, pub.Document.Id, doc.Document.Id, "alice should have her document back") + + pubList, err = alice.RPC.Documents.ListPublications(ctx, &documents.ListPublicationsRequest{}) + require.NoError(t, err) + require.Len(t, pubList.Publications, 3) + require.Equal(t, pubList.Publications[2].Document.Id, doc.Document.Id, "alice should see her document on the list") + + comm, err = alice.RPC.Documents.GetComment(ctx, &documents.GetCommentRequest{ + Id: comment.Id, + }) + require.NoError(t, err) + require.Equal(t, comment.Id, comm.Id, "alice should have her comment back") + require.Equal(t, comment.Content, comm.Content, "Comment's content should not have been deleted") + + rep, err := alice.RPC.Documents.GetComment(ctx, &documents.GetCommentRequest{ + Id: reply.Id, + }) + require.NoError(t, err) + require.Equal(t, reply.Id, rep.Id, "alice should have her own reply back") + require.Equal(t, reply.Content, rep.Content, "Replies's content should not have been deleted") +} + func TestBug_SyncHangs(t *testing.T) { // See: https://github.com/mintterteam/mintter/issues/712. t.Parallel() @@ -429,22 +593,33 @@ func getAddrs(t *testing.T, a *App) []string { return mttnet.AddrInfoToStrings(a.Net.MustGet().AddrInfo()) } -func publishDocument(t *testing.T, ctx context.Context, publisher *App) *documents.Publication { +func publishDocument(t *testing.T, ctx context.Context, publisher *App, link string) *documents.Publication { draft, err := publisher.RPC.Documents.CreateDraft(ctx, &documents.CreateDraftRequest{}) require.NoError(t, err) - + ann := []*documents.Annotation{} + if link != "" { + ann = append(ann, &documents.Annotation{ + Type: "link", + Ref: link, + Starts: []int32{0}, + Ends: []int32{5}, + }, + ) + } updated, err := publisher.RPC.Documents.UpdateDraft(ctx, &documents.UpdateDraftRequest{ DocumentId: draft.Id, Changes: []*documents.DocumentChange{ {Op: &documents.DocumentChange_SetTitle{SetTitle: "My new document title"}}, {Op: &documents.DocumentChange_MoveBlock_{MoveBlock: &documents.DocumentChange_MoveBlock{BlockId: "b1"}}}, {Op: &documents.DocumentChange_ReplaceBlock{ReplaceBlock: &documents.Block{ - Id: "b1", - Type: "statement", - Text: "Hello world!", + Id: "b1", + Type: "paragraph", + Text: "Hello world!", + Annotations: ann, }}}, }, }) + require.NoError(t, err) require.NotNil(t, updated) published, err := publisher.RPC.Documents.PublishDraft(ctx, &documents.PublishDraftRequest{DocumentId: draft.Id}) diff --git a/backend/daemon/storage/migrations.go b/backend/daemon/storage/migrations.go index 2185d2f748..6c12a2d014 100644 --- a/backend/daemon/storage/migrations.go +++ b/backend/daemon/storage/migrations.go @@ -453,6 +453,18 @@ var migrations = []migration{ JOIN public_keys pk ON pk.id = lb.author; `)) }}, + {Version: "2024-04-08.01", Run: func(_ *Dir, conn *sqlite.Conn) error { + return sqlitex.ExecScript(conn, sqlfmt(` + DROP TABLE IF EXISTS deleted_resources; + + CREATE TABLE IF NOT EXISTS deleted_resources ( + iri TEXT PRIMARY KEY, + delete_time INTEGER DEFAULT (strftime('%s', 'now')) NOT NULL, + reason TEXT, + meta TEXT + ); + `)) + }}, } const ( diff --git a/backend/daemon/storage/schema.gen.go b/backend/daemon/storage/schema.gen.go index e441d70bd0..0dc88a598c 100644 --- a/backend/daemon/storage/schema.gen.go +++ b/backend/daemon/storage/schema.gen.go @@ -58,6 +58,24 @@ const ( C_ChangeDepsParent = "change_deps.parent" ) +// Table deleted_resources. +const ( + DeletedResources sqlitegen.Table = "deleted_resources" + DeletedResourcesDeleteTime sqlitegen.Column = "deleted_resources.delete_time" + DeletedResourcesIRI sqlitegen.Column = "deleted_resources.iri" + DeletedResourcesMeta sqlitegen.Column = "deleted_resources.meta" + DeletedResourcesReason sqlitegen.Column = "deleted_resources.reason" +) + +// Table deleted_resources. Plain strings. +const ( + T_DeletedResources = "deleted_resources" + C_DeletedResourcesDeleteTime = "deleted_resources.delete_time" + C_DeletedResourcesIRI = "deleted_resources.iri" + C_DeletedResourcesMeta = "deleted_resources.meta" + C_DeletedResourcesReason = "deleted_resources.reason" +) + // Table drafts. const ( Drafts sqlitegen.Table = "drafts" @@ -368,6 +386,10 @@ var Schema = sqlitegen.Schema{ BlobsSize: {Table: Blobs, SQLType: "INTEGER"}, ChangeDepsChild: {Table: ChangeDeps, SQLType: "INTEGER"}, ChangeDepsParent: {Table: ChangeDeps, SQLType: "INTEGER"}, + DeletedResourcesDeleteTime: {Table: DeletedResources, SQLType: "INTEGER"}, + DeletedResourcesIRI: {Table: DeletedResources, SQLType: "TEXT"}, + DeletedResourcesMeta: {Table: DeletedResources, SQLType: "TEXT"}, + DeletedResourcesReason: {Table: DeletedResources, SQLType: "TEXT"}, DraftsBlob: {Table: Drafts, SQLType: "INTEGER"}, DraftsResource: {Table: Drafts, SQLType: "INTEGER"}, DraftsViewBlobID: {Table: DraftsView, SQLType: "INTEGER"}, diff --git a/backend/daemon/storage/schema.gensum b/backend/daemon/storage/schema.gensum index 1b01b9ecfd..a187c85b63 100644 --- a/backend/daemon/storage/schema.gensum +++ b/backend/daemon/storage/schema.gensum @@ -1,2 +1,2 @@ -srcs: 8f7984b962c288b761a8346ebfcab040 -outs: 67a994f0ff45ef5e3e3e60482412dc96 +srcs: c46f3f110843d024bdb92731ce4d0386 +outs: 1fca302b698393a5254a43746593a4bc diff --git a/backend/daemon/storage/schema.sql b/backend/daemon/storage/schema.sql index 7ff9ef08e1..8db4ed302f 100644 --- a/backend/daemon/storage/schema.sql +++ b/backend/daemon/storage/schema.sql @@ -156,6 +156,19 @@ CREATE TABLE resources ( CREATE INDEX resources_by_owner ON resources (owner) WHERE owner IS NOT NULL; +-- Stores deleted hypermedia resources. +-- In order to bring back content we need to keep track of +-- what's been deleted. Also, in order not to sync it back +-- accidentally, we need to check whether the blob is related +-- to a deleted resource. +CREATE TABLE deleted_resources ( + iri TEXT PRIMARY KEY, + delete_time INTEGER DEFAULT (strftime('%s', 'now')) NOT NULL, + reason TEXT, + -- Extra metadata can be stored like the title, probably in JSON format. + meta TEXT +); + -- Stores content-addressable links between blobs. -- Links are typed (rel) and directed. CREATE TABLE blob_links ( diff --git a/backend/genproto/documents/v1alpha/documents.pb.go b/backend/genproto/documents/v1alpha/documents.pb.go index ee800e5154..2282a27d08 100644 --- a/backend/genproto/documents/v1alpha/documents.pb.go +++ b/backend/genproto/documents/v1alpha/documents.pb.go @@ -744,56 +744,6 @@ func (x *GetPublicationRequest) GetLocalOnly() bool { return false } -// Request for deleting a publication. -type DeletePublicationRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Document ID of the publication to be removed. - // All versions will also be removed. - DocumentId string `protobuf:"bytes,1,opt,name=document_id,json=documentId,proto3" json:"document_id,omitempty"` -} - -func (x *DeletePublicationRequest) Reset() { - *x = DeletePublicationRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_documents_v1alpha_documents_proto_msgTypes[12] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *DeletePublicationRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*DeletePublicationRequest) ProtoMessage() {} - -func (x *DeletePublicationRequest) ProtoReflect() protoreflect.Message { - mi := &file_documents_v1alpha_documents_proto_msgTypes[12] - 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 DeletePublicationRequest.ProtoReflect.Descriptor instead. -func (*DeletePublicationRequest) Descriptor() ([]byte, []int) { - return file_documents_v1alpha_documents_proto_rawDescGZIP(), []int{12} -} - -func (x *DeletePublicationRequest) GetDocumentId() string { - if x != nil { - return x.DocumentId - } - return "" -} - // Request for getting a single publication. type PushPublicationRequest struct { state protoimpl.MessageState @@ -809,7 +759,7 @@ type PushPublicationRequest struct { func (x *PushPublicationRequest) Reset() { *x = PushPublicationRequest{} if protoimpl.UnsafeEnabled { - mi := &file_documents_v1alpha_documents_proto_msgTypes[13] + mi := &file_documents_v1alpha_documents_proto_msgTypes[12] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -822,7 +772,7 @@ func (x *PushPublicationRequest) String() string { func (*PushPublicationRequest) ProtoMessage() {} func (x *PushPublicationRequest) ProtoReflect() protoreflect.Message { - mi := &file_documents_v1alpha_documents_proto_msgTypes[13] + mi := &file_documents_v1alpha_documents_proto_msgTypes[12] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -835,7 +785,7 @@ func (x *PushPublicationRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use PushPublicationRequest.ProtoReflect.Descriptor instead. func (*PushPublicationRequest) Descriptor() ([]byte, []int) { - return file_documents_v1alpha_documents_proto_rawDescGZIP(), []int{13} + return file_documents_v1alpha_documents_proto_rawDescGZIP(), []int{12} } func (x *PushPublicationRequest) GetDocumentId() string { @@ -871,7 +821,7 @@ type ListPublicationsRequest struct { func (x *ListPublicationsRequest) Reset() { *x = ListPublicationsRequest{} if protoimpl.UnsafeEnabled { - mi := &file_documents_v1alpha_documents_proto_msgTypes[14] + mi := &file_documents_v1alpha_documents_proto_msgTypes[13] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -884,7 +834,7 @@ func (x *ListPublicationsRequest) String() string { func (*ListPublicationsRequest) ProtoMessage() {} func (x *ListPublicationsRequest) ProtoReflect() protoreflect.Message { - mi := &file_documents_v1alpha_documents_proto_msgTypes[14] + mi := &file_documents_v1alpha_documents_proto_msgTypes[13] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -897,7 +847,7 @@ func (x *ListPublicationsRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ListPublicationsRequest.ProtoReflect.Descriptor instead. func (*ListPublicationsRequest) Descriptor() ([]byte, []int) { - return file_documents_v1alpha_documents_proto_rawDescGZIP(), []int{14} + return file_documents_v1alpha_documents_proto_rawDescGZIP(), []int{13} } func (x *ListPublicationsRequest) GetPageSize() int32 { @@ -938,7 +888,7 @@ type ListPublicationsResponse struct { func (x *ListPublicationsResponse) Reset() { *x = ListPublicationsResponse{} if protoimpl.UnsafeEnabled { - mi := &file_documents_v1alpha_documents_proto_msgTypes[15] + mi := &file_documents_v1alpha_documents_proto_msgTypes[14] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -951,7 +901,7 @@ func (x *ListPublicationsResponse) String() string { func (*ListPublicationsResponse) ProtoMessage() {} func (x *ListPublicationsResponse) ProtoReflect() protoreflect.Message { - mi := &file_documents_v1alpha_documents_proto_msgTypes[15] + mi := &file_documents_v1alpha_documents_proto_msgTypes[14] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -964,7 +914,7 @@ func (x *ListPublicationsResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ListPublicationsResponse.ProtoReflect.Descriptor instead. func (*ListPublicationsResponse) Descriptor() ([]byte, []int) { - return file_documents_v1alpha_documents_proto_rawDescGZIP(), []int{15} + return file_documents_v1alpha_documents_proto_rawDescGZIP(), []int{14} } func (x *ListPublicationsResponse) GetPublications() []*Publication { @@ -998,7 +948,7 @@ type ListAccountPublicationsRequest struct { func (x *ListAccountPublicationsRequest) Reset() { *x = ListAccountPublicationsRequest{} if protoimpl.UnsafeEnabled { - mi := &file_documents_v1alpha_documents_proto_msgTypes[16] + mi := &file_documents_v1alpha_documents_proto_msgTypes[15] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1011,7 +961,7 @@ func (x *ListAccountPublicationsRequest) String() string { func (*ListAccountPublicationsRequest) ProtoMessage() {} func (x *ListAccountPublicationsRequest) ProtoReflect() protoreflect.Message { - mi := &file_documents_v1alpha_documents_proto_msgTypes[16] + mi := &file_documents_v1alpha_documents_proto_msgTypes[15] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1024,7 +974,7 @@ func (x *ListAccountPublicationsRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ListAccountPublicationsRequest.ProtoReflect.Descriptor instead. func (*ListAccountPublicationsRequest) Descriptor() ([]byte, []int) { - return file_documents_v1alpha_documents_proto_rawDescGZIP(), []int{16} + return file_documents_v1alpha_documents_proto_rawDescGZIP(), []int{15} } func (x *ListAccountPublicationsRequest) GetPageSize() int32 { @@ -1072,7 +1022,7 @@ type Publication struct { func (x *Publication) Reset() { *x = Publication{} if protoimpl.UnsafeEnabled { - mi := &file_documents_v1alpha_documents_proto_msgTypes[17] + mi := &file_documents_v1alpha_documents_proto_msgTypes[16] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1085,7 +1035,7 @@ func (x *Publication) String() string { func (*Publication) ProtoMessage() {} func (x *Publication) ProtoReflect() protoreflect.Message { - mi := &file_documents_v1alpha_documents_proto_msgTypes[17] + mi := &file_documents_v1alpha_documents_proto_msgTypes[16] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1098,7 +1048,7 @@ func (x *Publication) ProtoReflect() protoreflect.Message { // Deprecated: Use Publication.ProtoReflect.Descriptor instead. func (*Publication) Descriptor() ([]byte, []int) { - return file_documents_v1alpha_documents_proto_rawDescGZIP(), []int{17} + return file_documents_v1alpha_documents_proto_rawDescGZIP(), []int{16} } func (x *Publication) GetVersion() string { @@ -1115,6 +1065,82 @@ func (x *Publication) GetDocument() *Document { return nil } +// Publication that has been deleted +type DeletedPublication struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // EID of the deleted publication. + Eid string `protobuf:"bytes,1,opt,name=eid,proto3" json:"eid,omitempty"` + // When the publication was deleted. + DeletedTime *timestamppb.Timestamp `protobuf:"bytes,2,opt,name=deleted_time,json=deletedTime,proto3" json:"deleted_time,omitempty"` + // Reason why that publication was deleted. + DeletedReason string `protobuf:"bytes,3,opt,name=deleted_reason,json=deletedReason,proto3" json:"deleted_reason,omitempty"` + // Further metadata about the deleted Publication, title, etc ... + Metadata string `protobuf:"bytes,4,opt,name=metadata,proto3" json:"metadata,omitempty"` +} + +func (x *DeletedPublication) Reset() { + *x = DeletedPublication{} + if protoimpl.UnsafeEnabled { + mi := &file_documents_v1alpha_documents_proto_msgTypes[17] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *DeletedPublication) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*DeletedPublication) ProtoMessage() {} + +func (x *DeletedPublication) ProtoReflect() protoreflect.Message { + mi := &file_documents_v1alpha_documents_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 DeletedPublication.ProtoReflect.Descriptor instead. +func (*DeletedPublication) Descriptor() ([]byte, []int) { + return file_documents_v1alpha_documents_proto_rawDescGZIP(), []int{17} +} + +func (x *DeletedPublication) GetEid() string { + if x != nil { + return x.Eid + } + return "" +} + +func (x *DeletedPublication) GetDeletedTime() *timestamppb.Timestamp { + if x != nil { + return x.DeletedTime + } + return nil +} + +func (x *DeletedPublication) GetDeletedReason() string { + if x != nil { + return x.DeletedReason + } + return "" +} + +func (x *DeletedPublication) GetMetadata() string { + if x != nil { + return x.Metadata + } + return "" +} + // Document represents metadata and content of a draft or publication. type Document struct { state protoimpl.MessageState @@ -1651,208 +1677,208 @@ var file_documents_v1alpha_documents_proto_rawDesc = []byte{ 0x74, 0x49, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x1d, 0x0a, 0x0a, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x5f, 0x6f, 0x6e, 0x6c, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, - 0x08, 0x52, 0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x6e, 0x6c, 0x79, 0x22, 0x3b, 0x0a, 0x18, - 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x64, 0x6f, 0x63, 0x75, - 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x64, - 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x49, 0x64, 0x22, 0x4b, 0x0a, 0x16, 0x50, 0x75, 0x73, - 0x68, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x5f, - 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, - 0x6e, 0x74, 0x49, 0x64, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x72, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x03, 0x75, 0x72, 0x6c, 0x22, 0x78, 0x0a, 0x17, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x75, - 0x62, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x70, 0x61, 0x67, 0x65, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x1d, - 0x0a, 0x0a, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x09, 0x70, 0x61, 0x67, 0x65, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x21, 0x0a, - 0x0c, 0x74, 0x72, 0x75, 0x73, 0x74, 0x65, 0x64, 0x5f, 0x6f, 0x6e, 0x6c, 0x79, 0x18, 0x03, 0x20, - 0x01, 0x28, 0x08, 0x52, 0x0b, 0x74, 0x72, 0x75, 0x73, 0x74, 0x65, 0x64, 0x4f, 0x6e, 0x6c, 0x79, - 0x22, 0x92, 0x01, 0x0a, 0x18, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4e, 0x0a, - 0x0c, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x01, 0x20, - 0x03, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x6d, 0x69, 0x6e, 0x74, 0x74, 0x65, - 0x72, 0x2e, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x76, 0x31, 0x61, 0x6c, - 0x70, 0x68, 0x61, 0x2e, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, - 0x0c, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x26, 0x0a, - 0x0f, 0x6e, 0x65, 0x78, 0x74, 0x5f, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x6e, 0x65, 0x78, 0x74, 0x50, 0x61, 0x67, 0x65, - 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x22, 0x7b, 0x0a, 0x1e, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x63, 0x63, - 0x6f, 0x75, 0x6e, 0x74, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x70, 0x61, 0x67, 0x65, 0x5f, - 0x73, 0x69, 0x7a, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x70, 0x61, 0x67, 0x65, - 0x53, 0x69, 0x7a, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x74, 0x6f, 0x6b, - 0x65, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x70, 0x61, 0x67, 0x65, 0x54, 0x6f, - 0x6b, 0x65, 0x6e, 0x12, 0x1d, 0x0a, 0x0a, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x69, - 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, - 0x49, 0x64, 0x22, 0x6c, 0x0a, 0x0b, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x43, 0x0a, 0x08, 0x64, - 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, - 0x63, 0x6f, 0x6d, 0x2e, 0x6d, 0x69, 0x6e, 0x74, 0x74, 0x65, 0x72, 0x2e, 0x64, 0x6f, 0x63, 0x75, - 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x44, 0x6f, - 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x08, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, - 0x22, 0xe1, 0x02, 0x0a, 0x08, 0x44, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x0e, 0x0a, - 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x14, 0x0a, - 0x05, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x74, 0x69, - 0x74, 0x6c, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x18, 0x04, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x06, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x12, 0x18, 0x0a, 0x07, 0x65, - 0x64, 0x69, 0x74, 0x6f, 0x72, 0x73, 0x18, 0x0b, 0x20, 0x03, 0x28, 0x09, 0x52, 0x07, 0x65, 0x64, - 0x69, 0x74, 0x6f, 0x72, 0x73, 0x12, 0x44, 0x0a, 0x08, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x72, 0x65, - 0x6e, 0x18, 0x09, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x6d, 0x69, - 0x6e, 0x74, 0x74, 0x65, 0x72, 0x2e, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x2e, - 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x4e, 0x6f, 0x64, - 0x65, 0x52, 0x08, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x72, 0x65, 0x6e, 0x12, 0x3b, 0x0a, 0x0b, 0x63, - 0x72, 0x65, 0x61, 0x74, 0x65, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x06, 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, 0x0a, 0x63, 0x72, - 0x65, 0x61, 0x74, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x3b, 0x0a, 0x0b, 0x75, 0x70, 0x64, 0x61, - 0x74, 0x65, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x07, 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, 0x0a, 0x75, 0x70, 0x64, 0x61, 0x74, - 0x65, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x3d, 0x0a, 0x0c, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, - 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, + 0x08, 0x52, 0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x4f, 0x6e, 0x6c, 0x79, 0x22, 0x4b, 0x0a, 0x16, + 0x50, 0x75, 0x73, 0x68, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, + 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x64, 0x6f, 0x63, + 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x49, 0x64, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x72, 0x6c, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x75, 0x72, 0x6c, 0x22, 0x78, 0x0a, 0x17, 0x4c, 0x69, 0x73, + 0x74, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x73, 0x69, 0x7a, + 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x70, 0x61, 0x67, 0x65, 0x53, 0x69, 0x7a, + 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x70, 0x61, 0x67, 0x65, 0x54, 0x6f, 0x6b, 0x65, 0x6e, + 0x12, 0x21, 0x0a, 0x0c, 0x74, 0x72, 0x75, 0x73, 0x74, 0x65, 0x64, 0x5f, 0x6f, 0x6e, 0x6c, 0x79, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x74, 0x72, 0x75, 0x73, 0x74, 0x65, 0x64, 0x4f, + 0x6e, 0x6c, 0x79, 0x22, 0x92, 0x01, 0x0a, 0x18, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x75, 0x62, 0x6c, + 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x12, 0x4e, 0x0a, 0x0c, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, + 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x6d, 0x69, 0x6e, + 0x74, 0x74, 0x65, 0x72, 0x2e, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x76, + 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x52, 0x0c, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, + 0x12, 0x26, 0x0a, 0x0f, 0x6e, 0x65, 0x78, 0x74, 0x5f, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x74, 0x6f, + 0x6b, 0x65, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x6e, 0x65, 0x78, 0x74, 0x50, + 0x61, 0x67, 0x65, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x22, 0x7b, 0x0a, 0x1e, 0x4c, 0x69, 0x73, 0x74, + 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x70, 0x61, + 0x67, 0x65, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x70, + 0x61, 0x67, 0x65, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x70, 0x61, 0x67, 0x65, 0x5f, + 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x70, 0x61, 0x67, + 0x65, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x1d, 0x0a, 0x0a, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, + 0x74, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x61, 0x63, 0x63, 0x6f, + 0x75, 0x6e, 0x74, 0x49, 0x64, 0x22, 0x6c, 0x0a, 0x0b, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x43, + 0x0a, 0x08, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x27, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x6d, 0x69, 0x6e, 0x74, 0x74, 0x65, 0x72, 0x2e, 0x64, + 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, + 0x2e, 0x44, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x08, 0x64, 0x6f, 0x63, 0x75, 0x6d, + 0x65, 0x6e, 0x74, 0x22, 0xa8, 0x01, 0x0a, 0x12, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x64, 0x50, + 0x75, 0x62, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x10, 0x0a, 0x03, 0x65, 0x69, + 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x65, 0x69, 0x64, 0x12, 0x3d, 0x0a, 0x0c, + 0x64, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x64, 0x5f, 0x74, 0x69, 0x6d, 0x65, 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, 0x52, 0x0b, + 0x64, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x64, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x25, 0x0a, 0x0e, 0x64, + 0x65, 0x6c, 0x65, 0x74, 0x65, 0x64, 0x5f, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x0d, 0x64, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x64, 0x52, 0x65, 0x61, 0x73, + 0x6f, 0x6e, 0x12, 0x1a, 0x0a, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x04, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x22, 0xe1, + 0x02, 0x0a, 0x08, 0x44, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, + 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x74, + 0x69, 0x74, 0x6c, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x74, 0x69, 0x74, 0x6c, + 0x65, 0x12, 0x16, 0x0a, 0x06, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x06, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x12, 0x18, 0x0a, 0x07, 0x65, 0x64, 0x69, + 0x74, 0x6f, 0x72, 0x73, 0x18, 0x0b, 0x20, 0x03, 0x28, 0x09, 0x52, 0x07, 0x65, 0x64, 0x69, 0x74, + 0x6f, 0x72, 0x73, 0x12, 0x44, 0x0a, 0x08, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x72, 0x65, 0x6e, 0x18, + 0x09, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x6d, 0x69, 0x6e, 0x74, + 0x74, 0x65, 0x72, 0x2e, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x76, 0x31, + 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x4e, 0x6f, 0x64, 0x65, 0x52, + 0x08, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x72, 0x65, 0x6e, 0x12, 0x3b, 0x0a, 0x0b, 0x63, 0x72, 0x65, + 0x61, 0x74, 0x65, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x06, 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, 0x0a, 0x63, 0x72, 0x65, 0x61, + 0x74, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x3b, 0x0a, 0x0b, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, + 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x07, 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, 0x0b, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, - 0x54, 0x69, 0x6d, 0x65, 0x22, 0x8d, 0x01, 0x0a, 0x09, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x4e, 0x6f, - 0x64, 0x65, 0x12, 0x3a, 0x0a, 0x05, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x24, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x6d, 0x69, 0x6e, 0x74, 0x74, 0x65, 0x72, 0x2e, + 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0a, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x54, + 0x69, 0x6d, 0x65, 0x12, 0x3d, 0x0a, 0x0c, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x5f, 0x74, + 0x69, 0x6d, 0x65, 0x18, 0x08, 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, 0x0b, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x54, 0x69, + 0x6d, 0x65, 0x22, 0x8d, 0x01, 0x0a, 0x09, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x4e, 0x6f, 0x64, 0x65, + 0x12, 0x3a, 0x0a, 0x05, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x24, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x6d, 0x69, 0x6e, 0x74, 0x74, 0x65, 0x72, 0x2e, 0x64, 0x6f, + 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, + 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x05, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x44, 0x0a, 0x08, + 0x63, 0x68, 0x69, 0x6c, 0x64, 0x72, 0x65, 0x6e, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x28, + 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x6d, 0x69, 0x6e, 0x74, 0x74, 0x65, 0x72, 0x2e, 0x64, 0x6f, 0x63, + 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x42, + 0x6c, 0x6f, 0x63, 0x6b, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x08, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x72, + 0x65, 0x6e, 0x22, 0xcf, 0x02, 0x0a, 0x05, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x0e, 0x0a, 0x02, + 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, + 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, + 0x12, 0x12, 0x0a, 0x04, 0x74, 0x65, 0x78, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, + 0x74, 0x65, 0x78, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x72, 0x65, 0x66, 0x18, 0x07, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x03, 0x72, 0x65, 0x66, 0x12, 0x54, 0x0a, 0x0a, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, + 0x75, 0x74, 0x65, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x34, 0x2e, 0x63, 0x6f, 0x6d, + 0x2e, 0x6d, 0x69, 0x6e, 0x74, 0x74, 0x65, 0x72, 0x2e, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, + 0x74, 0x73, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, + 0x2e, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, + 0x52, 0x0a, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x12, 0x4b, 0x0a, 0x0b, + 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, + 0x0b, 0x32, 0x29, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x6d, 0x69, 0x6e, 0x74, 0x74, 0x65, 0x72, 0x2e, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, - 0x61, 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x05, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x44, - 0x0a, 0x08, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x72, 0x65, 0x6e, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, - 0x32, 0x28, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x6d, 0x69, 0x6e, 0x74, 0x74, 0x65, 0x72, 0x2e, 0x64, - 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, - 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x08, 0x63, 0x68, 0x69, 0x6c, - 0x64, 0x72, 0x65, 0x6e, 0x22, 0xcf, 0x02, 0x0a, 0x05, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x0e, - 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x12, - 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, - 0x70, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x65, 0x78, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x04, 0x74, 0x65, 0x78, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x72, 0x65, 0x66, 0x18, 0x07, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x03, 0x72, 0x65, 0x66, 0x12, 0x54, 0x0a, 0x0a, 0x61, 0x74, 0x74, 0x72, - 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x34, 0x2e, 0x63, + 0x61, 0x2e, 0x41, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0b, 0x61, 0x6e, + 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x72, 0x65, 0x76, + 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x72, 0x65, 0x76, + 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x1a, 0x3d, 0x0a, 0x0f, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, + 0x74, 0x65, 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, 0xf8, 0x01, 0x0a, 0x0a, 0x41, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x72, 0x65, 0x66, 0x18, 0x05, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x72, 0x65, 0x66, 0x12, 0x59, 0x0a, 0x0a, 0x61, 0x74, 0x74, + 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x39, 0x2e, + 0x63, 0x6f, 0x6d, 0x2e, 0x6d, 0x69, 0x6e, 0x74, 0x74, 0x65, 0x72, 0x2e, 0x64, 0x6f, 0x63, 0x75, + 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x41, 0x6e, + 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, + 0x74, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0a, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, + 0x75, 0x74, 0x65, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x72, 0x74, 0x73, 0x18, 0x03, + 0x20, 0x03, 0x28, 0x05, 0x52, 0x06, 0x73, 0x74, 0x61, 0x72, 0x74, 0x73, 0x12, 0x12, 0x0a, 0x04, + 0x65, 0x6e, 0x64, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x05, 0x52, 0x04, 0x65, 0x6e, 0x64, 0x73, + 0x1a, 0x3d, 0x0a, 0x0f, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 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, 0x32, + 0x97, 0x06, 0x0a, 0x06, 0x44, 0x72, 0x61, 0x66, 0x74, 0x73, 0x12, 0x69, 0x0a, 0x0b, 0x43, 0x72, + 0x65, 0x61, 0x74, 0x65, 0x44, 0x72, 0x61, 0x66, 0x74, 0x12, 0x31, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, + 0x6d, 0x69, 0x6e, 0x74, 0x74, 0x65, 0x72, 0x2e, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, + 0x73, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, + 0x44, 0x72, 0x61, 0x66, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x6d, 0x69, 0x6e, 0x74, 0x74, 0x65, 0x72, 0x2e, 0x64, 0x6f, 0x63, 0x75, 0x6d, - 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x42, 0x6c, 0x6f, - 0x63, 0x6b, 0x2e, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x45, 0x6e, 0x74, - 0x72, 0x79, 0x52, 0x0a, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x12, 0x4b, - 0x0a, 0x0b, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x05, 0x20, - 0x03, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x6d, 0x69, 0x6e, 0x74, 0x74, 0x65, - 0x72, 0x2e, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x76, 0x31, 0x61, 0x6c, - 0x70, 0x68, 0x61, 0x2e, 0x41, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0b, - 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x72, - 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x72, - 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x1a, 0x3d, 0x0a, 0x0f, 0x41, 0x74, 0x74, 0x72, 0x69, - 0x62, 0x75, 0x74, 0x65, 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, 0xf8, 0x01, 0x0a, 0x0a, 0x41, 0x6e, 0x6e, 0x6f, 0x74, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x72, 0x65, 0x66, - 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x72, 0x65, 0x66, 0x12, 0x59, 0x0a, 0x0a, 0x61, - 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, - 0x39, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x6d, 0x69, 0x6e, 0x74, 0x74, 0x65, 0x72, 0x2e, 0x64, 0x6f, - 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, - 0x41, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x41, 0x74, 0x74, 0x72, 0x69, - 0x62, 0x75, 0x74, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0a, 0x61, 0x74, 0x74, 0x72, - 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x72, 0x74, 0x73, - 0x18, 0x03, 0x20, 0x03, 0x28, 0x05, 0x52, 0x06, 0x73, 0x74, 0x61, 0x72, 0x74, 0x73, 0x12, 0x12, - 0x0a, 0x04, 0x65, 0x6e, 0x64, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x05, 0x52, 0x04, 0x65, 0x6e, - 0x64, 0x73, 0x1a, 0x3d, 0x0a, 0x0f, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 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, 0x32, 0x97, 0x06, 0x0a, 0x06, 0x44, 0x72, 0x61, 0x66, 0x74, 0x73, 0x12, 0x69, 0x0a, 0x0b, - 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x44, 0x72, 0x61, 0x66, 0x74, 0x12, 0x31, 0x2e, 0x63, 0x6f, + 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x44, 0x6f, 0x63, + 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x58, 0x0a, 0x0b, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x44, + 0x72, 0x61, 0x66, 0x74, 0x12, 0x31, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x6d, 0x69, 0x6e, 0x74, 0x74, + 0x65, 0x72, 0x2e, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x76, 0x31, 0x61, + 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x44, 0x72, 0x61, 0x66, 0x74, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, + 0x63, 0x0a, 0x08, 0x47, 0x65, 0x74, 0x44, 0x72, 0x61, 0x66, 0x74, 0x12, 0x2e, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x6d, 0x69, 0x6e, 0x74, 0x74, 0x65, 0x72, 0x2e, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, - 0x6e, 0x74, 0x73, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x43, 0x72, 0x65, 0x61, - 0x74, 0x65, 0x44, 0x72, 0x61, 0x66, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, - 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x6d, 0x69, 0x6e, 0x74, 0x74, 0x65, 0x72, 0x2e, 0x64, 0x6f, 0x63, - 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x44, - 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x58, 0x0a, 0x0b, 0x44, 0x65, 0x6c, 0x65, 0x74, - 0x65, 0x44, 0x72, 0x61, 0x66, 0x74, 0x12, 0x31, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x6d, 0x69, 0x6e, + 0x6e, 0x74, 0x73, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x47, 0x65, 0x74, 0x44, + 0x72, 0x61, 0x66, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e, 0x63, 0x6f, + 0x6d, 0x2e, 0x6d, 0x69, 0x6e, 0x74, 0x74, 0x65, 0x72, 0x2e, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, + 0x6e, 0x74, 0x73, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x44, 0x6f, 0x63, 0x75, + 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x74, 0x0a, 0x0b, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x44, 0x72, + 0x61, 0x66, 0x74, 0x12, 0x31, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x6d, 0x69, 0x6e, 0x74, 0x74, 0x65, + 0x72, 0x2e, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x76, 0x31, 0x61, 0x6c, + 0x70, 0x68, 0x61, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x44, 0x72, 0x61, 0x66, 0x74, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x32, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x6d, 0x69, 0x6e, 0x74, 0x74, 0x65, 0x72, 0x2e, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x76, - 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x44, 0x72, 0x61, - 0x66, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, - 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, - 0x79, 0x12, 0x63, 0x0a, 0x08, 0x47, 0x65, 0x74, 0x44, 0x72, 0x61, 0x66, 0x74, 0x12, 0x2e, 0x2e, - 0x63, 0x6f, 0x6d, 0x2e, 0x6d, 0x69, 0x6e, 0x74, 0x74, 0x65, 0x72, 0x2e, 0x64, 0x6f, 0x63, 0x75, - 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x47, 0x65, - 0x74, 0x44, 0x72, 0x61, 0x66, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e, - 0x63, 0x6f, 0x6d, 0x2e, 0x6d, 0x69, 0x6e, 0x74, 0x74, 0x65, 0x72, 0x2e, 0x64, 0x6f, 0x63, 0x75, - 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x44, 0x6f, - 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x74, 0x0a, 0x0b, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, - 0x44, 0x72, 0x61, 0x66, 0x74, 0x12, 0x31, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x6d, 0x69, 0x6e, 0x74, - 0x74, 0x65, 0x72, 0x2e, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x76, 0x31, - 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x44, 0x72, 0x61, 0x66, - 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x32, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x6d, + 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x44, 0x72, 0x61, + 0x66, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x71, 0x0a, 0x0a, 0x4c, 0x69, + 0x73, 0x74, 0x44, 0x72, 0x61, 0x66, 0x74, 0x73, 0x12, 0x30, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x6d, 0x69, 0x6e, 0x74, 0x74, 0x65, 0x72, 0x2e, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x73, - 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x44, - 0x72, 0x61, 0x66, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x71, 0x0a, 0x0a, - 0x4c, 0x69, 0x73, 0x74, 0x44, 0x72, 0x61, 0x66, 0x74, 0x73, 0x12, 0x30, 0x2e, 0x63, 0x6f, 0x6d, + 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x44, 0x72, 0x61, + 0x66, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x31, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x6d, 0x69, 0x6e, 0x74, 0x74, 0x65, 0x72, 0x2e, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x44, - 0x72, 0x61, 0x66, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x31, 0x2e, 0x63, + 0x72, 0x61, 0x66, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x89, 0x01, + 0x0a, 0x12, 0x4c, 0x69, 0x73, 0x74, 0x44, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x44, 0x72, + 0x61, 0x66, 0x74, 0x73, 0x12, 0x38, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x6d, 0x69, 0x6e, 0x74, 0x74, + 0x65, 0x72, 0x2e, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x76, 0x31, 0x61, + 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x44, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, + 0x74, 0x44, 0x72, 0x61, 0x66, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x39, + 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x6d, 0x69, 0x6e, 0x74, 0x74, 0x65, 0x72, 0x2e, 0x64, 0x6f, 0x63, + 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x4c, + 0x69, 0x73, 0x74, 0x44, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x44, 0x72, 0x61, 0x66, 0x74, + 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6e, 0x0a, 0x0c, 0x50, 0x75, 0x62, + 0x6c, 0x69, 0x73, 0x68, 0x44, 0x72, 0x61, 0x66, 0x74, 0x12, 0x32, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, + 0x6d, 0x69, 0x6e, 0x74, 0x74, 0x65, 0x72, 0x2e, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, + 0x73, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x73, + 0x68, 0x44, 0x72, 0x61, 0x66, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e, + 0x63, 0x6f, 0x6d, 0x2e, 0x6d, 0x69, 0x6e, 0x74, 0x74, 0x65, 0x72, 0x2e, 0x64, 0x6f, 0x63, 0x75, + 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x50, 0x75, + 0x62, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x32, 0xfe, 0x03, 0x0a, 0x0c, 0x50, 0x75, + 0x62, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x72, 0x0a, 0x0e, 0x47, 0x65, + 0x74, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x34, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x6d, 0x69, 0x6e, 0x74, 0x74, 0x65, 0x72, 0x2e, 0x64, 0x6f, 0x63, 0x75, 0x6d, - 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x4c, 0x69, 0x73, - 0x74, 0x44, 0x72, 0x61, 0x66, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x89, 0x01, 0x0a, 0x12, 0x4c, 0x69, 0x73, 0x74, 0x44, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, - 0x44, 0x72, 0x61, 0x66, 0x74, 0x73, 0x12, 0x38, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x6d, 0x69, 0x6e, - 0x74, 0x74, 0x65, 0x72, 0x2e, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x76, - 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x44, 0x6f, 0x63, 0x75, 0x6d, - 0x65, 0x6e, 0x74, 0x44, 0x72, 0x61, 0x66, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x39, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x6d, 0x69, 0x6e, 0x74, 0x74, 0x65, 0x72, 0x2e, 0x64, - 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, - 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x44, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x44, 0x72, 0x61, - 0x66, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6e, 0x0a, 0x0c, 0x50, - 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x44, 0x72, 0x61, 0x66, 0x74, 0x12, 0x32, 0x2e, 0x63, 0x6f, + 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x47, 0x65, 0x74, + 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x6d, 0x69, 0x6e, 0x74, 0x74, 0x65, 0x72, + 0x2e, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, + 0x68, 0x61, 0x2e, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x83, + 0x01, 0x0a, 0x10, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x73, 0x12, 0x36, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x6d, 0x69, 0x6e, 0x74, 0x74, 0x65, + 0x72, 0x2e, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x76, 0x31, 0x61, 0x6c, + 0x70, 0x68, 0x61, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x37, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x6d, 0x69, 0x6e, 0x74, 0x74, 0x65, 0x72, 0x2e, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, - 0x6e, 0x74, 0x73, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x50, 0x75, 0x62, 0x6c, - 0x69, 0x73, 0x68, 0x44, 0x72, 0x61, 0x66, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x2a, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x6d, 0x69, 0x6e, 0x74, 0x74, 0x65, 0x72, 0x2e, 0x64, 0x6f, - 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, - 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x32, 0xe4, 0x04, 0x0a, 0x0c, - 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x72, 0x0a, 0x0e, - 0x47, 0x65, 0x74, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x34, - 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x6d, 0x69, 0x6e, 0x74, 0x74, 0x65, 0x72, 0x2e, 0x64, 0x6f, 0x63, - 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x47, - 0x65, 0x74, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x6d, 0x69, 0x6e, 0x74, 0x74, - 0x65, 0x72, 0x2e, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x76, 0x31, 0x61, - 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x12, 0x64, 0x0a, 0x11, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x37, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x6d, 0x69, 0x6e, 0x74, - 0x74, 0x65, 0x72, 0x2e, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x76, 0x31, - 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x50, 0x75, 0x62, 0x6c, + 0x6e, 0x74, 0x73, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x4c, 0x69, 0x73, 0x74, + 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x60, 0x0a, 0x0f, 0x50, 0x75, 0x73, 0x68, 0x50, 0x75, 0x62, 0x6c, + 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x35, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x6d, 0x69, + 0x6e, 0x74, 0x74, 0x65, 0x72, 0x2e, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x2e, + 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x50, 0x75, 0x73, 0x68, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, - 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x83, 0x01, 0x0a, 0x10, 0x4c, 0x69, 0x73, 0x74, 0x50, - 0x75, 0x62, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x36, 0x2e, 0x63, 0x6f, - 0x6d, 0x2e, 0x6d, 0x69, 0x6e, 0x74, 0x74, 0x65, 0x72, 0x2e, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, - 0x6e, 0x74, 0x73, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x4c, 0x69, 0x73, 0x74, - 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x37, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x6d, 0x69, 0x6e, 0x74, 0x74, 0x65, - 0x72, 0x2e, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x76, 0x31, 0x61, 0x6c, - 0x70, 0x68, 0x61, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x60, 0x0a, 0x0f, - 0x50, 0x75, 0x73, 0x68, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, - 0x35, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x6d, 0x69, 0x6e, 0x74, 0x74, 0x65, 0x72, 0x2e, 0x64, 0x6f, - 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, - 0x50, 0x75, 0x73, 0x68, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x91, - 0x01, 0x0a, 0x17, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x50, 0x75, - 0x62, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x3d, 0x2e, 0x63, 0x6f, 0x6d, - 0x2e, 0x6d, 0x69, 0x6e, 0x74, 0x74, 0x65, 0x72, 0x2e, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, - 0x74, 0x73, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x41, + 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x91, 0x01, 0x0a, 0x17, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x37, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, - 0x6d, 0x69, 0x6e, 0x74, 0x74, 0x65, 0x72, 0x2e, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, - 0x73, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x75, - 0x62, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x42, 0x36, 0x5a, 0x34, 0x6d, 0x69, 0x6e, 0x74, 0x74, 0x65, 0x72, 0x2f, 0x62, 0x61, - 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x2f, 0x67, 0x65, 0x6e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x64, - 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, - 0x3b, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x33, + 0x6e, 0x73, 0x12, 0x3d, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x6d, 0x69, 0x6e, 0x74, 0x74, 0x65, 0x72, + 0x2e, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, + 0x68, 0x61, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x50, 0x75, + 0x62, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x37, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x6d, 0x69, 0x6e, 0x74, 0x74, 0x65, 0x72, 0x2e, + 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, + 0x61, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x36, 0x5a, 0x34, 0x6d, 0x69, + 0x6e, 0x74, 0x74, 0x65, 0x72, 0x2f, 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x2f, 0x67, 0x65, + 0x6e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x73, + 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x3b, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, + 0x74, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -1881,12 +1907,12 @@ var file_documents_v1alpha_documents_proto_goTypes = []interface{}{ (*ListDocumentDraftsResponse)(nil), // 9: com.mintter.documents.v1alpha.ListDocumentDraftsResponse (*PublishDraftRequest)(nil), // 10: com.mintter.documents.v1alpha.PublishDraftRequest (*GetPublicationRequest)(nil), // 11: com.mintter.documents.v1alpha.GetPublicationRequest - (*DeletePublicationRequest)(nil), // 12: com.mintter.documents.v1alpha.DeletePublicationRequest - (*PushPublicationRequest)(nil), // 13: com.mintter.documents.v1alpha.PushPublicationRequest - (*ListPublicationsRequest)(nil), // 14: com.mintter.documents.v1alpha.ListPublicationsRequest - (*ListPublicationsResponse)(nil), // 15: com.mintter.documents.v1alpha.ListPublicationsResponse - (*ListAccountPublicationsRequest)(nil), // 16: com.mintter.documents.v1alpha.ListAccountPublicationsRequest - (*Publication)(nil), // 17: com.mintter.documents.v1alpha.Publication + (*PushPublicationRequest)(nil), // 12: com.mintter.documents.v1alpha.PushPublicationRequest + (*ListPublicationsRequest)(nil), // 13: com.mintter.documents.v1alpha.ListPublicationsRequest + (*ListPublicationsResponse)(nil), // 14: com.mintter.documents.v1alpha.ListPublicationsResponse + (*ListAccountPublicationsRequest)(nil), // 15: com.mintter.documents.v1alpha.ListAccountPublicationsRequest + (*Publication)(nil), // 16: com.mintter.documents.v1alpha.Publication + (*DeletedPublication)(nil), // 17: com.mintter.documents.v1alpha.DeletedPublication (*Document)(nil), // 18: com.mintter.documents.v1alpha.Document (*BlockNode)(nil), // 19: com.mintter.documents.v1alpha.BlockNode (*Block)(nil), // 20: com.mintter.documents.v1alpha.Block @@ -1904,46 +1930,45 @@ var file_documents_v1alpha_documents_proto_depIdxs = []int32{ 20, // 3: com.mintter.documents.v1alpha.DocumentChange.replace_block:type_name -> com.mintter.documents.v1alpha.Block 18, // 4: com.mintter.documents.v1alpha.ListDraftsResponse.documents:type_name -> com.mintter.documents.v1alpha.Document 18, // 5: com.mintter.documents.v1alpha.ListDocumentDraftsResponse.drafts:type_name -> com.mintter.documents.v1alpha.Document - 17, // 6: com.mintter.documents.v1alpha.ListPublicationsResponse.publications:type_name -> com.mintter.documents.v1alpha.Publication + 16, // 6: com.mintter.documents.v1alpha.ListPublicationsResponse.publications:type_name -> com.mintter.documents.v1alpha.Publication 18, // 7: com.mintter.documents.v1alpha.Publication.document:type_name -> com.mintter.documents.v1alpha.Document - 19, // 8: com.mintter.documents.v1alpha.Document.children:type_name -> com.mintter.documents.v1alpha.BlockNode - 25, // 9: com.mintter.documents.v1alpha.Document.create_time:type_name -> google.protobuf.Timestamp - 25, // 10: com.mintter.documents.v1alpha.Document.update_time:type_name -> google.protobuf.Timestamp - 25, // 11: com.mintter.documents.v1alpha.Document.publish_time:type_name -> google.protobuf.Timestamp - 20, // 12: com.mintter.documents.v1alpha.BlockNode.block:type_name -> com.mintter.documents.v1alpha.Block - 19, // 13: com.mintter.documents.v1alpha.BlockNode.children:type_name -> com.mintter.documents.v1alpha.BlockNode - 23, // 14: com.mintter.documents.v1alpha.Block.attributes:type_name -> com.mintter.documents.v1alpha.Block.AttributesEntry - 21, // 15: com.mintter.documents.v1alpha.Block.annotations:type_name -> com.mintter.documents.v1alpha.Annotation - 24, // 16: com.mintter.documents.v1alpha.Annotation.attributes:type_name -> com.mintter.documents.v1alpha.Annotation.AttributesEntry - 0, // 17: com.mintter.documents.v1alpha.Drafts.CreateDraft:input_type -> com.mintter.documents.v1alpha.CreateDraftRequest - 1, // 18: com.mintter.documents.v1alpha.Drafts.DeleteDraft:input_type -> com.mintter.documents.v1alpha.DeleteDraftRequest - 2, // 19: com.mintter.documents.v1alpha.Drafts.GetDraft:input_type -> com.mintter.documents.v1alpha.GetDraftRequest - 3, // 20: com.mintter.documents.v1alpha.Drafts.UpdateDraft:input_type -> com.mintter.documents.v1alpha.UpdateDraftRequest - 6, // 21: com.mintter.documents.v1alpha.Drafts.ListDrafts:input_type -> com.mintter.documents.v1alpha.ListDraftsRequest - 8, // 22: com.mintter.documents.v1alpha.Drafts.ListDocumentDrafts:input_type -> com.mintter.documents.v1alpha.ListDocumentDraftsRequest - 10, // 23: com.mintter.documents.v1alpha.Drafts.PublishDraft:input_type -> com.mintter.documents.v1alpha.PublishDraftRequest - 11, // 24: com.mintter.documents.v1alpha.Publications.GetPublication:input_type -> com.mintter.documents.v1alpha.GetPublicationRequest - 12, // 25: com.mintter.documents.v1alpha.Publications.DeletePublication:input_type -> com.mintter.documents.v1alpha.DeletePublicationRequest - 14, // 26: com.mintter.documents.v1alpha.Publications.ListPublications:input_type -> com.mintter.documents.v1alpha.ListPublicationsRequest - 13, // 27: com.mintter.documents.v1alpha.Publications.PushPublication:input_type -> com.mintter.documents.v1alpha.PushPublicationRequest - 16, // 28: com.mintter.documents.v1alpha.Publications.ListAccountPublications:input_type -> com.mintter.documents.v1alpha.ListAccountPublicationsRequest + 25, // 8: com.mintter.documents.v1alpha.DeletedPublication.deleted_time:type_name -> google.protobuf.Timestamp + 19, // 9: com.mintter.documents.v1alpha.Document.children:type_name -> com.mintter.documents.v1alpha.BlockNode + 25, // 10: com.mintter.documents.v1alpha.Document.create_time:type_name -> google.protobuf.Timestamp + 25, // 11: com.mintter.documents.v1alpha.Document.update_time:type_name -> google.protobuf.Timestamp + 25, // 12: com.mintter.documents.v1alpha.Document.publish_time:type_name -> google.protobuf.Timestamp + 20, // 13: com.mintter.documents.v1alpha.BlockNode.block:type_name -> com.mintter.documents.v1alpha.Block + 19, // 14: com.mintter.documents.v1alpha.BlockNode.children:type_name -> com.mintter.documents.v1alpha.BlockNode + 23, // 15: com.mintter.documents.v1alpha.Block.attributes:type_name -> com.mintter.documents.v1alpha.Block.AttributesEntry + 21, // 16: com.mintter.documents.v1alpha.Block.annotations:type_name -> com.mintter.documents.v1alpha.Annotation + 24, // 17: com.mintter.documents.v1alpha.Annotation.attributes:type_name -> com.mintter.documents.v1alpha.Annotation.AttributesEntry + 0, // 18: com.mintter.documents.v1alpha.Drafts.CreateDraft:input_type -> com.mintter.documents.v1alpha.CreateDraftRequest + 1, // 19: com.mintter.documents.v1alpha.Drafts.DeleteDraft:input_type -> com.mintter.documents.v1alpha.DeleteDraftRequest + 2, // 20: com.mintter.documents.v1alpha.Drafts.GetDraft:input_type -> com.mintter.documents.v1alpha.GetDraftRequest + 3, // 21: com.mintter.documents.v1alpha.Drafts.UpdateDraft:input_type -> com.mintter.documents.v1alpha.UpdateDraftRequest + 6, // 22: com.mintter.documents.v1alpha.Drafts.ListDrafts:input_type -> com.mintter.documents.v1alpha.ListDraftsRequest + 8, // 23: com.mintter.documents.v1alpha.Drafts.ListDocumentDrafts:input_type -> com.mintter.documents.v1alpha.ListDocumentDraftsRequest + 10, // 24: com.mintter.documents.v1alpha.Drafts.PublishDraft:input_type -> com.mintter.documents.v1alpha.PublishDraftRequest + 11, // 25: com.mintter.documents.v1alpha.Publications.GetPublication:input_type -> com.mintter.documents.v1alpha.GetPublicationRequest + 13, // 26: com.mintter.documents.v1alpha.Publications.ListPublications:input_type -> com.mintter.documents.v1alpha.ListPublicationsRequest + 12, // 27: com.mintter.documents.v1alpha.Publications.PushPublication:input_type -> com.mintter.documents.v1alpha.PushPublicationRequest + 15, // 28: com.mintter.documents.v1alpha.Publications.ListAccountPublications:input_type -> com.mintter.documents.v1alpha.ListAccountPublicationsRequest 18, // 29: com.mintter.documents.v1alpha.Drafts.CreateDraft:output_type -> com.mintter.documents.v1alpha.Document 26, // 30: com.mintter.documents.v1alpha.Drafts.DeleteDraft:output_type -> google.protobuf.Empty 18, // 31: com.mintter.documents.v1alpha.Drafts.GetDraft:output_type -> com.mintter.documents.v1alpha.Document 4, // 32: com.mintter.documents.v1alpha.Drafts.UpdateDraft:output_type -> com.mintter.documents.v1alpha.UpdateDraftResponse 7, // 33: com.mintter.documents.v1alpha.Drafts.ListDrafts:output_type -> com.mintter.documents.v1alpha.ListDraftsResponse 9, // 34: com.mintter.documents.v1alpha.Drafts.ListDocumentDrafts:output_type -> com.mintter.documents.v1alpha.ListDocumentDraftsResponse - 17, // 35: com.mintter.documents.v1alpha.Drafts.PublishDraft:output_type -> com.mintter.documents.v1alpha.Publication - 17, // 36: com.mintter.documents.v1alpha.Publications.GetPublication:output_type -> com.mintter.documents.v1alpha.Publication - 26, // 37: com.mintter.documents.v1alpha.Publications.DeletePublication:output_type -> google.protobuf.Empty - 15, // 38: com.mintter.documents.v1alpha.Publications.ListPublications:output_type -> com.mintter.documents.v1alpha.ListPublicationsResponse - 26, // 39: com.mintter.documents.v1alpha.Publications.PushPublication:output_type -> google.protobuf.Empty - 15, // 40: com.mintter.documents.v1alpha.Publications.ListAccountPublications:output_type -> com.mintter.documents.v1alpha.ListPublicationsResponse - 29, // [29:41] is the sub-list for method output_type - 17, // [17:29] is the sub-list for method input_type - 17, // [17:17] is the sub-list for extension type_name - 17, // [17:17] is the sub-list for extension extendee - 0, // [0:17] is the sub-list for field type_name + 16, // 35: com.mintter.documents.v1alpha.Drafts.PublishDraft:output_type -> com.mintter.documents.v1alpha.Publication + 16, // 36: com.mintter.documents.v1alpha.Publications.GetPublication:output_type -> com.mintter.documents.v1alpha.Publication + 14, // 37: com.mintter.documents.v1alpha.Publications.ListPublications:output_type -> com.mintter.documents.v1alpha.ListPublicationsResponse + 26, // 38: com.mintter.documents.v1alpha.Publications.PushPublication:output_type -> google.protobuf.Empty + 14, // 39: com.mintter.documents.v1alpha.Publications.ListAccountPublications:output_type -> com.mintter.documents.v1alpha.ListPublicationsResponse + 29, // [29:40] is the sub-list for method output_type + 18, // [18:29] is the sub-list for method input_type + 18, // [18:18] is the sub-list for extension type_name + 18, // [18:18] is the sub-list for extension extendee + 0, // [0:18] is the sub-list for field type_name } func init() { file_documents_v1alpha_documents_proto_init() } @@ -2097,7 +2122,7 @@ func file_documents_v1alpha_documents_proto_init() { } } file_documents_v1alpha_documents_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DeletePublicationRequest); i { + switch v := v.(*PushPublicationRequest); i { case 0: return &v.state case 1: @@ -2109,7 +2134,7 @@ func file_documents_v1alpha_documents_proto_init() { } } file_documents_v1alpha_documents_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*PushPublicationRequest); i { + switch v := v.(*ListPublicationsRequest); i { case 0: return &v.state case 1: @@ -2121,7 +2146,7 @@ func file_documents_v1alpha_documents_proto_init() { } } file_documents_v1alpha_documents_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ListPublicationsRequest); i { + switch v := v.(*ListPublicationsResponse); i { case 0: return &v.state case 1: @@ -2133,7 +2158,7 @@ func file_documents_v1alpha_documents_proto_init() { } } file_documents_v1alpha_documents_proto_msgTypes[15].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ListPublicationsResponse); i { + switch v := v.(*ListAccountPublicationsRequest); i { case 0: return &v.state case 1: @@ -2145,7 +2170,7 @@ func file_documents_v1alpha_documents_proto_init() { } } file_documents_v1alpha_documents_proto_msgTypes[16].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ListAccountPublicationsRequest); i { + switch v := v.(*Publication); i { case 0: return &v.state case 1: @@ -2157,7 +2182,7 @@ func file_documents_v1alpha_documents_proto_init() { } } file_documents_v1alpha_documents_proto_msgTypes[17].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Publication); i { + switch v := v.(*DeletedPublication); i { case 0: return &v.state case 1: diff --git a/backend/genproto/documents/v1alpha/documents_grpc.pb.go b/backend/genproto/documents/v1alpha/documents_grpc.pb.go index b75e8faa5c..7450a4ff7e 100644 --- a/backend/genproto/documents/v1alpha/documents_grpc.pb.go +++ b/backend/genproto/documents/v1alpha/documents_grpc.pb.go @@ -339,8 +339,6 @@ var Drafts_ServiceDesc = grpc.ServiceDesc{ type PublicationsClient interface { // Gets a single publication. GetPublication(ctx context.Context, in *GetPublicationRequest, opts ...grpc.CallOption) (*Publication, error) - // Deletes a publication from the local node. It removes all the patches corresponding to a document. - DeletePublication(ctx context.Context, in *DeletePublicationRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) // Lists stored publications. Only the most recent versions show up. ListPublications(ctx context.Context, in *ListPublicationsRequest, opts ...grpc.CallOption) (*ListPublicationsResponse, error) // Push Local publication to the gateway. @@ -366,15 +364,6 @@ func (c *publicationsClient) GetPublication(ctx context.Context, in *GetPublicat return out, nil } -func (c *publicationsClient) DeletePublication(ctx context.Context, in *DeletePublicationRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) { - out := new(emptypb.Empty) - err := c.cc.Invoke(ctx, "/com.mintter.documents.v1alpha.Publications/DeletePublication", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - func (c *publicationsClient) ListPublications(ctx context.Context, in *ListPublicationsRequest, opts ...grpc.CallOption) (*ListPublicationsResponse, error) { out := new(ListPublicationsResponse) err := c.cc.Invoke(ctx, "/com.mintter.documents.v1alpha.Publications/ListPublications", in, out, opts...) @@ -408,8 +397,6 @@ func (c *publicationsClient) ListAccountPublications(ctx context.Context, in *Li type PublicationsServer interface { // Gets a single publication. GetPublication(context.Context, *GetPublicationRequest) (*Publication, error) - // Deletes a publication from the local node. It removes all the patches corresponding to a document. - DeletePublication(context.Context, *DeletePublicationRequest) (*emptypb.Empty, error) // Lists stored publications. Only the most recent versions show up. ListPublications(context.Context, *ListPublicationsRequest) (*ListPublicationsResponse, error) // Push Local publication to the gateway. @@ -425,9 +412,6 @@ type UnimplementedPublicationsServer struct { func (UnimplementedPublicationsServer) GetPublication(context.Context, *GetPublicationRequest) (*Publication, error) { return nil, status.Errorf(codes.Unimplemented, "method GetPublication not implemented") } -func (UnimplementedPublicationsServer) DeletePublication(context.Context, *DeletePublicationRequest) (*emptypb.Empty, error) { - return nil, status.Errorf(codes.Unimplemented, "method DeletePublication not implemented") -} func (UnimplementedPublicationsServer) ListPublications(context.Context, *ListPublicationsRequest) (*ListPublicationsResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method ListPublications not implemented") } @@ -467,24 +451,6 @@ func _Publications_GetPublication_Handler(srv interface{}, ctx context.Context, return interceptor(ctx, in, info, handler) } -func _Publications_DeletePublication_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(DeletePublicationRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(PublicationsServer).DeletePublication(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/com.mintter.documents.v1alpha.Publications/DeletePublication", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(PublicationsServer).DeletePublication(ctx, req.(*DeletePublicationRequest)) - } - return interceptor(ctx, in, info, handler) -} - func _Publications_ListPublications_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(ListPublicationsRequest) if err := dec(in); err != nil { @@ -550,10 +516,6 @@ var Publications_ServiceDesc = grpc.ServiceDesc{ MethodName: "GetPublication", Handler: _Publications_GetPublication_Handler, }, - { - MethodName: "DeletePublication", - Handler: _Publications_DeletePublication_Handler, - }, { MethodName: "ListPublications", Handler: _Publications_ListPublications_Handler, diff --git a/backend/genproto/entities/v1alpha/entities.pb.go b/backend/genproto/entities/v1alpha/entities.pb.go index 632453c1ef..57ea85cef5 100644 --- a/backend/genproto/entities/v1alpha/entities.pb.go +++ b/backend/genproto/entities/v1alpha/entities.pb.go @@ -9,6 +9,7 @@ package entities import ( protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" + emptypb "google.golang.org/protobuf/types/known/emptypb" timestamppb "google.golang.org/protobuf/types/known/timestamppb" reflect "reflect" sync "sync" @@ -563,6 +564,82 @@ func (x *Entity) GetOwner() string { return "" } +// Publication that has been deleted +type DeletedEntity struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // EID of the deleted entity. + Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` + // When the entity was deleted. + DeleteTime *timestamppb.Timestamp `protobuf:"bytes,2,opt,name=delete_time,json=deleteTime,proto3" json:"delete_time,omitempty"` + // Reason why this entity was deleted. + DeletedReason string `protobuf:"bytes,3,opt,name=deleted_reason,json=deletedReason,proto3" json:"deleted_reason,omitempty"` + // Further metadata about the deleted entity, title, etc ... + Metadata string `protobuf:"bytes,4,opt,name=metadata,proto3" json:"metadata,omitempty"` +} + +func (x *DeletedEntity) Reset() { + *x = DeletedEntity{} + if protoimpl.UnsafeEnabled { + mi := &file_entities_v1alpha_entities_proto_msgTypes[8] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *DeletedEntity) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*DeletedEntity) ProtoMessage() {} + +func (x *DeletedEntity) ProtoReflect() protoreflect.Message { + mi := &file_entities_v1alpha_entities_proto_msgTypes[8] + 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 DeletedEntity.ProtoReflect.Descriptor instead. +func (*DeletedEntity) Descriptor() ([]byte, []int) { + return file_entities_v1alpha_entities_proto_rawDescGZIP(), []int{8} +} + +func (x *DeletedEntity) GetId() string { + if x != nil { + return x.Id + } + return "" +} + +func (x *DeletedEntity) GetDeleteTime() *timestamppb.Timestamp { + if x != nil { + return x.DeleteTime + } + return nil +} + +func (x *DeletedEntity) GetDeletedReason() string { + if x != nil { + return x.DeletedReason + } + return "" +} + +func (x *DeletedEntity) GetMetadata() string { + if x != nil { + return x.Metadata + } + return "" +} + // Request to type SearchEntitiesRequest struct { state protoimpl.MessageState @@ -578,7 +655,7 @@ type SearchEntitiesRequest struct { func (x *SearchEntitiesRequest) Reset() { *x = SearchEntitiesRequest{} if protoimpl.UnsafeEnabled { - mi := &file_entities_v1alpha_entities_proto_msgTypes[8] + mi := &file_entities_v1alpha_entities_proto_msgTypes[9] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -591,7 +668,7 @@ func (x *SearchEntitiesRequest) String() string { func (*SearchEntitiesRequest) ProtoMessage() {} func (x *SearchEntitiesRequest) ProtoReflect() protoreflect.Message { - mi := &file_entities_v1alpha_entities_proto_msgTypes[8] + mi := &file_entities_v1alpha_entities_proto_msgTypes[9] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -604,7 +681,7 @@ func (x *SearchEntitiesRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use SearchEntitiesRequest.ProtoReflect.Descriptor instead. func (*SearchEntitiesRequest) Descriptor() ([]byte, []int) { - return file_entities_v1alpha_entities_proto_rawDescGZIP(), []int{8} + return file_entities_v1alpha_entities_proto_rawDescGZIP(), []int{9} } func (x *SearchEntitiesRequest) GetQuery() string { @@ -629,7 +706,7 @@ type SearchEntitiesResponse struct { func (x *SearchEntitiesResponse) Reset() { *x = SearchEntitiesResponse{} if protoimpl.UnsafeEnabled { - mi := &file_entities_v1alpha_entities_proto_msgTypes[9] + mi := &file_entities_v1alpha_entities_proto_msgTypes[10] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -642,7 +719,7 @@ func (x *SearchEntitiesResponse) String() string { func (*SearchEntitiesResponse) ProtoMessage() {} func (x *SearchEntitiesResponse) ProtoReflect() protoreflect.Message { - mi := &file_entities_v1alpha_entities_proto_msgTypes[9] + mi := &file_entities_v1alpha_entities_proto_msgTypes[10] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -655,7 +732,7 @@ func (x *SearchEntitiesResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use SearchEntitiesResponse.ProtoReflect.Descriptor instead. func (*SearchEntitiesResponse) Descriptor() ([]byte, []int) { - return file_entities_v1alpha_entities_proto_rawDescGZIP(), []int{9} + return file_entities_v1alpha_entities_proto_rawDescGZIP(), []int{10} } func (x *SearchEntitiesResponse) GetEntities() []*Entity { @@ -672,6 +749,231 @@ func (x *SearchEntitiesResponse) GetNextPageToken() string { return "" } +// Request for deleting an entity. +type DeleteEntityRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Entity ID of the entity to be removed. + // All versions will also be removed. + Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` + // Optional. Reason why the user wants to delete that entity. + Reason string `protobuf:"bytes,2,opt,name=reason,proto3" json:"reason,omitempty"` +} + +func (x *DeleteEntityRequest) Reset() { + *x = DeleteEntityRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_entities_v1alpha_entities_proto_msgTypes[11] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *DeleteEntityRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*DeleteEntityRequest) ProtoMessage() {} + +func (x *DeleteEntityRequest) ProtoReflect() protoreflect.Message { + mi := &file_entities_v1alpha_entities_proto_msgTypes[11] + 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 DeleteEntityRequest.ProtoReflect.Descriptor instead. +func (*DeleteEntityRequest) Descriptor() ([]byte, []int) { + return file_entities_v1alpha_entities_proto_rawDescGZIP(), []int{11} +} + +func (x *DeleteEntityRequest) GetId() string { + if x != nil { + return x.Id + } + return "" +} + +func (x *DeleteEntityRequest) GetReason() string { + if x != nil { + return x.Reason + } + return "" +} + +// Request for listing deleted entities. +type ListDeletedEntitiesRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Optional. Number of results per page. Default is defined by the server. + PageSize int32 `protobuf:"varint,1,opt,name=page_size,json=pageSize,proto3" json:"page_size,omitempty"` + // Optional. Value from next_page_token obtains from a previous response. + PageToken string `protobuf:"bytes,2,opt,name=page_token,json=pageToken,proto3" json:"page_token,omitempty"` +} + +func (x *ListDeletedEntitiesRequest) Reset() { + *x = ListDeletedEntitiesRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_entities_v1alpha_entities_proto_msgTypes[12] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ListDeletedEntitiesRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListDeletedEntitiesRequest) ProtoMessage() {} + +func (x *ListDeletedEntitiesRequest) ProtoReflect() protoreflect.Message { + mi := &file_entities_v1alpha_entities_proto_msgTypes[12] + 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 ListDeletedEntitiesRequest.ProtoReflect.Descriptor instead. +func (*ListDeletedEntitiesRequest) Descriptor() ([]byte, []int) { + return file_entities_v1alpha_entities_proto_rawDescGZIP(), []int{12} +} + +func (x *ListDeletedEntitiesRequest) GetPageSize() int32 { + if x != nil { + return x.PageSize + } + return 0 +} + +func (x *ListDeletedEntitiesRequest) GetPageToken() string { + if x != nil { + return x.PageToken + } + return "" +} + +// Response with list of deleted entities. +type ListDeletedEntitiesResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // List of deleted entities. + DeletedEntities []*DeletedEntity `protobuf:"bytes,1,rep,name=deleted_entities,json=deletedEntities,proto3" json:"deleted_entities,omitempty"` + // Token for the next page if there're more results. + NextPageToken string `protobuf:"bytes,2,opt,name=next_page_token,json=nextPageToken,proto3" json:"next_page_token,omitempty"` +} + +func (x *ListDeletedEntitiesResponse) Reset() { + *x = ListDeletedEntitiesResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_entities_v1alpha_entities_proto_msgTypes[13] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ListDeletedEntitiesResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListDeletedEntitiesResponse) ProtoMessage() {} + +func (x *ListDeletedEntitiesResponse) ProtoReflect() protoreflect.Message { + mi := &file_entities_v1alpha_entities_proto_msgTypes[13] + 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 ListDeletedEntitiesResponse.ProtoReflect.Descriptor instead. +func (*ListDeletedEntitiesResponse) Descriptor() ([]byte, []int) { + return file_entities_v1alpha_entities_proto_rawDescGZIP(), []int{13} +} + +func (x *ListDeletedEntitiesResponse) GetDeletedEntities() []*DeletedEntity { + if x != nil { + return x.DeletedEntities + } + return nil +} + +func (x *ListDeletedEntitiesResponse) GetNextPageToken() string { + if x != nil { + return x.NextPageToken + } + return "" +} + +// Request for restoring an entity. +type UndeleteEntityRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Entity ID of the entity to be restored. + // All versions will also be restored. + Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` +} + +func (x *UndeleteEntityRequest) Reset() { + *x = UndeleteEntityRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_entities_v1alpha_entities_proto_msgTypes[14] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *UndeleteEntityRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*UndeleteEntityRequest) ProtoMessage() {} + +func (x *UndeleteEntityRequest) ProtoReflect() protoreflect.Message { + mi := &file_entities_v1alpha_entities_proto_msgTypes[14] + 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 UndeleteEntityRequest.ProtoReflect.Descriptor instead. +func (*UndeleteEntityRequest) Descriptor() ([]byte, []int) { + return file_entities_v1alpha_entities_proto_rawDescGZIP(), []int{14} +} + +func (x *UndeleteEntityRequest) GetId() string { + if x != nil { + return x.Id + } + return "" +} + // Request to list mentions of an entity. type ListEntityMentionsRequest struct { state protoimpl.MessageState @@ -685,18 +987,21 @@ type ListEntityMentionsRequest struct { PageSize int32 `protobuf:"varint,2,opt,name=page_size,json=pageSize,proto3" json:"page_size,omitempty"` // Optional. The page token to continue the pagination. PageToken string `protobuf:"bytes,3,opt,name=page_token,json=pageToken,proto3" json:"page_token,omitempty"` - // Optional. Whether to return the results in the descending order (newest-first). + // Optional. Whether to return the results in descending order (newest-first). // By default mentions are listed in the chronological order, // according to the *locally perceived* order of the blobs that contain the mentions. + // // I.e. we sort the links according to the time we receive the blobs, not according to the time blobs claim to have been created. // This is to prevent losing new mentions in case of receiving out-of-date blobs. + // + // This flag must remain the same when paginating through the results. ReverseOrder bool `protobuf:"varint,4,opt,name=reverse_order,json=reverseOrder,proto3" json:"reverse_order,omitempty"` } func (x *ListEntityMentionsRequest) Reset() { *x = ListEntityMentionsRequest{} if protoimpl.UnsafeEnabled { - mi := &file_entities_v1alpha_entities_proto_msgTypes[10] + mi := &file_entities_v1alpha_entities_proto_msgTypes[15] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -709,7 +1014,7 @@ func (x *ListEntityMentionsRequest) String() string { func (*ListEntityMentionsRequest) ProtoMessage() {} func (x *ListEntityMentionsRequest) ProtoReflect() protoreflect.Message { - mi := &file_entities_v1alpha_entities_proto_msgTypes[10] + mi := &file_entities_v1alpha_entities_proto_msgTypes[15] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -722,7 +1027,7 @@ func (x *ListEntityMentionsRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ListEntityMentionsRequest.ProtoReflect.Descriptor instead. func (*ListEntityMentionsRequest) Descriptor() ([]byte, []int) { - return file_entities_v1alpha_entities_proto_rawDescGZIP(), []int{10} + return file_entities_v1alpha_entities_proto_rawDescGZIP(), []int{15} } func (x *ListEntityMentionsRequest) GetId() string { @@ -768,7 +1073,7 @@ type ListEntityMentionsResponse struct { func (x *ListEntityMentionsResponse) Reset() { *x = ListEntityMentionsResponse{} if protoimpl.UnsafeEnabled { - mi := &file_entities_v1alpha_entities_proto_msgTypes[11] + mi := &file_entities_v1alpha_entities_proto_msgTypes[16] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -781,7 +1086,7 @@ func (x *ListEntityMentionsResponse) String() string { func (*ListEntityMentionsResponse) ProtoMessage() {} func (x *ListEntityMentionsResponse) ProtoReflect() protoreflect.Message { - mi := &file_entities_v1alpha_entities_proto_msgTypes[11] + mi := &file_entities_v1alpha_entities_proto_msgTypes[16] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -794,7 +1099,7 @@ func (x *ListEntityMentionsResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ListEntityMentionsResponse.ProtoReflect.Descriptor instead. func (*ListEntityMentionsResponse) Descriptor() ([]byte, []int) { - return file_entities_v1alpha_entities_proto_rawDescGZIP(), []int{11} + return file_entities_v1alpha_entities_proto_rawDescGZIP(), []int{16} } func (x *ListEntityMentionsResponse) GetMentions() []*Mention { @@ -841,7 +1146,7 @@ type Mention struct { func (x *Mention) Reset() { *x = Mention{} if protoimpl.UnsafeEnabled { - mi := &file_entities_v1alpha_entities_proto_msgTypes[12] + mi := &file_entities_v1alpha_entities_proto_msgTypes[17] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -854,7 +1159,7 @@ func (x *Mention) String() string { func (*Mention) ProtoMessage() {} func (x *Mention) ProtoReflect() protoreflect.Message { - mi := &file_entities_v1alpha_entities_proto_msgTypes[12] + mi := &file_entities_v1alpha_entities_proto_msgTypes[17] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -867,7 +1172,7 @@ func (x *Mention) ProtoReflect() protoreflect.Message { // Deprecated: Use Mention.ProtoReflect.Descriptor instead. func (*Mention) Descriptor() ([]byte, []int) { - return file_entities_v1alpha_entities_proto_rawDescGZIP(), []int{12} + return file_entities_v1alpha_entities_proto_rawDescGZIP(), []int{17} } func (x *Mention) GetSource() string { @@ -931,7 +1236,7 @@ type Mention_BlobInfo struct { func (x *Mention_BlobInfo) Reset() { *x = Mention_BlobInfo{} if protoimpl.UnsafeEnabled { - mi := &file_entities_v1alpha_entities_proto_msgTypes[14] + mi := &file_entities_v1alpha_entities_proto_msgTypes[19] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -944,7 +1249,7 @@ func (x *Mention_BlobInfo) String() string { func (*Mention_BlobInfo) ProtoMessage() {} func (x *Mention_BlobInfo) ProtoReflect() protoreflect.Message { - mi := &file_entities_v1alpha_entities_proto_msgTypes[14] + mi := &file_entities_v1alpha_entities_proto_msgTypes[19] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -957,7 +1262,7 @@ func (x *Mention_BlobInfo) ProtoReflect() protoreflect.Message { // Deprecated: Use Mention_BlobInfo.ProtoReflect.Descriptor instead. func (*Mention_BlobInfo) Descriptor() ([]byte, []int) { - return file_entities_v1alpha_entities_proto_rawDescGZIP(), []int{12, 0} + return file_entities_v1alpha_entities_proto_rawDescGZIP(), []int{17, 0} } func (x *Mention_BlobInfo) GetCid() string { @@ -997,167 +1302,221 @@ var file_entities_v1alpha_entities_proto_rawDesc = []byte{ 0x6e, 0x74, 0x69, 0x74, 0x69, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 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, 0x22, 0x0a, 0x10, 0x47, 0x65, 0x74, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x02, 0x69, 0x64, 0x22, 0x2a, 0x0a, 0x18, 0x47, 0x65, 0x74, 0x45, 0x6e, 0x74, 0x69, 0x74, - 0x79, 0x54, 0x69, 0x6d, 0x65, 0x6c, 0x69, 0x6e, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, - 0x22, 0x41, 0x0a, 0x15, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x45, 0x6e, 0x74, 0x69, - 0x74, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, - 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, - 0x69, 0x6f, 0x6e, 0x22, 0x18, 0x0a, 0x16, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x45, - 0x6e, 0x74, 0x69, 0x74, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0xbc, 0x01, - 0x0a, 0x06, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x61, 0x75, 0x74, 0x68, + 0x1a, 0x1b, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, + 0x66, 0x2f, 0x65, 0x6d, 0x70, 0x74, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x22, 0x0a, + 0x10, 0x47, 0x65, 0x74, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, + 0x64, 0x22, 0x2a, 0x0a, 0x18, 0x47, 0x65, 0x74, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x54, 0x69, + 0x6d, 0x65, 0x6c, 0x69, 0x6e, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, + 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x22, 0x41, 0x0a, + 0x15, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, + 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, + 0x22, 0x18, 0x0a, 0x16, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x45, 0x6e, 0x74, 0x69, + 0x74, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0xbc, 0x01, 0x0a, 0x06, 0x43, + 0x68, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x12, 0x3b, 0x0a, + 0x0b, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x5f, 0x74, 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, 0x0a, + 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x64, 0x65, + 0x70, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x04, 0x64, 0x65, 0x70, 0x73, 0x12, 0x1a, + 0x0a, 0x08, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x72, 0x65, 0x6e, 0x18, 0x06, 0x20, 0x03, 0x28, 0x09, + 0x52, 0x08, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x72, 0x65, 0x6e, 0x12, 0x1d, 0x0a, 0x0a, 0x69, 0x73, + 0x5f, 0x74, 0x72, 0x75, 0x73, 0x74, 0x65, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, + 0x69, 0x73, 0x54, 0x72, 0x75, 0x73, 0x74, 0x65, 0x64, 0x22, 0x97, 0x03, 0x0a, 0x0e, 0x45, 0x6e, + 0x74, 0x69, 0x74, 0x79, 0x54, 0x69, 0x6d, 0x65, 0x6c, 0x69, 0x6e, 0x65, 0x12, 0x0e, 0x0a, 0x02, + 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x14, 0x0a, 0x05, + 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x6f, 0x77, 0x6e, + 0x65, 0x72, 0x12, 0x53, 0x0a, 0x07, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x18, 0x03, 0x20, + 0x03, 0x28, 0x0b, 0x32, 0x39, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x6d, 0x69, 0x6e, 0x74, 0x74, 0x65, + 0x72, 0x2e, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x69, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, + 0x68, 0x61, 0x2e, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x54, 0x69, 0x6d, 0x65, 0x6c, 0x69, 0x6e, + 0x65, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x07, + 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x12, 0x26, 0x0a, 0x0f, 0x63, 0x68, 0x61, 0x6e, 0x67, + 0x65, 0x73, 0x5f, 0x62, 0x79, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, + 0x52, 0x0d, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x42, 0x79, 0x54, 0x69, 0x6d, 0x65, 0x12, + 0x14, 0x0a, 0x05, 0x72, 0x6f, 0x6f, 0x74, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x09, 0x52, 0x05, + 0x72, 0x6f, 0x6f, 0x74, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x68, 0x65, 0x61, 0x64, 0x73, 0x18, 0x06, + 0x20, 0x03, 0x28, 0x09, 0x52, 0x05, 0x68, 0x65, 0x61, 0x64, 0x73, 0x12, 0x54, 0x0a, 0x0f, 0x61, + 0x75, 0x74, 0x68, 0x6f, 0x72, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x07, + 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x6d, 0x69, 0x6e, 0x74, 0x74, + 0x65, 0x72, 0x2e, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x69, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x61, 0x6c, + 0x70, 0x68, 0x61, 0x2e, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, + 0x6e, 0x52, 0x0e, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, + 0x73, 0x1a, 0x60, 0x0a, 0x0c, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 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, 0x3a, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x6d, 0x69, 0x6e, 0x74, 0x74, 0x65, 0x72, + 0x2e, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x69, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, + 0x61, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, + 0x02, 0x38, 0x01, 0x22, 0x96, 0x01, 0x0a, 0x0d, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x56, 0x65, + 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x16, 0x0a, 0x06, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x12, 0x14, 0x0a, + 0x05, 0x68, 0x65, 0x61, 0x64, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x05, 0x68, 0x65, + 0x61, 0x64, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x3d, 0x0a, + 0x0c, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x04, 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, + 0x0b, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x54, 0x69, 0x6d, 0x65, 0x22, 0x44, 0x0a, 0x06, + 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x12, 0x14, 0x0a, 0x05, + 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x6f, 0x77, 0x6e, + 0x65, 0x72, 0x22, 0x9f, 0x01, 0x0a, 0x0d, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x64, 0x45, 0x6e, + 0x74, 0x69, 0x74, 0x79, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x02, 0x69, 0x64, 0x12, 0x3b, 0x0a, 0x0b, 0x64, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x5f, 0x74, + 0x69, 0x6d, 0x65, 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, 0x52, 0x0a, 0x64, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x54, 0x69, 0x6d, + 0x65, 0x12, 0x25, 0x0a, 0x0e, 0x64, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x64, 0x5f, 0x72, 0x65, 0x61, + 0x73, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x64, 0x65, 0x6c, 0x65, 0x74, + 0x65, 0x64, 0x52, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x12, 0x1a, 0x0a, 0x08, 0x6d, 0x65, 0x74, 0x61, + 0x64, 0x61, 0x74, 0x61, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x6d, 0x65, 0x74, 0x61, + 0x64, 0x61, 0x74, 0x61, 0x22, 0x2d, 0x0a, 0x15, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x45, 0x6e, + 0x74, 0x69, 0x74, 0x69, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x14, 0x0a, + 0x05, 0x71, 0x75, 0x65, 0x72, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x71, 0x75, + 0x65, 0x72, 0x79, 0x22, 0x82, 0x01, 0x0a, 0x16, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x45, 0x6e, + 0x74, 0x69, 0x74, 0x69, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x40, + 0x0a, 0x08, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x69, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, + 0x32, 0x24, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x6d, 0x69, 0x6e, 0x74, 0x74, 0x65, 0x72, 0x2e, 0x65, + 0x6e, 0x74, 0x69, 0x74, 0x69, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, + 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x52, 0x08, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x69, 0x65, 0x73, + 0x12, 0x26, 0x0a, 0x0f, 0x6e, 0x65, 0x78, 0x74, 0x5f, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x74, 0x6f, + 0x6b, 0x65, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x6e, 0x65, 0x78, 0x74, 0x50, + 0x61, 0x67, 0x65, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x22, 0x3d, 0x0a, 0x13, 0x44, 0x65, 0x6c, 0x65, + 0x74, 0x65, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, + 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, + 0x16, 0x0a, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x22, 0x58, 0x0a, 0x1a, 0x4c, 0x69, 0x73, 0x74, 0x44, + 0x65, 0x6c, 0x65, 0x74, 0x65, 0x64, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x69, 0x65, 0x73, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x73, 0x69, + 0x7a, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x70, 0x61, 0x67, 0x65, 0x53, 0x69, + 0x7a, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x70, 0x61, 0x67, 0x65, 0x54, 0x6f, 0x6b, 0x65, + 0x6e, 0x22, 0x9d, 0x01, 0x0a, 0x1b, 0x4c, 0x69, 0x73, 0x74, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, + 0x64, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x69, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x56, 0x0a, 0x10, 0x64, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x64, 0x5f, 0x65, 0x6e, 0x74, + 0x69, 0x74, 0x69, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x63, 0x6f, + 0x6d, 0x2e, 0x6d, 0x69, 0x6e, 0x74, 0x74, 0x65, 0x72, 0x2e, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x69, + 0x65, 0x73, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, + 0x65, 0x64, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x52, 0x0f, 0x64, 0x65, 0x6c, 0x65, 0x74, 0x65, + 0x64, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x69, 0x65, 0x73, 0x12, 0x26, 0x0a, 0x0f, 0x6e, 0x65, 0x78, + 0x74, 0x5f, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x0d, 0x6e, 0x65, 0x78, 0x74, 0x50, 0x61, 0x67, 0x65, 0x54, 0x6f, 0x6b, 0x65, + 0x6e, 0x22, 0x27, 0x0a, 0x15, 0x55, 0x6e, 0x64, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x45, 0x6e, 0x74, + 0x69, 0x74, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x22, 0x8c, 0x01, 0x0a, 0x19, 0x4c, + 0x69, 0x73, 0x74, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x4d, 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, + 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x70, 0x61, 0x67, 0x65, + 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x70, 0x61, 0x67, + 0x65, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x74, 0x6f, + 0x6b, 0x65, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x70, 0x61, 0x67, 0x65, 0x54, + 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x23, 0x0a, 0x0d, 0x72, 0x65, 0x76, 0x65, 0x72, 0x73, 0x65, 0x5f, + 0x6f, 0x72, 0x64, 0x65, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x72, 0x65, 0x76, + 0x65, 0x72, 0x73, 0x65, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x22, 0x87, 0x01, 0x0a, 0x1a, 0x4c, 0x69, + 0x73, 0x74, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x4d, 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x73, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x41, 0x0a, 0x08, 0x6d, 0x65, 0x6e, 0x74, + 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x63, 0x6f, 0x6d, + 0x2e, 0x6d, 0x69, 0x6e, 0x74, 0x74, 0x65, 0x72, 0x2e, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x69, 0x65, + 0x73, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x4d, 0x65, 0x6e, 0x74, 0x69, 0x6f, + 0x6e, 0x52, 0x08, 0x6d, 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x26, 0x0a, 0x0f, 0x6e, + 0x65, 0x78, 0x74, 0x5f, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x6e, 0x65, 0x78, 0x74, 0x50, 0x61, 0x67, 0x65, 0x54, 0x6f, + 0x6b, 0x65, 0x6e, 0x22, 0xa2, 0x03, 0x0a, 0x07, 0x4d, 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x12, + 0x16, 0x0a, 0x06, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x06, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x25, 0x0a, 0x0e, 0x73, 0x6f, 0x75, 0x72, 0x63, + 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x0d, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x12, 0x4f, + 0x0a, 0x0b, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x62, 0x6c, 0x6f, 0x62, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x6d, 0x69, 0x6e, 0x74, 0x74, 0x65, + 0x72, 0x2e, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x69, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, + 0x68, 0x61, 0x2e, 0x4d, 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x42, 0x6c, 0x6f, 0x62, 0x49, + 0x6e, 0x66, 0x6f, 0x52, 0x0a, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x42, 0x6c, 0x6f, 0x62, 0x12, + 0x25, 0x0a, 0x0e, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, + 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x56, + 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x28, 0x0a, 0x10, 0x69, 0x73, 0x5f, 0x65, 0x78, 0x61, + 0x63, 0x74, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, + 0x52, 0x0e, 0x69, 0x73, 0x45, 0x78, 0x61, 0x63, 0x74, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, + 0x12, 0x27, 0x0a, 0x0f, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x66, 0x72, 0x61, 0x67, 0x6d, + 0x65, 0x6e, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x74, 0x61, 0x72, 0x67, 0x65, + 0x74, 0x46, 0x72, 0x61, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x1a, 0x8c, 0x01, 0x0a, 0x08, 0x42, 0x6c, + 0x6f, 0x62, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x10, 0x0a, 0x03, 0x63, 0x69, 0x64, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x03, 0x63, 0x69, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x12, 0x3b, 0x0a, 0x0b, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x5f, 0x74, 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, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x12, 0x0a, - 0x04, 0x64, 0x65, 0x70, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x04, 0x64, 0x65, 0x70, - 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x72, 0x65, 0x6e, 0x18, 0x06, 0x20, - 0x03, 0x28, 0x09, 0x52, 0x08, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x72, 0x65, 0x6e, 0x12, 0x1d, 0x0a, - 0x0a, 0x69, 0x73, 0x5f, 0x74, 0x72, 0x75, 0x73, 0x74, 0x65, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, - 0x08, 0x52, 0x09, 0x69, 0x73, 0x54, 0x72, 0x75, 0x73, 0x74, 0x65, 0x64, 0x22, 0x97, 0x03, 0x0a, - 0x0e, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x54, 0x69, 0x6d, 0x65, 0x6c, 0x69, 0x6e, 0x65, 0x12, - 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, - 0x14, 0x0a, 0x05, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, - 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x12, 0x53, 0x0a, 0x07, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73, - 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x39, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x6d, 0x69, 0x6e, - 0x74, 0x74, 0x65, 0x72, 0x2e, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x69, 0x65, 0x73, 0x2e, 0x76, 0x31, - 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x54, 0x69, 0x6d, 0x65, - 0x6c, 0x69, 0x6e, 0x65, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, - 0x79, 0x52, 0x07, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x12, 0x26, 0x0a, 0x0f, 0x63, 0x68, - 0x61, 0x6e, 0x67, 0x65, 0x73, 0x5f, 0x62, 0x79, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x04, 0x20, - 0x03, 0x28, 0x09, 0x52, 0x0d, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x42, 0x79, 0x54, 0x69, - 0x6d, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x72, 0x6f, 0x6f, 0x74, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, - 0x09, 0x52, 0x05, 0x72, 0x6f, 0x6f, 0x74, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x68, 0x65, 0x61, 0x64, - 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x09, 0x52, 0x05, 0x68, 0x65, 0x61, 0x64, 0x73, 0x12, 0x54, - 0x0a, 0x0f, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, - 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x6d, 0x69, - 0x6e, 0x74, 0x74, 0x65, 0x72, 0x2e, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x69, 0x65, 0x73, 0x2e, 0x76, - 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x56, 0x65, 0x72, - 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x0e, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x56, 0x65, 0x72, 0x73, - 0x69, 0x6f, 0x6e, 0x73, 0x1a, 0x60, 0x0a, 0x0c, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 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, 0x3a, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x6d, 0x69, 0x6e, 0x74, + 0x70, 0x52, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x19, 0x0a, + 0x08, 0x69, 0x73, 0x5f, 0x64, 0x72, 0x61, 0x66, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, + 0x07, 0x69, 0x73, 0x44, 0x72, 0x61, 0x66, 0x74, 0x32, 0xb3, 0x07, 0x0a, 0x08, 0x45, 0x6e, 0x74, + 0x69, 0x74, 0x69, 0x65, 0x73, 0x12, 0x61, 0x0a, 0x09, 0x47, 0x65, 0x74, 0x43, 0x68, 0x61, 0x6e, + 0x67, 0x65, 0x12, 0x2e, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x6d, 0x69, 0x6e, 0x74, 0x74, 0x65, 0x72, + 0x2e, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x69, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, + 0x61, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x6d, 0x69, 0x6e, 0x74, 0x74, 0x65, 0x72, + 0x2e, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x69, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, + 0x61, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x79, 0x0a, 0x11, 0x47, 0x65, 0x74, 0x45, + 0x6e, 0x74, 0x69, 0x74, 0x79, 0x54, 0x69, 0x6d, 0x65, 0x6c, 0x69, 0x6e, 0x65, 0x12, 0x36, 0x2e, + 0x63, 0x6f, 0x6d, 0x2e, 0x6d, 0x69, 0x6e, 0x74, 0x74, 0x65, 0x72, 0x2e, 0x65, 0x6e, 0x74, 0x69, + 0x74, 0x69, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x47, 0x65, 0x74, + 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x54, 0x69, 0x6d, 0x65, 0x6c, 0x69, 0x6e, 0x65, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2c, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x6d, 0x69, 0x6e, 0x74, 0x74, 0x65, 0x72, 0x2e, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x69, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x61, - 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, - 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x96, 0x01, 0x0a, 0x0d, 0x41, 0x75, 0x74, 0x68, 0x6f, - 0x72, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x16, 0x0a, 0x06, 0x61, 0x75, 0x74, 0x68, - 0x6f, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, - 0x12, 0x14, 0x0a, 0x05, 0x68, 0x65, 0x61, 0x64, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, - 0x05, 0x68, 0x65, 0x61, 0x64, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, - 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, - 0x12, 0x3d, 0x0a, 0x0c, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x74, 0x69, 0x6d, 0x65, - 0x18, 0x04, 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, 0x0b, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x54, 0x69, 0x6d, 0x65, 0x22, - 0x44, 0x0a, 0x06, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x69, 0x74, - 0x6c, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x12, - 0x14, 0x0a, 0x05, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, - 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x22, 0x2d, 0x0a, 0x15, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x45, - 0x6e, 0x74, 0x69, 0x74, 0x69, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x14, - 0x0a, 0x05, 0x71, 0x75, 0x65, 0x72, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x71, - 0x75, 0x65, 0x72, 0x79, 0x22, 0x82, 0x01, 0x0a, 0x16, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x45, - 0x6e, 0x74, 0x69, 0x74, 0x69, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x40, 0x0a, 0x08, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x69, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, - 0x0b, 0x32, 0x24, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x6d, 0x69, 0x6e, 0x74, 0x74, 0x65, 0x72, 0x2e, - 0x65, 0x6e, 0x74, 0x69, 0x74, 0x69, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, - 0x2e, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x52, 0x08, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x69, 0x65, - 0x73, 0x12, 0x26, 0x0a, 0x0f, 0x6e, 0x65, 0x78, 0x74, 0x5f, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x74, - 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x6e, 0x65, 0x78, 0x74, - 0x50, 0x61, 0x67, 0x65, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x22, 0x8c, 0x01, 0x0a, 0x19, 0x4c, 0x69, - 0x73, 0x74, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x4d, 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x73, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x70, 0x61, 0x67, 0x65, 0x5f, - 0x73, 0x69, 0x7a, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x70, 0x61, 0x67, 0x65, - 0x53, 0x69, 0x7a, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x74, 0x6f, 0x6b, - 0x65, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x70, 0x61, 0x67, 0x65, 0x54, 0x6f, - 0x6b, 0x65, 0x6e, 0x12, 0x23, 0x0a, 0x0d, 0x72, 0x65, 0x76, 0x65, 0x72, 0x73, 0x65, 0x5f, 0x6f, - 0x72, 0x64, 0x65, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x72, 0x65, 0x76, 0x65, - 0x72, 0x73, 0x65, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x22, 0x87, 0x01, 0x0a, 0x1a, 0x4c, 0x69, 0x73, - 0x74, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x4d, 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x41, 0x0a, 0x08, 0x6d, 0x65, 0x6e, 0x74, 0x69, - 0x6f, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, - 0x6d, 0x69, 0x6e, 0x74, 0x74, 0x65, 0x72, 0x2e, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x69, 0x65, 0x73, - 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x4d, 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, - 0x52, 0x08, 0x6d, 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x26, 0x0a, 0x0f, 0x6e, 0x65, - 0x78, 0x74, 0x5f, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x0d, 0x6e, 0x65, 0x78, 0x74, 0x50, 0x61, 0x67, 0x65, 0x54, 0x6f, 0x6b, - 0x65, 0x6e, 0x22, 0xa2, 0x03, 0x0a, 0x07, 0x4d, 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x16, - 0x0a, 0x06, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, - 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x25, 0x0a, 0x0e, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, - 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, - 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x12, 0x4f, 0x0a, - 0x0b, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x62, 0x6c, 0x6f, 0x62, 0x18, 0x03, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x6d, 0x69, 0x6e, 0x74, 0x74, 0x65, 0x72, + 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x54, 0x69, 0x6d, 0x65, 0x6c, + 0x69, 0x6e, 0x65, 0x12, 0x7b, 0x0a, 0x0e, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x45, + 0x6e, 0x74, 0x69, 0x74, 0x79, 0x12, 0x33, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x6d, 0x69, 0x6e, 0x74, + 0x74, 0x65, 0x72, 0x2e, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x69, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x61, + 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x45, 0x6e, 0x74, + 0x69, 0x74, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x34, 0x2e, 0x63, 0x6f, 0x6d, + 0x2e, 0x6d, 0x69, 0x6e, 0x74, 0x74, 0x65, 0x72, 0x2e, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x69, 0x65, + 0x73, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x76, + 0x65, 0x72, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x12, 0x7b, 0x0a, 0x0e, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x69, + 0x65, 0x73, 0x12, 0x33, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x6d, 0x69, 0x6e, 0x74, 0x74, 0x65, 0x72, 0x2e, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x69, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, - 0x61, 0x2e, 0x4d, 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x42, 0x6c, 0x6f, 0x62, 0x49, 0x6e, - 0x66, 0x6f, 0x52, 0x0a, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x42, 0x6c, 0x6f, 0x62, 0x12, 0x25, - 0x0a, 0x0e, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, - 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x56, 0x65, - 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x28, 0x0a, 0x10, 0x69, 0x73, 0x5f, 0x65, 0x78, 0x61, 0x63, - 0x74, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, - 0x0e, 0x69, 0x73, 0x45, 0x78, 0x61, 0x63, 0x74, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, - 0x27, 0x0a, 0x0f, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x66, 0x72, 0x61, 0x67, 0x6d, 0x65, - 0x6e, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, - 0x46, 0x72, 0x61, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x1a, 0x8c, 0x01, 0x0a, 0x08, 0x42, 0x6c, 0x6f, - 0x62, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x10, 0x0a, 0x03, 0x63, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x03, 0x63, 0x69, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x61, 0x75, 0x74, 0x68, 0x6f, - 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x12, - 0x3b, 0x0a, 0x0b, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x5f, 0x74, 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, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x19, 0x0a, 0x08, - 0x69, 0x73, 0x5f, 0x64, 0x72, 0x61, 0x66, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, - 0x69, 0x73, 0x44, 0x72, 0x61, 0x66, 0x74, 0x32, 0xec, 0x04, 0x0a, 0x08, 0x45, 0x6e, 0x74, 0x69, - 0x74, 0x69, 0x65, 0x73, 0x12, 0x61, 0x0a, 0x09, 0x47, 0x65, 0x74, 0x43, 0x68, 0x61, 0x6e, 0x67, - 0x65, 0x12, 0x2e, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x6d, 0x69, 0x6e, 0x74, 0x74, 0x65, 0x72, 0x2e, - 0x65, 0x6e, 0x74, 0x69, 0x74, 0x69, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, - 0x2e, 0x47, 0x65, 0x74, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x24, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x6d, 0x69, 0x6e, 0x74, 0x74, 0x65, 0x72, 0x2e, - 0x65, 0x6e, 0x74, 0x69, 0x74, 0x69, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, - 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x79, 0x0a, 0x11, 0x47, 0x65, 0x74, 0x45, 0x6e, - 0x74, 0x69, 0x74, 0x79, 0x54, 0x69, 0x6d, 0x65, 0x6c, 0x69, 0x6e, 0x65, 0x12, 0x36, 0x2e, 0x63, - 0x6f, 0x6d, 0x2e, 0x6d, 0x69, 0x6e, 0x74, 0x74, 0x65, 0x72, 0x2e, 0x65, 0x6e, 0x74, 0x69, 0x74, - 0x69, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x47, 0x65, 0x74, 0x45, - 0x6e, 0x74, 0x69, 0x74, 0x79, 0x54, 0x69, 0x6d, 0x65, 0x6c, 0x69, 0x6e, 0x65, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2c, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x6d, 0x69, 0x6e, 0x74, 0x74, - 0x65, 0x72, 0x2e, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x69, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x61, 0x6c, - 0x70, 0x68, 0x61, 0x2e, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x54, 0x69, 0x6d, 0x65, 0x6c, 0x69, - 0x6e, 0x65, 0x12, 0x7b, 0x0a, 0x0e, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x45, 0x6e, - 0x74, 0x69, 0x74, 0x79, 0x12, 0x33, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x6d, 0x69, 0x6e, 0x74, 0x74, + 0x61, 0x2e, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x69, 0x65, 0x73, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x34, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x6d, 0x69, + 0x6e, 0x74, 0x74, 0x65, 0x72, 0x2e, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x69, 0x65, 0x73, 0x2e, 0x76, + 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x45, 0x6e, 0x74, + 0x69, 0x74, 0x69, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x59, 0x0a, + 0x0c, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x12, 0x31, 0x2e, + 0x63, 0x6f, 0x6d, 0x2e, 0x6d, 0x69, 0x6e, 0x74, 0x74, 0x65, 0x72, 0x2e, 0x65, 0x6e, 0x74, 0x69, + 0x74, 0x69, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x44, 0x65, 0x6c, + 0x65, 0x74, 0x65, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, + 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x8a, 0x01, 0x0a, 0x13, 0x4c, 0x69, 0x73, + 0x74, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x64, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x69, 0x65, 0x73, + 0x12, 0x38, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x6d, 0x69, 0x6e, 0x74, 0x74, 0x65, 0x72, 0x2e, 0x65, + 0x6e, 0x74, 0x69, 0x74, 0x69, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, + 0x4c, 0x69, 0x73, 0x74, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x64, 0x45, 0x6e, 0x74, 0x69, 0x74, + 0x69, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x39, 0x2e, 0x63, 0x6f, 0x6d, + 0x2e, 0x6d, 0x69, 0x6e, 0x74, 0x74, 0x65, 0x72, 0x2e, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x69, 0x65, + 0x73, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x44, 0x65, + 0x6c, 0x65, 0x74, 0x65, 0x64, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x69, 0x65, 0x73, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x5d, 0x0a, 0x0e, 0x55, 0x6e, 0x64, 0x65, 0x6c, 0x65, 0x74, + 0x65, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x12, 0x33, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x6d, 0x69, + 0x6e, 0x74, 0x74, 0x65, 0x72, 0x2e, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x69, 0x65, 0x73, 0x2e, 0x76, + 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x55, 0x6e, 0x64, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x45, + 0x6e, 0x74, 0x69, 0x74, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, + 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, + 0x6d, 0x70, 0x74, 0x79, 0x12, 0x87, 0x01, 0x0a, 0x12, 0x4c, 0x69, 0x73, 0x74, 0x45, 0x6e, 0x74, + 0x69, 0x74, 0x79, 0x4d, 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x37, 0x2e, 0x63, 0x6f, + 0x6d, 0x2e, 0x6d, 0x69, 0x6e, 0x74, 0x74, 0x65, 0x72, 0x2e, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x69, + 0x65, 0x73, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x45, + 0x6e, 0x74, 0x69, 0x74, 0x79, 0x4d, 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x38, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x6d, 0x69, 0x6e, 0x74, 0x74, 0x65, 0x72, 0x2e, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x69, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x61, 0x6c, - 0x70, 0x68, 0x61, 0x2e, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x45, 0x6e, 0x74, 0x69, - 0x74, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x34, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, - 0x6d, 0x69, 0x6e, 0x74, 0x74, 0x65, 0x72, 0x2e, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x69, 0x65, 0x73, - 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, - 0x72, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x7b, 0x0a, 0x0e, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x69, 0x65, - 0x73, 0x12, 0x33, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x6d, 0x69, 0x6e, 0x74, 0x74, 0x65, 0x72, 0x2e, - 0x65, 0x6e, 0x74, 0x69, 0x74, 0x69, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, - 0x2e, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x69, 0x65, 0x73, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x34, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x6d, 0x69, 0x6e, - 0x74, 0x74, 0x65, 0x72, 0x2e, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x69, 0x65, 0x73, 0x2e, 0x76, 0x31, - 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x45, 0x6e, 0x74, 0x69, - 0x74, 0x69, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x87, 0x01, 0x0a, - 0x12, 0x4c, 0x69, 0x73, 0x74, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x4d, 0x65, 0x6e, 0x74, 0x69, - 0x6f, 0x6e, 0x73, 0x12, 0x37, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x6d, 0x69, 0x6e, 0x74, 0x74, 0x65, - 0x72, 0x2e, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x69, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, - 0x68, 0x61, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x4d, 0x65, 0x6e, - 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x38, 0x2e, 0x63, - 0x6f, 0x6d, 0x2e, 0x6d, 0x69, 0x6e, 0x74, 0x74, 0x65, 0x72, 0x2e, 0x65, 0x6e, 0x74, 0x69, 0x74, - 0x69, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x4c, 0x69, 0x73, 0x74, - 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x4d, 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x34, 0x5a, 0x32, 0x6d, 0x69, 0x6e, 0x74, 0x74, 0x65, - 0x72, 0x2f, 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x2f, 0x67, 0x65, 0x6e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x2f, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x69, 0x65, 0x73, 0x2f, 0x76, 0x31, 0x61, 0x6c, - 0x70, 0x68, 0x61, 0x3b, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x69, 0x65, 0x73, 0x62, 0x06, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x33, + 0x70, 0x68, 0x61, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x4d, 0x65, + 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x34, + 0x5a, 0x32, 0x6d, 0x69, 0x6e, 0x74, 0x74, 0x65, 0x72, 0x2f, 0x62, 0x61, 0x63, 0x6b, 0x65, 0x6e, + 0x64, 0x2f, 0x67, 0x65, 0x6e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x65, 0x6e, 0x74, 0x69, 0x74, + 0x69, 0x65, 0x73, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x3b, 0x65, 0x6e, 0x74, 0x69, + 0x74, 0x69, 0x65, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -1172,50 +1531,64 @@ func file_entities_v1alpha_entities_proto_rawDescGZIP() []byte { return file_entities_v1alpha_entities_proto_rawDescData } -var file_entities_v1alpha_entities_proto_msgTypes = make([]protoimpl.MessageInfo, 15) +var file_entities_v1alpha_entities_proto_msgTypes = make([]protoimpl.MessageInfo, 20) var file_entities_v1alpha_entities_proto_goTypes = []interface{}{ - (*GetChangeRequest)(nil), // 0: com.mintter.entities.v1alpha.GetChangeRequest - (*GetEntityTimelineRequest)(nil), // 1: com.mintter.entities.v1alpha.GetEntityTimelineRequest - (*DiscoverEntityRequest)(nil), // 2: com.mintter.entities.v1alpha.DiscoverEntityRequest - (*DiscoverEntityResponse)(nil), // 3: com.mintter.entities.v1alpha.DiscoverEntityResponse - (*Change)(nil), // 4: com.mintter.entities.v1alpha.Change - (*EntityTimeline)(nil), // 5: com.mintter.entities.v1alpha.EntityTimeline - (*AuthorVersion)(nil), // 6: com.mintter.entities.v1alpha.AuthorVersion - (*Entity)(nil), // 7: com.mintter.entities.v1alpha.Entity - (*SearchEntitiesRequest)(nil), // 8: com.mintter.entities.v1alpha.SearchEntitiesRequest - (*SearchEntitiesResponse)(nil), // 9: com.mintter.entities.v1alpha.SearchEntitiesResponse - (*ListEntityMentionsRequest)(nil), // 10: com.mintter.entities.v1alpha.ListEntityMentionsRequest - (*ListEntityMentionsResponse)(nil), // 11: com.mintter.entities.v1alpha.ListEntityMentionsResponse - (*Mention)(nil), // 12: com.mintter.entities.v1alpha.Mention - nil, // 13: com.mintter.entities.v1alpha.EntityTimeline.ChangesEntry - (*Mention_BlobInfo)(nil), // 14: com.mintter.entities.v1alpha.Mention.BlobInfo - (*timestamppb.Timestamp)(nil), // 15: google.protobuf.Timestamp + (*GetChangeRequest)(nil), // 0: com.mintter.entities.v1alpha.GetChangeRequest + (*GetEntityTimelineRequest)(nil), // 1: com.mintter.entities.v1alpha.GetEntityTimelineRequest + (*DiscoverEntityRequest)(nil), // 2: com.mintter.entities.v1alpha.DiscoverEntityRequest + (*DiscoverEntityResponse)(nil), // 3: com.mintter.entities.v1alpha.DiscoverEntityResponse + (*Change)(nil), // 4: com.mintter.entities.v1alpha.Change + (*EntityTimeline)(nil), // 5: com.mintter.entities.v1alpha.EntityTimeline + (*AuthorVersion)(nil), // 6: com.mintter.entities.v1alpha.AuthorVersion + (*Entity)(nil), // 7: com.mintter.entities.v1alpha.Entity + (*DeletedEntity)(nil), // 8: com.mintter.entities.v1alpha.DeletedEntity + (*SearchEntitiesRequest)(nil), // 9: com.mintter.entities.v1alpha.SearchEntitiesRequest + (*SearchEntitiesResponse)(nil), // 10: com.mintter.entities.v1alpha.SearchEntitiesResponse + (*DeleteEntityRequest)(nil), // 11: com.mintter.entities.v1alpha.DeleteEntityRequest + (*ListDeletedEntitiesRequest)(nil), // 12: com.mintter.entities.v1alpha.ListDeletedEntitiesRequest + (*ListDeletedEntitiesResponse)(nil), // 13: com.mintter.entities.v1alpha.ListDeletedEntitiesResponse + (*UndeleteEntityRequest)(nil), // 14: com.mintter.entities.v1alpha.UndeleteEntityRequest + (*ListEntityMentionsRequest)(nil), // 15: com.mintter.entities.v1alpha.ListEntityMentionsRequest + (*ListEntityMentionsResponse)(nil), // 16: com.mintter.entities.v1alpha.ListEntityMentionsResponse + (*Mention)(nil), // 17: com.mintter.entities.v1alpha.Mention + nil, // 18: com.mintter.entities.v1alpha.EntityTimeline.ChangesEntry + (*Mention_BlobInfo)(nil), // 19: com.mintter.entities.v1alpha.Mention.BlobInfo + (*timestamppb.Timestamp)(nil), // 20: google.protobuf.Timestamp + (*emptypb.Empty)(nil), // 21: google.protobuf.Empty } var file_entities_v1alpha_entities_proto_depIdxs = []int32{ - 15, // 0: com.mintter.entities.v1alpha.Change.create_time:type_name -> google.protobuf.Timestamp - 13, // 1: com.mintter.entities.v1alpha.EntityTimeline.changes:type_name -> com.mintter.entities.v1alpha.EntityTimeline.ChangesEntry + 20, // 0: com.mintter.entities.v1alpha.Change.create_time:type_name -> google.protobuf.Timestamp + 18, // 1: com.mintter.entities.v1alpha.EntityTimeline.changes:type_name -> com.mintter.entities.v1alpha.EntityTimeline.ChangesEntry 6, // 2: com.mintter.entities.v1alpha.EntityTimeline.author_versions:type_name -> com.mintter.entities.v1alpha.AuthorVersion - 15, // 3: com.mintter.entities.v1alpha.AuthorVersion.version_time:type_name -> google.protobuf.Timestamp - 7, // 4: com.mintter.entities.v1alpha.SearchEntitiesResponse.entities:type_name -> com.mintter.entities.v1alpha.Entity - 12, // 5: com.mintter.entities.v1alpha.ListEntityMentionsResponse.mentions:type_name -> com.mintter.entities.v1alpha.Mention - 14, // 6: com.mintter.entities.v1alpha.Mention.source_blob:type_name -> com.mintter.entities.v1alpha.Mention.BlobInfo - 4, // 7: com.mintter.entities.v1alpha.EntityTimeline.ChangesEntry.value:type_name -> com.mintter.entities.v1alpha.Change - 15, // 8: com.mintter.entities.v1alpha.Mention.BlobInfo.create_time:type_name -> google.protobuf.Timestamp - 0, // 9: com.mintter.entities.v1alpha.Entities.GetChange:input_type -> com.mintter.entities.v1alpha.GetChangeRequest - 1, // 10: com.mintter.entities.v1alpha.Entities.GetEntityTimeline:input_type -> com.mintter.entities.v1alpha.GetEntityTimelineRequest - 2, // 11: com.mintter.entities.v1alpha.Entities.DiscoverEntity:input_type -> com.mintter.entities.v1alpha.DiscoverEntityRequest - 8, // 12: com.mintter.entities.v1alpha.Entities.SearchEntities:input_type -> com.mintter.entities.v1alpha.SearchEntitiesRequest - 10, // 13: com.mintter.entities.v1alpha.Entities.ListEntityMentions:input_type -> com.mintter.entities.v1alpha.ListEntityMentionsRequest - 4, // 14: com.mintter.entities.v1alpha.Entities.GetChange:output_type -> com.mintter.entities.v1alpha.Change - 5, // 15: com.mintter.entities.v1alpha.Entities.GetEntityTimeline:output_type -> com.mintter.entities.v1alpha.EntityTimeline - 3, // 16: com.mintter.entities.v1alpha.Entities.DiscoverEntity:output_type -> com.mintter.entities.v1alpha.DiscoverEntityResponse - 9, // 17: com.mintter.entities.v1alpha.Entities.SearchEntities:output_type -> com.mintter.entities.v1alpha.SearchEntitiesResponse - 11, // 18: com.mintter.entities.v1alpha.Entities.ListEntityMentions:output_type -> com.mintter.entities.v1alpha.ListEntityMentionsResponse - 14, // [14:19] is the sub-list for method output_type - 9, // [9:14] 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 + 20, // 3: com.mintter.entities.v1alpha.AuthorVersion.version_time:type_name -> google.protobuf.Timestamp + 20, // 4: com.mintter.entities.v1alpha.DeletedEntity.delete_time:type_name -> google.protobuf.Timestamp + 7, // 5: com.mintter.entities.v1alpha.SearchEntitiesResponse.entities:type_name -> com.mintter.entities.v1alpha.Entity + 8, // 6: com.mintter.entities.v1alpha.ListDeletedEntitiesResponse.deleted_entities:type_name -> com.mintter.entities.v1alpha.DeletedEntity + 17, // 7: com.mintter.entities.v1alpha.ListEntityMentionsResponse.mentions:type_name -> com.mintter.entities.v1alpha.Mention + 19, // 8: com.mintter.entities.v1alpha.Mention.source_blob:type_name -> com.mintter.entities.v1alpha.Mention.BlobInfo + 4, // 9: com.mintter.entities.v1alpha.EntityTimeline.ChangesEntry.value:type_name -> com.mintter.entities.v1alpha.Change + 20, // 10: com.mintter.entities.v1alpha.Mention.BlobInfo.create_time:type_name -> google.protobuf.Timestamp + 0, // 11: com.mintter.entities.v1alpha.Entities.GetChange:input_type -> com.mintter.entities.v1alpha.GetChangeRequest + 1, // 12: com.mintter.entities.v1alpha.Entities.GetEntityTimeline:input_type -> com.mintter.entities.v1alpha.GetEntityTimelineRequest + 2, // 13: com.mintter.entities.v1alpha.Entities.DiscoverEntity:input_type -> com.mintter.entities.v1alpha.DiscoverEntityRequest + 9, // 14: com.mintter.entities.v1alpha.Entities.SearchEntities:input_type -> com.mintter.entities.v1alpha.SearchEntitiesRequest + 11, // 15: com.mintter.entities.v1alpha.Entities.DeleteEntity:input_type -> com.mintter.entities.v1alpha.DeleteEntityRequest + 12, // 16: com.mintter.entities.v1alpha.Entities.ListDeletedEntities:input_type -> com.mintter.entities.v1alpha.ListDeletedEntitiesRequest + 14, // 17: com.mintter.entities.v1alpha.Entities.UndeleteEntity:input_type -> com.mintter.entities.v1alpha.UndeleteEntityRequest + 15, // 18: com.mintter.entities.v1alpha.Entities.ListEntityMentions:input_type -> com.mintter.entities.v1alpha.ListEntityMentionsRequest + 4, // 19: com.mintter.entities.v1alpha.Entities.GetChange:output_type -> com.mintter.entities.v1alpha.Change + 5, // 20: com.mintter.entities.v1alpha.Entities.GetEntityTimeline:output_type -> com.mintter.entities.v1alpha.EntityTimeline + 3, // 21: com.mintter.entities.v1alpha.Entities.DiscoverEntity:output_type -> com.mintter.entities.v1alpha.DiscoverEntityResponse + 10, // 22: com.mintter.entities.v1alpha.Entities.SearchEntities:output_type -> com.mintter.entities.v1alpha.SearchEntitiesResponse + 21, // 23: com.mintter.entities.v1alpha.Entities.DeleteEntity:output_type -> google.protobuf.Empty + 13, // 24: com.mintter.entities.v1alpha.Entities.ListDeletedEntities:output_type -> com.mintter.entities.v1alpha.ListDeletedEntitiesResponse + 21, // 25: com.mintter.entities.v1alpha.Entities.UndeleteEntity:output_type -> google.protobuf.Empty + 16, // 26: com.mintter.entities.v1alpha.Entities.ListEntityMentions:output_type -> com.mintter.entities.v1alpha.ListEntityMentionsResponse + 19, // [19:27] is the sub-list for method output_type + 11, // [11:19] 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_entities_v1alpha_entities_proto_init() } @@ -1321,7 +1694,7 @@ func file_entities_v1alpha_entities_proto_init() { } } file_entities_v1alpha_entities_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SearchEntitiesRequest); i { + switch v := v.(*DeletedEntity); i { case 0: return &v.state case 1: @@ -1333,7 +1706,7 @@ func file_entities_v1alpha_entities_proto_init() { } } file_entities_v1alpha_entities_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SearchEntitiesResponse); i { + switch v := v.(*SearchEntitiesRequest); i { case 0: return &v.state case 1: @@ -1345,7 +1718,7 @@ func file_entities_v1alpha_entities_proto_init() { } } file_entities_v1alpha_entities_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ListEntityMentionsRequest); i { + switch v := v.(*SearchEntitiesResponse); i { case 0: return &v.state case 1: @@ -1357,7 +1730,7 @@ func file_entities_v1alpha_entities_proto_init() { } } file_entities_v1alpha_entities_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ListEntityMentionsResponse); i { + switch v := v.(*DeleteEntityRequest); i { case 0: return &v.state case 1: @@ -1369,7 +1742,19 @@ func file_entities_v1alpha_entities_proto_init() { } } file_entities_v1alpha_entities_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Mention); i { + switch v := v.(*ListDeletedEntitiesRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_entities_v1alpha_entities_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ListDeletedEntitiesResponse); i { case 0: return &v.state case 1: @@ -1381,6 +1766,54 @@ func file_entities_v1alpha_entities_proto_init() { } } file_entities_v1alpha_entities_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*UndeleteEntityRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_entities_v1alpha_entities_proto_msgTypes[15].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ListEntityMentionsRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_entities_v1alpha_entities_proto_msgTypes[16].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ListEntityMentionsResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_entities_v1alpha_entities_proto_msgTypes[17].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Mention); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_entities_v1alpha_entities_proto_msgTypes[19].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*Mention_BlobInfo); i { case 0: return &v.state @@ -1399,7 +1832,7 @@ func file_entities_v1alpha_entities_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_entities_v1alpha_entities_proto_rawDesc, NumEnums: 0, - NumMessages: 15, + NumMessages: 20, NumExtensions: 0, NumServices: 1, }, diff --git a/backend/genproto/entities/v1alpha/entities_grpc.pb.go b/backend/genproto/entities/v1alpha/entities_grpc.pb.go index 388c03601c..6904c1b881 100644 --- a/backend/genproto/entities/v1alpha/entities_grpc.pb.go +++ b/backend/genproto/entities/v1alpha/entities_grpc.pb.go @@ -11,6 +11,7 @@ import ( grpc "google.golang.org/grpc" codes "google.golang.org/grpc/codes" status "google.golang.org/grpc/status" + emptypb "google.golang.org/protobuf/types/known/emptypb" ) // This is a compile-time assertion to ensure that this generated file @@ -32,6 +33,13 @@ type EntitiesClient interface { // A fuzzy search is performed among documents, groups and accounts. // For groups and documents, we match the title, while we match alias in accounts. SearchEntities(ctx context.Context, in *SearchEntitiesRequest, opts ...grpc.CallOption) (*SearchEntitiesResponse, error) + // Deletes an entity from the local node. It removes all the patches corresponding to it, including comments. + DeleteEntity(ctx context.Context, in *DeleteEntityRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) + // Lists deleted entities. + ListDeletedEntities(ctx context.Context, in *ListDeletedEntitiesRequest, opts ...grpc.CallOption) (*ListDeletedEntitiesResponse, error) + // Undo the entity delition by removing the entity from the deleted list. That entity, if available + // will be synced back in the next syncing round (or manually discovered). + UndeleteEntity(ctx context.Context, in *UndeleteEntityRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) // List mentions of a given Entity across the locally-available content. ListEntityMentions(ctx context.Context, in *ListEntityMentionsRequest, opts ...grpc.CallOption) (*ListEntityMentionsResponse, error) } @@ -80,6 +88,33 @@ func (c *entitiesClient) SearchEntities(ctx context.Context, in *SearchEntitiesR return out, nil } +func (c *entitiesClient) DeleteEntity(ctx context.Context, in *DeleteEntityRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) { + out := new(emptypb.Empty) + err := c.cc.Invoke(ctx, "/com.mintter.entities.v1alpha.Entities/DeleteEntity", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *entitiesClient) ListDeletedEntities(ctx context.Context, in *ListDeletedEntitiesRequest, opts ...grpc.CallOption) (*ListDeletedEntitiesResponse, error) { + out := new(ListDeletedEntitiesResponse) + err := c.cc.Invoke(ctx, "/com.mintter.entities.v1alpha.Entities/ListDeletedEntities", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *entitiesClient) UndeleteEntity(ctx context.Context, in *UndeleteEntityRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) { + out := new(emptypb.Empty) + err := c.cc.Invoke(ctx, "/com.mintter.entities.v1alpha.Entities/UndeleteEntity", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + func (c *entitiesClient) ListEntityMentions(ctx context.Context, in *ListEntityMentionsRequest, opts ...grpc.CallOption) (*ListEntityMentionsResponse, error) { out := new(ListEntityMentionsResponse) err := c.cc.Invoke(ctx, "/com.mintter.entities.v1alpha.Entities/ListEntityMentions", in, out, opts...) @@ -103,6 +138,13 @@ type EntitiesServer interface { // A fuzzy search is performed among documents, groups and accounts. // For groups and documents, we match the title, while we match alias in accounts. SearchEntities(context.Context, *SearchEntitiesRequest) (*SearchEntitiesResponse, error) + // Deletes an entity from the local node. It removes all the patches corresponding to it, including comments. + DeleteEntity(context.Context, *DeleteEntityRequest) (*emptypb.Empty, error) + // Lists deleted entities. + ListDeletedEntities(context.Context, *ListDeletedEntitiesRequest) (*ListDeletedEntitiesResponse, error) + // Undo the entity delition by removing the entity from the deleted list. That entity, if available + // will be synced back in the next syncing round (or manually discovered). + UndeleteEntity(context.Context, *UndeleteEntityRequest) (*emptypb.Empty, error) // List mentions of a given Entity across the locally-available content. ListEntityMentions(context.Context, *ListEntityMentionsRequest) (*ListEntityMentionsResponse, error) } @@ -123,6 +165,15 @@ func (UnimplementedEntitiesServer) DiscoverEntity(context.Context, *DiscoverEnti func (UnimplementedEntitiesServer) SearchEntities(context.Context, *SearchEntitiesRequest) (*SearchEntitiesResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method SearchEntities not implemented") } +func (UnimplementedEntitiesServer) DeleteEntity(context.Context, *DeleteEntityRequest) (*emptypb.Empty, error) { + return nil, status.Errorf(codes.Unimplemented, "method DeleteEntity not implemented") +} +func (UnimplementedEntitiesServer) ListDeletedEntities(context.Context, *ListDeletedEntitiesRequest) (*ListDeletedEntitiesResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method ListDeletedEntities not implemented") +} +func (UnimplementedEntitiesServer) UndeleteEntity(context.Context, *UndeleteEntityRequest) (*emptypb.Empty, error) { + return nil, status.Errorf(codes.Unimplemented, "method UndeleteEntity not implemented") +} func (UnimplementedEntitiesServer) ListEntityMentions(context.Context, *ListEntityMentionsRequest) (*ListEntityMentionsResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method ListEntityMentions not implemented") } @@ -210,6 +261,60 @@ func _Entities_SearchEntities_Handler(srv interface{}, ctx context.Context, dec return interceptor(ctx, in, info, handler) } +func _Entities_DeleteEntity_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(DeleteEntityRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(EntitiesServer).DeleteEntity(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/com.mintter.entities.v1alpha.Entities/DeleteEntity", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(EntitiesServer).DeleteEntity(ctx, req.(*DeleteEntityRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Entities_ListDeletedEntities_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(ListDeletedEntitiesRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(EntitiesServer).ListDeletedEntities(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/com.mintter.entities.v1alpha.Entities/ListDeletedEntities", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(EntitiesServer).ListDeletedEntities(ctx, req.(*ListDeletedEntitiesRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Entities_UndeleteEntity_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(UndeleteEntityRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(EntitiesServer).UndeleteEntity(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/com.mintter.entities.v1alpha.Entities/UndeleteEntity", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(EntitiesServer).UndeleteEntity(ctx, req.(*UndeleteEntityRequest)) + } + return interceptor(ctx, in, info, handler) +} + func _Entities_ListEntityMentions_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(ListEntityMentionsRequest) if err := dec(in); err != nil { @@ -251,6 +356,18 @@ var Entities_ServiceDesc = grpc.ServiceDesc{ MethodName: "SearchEntities", Handler: _Entities_SearchEntities_Handler, }, + { + MethodName: "DeleteEntity", + Handler: _Entities_DeleteEntity_Handler, + }, + { + MethodName: "ListDeletedEntities", + Handler: _Entities_ListDeletedEntities_Handler, + }, + { + MethodName: "UndeleteEntity", + Handler: _Entities_UndeleteEntity_Handler, + }, { MethodName: "ListEntityMentions", Handler: _Entities_ListEntityMentions_Handler, diff --git a/backend/hyper/entity.go b/backend/hyper/entity.go index 1b40b8cf9e..9ed5cf04ea 100644 --- a/backend/hyper/entity.go +++ b/backend/hyper/entity.go @@ -33,7 +33,7 @@ import ( // EntityID is a type for IDs of mutable entities. type EntityID string -// EntityIDFromCID converts a previously CID-encoded Entity ID bas into the initial form. +// EntityIDFromCID converts a previously CID-encoded Entity ID back into the initial form. func EntityIDFromCID(c cid.Cid) (EntityID, error) { codec, hash := ipfs.DecodeCID(c) @@ -324,7 +324,8 @@ func SortCIDs(cids []cid.Cid) []cid.Cid { return cids } -func (bs *Storage) ForEachComment(ctx context.Context, target string, fn func(c cid.Cid, cmt Comment) error) (err error) { +// ForEachComment iterates through a target document comments to manipulate them. +func (bs *Storage) ForEachComment(ctx context.Context, target string, fn func(c cid.Cid, cmt Comment, conn *sqlite.Conn) error) (err error) { conn, release, err := bs.db.Conn(ctx) if err != nil { return err @@ -360,7 +361,7 @@ func (bs *Storage) ForEachComment(ctx context.Context, target string, fn func(c return fmt.Errorf("forEachComment: failed to decode comment %s for target %s: %w", chcid, target, err) } - if err := fn(chcid, cmt); err != nil { + if err := fn(chcid, cmt, conn); err != nil { return err } diff --git a/backend/hyper/hyper.go b/backend/hyper/hyper.go index 5384ef243d..10588360eb 100644 --- a/backend/hyper/hyper.go +++ b/backend/hyper/hyper.go @@ -25,6 +25,11 @@ import ( "go.uber.org/zap" ) +var ( + // ErrEntityNotFound used when looking for an entity not present in the database. + ErrEntityNotFound = errors.New("entity not found") +) + // BlobType is a named type for Mintter Terra Blobs. type BlobType string @@ -326,6 +331,7 @@ func (bs *Storage) DeleteDraft(ctx context.Context, eid EntityID) error { }) } +// DeleteEntity deletes an entity from the database. func (bs *Storage) DeleteEntity(ctx context.Context, eid EntityID) error { conn, release, err := bs.db.Conn(ctx) if err != nil { @@ -336,21 +342,18 @@ func (bs *Storage) DeleteEntity(ctx context.Context, eid EntityID) error { return sqlitex.WithTx(conn, func() error { edb, err := hypersql.EntitiesLookupID(conn, string(eid)) if err != nil { - return err + return fmt.Errorf("%w. problem with the query: %s", ErrEntityNotFound, err.Error()) } if edb.ResourcesID == 0 { - return fmt.Errorf("no such entity: %s", eid) + return fmt.Errorf("%w: %s", ErrEntityNotFound, eid) } if err := hypersql.ChangesDeleteForEntity(conn, edb.ResourcesID); err != nil { return err } - if err := hypersql.EntitiesDelete(conn, string(eid)); err != nil { - return err - } + return hypersql.EntitiesDelete(conn, string(eid)) - return nil }) } diff --git a/backend/hyper/hypersql/queries.gen.go b/backend/hyper/hypersql/queries.gen.go index 4d42eddfae..ff826c4a2d 100644 --- a/backend/hyper/hypersql/queries.gen.go +++ b/backend/hyper/hypersql/queries.gen.go @@ -187,6 +187,68 @@ RETURNING blobs.id` return out, err } +func BlobsEmptyByHash(conn *sqlite.Conn, blobsMultihash []byte) error { + const query = `UPDATE blobs +SET data ='NULL', size =-1 +WHERE blobs.multihash = :blobsMultihash` + + before := func(stmt *sqlite.Stmt) { + stmt.SetBytes(":blobsMultihash", blobsMultihash) + } + + onStep := func(i int, stmt *sqlite.Stmt) error { + return nil + } + + err := sqlitegen.ExecStmt(conn, query, before, onStep) + if err != nil { + err = fmt.Errorf("failed query: BlobsEmptyByHash: %w", err) + } + + return err +} + +func BlobsEmptyByEID(conn *sqlite.Conn, eid string) error { + const query = `UPDATE blobs +SET data = 'NULL', size =-1 +WHERE blobs.id IN (SELECT structural_blobs_view.blob_id FROM structural_blobs_view WHERE structural_blobs_view.resource = :eid)` + + before := func(stmt *sqlite.Stmt) { + stmt.SetText(":eid", eid) + } + + onStep := func(i int, stmt *sqlite.Stmt) error { + return nil + } + + err := sqlitegen.ExecStmt(conn, query, before, onStep) + if err != nil { + err = fmt.Errorf("failed query: BlobsEmptyByEID: %w", err) + } + + return err +} + +func BlobsStructuralDelete(conn *sqlite.Conn, eid string) error { + const query = `DELETE FROM structural_blobs +WHERE structural_blobs.id IN (SELECT structural_blobs_view.blob_id FROM structural_blobs_view WHERE structural_blobs_view.resource = :eid)` + + before := func(stmt *sqlite.Stmt) { + stmt.SetText(":eid", eid) + } + + onStep := func(i int, stmt *sqlite.Stmt) error { + return nil + } + + err := sqlitegen.ExecStmt(conn, query, before, onStep) + if err != nil { + err = fmt.Errorf("failed query: BlobsStructuralDelete: %w", err) + } + + return err +} + type BlobsListKnownResult struct { BlobsID int64 BlobsMultihash []byte @@ -688,6 +750,134 @@ WHERE resources.iri = :entities_eid` return err } +type EntitiesInsertRemovedRecordResult struct { + ResourceEID string +} + +func EntitiesInsertRemovedRecord(conn *sqlite.Conn, iri string, reason string, meta string) (EntitiesInsertRemovedRecordResult, error) { + const query = `INSERT OR IGNORE INTO deleted_resources (iri, reason, meta) +VALUES (:iri, :reason, :meta) +RETURNING deleted_resources.iri AS resource_eid` + + var out EntitiesInsertRemovedRecordResult + + before := func(stmt *sqlite.Stmt) { + stmt.SetText(":iri", iri) + stmt.SetText(":reason", reason) + stmt.SetText(":meta", meta) + } + + onStep := func(i int, stmt *sqlite.Stmt) error { + if i > 1 { + return errors.New("EntitiesInsertRemovedRecord: more than one result return for a single-kind query") + } + + out.ResourceEID = stmt.ColumnText(0) + return nil + } + + err := sqlitegen.ExecStmt(conn, query, before, onStep) + if err != nil { + err = fmt.Errorf("failed query: EntitiesInsertRemovedRecord: %w", err) + } + + return out, err +} + +func EntitiesDeleteRemovedRecord(conn *sqlite.Conn, resource_eid string) error { + const query = `DELETE FROM deleted_resources +WHERE deleted_resources.iri = :resource_eid` + + before := func(stmt *sqlite.Stmt) { + stmt.SetText(":resource_eid", resource_eid) + } + + onStep := func(i int, stmt *sqlite.Stmt) error { + return nil + } + + err := sqlitegen.ExecStmt(conn, query, before, onStep) + if err != nil { + err = fmt.Errorf("failed query: EntitiesDeleteRemovedRecord: %w", err) + } + + return err +} + +type EntitiesLookupRemovedRecordResult struct { + DeletedResourcesIRI string + DeletedResourcesDeleteTime int64 + DeletedResourcesReason string + DeletedResourcesMeta string +} + +func EntitiesLookupRemovedRecord(conn *sqlite.Conn, resource_eid string) (EntitiesLookupRemovedRecordResult, error) { + const query = `SELECT deleted_resources.iri, deleted_resources.delete_time, deleted_resources.reason, deleted_resources.meta +FROM deleted_resources +WHERE deleted_resources.iri = :resource_eid +LIMIT 1` + + var out EntitiesLookupRemovedRecordResult + + before := func(stmt *sqlite.Stmt) { + stmt.SetText(":resource_eid", resource_eid) + } + + onStep := func(i int, stmt *sqlite.Stmt) error { + if i > 1 { + return errors.New("EntitiesLookupRemovedRecord: more than one result return for a single-kind query") + } + + out.DeletedResourcesIRI = stmt.ColumnText(0) + out.DeletedResourcesDeleteTime = stmt.ColumnInt64(1) + out.DeletedResourcesReason = stmt.ColumnText(2) + out.DeletedResourcesMeta = stmt.ColumnText(3) + return nil + } + + err := sqlitegen.ExecStmt(conn, query, before, onStep) + if err != nil { + err = fmt.Errorf("failed query: EntitiesLookupRemovedRecord: %w", err) + } + + return out, err +} + +type EntitiesListRemovedRecordsResult struct { + DeletedResourcesIRI string + DeletedResourcesDeleteTime int64 + DeletedResourcesReason string + DeletedResourcesMeta string +} + +func EntitiesListRemovedRecords(conn *sqlite.Conn) ([]EntitiesListRemovedRecordsResult, error) { + const query = `SELECT deleted_resources.iri, deleted_resources.delete_time, deleted_resources.reason, deleted_resources.meta +FROM deleted_resources` + + var out []EntitiesListRemovedRecordsResult + + before := func(stmt *sqlite.Stmt) { + } + + onStep := func(i int, stmt *sqlite.Stmt) error { + out = append(out, EntitiesListRemovedRecordsResult{ + DeletedResourcesIRI: stmt.ColumnText(0), + DeletedResourcesDeleteTime: stmt.ColumnInt64(1), + DeletedResourcesReason: stmt.ColumnText(2), + DeletedResourcesMeta: stmt.ColumnText(3), + }) + + return nil + } + + err := sqlitegen.ExecStmt(conn, query, before, onStep) + if err != nil { + err = fmt.Errorf("failed query: EntitiesListRemovedRecords: %w", err) + } + + return out, err +} + type ChangesListFromChangeSetResult struct { StructuralBlobsViewBlobID int64 StructuralBlobsViewCodec int64 diff --git a/backend/hyper/hypersql/queries.gensum b/backend/hyper/hypersql/queries.gensum index e4aa00d6dd..534f43bdf6 100644 --- a/backend/hyper/hypersql/queries.gensum +++ b/backend/hyper/hypersql/queries.gensum @@ -1,2 +1,2 @@ -srcs: e80150f42251938329daac92fb5a9c42 -outs: ff29159baa5946b69e98f85b93b400a4 +srcs: b3ba38c570e3e0b01d49c1fffff0cc2e +outs: 9e8e37578ee68a595ae5e5a0f124aee7 diff --git a/backend/hyper/hypersql/queries.go b/backend/hyper/hypersql/queries.go index 91161e3101..5dcd4856df 100644 --- a/backend/hyper/hypersql/queries.go +++ b/backend/hyper/hypersql/queries.go @@ -60,6 +60,29 @@ func generateQueries() error { "WHERE", s.BlobsMultihash, "=", qb.VarCol(s.BlobsMultihash), '\n', "RETURNING", qb.Results(s.BlobsID), ), + qb.MakeQuery(s.Schema, "BlobsEmptyByHash", sgen.QueryKindExec, + "UPDATE", s.Blobs, '\n', + "SET", s.BlobsData.ShortName(), "='NULL',", s.BlobsSize.ShortName(), "=-1", '\n', + "WHERE", s.BlobsMultihash, "=", qb.VarCol(s.BlobsMultihash), + ), + qb.MakeQuery(s.Schema, "BlobsEmptyByEID", sgen.QueryKindExec, + "UPDATE", s.Blobs, '\n', + "SET", s.BlobsData.ShortName(), "= 'NULL',", s.BlobsSize.ShortName(), "=-1", '\n', + "WHERE", s.BlobsID, "IN", qb.SubQuery( + "SELECT", s.StructuralBlobsViewBlobID, + "FROM", s.StructuralBlobsView, + "WHERE", s.StructuralBlobsViewResource, "=", qb.Var("eid", sgen.TypeText), + ), + ), + + qb.MakeQuery(s.Schema, "BlobsStructuralDelete", sgen.QueryKindExec, + "DELETE FROM", s.StructuralBlobs, '\n', + "WHERE", s.StructuralBlobsID, "IN", qb.SubQuery( + "SELECT", s.StructuralBlobsViewBlobID, + "FROM", s.StructuralBlobsView, + "WHERE", s.StructuralBlobsViewResource, "=", qb.Var("eid", sgen.TypeText), + ), + ), qb.MakeQuery(s.Schema, "BlobsListKnown", sgen.QueryKindMany, "SELECT", qb.Results( s.BlobsID, @@ -210,7 +233,43 @@ func generateQueries() error { "DELETE FROM", s.Resources, '\n', "WHERE", s.ResourcesIRI, "=", qb.Var("entities_eid", sgen.TypeText), ), - + qb.MakeQuery(s.Schema, "EntitiesInsertRemovedRecord", sgen.QueryKindSingle, + "INSERT OR IGNORE INTO", s.DeletedResources, qb.ListColShort( + s.DeletedResourcesIRI, + s.DeletedResourcesReason, + s.DeletedResourcesMeta, + ), '\n', + "VALUES", qb.List( + qb.Var("iri", sgen.TypeText), + qb.Var("reason", sgen.TypeText), + qb.Var("meta", sgen.TypeText), + ), '\n', + "RETURNING", qb.Results(qb.ResultColAlias(s.DeletedResourcesIRI, "resource_eid")), + ), + qb.MakeQuery(s.Schema, "EntitiesDeleteRemovedRecord", sgen.QueryKindExec, + "DELETE FROM", s.DeletedResources, '\n', + "WHERE", s.DeletedResourcesIRI, "=", qb.Var("resource_eid", sgen.TypeText), + ), + qb.MakeQuery(s.Schema, "EntitiesLookupRemovedRecord", sgen.QueryKindSingle, + "SELECT", qb.Results( + s.DeletedResourcesIRI, + s.DeletedResourcesDeleteTime, + s.DeletedResourcesReason, + s.DeletedResourcesMeta, + ), '\n', + "FROM", s.DeletedResources, '\n', + "WHERE", s.DeletedResourcesIRI, "=", qb.Var("resource_eid", sgen.TypeText), '\n', + "LIMIT 1", + ), + qb.MakeQuery(s.Schema, "EntitiesListRemovedRecords", sgen.QueryKindMany, + "SELECT", qb.Results( + s.DeletedResourcesIRI, + s.DeletedResourcesDeleteTime, + s.DeletedResourcesReason, + s.DeletedResourcesMeta, + ), '\n', + "FROM", s.DeletedResources, + ), qb.MakeQuery(s.Schema, "ChangesListFromChangeSet", sgen.QueryKindMany, "SELECT", qb.Results( s.StructuralBlobsViewBlobID, diff --git a/backend/hyper/indexing.go b/backend/hyper/indexing.go index 5ecad13a76..e137987112 100644 --- a/backend/hyper/indexing.go +++ b/backend/hyper/indexing.go @@ -339,6 +339,10 @@ func (bs *indexer) indexChange(idx *indexingCtx, id int64, c cid.Cid, v Change) // Indexing specific to various types of Entities switch { case v.Entity.HasPrefix("hm://a/"): + res, err := hypersql.EntitiesLookupRemovedRecord(idx.conn, sb.Resource.ID.String()) + if err == nil && res.DeletedResourcesIRI == sb.Resource.ID.String() { + return fmt.Errorf("Change belongs to a deleted account [%s]", res.DeletedResourcesIRI) + } if v, ok := v.Patch["avatar"].(cid.Cid); ok { sb.AddBlobLink("account/avatar", v) } @@ -356,6 +360,12 @@ func (bs *indexer) indexChange(idx *indexingCtx, id int64, c cid.Cid, v Change) sb.Meta = title } blocks, ok := v.Patch["blocks"].(map[string]any) + + res, err := hypersql.EntitiesLookupRemovedRecord(idx.conn, sb.Resource.ID.String()) + if err == nil && res.DeletedResourcesIRI == sb.Resource.ID.String() { + return fmt.Errorf("Change belongs to a deleted document [%s]", res.DeletedResourcesIRI) + } + if ok { for id, blk := range blocks { v, ok := blk.(map[string]any)["#map"] @@ -374,7 +384,6 @@ func (bs *indexer) indexChange(idx *indexingCtx, id int64, c cid.Cid, v Change) } blk.Id = id blk.Revision = c.String() - if err := indexURL(&sb, bs.log, blk.Id, "doc/"+blk.Type, blk.Ref); err != nil { return err } @@ -394,6 +403,10 @@ func (bs *indexer) indexChange(idx *indexingCtx, id int64, c cid.Cid, v Change) sb.Meta = title } var currentRole groups.Role + res, err := hypersql.EntitiesLookupRemovedRecord(idx.conn, sb.Resource.ID.String()) + if err == nil && res.DeletedResourcesIRI == sb.Resource.ID.String() { + return fmt.Errorf("Change belongs to a deleted group [%s]", res.DeletedResourcesIRI) + } if v.Action == ActionCreate { currentRole = groups.Role_OWNER sb.AddResourceLink("group/member", authorEntity, false, GroupLinkMeta{Role: currentRole}) @@ -516,6 +529,11 @@ func (bs *indexer) indexComment(idx *indexingCtx, id int64, c cid.Cid, v Comment if !strings.HasPrefix(v.Target, "hm://") { return fmt.Errorf("comment target must be a hypermedia resource, got %s", v.Target) } + iri := strings.Split(v.Target, "?v=")[0] + res, err := hypersql.EntitiesLookupRemovedRecord(idx.conn, iri) + if err == nil && res.DeletedResourcesIRI == iri { + return fmt.Errorf("Comment references to a deleted entity [%s]", res.DeletedResourcesIRI) + } isReply := v.RepliedComment.Defined() || v.ThreadRoot.Defined() diff --git a/frontend/packages/app/components/delete-dialog.tsx b/frontend/packages/app/components/delete-dialog.tsx index b244cef17b..0897039cac 100644 --- a/frontend/packages/app/components/delete-dialog.tsx +++ b/frontend/packages/app/components/delete-dialog.tsx @@ -1,16 +1,24 @@ +import {zodResolver} from '@hookform/resolvers/zod' +import {HYPERMEDIA_ENTITY_TYPES, unpackHmId} from '@mintter/shared' import { AlertDialog, AlertDialogContentProps, AlertDialogProps, Button, + Form, HeadingProps, ParagraphProps, XStack, XStackProps, YStack, } from '@mintter/ui' -import {ReactNode} from 'react' -import {useDeletePublication} from '../models/documents' +import {ReactNode, useEffect} from 'react' +import {SubmitHandler, useForm} from 'react-hook-form' +import {z} from 'zod' +import {useDeleteEntity} from '../models/entities' +import {useAppDialog} from './dialog' +import {FormTextArea} from './form-input' +import {FormField} from './forms' export type DeleteDialogProps = AlertDialogProps & { dialogContentProps?: AlertDialogContentProps @@ -25,41 +33,86 @@ export type DeleteDialogProps = AlertDialogProps & { descriptionProps?: ParagraphProps } -export function DeleteDocumentDialog({ - input: docId, +const deleteFormSchema = z.object({ + description: z.string(), +}) +type DeleteFormFields = z.infer + +export function useDeleteDialog() { + return useAppDialog(DeleteEntityDialog, {isAlert: true}) +} + +export function DeleteEntityDialog({ + input: {id, title, onSuccess}, onClose, }: { - input: string + input: {id: string; title?: string; onSuccess?: () => void} onClose?: () => void }) { - const deletePub = useDeletePublication({ - onSuccess: onClose, + const deleteEntity = useDeleteEntity({ + onSuccess: () => { + onClose?.(), onSuccess?.() + }, + }) + const { + control, + handleSubmit, + setFocus, + formState: {errors}, + } = useForm({ + resolver: zodResolver(deleteFormSchema), + defaultValues: { + description: title + ? `Deleted "${title}" because...` + : 'Deleted because...', + }, }) + const hid = unpackHmId(id) + const onSubmit: SubmitHandler = (data) => { + console.log('DeleteEntityDialog.onSubmit', {id, data}) + deleteEntity.mutate({ + id, + reason: data.description, + }) + } + useEffect(() => { + setFocus('description') + }, [setFocus]) + if (!hid) throw new Error('Invalid id passed to DeleteEntityDialog') return ( - Delete document + + Delete this {HYPERMEDIA_ENTITY_TYPES[hid.type]} + - Are you sure you want to delete this document? This action is not - reversible. + Are you sure you want to delete this from your computer? It will also be + blocked to prevent you seeing it again. - - - - - - - - - + + You may describe your reason for deleting+blocking this{' '} + {HYPERMEDIA_ENTITY_TYPES[hid.type].toLocaleLowerCase()} below. + +
+ + + + + + + + + + + +
) } diff --git a/frontend/packages/app/components/forms.tsx b/frontend/packages/app/components/forms.tsx index 2d2e2adfa7..1d1cb1c031 100644 --- a/frontend/packages/app/components/forms.tsx +++ b/frontend/packages/app/components/forms.tsx @@ -21,17 +21,19 @@ export function FormField({ }: PropsWithChildren<{ name: keyof Fields errors: FieldErrors - label: string + label?: string }>) { return (
- + {label ? ( + + ) : null} {errors[name]?.message} {children} diff --git a/frontend/packages/app/components/titlebar-common.tsx b/frontend/packages/app/components/titlebar-common.tsx index 48d95c9dfa..d4324c3659 100644 --- a/frontend/packages/app/components/titlebar-common.tsx +++ b/frontend/packages/app/components/titlebar-common.tsx @@ -40,11 +40,13 @@ import { Pencil, Plus, Send, + Trash, UploadCloud, } from '@tamagui/lucide-icons' import copyTextToClipboard from 'copy-text-to-clipboard' import {ReactNode, useState} from 'react' import {useAppContext} from '../app-context' +import {useAccount} from '../models/accounts' import {useEntityTimeline} from '../models/changes' import {usePushPublication} from '../models/documents' import {useGatewayHost, useGatewayUrl} from '../models/gateway-settings' @@ -59,6 +61,7 @@ import {useOpenDraft} from '../utils/open-draft' import {NavRoute} from '../utils/routes' import {CloneGroupDialog} from './clone-group' import {useCopyGatewayReference} from './copy-gateway-reference' +import {useDeleteDialog} from './delete-dialog' import {useAppDialog} from './dialog' import {useEditGroupInfoDialog} from './edit-group-info' import {useFavoriteMenuItem} from './favoriting' @@ -74,6 +77,7 @@ import { export function DocOptionsButton() { const route = useNavRoute() + const dispatch = useNavigationDispatch() if (route.key !== 'publication') throw new Error( 'DocOptionsButton can only be rendered on publication route', @@ -87,7 +91,13 @@ export function DocOptionsButton() { const gwHost = useGatewayHost() const addToCategoryDialog = useAppDialog(AddToCategoryDialog) const push = usePushPublication() + const deleteEntity = useDeleteDialog() const [copyContent, onCopy, host] = useCopyGatewayReference() + const pub = usePublicationVariant({ + documentId: route.documentId, + versionId: route.versionId, + variants: route.variants, + }) const menuItems: MenuItemType[] = [ { key: 'link', @@ -117,6 +127,21 @@ export function DocOptionsButton() { }) }, }, + { + key: 'delete', + label: 'Delete Publication', + icon: Trash, + onPress: () => { + deleteEntity.open({ + id: route.documentId, + title: pub.data?.publication?.document?.title, + onSuccess: () => { + // dispatch({type: 'backplace', route: {key: 'feed', tab: 'trusted'}}) + dispatch({type: 'pop'}) + }, + }) + }, + }, // ...(groupVariant && groupVariant.pathName // ? [ // { @@ -144,6 +169,7 @@ export function DocOptionsButton() { <> {copyContent} {addToCategoryDialog.content} + {deleteEntity.content} ) @@ -158,9 +184,27 @@ export function AccountOptionsButton() { const menuItems: MenuItemType[] = [] const accountUrl = createHmId('a', route.accountId) menuItems.push(useFavoriteMenuItem(accountUrl)) + const account = useAccount(route.accountId) + const dispatch = useNavigationDispatch() + const deleteEntity = useDeleteDialog() + menuItems.push({ + key: 'delete', + label: 'Delete Account', + icon: Trash, + onPress: () => { + deleteEntity.open({ + id: createHmId('a', route.accountId), + title: account.data?.profile?.alias, + onSuccess: () => { + dispatch({type: 'pop'}) + }, + }) + }, + }) return ( <> + {deleteEntity.content} ) @@ -180,7 +224,9 @@ export function GroupOptionsButton() { const isGroupOwner = myAccount.data?.id && group.data?.ownerAccountId === myAccount.data?.id const cloneGroup = useAppDialog(CloneGroupDialog) + const deleteEntity = useDeleteDialog() const gwUrl = useGatewayUrl() + const dispatch = useNavigationDispatch() const menuItems: MenuItemType[] = [ { key: 'clone', @@ -206,6 +252,20 @@ export function GroupOptionsButton() { toast.success('Copied Public Group URL') }, }, + { + key: 'delete', + label: 'Delete Group', + icon: Trash, + onPress: () => { + deleteEntity.open({ + id: groupId, + title: group.data?.title, + onSuccess: () => { + dispatch({type: 'pop'}) + }, + }) + }, + }, ] menuItems.push(useFavoriteMenuItem(groupId)) @@ -236,6 +296,7 @@ export function GroupOptionsButton() { <> {publish.content} + {deleteEntity.content} {editInfo.content} {cloneGroup.content} diff --git a/frontend/packages/app/models/accounts.ts b/frontend/packages/app/models/accounts.ts index 18011f7928..159b3d618b 100644 --- a/frontend/packages/app/models/accounts.ts +++ b/frontend/packages/app/models/accounts.ts @@ -94,7 +94,7 @@ export function useSetTrusted( }) } -export function useAccountIsConnected(account: Account) { +export function useAccountIsConnected(account: HMAccount) { const peers = useConnectedPeers() return !!peers.data?.find((peer) => peer.accountId == account.id) } diff --git a/frontend/packages/app/models/documents.ts b/frontend/packages/app/models/documents.ts index 7afa8cf90d..176863b7fb 100644 --- a/frontend/packages/app/models/documents.ts +++ b/frontend/packages/app/models/documents.ts @@ -185,23 +185,6 @@ export function useDeleteDraft( }) } -export function useDeletePublication( - opts: UseMutationOptions, -) { - const invalidate = useQueryInvalidator() - const grpcClient = useGRPCClient() - return useMutation({ - ...opts, - mutationFn: async (documentId) => { - await grpcClient.publications.deletePublication({documentId}) - }, - onSuccess: (...args) => { - invalidate([queryKeys.GET_PUBLICATION_LIST]) - opts?.onSuccess?.(...args) - }, - }) -} - export function usePublication( { id, diff --git a/frontend/packages/app/models/entities.ts b/frontend/packages/app/models/entities.ts new file mode 100644 index 0000000000..54795a582b --- /dev/null +++ b/frontend/packages/app/models/entities.ts @@ -0,0 +1,47 @@ +import {unpackHmId} from '@mintter/shared' +import {UseMutationOptions, useMutation} from '@tanstack/react-query' +import {useGRPCClient, useQueryInvalidator} from '../app-context' +import {queryKeys} from './query-keys' + +export function useDeleteEntity( + opts: UseMutationOptions, +) { + const invalidate = useQueryInvalidator() + const grpcClient = useGRPCClient() + return useMutation({ + ...opts, + mutationFn: async ({id, reason}: {id: string; reason: string}) => { + await grpcClient.entities.deleteEntity({id, reason}) + }, + onSuccess: ( + result: void, + variables: {id: string; reason: string}, + context, + ) => { + const hmId = unpackHmId(variables.id) + if (hmId?.type === 'd') { + invalidate([queryKeys.GET_PUBLICATION, variables.id]) + invalidate([queryKeys.GET_ACCOUNT_PUBLICATIONS]) + invalidate([queryKeys.GET_PUBLICATION_LIST]) + } else if (hmId?.type === 'a') { + invalidate([queryKeys.GET_ALL_ACCOUNTS]) + invalidate([queryKeys.GET_ACCOUNT, hmId.eid]) + } else if (hmId?.type === 'c') { + invalidate([queryKeys.COMMENT, variables.id]) + invalidate([queryKeys.PUBLICATION_COMMENTS]) + } else if (hmId?.type === 'g') { + invalidate([queryKeys.GET_GROUP, variables.id]) + invalidate([queryKeys.GET_GROUPS]) + invalidate([queryKeys.GET_GROUPS_FOR_DOCUMENT]) + invalidate([queryKeys.GET_GROUPS_FOR_ACCOUNT]) + } + invalidate([queryKeys.FEED]) + invalidate([queryKeys.FEED_LATEST_EVENT]) + invalidate([queryKeys.RESOURCE_FEED]) + invalidate([queryKeys.RESOURCE_FEED_LATEST_EVENT]) + invalidate([queryKeys.ENTITY_CITATIONS]) + invalidate([queryKeys.SEARCH]) + opts?.onSuccess?.(result, variables, context) + }, + }) +} diff --git a/frontend/packages/app/models/query-keys.ts b/frontend/packages/app/models/query-keys.ts index 01fd0ecfdb..465cc70117 100644 --- a/frontend/packages/app/models/query-keys.ts +++ b/frontend/packages/app/models/query-keys.ts @@ -56,7 +56,6 @@ export const queryKeys = { // changes CHANGE: 'CHANGE', //, changeId: string - ALL_ENTITY_CHANGES: 'ALL_ENTITY_CHANGES', //, entityId: string // cid BLOB_DATA: 'BLOB_DATA', //, cid: string @@ -143,8 +142,6 @@ export function labelOfQueryKey(key: QueryKey) { // changes case queryKeys.CHANGE: return 'Change' - case queryKeys.ALL_ENTITY_CHANGES: - return 'Entity Changes' // cid case queryKeys.BLOB_DATA: diff --git a/frontend/packages/app/pages/account-content-page.tsx b/frontend/packages/app/pages/account-content-page.tsx index 0bb0dd70d6..36925daa02 100644 --- a/frontend/packages/app/pages/account-content-page.tsx +++ b/frontend/packages/app/pages/account-content-page.tsx @@ -21,6 +21,7 @@ import { import {ReactNode, useMemo} from 'react' import {AccessoryLayout} from '../components/accessory-sidebar' import {useCopyGatewayReference} from '../components/copy-gateway-reference' +import {useDeleteDialog} from '../components/delete-dialog' import {copyLinkMenuItem} from '../components/list-item' import {MainWrapperNoScroll} from '../components/main-wrapper' import {useAllAccounts} from '../models/accounts' @@ -178,7 +179,7 @@ function AccountGroups() { if (!accountId) throw new Error('Invalid route, no account id') const {data: groups} = useAccountGroups(accountId) const [copyDialogContent, onCopyId] = useCopyGatewayReference() - + const deleteDialog = useDeleteDialog() return ( <> @@ -193,11 +194,13 @@ function AccountGroups() { if (!groupId) return onCopyId(groupId) }} + onDelete={deleteDialog.open} /> )} /> ) : null} {copyDialogContent} + {deleteDialog.content}
diff --git a/frontend/packages/app/pages/contacts-page.tsx b/frontend/packages/app/pages/contacts-page.tsx index 8a94b348ac..6bbac93f59 100644 --- a/frontend/packages/app/pages/contacts-page.tsx +++ b/frontend/packages/app/pages/contacts-page.tsx @@ -14,9 +14,11 @@ import { XStack, YStack, } from '@mintter/ui' +import {Trash} from '@tamagui/lucide-icons' import {AccountTrustButton} from '../components/account-trust' import {Avatar} from '../components/avatar' import {useCopyGatewayReference} from '../components/copy-gateway-reference' +import {useDeleteDialog} from '../components/delete-dialog' import {FavoriteButton} from '../components/favoriting' import {OnlineIndicator} from '../components/indicator' import {ListItem, copyLinkMenuItem} from '../components/list-item' @@ -30,9 +32,11 @@ import {AccountRoute} from '../utils/routes' export function ContactItem({ account, onCopy, + onDelete, }: { account: HMAccount onCopy: () => void + onDelete: (input: {id: string; title?: string}) => void }) { const navigate = useNavigate() const spawn = useNavigate('spawn') @@ -41,7 +45,9 @@ export function ContactItem({ const favorite = useFavorite(accountUrl) const alias = account.profile?.alias const gwUrl = useGatewayUrl() - const openRoute: AccountRoute = {key: 'account', accountId: account.id} + const accountId = account.id + if (!accountId) throw new Error('Account ID is required') + const openRoute: AccountRoute = {key: 'account', accountId} return ( { navigate(openRoute) }} - title={alias || account.id.slice(0, 5) + '...' + account.id.slice(-5)} + title={alias || accountId.slice(0, 5) + '...' + accountId.slice(-5)} accessory={ <> {accountUrl && ( @@ -69,7 +75,7 @@ export function ContactItem({ )} @@ -90,6 +96,17 @@ export function ContactItem({ ? `${account.profile.alias}'s Profile` : `Profile`, ), + { + key: 'delete', + label: 'Delete Account', + icon: Trash, + onPress: () => { + onDelete({ + id: createHmId('a', accountId), + title: account.profile?.alias, + }) + }, + }, ]} /> ) @@ -118,6 +135,7 @@ export default function ContactsPage() { const untrustedAccounts = allAccounts.filter( (account) => !account.isTrusted && !!account.profile?.alias, // hide contacts without an alias because this is confusing for users ) + const deleteEntity = useDeleteDialog() const [copyDialogContent, onCopy] = useCopyGatewayReference() if (contacts.isLoading) { return ( @@ -161,6 +179,7 @@ export default function ContactsPage() { onCopy={() => { onCopy(hmId('a', item.id)) }} + onDelete={deleteEntity.open} /> ) }} @@ -170,6 +189,7 @@ export default function ContactsPage() { /> {copyDialogContent} + {deleteEntity.content}