diff --git a/.envrc b/.envrc index fb0a886d24..8ac5b114e3 100644 --- a/.envrc +++ b/.envrc @@ -25,7 +25,7 @@ export VITE_BACKEND_HTTP_PORT='55002' export VITE_BACKEND_GRPC_PORT="56002" export VITE_BACKEND_P2P_PORT="56003" -export NEXT_PUBLIC_GRPC_HOST="https://gateway.mintter.com" +export NEXT_PUBLIC_GRPC_HOST="http://localhost:57001" # export NEXT_PUBLIC_GRPC_HOST="http://localhost:56001" export NEXT_PUBLIC_LN_HOST="https://ln.mintter.com" export MINTTER_IS_GATEWAY="1" diff --git a/.github/workflows/generate-docker-images.yml b/.github/workflows/generate-docker-images.yml index bb5f64bb59..5ed56e8caa 100644 --- a/.github/workflows/generate-docker-images.yml +++ b/.github/workflows/generate-docker-images.yml @@ -23,6 +23,12 @@ jobs: with: username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }} + - name: Build and push mintter-site + uses: docker/build-push-action@v4 + with: + push: true + file: backend/cmd/mintter-site/Dockerfile + tags: mintter/mintter-site:latest - name: Build and push mintterd uses: docker/build-push-action@v4 with: diff --git a/.golangci.yaml b/.golangci.yaml index 4eac5000cd..daf2482c90 100644 --- a/.golangci.yaml +++ b/.golangci.yaml @@ -12,17 +12,21 @@ issues: exclude-rules: # Unused parameter warnings are annoying in tests. - path: _test\.go - linters: ['revive'] - text: 'unused-parameter' + linters: ["revive"] + text: "unused-parameter" # For test helpers it's often convenient to pass *testing.T as the first parameter. # We don't care if context is not the first argument here. - path: _test\.go - text: 'context-as-argument' - linters: ['revive'] + text: "context-as-argument" + linters: ["revive"] # In tests we can use math/rand instead of crypto/rand. - path: _test\.go - text: 'weak random number generator' - linters: ['gosec'] + text: "weak random number generator" + linters: ["gosec"] + # Get rid of the annoying "if-return" rule. + # It gets in the way as soon as you decide to wrap the last error instead of returning it. + - text: "if-return" + linters: ["revive"] include: # Include revive rules that check comments on exported identifiers. These rules # are excluded by default, and IMHO this doesn't serve well the Go community. diff --git a/backend/BUILD.plz b/backend/BUILD.plz index 0f15a81d34..a6fe5ab9dd 100644 --- a/backend/BUILD.plz +++ b/backend/BUILD.plz @@ -8,10 +8,10 @@ go_binary( ["**/*.go"], exclude = ["**/*_test.go"], ) + [ + "//backend/cmd/mintter-site/sitesql:go_library", "//backend/daemon/storage:go_library", "//backend/hyper/hypersql:go_library", "//backend/lndhub/lndhubsql:go_library", - "//backend/mttnet/sitesql:go_library", "//backend/wallet/walletsql:go_library", ], out = "mintterd-" + target_platform_triple(), diff --git a/backend/cmd/minttergw/Dockerfile b/backend/cmd/mintter-site/Dockerfile similarity index 61% rename from backend/cmd/minttergw/Dockerfile rename to backend/cmd/mintter-site/Dockerfile index 9e67a1c898..5cad8d79e5 100644 --- a/backend/cmd/minttergw/Dockerfile +++ b/backend/cmd/mintter-site/Dockerfile @@ -1,4 +1,4 @@ -# Build from the root with `docker build . -f ./backend/cmd/minttergw/Dockerfile`. +# Build from the root with `docker build . -f ./backend/cmd/mintter-site/Dockerfile`. FROM golang:1.20-alpine AS builder WORKDIR /code COPY go.mod go.sum ./ @@ -6,9 +6,9 @@ COPY third_party ./third_party RUN go mod download COPY backend ./backend RUN apk add build-base -RUN go install ./backend/cmd/minttergw/ +RUN go install ./backend/cmd/mintter-site/ FROM alpine:latest -COPY --from=builder /go/bin/minttergw /usr/local/bin/minttergw +COPY --from=builder /go/bin/mintter-site /usr/local/bin/mintter-site EXPOSE 55000 55001 55002 -CMD ["/usr/local/bin/minttergw"] +CMD ["/usr/local/bin/mintter-site"] diff --git a/backend/cmd/mintter-site/main.go b/backend/cmd/mintter-site/main.go new file mode 100644 index 0000000000..bab22e7e75 --- /dev/null +++ b/backend/cmd/mintter-site/main.go @@ -0,0 +1,77 @@ +// Program mintter-site implements the Hypermedia Site server. +package main + +import ( + "context" + "errors" + "flag" + "fmt" + "os" + + "mintter/backend/cmd/mintter-site/sites" + "mintter/backend/daemon" + + "github.com/burdiyan/go/mainutil" + "github.com/peterbourgon/ff/v3" +) + +func main() { + const envVarPrefix = "MINTTER" + + mainutil.Run(func() error { + ctx := mainutil.TrapSignals() + + fs := flag.NewFlagSet("mintter-site", flag.ExitOnError) + fs.Usage = func() { + fmt.Fprintf(fs.Output(), `Usage: %s ADDRESS [flags] + +This program is similar to our main mintterd program in a lot of ways, but has more suitable defaults for running on a server as site. + +It requires one positional argument ADDRESS, which has to be a Web network address this site is supposed to be available at. +The address can be a DNS name, or an IP address, and it has to be a URL with a scheme and port (if applicable). +Examples: + - http://127.0.0.1:42542 + - https://mintter.com + - http://example.com + +Flags: +`, fs.Name()) + fs.PrintDefaults() + } + + cfg := sites.DefaultConfig() + cfg.BindFlags(fs) + if err := ff.Parse(fs, os.Args[1:], ff.WithEnvVarPrefix(envVarPrefix)); err != nil { + return err + } + + if len(os.Args) < 2 { + fs.Usage() + fmt.Fprintf(fs.Output(), "Error: Positional argument ADDRESS is missing.\n") + os.Exit(1) + } + + rawURL := os.Args[1] + + if err := cfg.Base.ExpandDataDir(); err != nil { + return err + } + + dir, err := daemon.InitRepo(cfg.Base.DataDir, nil) + if err != nil { + return err + } + + app, err := sites.Load(ctx, rawURL, cfg, dir) + if err != nil { + return err + } + + err = app.Wait() + if errors.Is(err, context.Canceled) { + return nil + } + + return err + }) +} diff --git a/backend/cmd/mintter-site/sites/config.go b/backend/cmd/mintter-site/sites/config.go new file mode 100644 index 0000000000..3bac85bd53 --- /dev/null +++ b/backend/cmd/mintter-site/sites/config.go @@ -0,0 +1,14 @@ +package sites + +import "mintter/backend/config" + +// DefaultConfig for sites. +func DefaultConfig() config.Config { + cfg := config.Default() + cfg.DataDir = "~/.mintter-site" + cfg.Syncing.Disabled = true + cfg.P2P.ForceReachabilityPublic = true + cfg.P2P.NoRelay = true + + return cfg +} diff --git a/backend/cmd/mintter-site/sites/daemon.go b/backend/cmd/mintter-site/sites/daemon.go new file mode 100644 index 0000000000..f66e037312 --- /dev/null +++ b/backend/cmd/mintter-site/sites/daemon.go @@ -0,0 +1,106 @@ +package sites + +import ( + "context" + "errors" + "fmt" + "mintter/backend/config" + "mintter/backend/core" + "mintter/backend/daemon" + "mintter/backend/daemon/storage" + accounts "mintter/backend/genproto/accounts/v1alpha" + "mintter/backend/ipfs" + "mintter/backend/mttnet" + "mintter/backend/pkg/future" + "mintter/backend/pkg/must" + "net/url" + + "crawshaw.io/sqlite/sqlitex" +) + +// App is the site daemon app. +type App struct { + *daemon.App + + Website *Website + Address *url.URL + Config config.Config +} + +// Load the site daemon. +func Load(ctx context.Context, address string, cfg config.Config, dir *storage.Dir) (*App, error) { + u, err := url.Parse(address) + if err != nil { + return nil, fmt.Errorf("failed to parse address: %w", err) + } + + if u.Scheme != "http" && u.Scheme != "https" { + return nil, fmt.Errorf("address URL only supports http or https: got %q", address) + } + + if u.Path != "" { + return nil, fmt.Errorf("address URL must not have a path: %s", address) + } + + cfg.P2P.AnnounceAddrs = must.Do2( + ipfs.ParseMultiaddrs( + ipfs.DefaultListenAddrsDNS(u.Hostname(), cfg.P2P.Port))) + + nf := future.New[*mttnet.Node]() + ndb := future.New[*sqlitex.Pool]() + site := NewServer(address, nf.ReadOnly, ndb.ReadOnly) + + app, err := daemon.Load(ctx, cfg, dir, site, daemon.GenericHandler{ + Path: "/.well-known/hypermedia-site", + Handler: site, + Mode: daemon.RouteNav, + }) + if err != nil { + return nil, err + } + + // This is some ugly stuff. Site server needs some stuff that are passed from the daemon. + go func() { + if err := ndb.Resolve(app.DB); err != nil { + panic(err) + } + + node, err := app.Net.Await(ctx) + if err != nil && !errors.Is(err, context.Canceled) { + panic(err) + } + + if err := nf.Resolve(node); err != nil { + panic(err) + } + }() + + if _, ok := dir.Identity().Get(); !ok { + account, err := core.NewKeyPairRandom() + if err != nil { + return nil, fmt.Errorf("failed to generate random account key pair: %w", err) + } + + if err := app.RPC.Daemon.RegisterAccount(ctx, account); err != nil { + return nil, fmt.Errorf("failed to create registration: %w", err) + } + } + + if _, err := app.RPC.Accounts.UpdateProfile(ctx, &accounts.Profile{ + Alias: address, + Bio: "Hypermedia Site. Powered by Mintter.", + }); err != nil { + return nil, fmt.Errorf("failed to update profile: %w", err) + } + + setupURL := site.GetSetupURL(ctx) + + fmt.Println("Site Invitation secret token: " + setupURL) + + return &App{ + App: app, + Website: site, + Address: u, + Config: cfg, + }, nil +} diff --git a/backend/cmd/mintter-site/sites/sites.go b/backend/cmd/mintter-site/sites/sites.go new file mode 100644 index 0000000000..0793c36ce0 --- /dev/null +++ b/backend/cmd/mintter-site/sites/sites.go @@ -0,0 +1,351 @@ +// Package sites implements mintter-site server. +package sites + +import ( + "context" + "crypto/sha256" + "encoding/base64" + "errors" + "fmt" + "mintter/backend/cmd/mintter-site/sitesql" + "mintter/backend/daemon/storage" + groups "mintter/backend/genproto/groups/v1alpha" + "mintter/backend/hyper" + "mintter/backend/hyper/hypersql" + "mintter/backend/mttnet" + "mintter/backend/pkg/future" + "net/http" + "sync" + + "google.golang.org/grpc/codes" + rpcpeer "google.golang.org/grpc/peer" + "google.golang.org/grpc/status" + + "crawshaw.io/sqlite/sqlitex" + "github.com/ipfs/go-cid" + "github.com/libp2p/go-libp2p/core/peer" + "google.golang.org/protobuf/encoding/protojson" +) + +// Website is the gate to manipulate internal node structures +type Website struct { + // Network of the node. + node *future.ReadOnly[*mttnet.Node] + // db access to the node. + db *future.ReadOnly[*sqlitex.Pool] + // url is the protocol + hostname the group is being served at. + url string + + once sync.Once + setupSecret string +} + +var errNodeNotReadyYet = errors.New("P2P node is not ready yet") + +// NewServer creates a new server for the site. +func NewServer(url string, n *future.ReadOnly[*mttnet.Node], db *future.ReadOnly[*sqlitex.Pool]) *Website { + return &Website{ + node: n, + db: db, + url: url, + } +} +func (ws *Website) ServeHTTP(w http.ResponseWriter, _ *http.Request) { + w.Header().Set("Access-Control-Allow-Origin", "*") + w.Header().Set("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept") + w.Header().Set("Access-Control-Allow-Methods", "OPTIONS, GET") + siteInfo, err := ws.GetSiteInfo(context.Background(), &groups.GetSiteInfoRequest{}) + + if err != nil { + if errors.Is(err, errNodeNotReadyYet) { + w.Header().Set("Retry-After", "30") + http.Error(w, err.Error(), http.StatusServiceUnavailable) + } else { + http.Error(w, "Could not get site info: "+err.Error(), http.StatusInternalServerError) + } + return + } + + data, err := protojson.MarshalOptions{Indent: " ", EmitUnpopulated: true}.Marshal(siteInfo) + if err != nil { + http.Error(w, "Failed to marshal site info: "+err.Error(), http.StatusInternalServerError) + return + } + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + _, err = w.Write(data) + if err != nil { + return + } +} + +// GetSetupURL returns the secret URL to setup this site. +// We want to make the secret URL deterministic so that it persists across restarts. +// We could use a random string, but that would require persisting it in the database, +// which is not a problem, but seems unnecessary. +func (ws *Website) GetSetupURL(ctx context.Context) string { + return ws.url + "/secret-invite/" + ws.getSetupSecret(ctx) +} + +func (ws *Website) getSetupSecret(ctx context.Context) string { + ws.once.Do(func() { + node, err := ws.node.Await(ctx) + if err != nil { + panic(err) + } + + signature, err := node.ID().DeviceKey().Sign([]byte("hypermedia-site-setup-secret")) + if err != nil { + panic(err) + } + + sum := sha256.Sum256(signature) + + ws.setupSecret = base64.RawURLEncoding.EncodeToString(sum[:16]) + }) + + return ws.setupSecret +} + +// GetSiteInfo exposes the public information of a site. Which group is serving and how to reach the site via p2p. +func (ws *Website) GetSiteInfo(ctx context.Context, in *groups.GetSiteInfoRequest) (*groups.PublicSiteInfo, error) { + n, ok := ws.node.Get() + if !ok { + return nil, errNodeNotReadyYet + } + + db, err := ws.db.Await(ctx) + if err != nil { + return nil, err + } + + conn, release, err := db.Conn(ctx) + if err != nil { + return nil, fmt.Errorf("Failed to get db connection: %w", err) + } + defer release() + + gid, err := sitesql.GetServedGroupID(conn) + if err != nil { + return nil, fmt.Errorf("Failed to get group id from the db: %w", err) + } + + resp := &groups.PublicSiteInfo{ + PeerInfo: &groups.PeerInfo{}, + GroupId: gid.KVValue, + } + + for _, address := range n.AddrInfo().Addrs { + resp.PeerInfo.Addrs = append(resp.PeerInfo.Addrs, address.String()) + } + resp.PeerInfo.PeerId = n.ID().DeviceKey().PeerID().String() + resp.PeerInfo.AccountId = n.ID().Account().ID().String() + + groupID, err := sitesql.GetServedGroupID(conn) + if err != nil { + return nil, fmt.Errorf("Could not get group ID: %w", err) + } + if groupID.KVValue == "" { + // The site is not initialized yet + return resp, nil + } + + entity, err := n.Blobs().LoadEntity(ctx, hyper.EntityID(groupID.KVValue)) + if err != nil { + return nil, fmt.Errorf("could not get entity [%s]: %w", groupID.KVValue, err) + } + + if entity != nil { + resp.GroupVersion = entity.Version().String() + } + + return resp, nil +} + +// InitializeServer starts serving a group in this site. +func (ws *Website) InitializeServer(ctx context.Context, in *groups.InitializeServerRequest) (*groups.InitializeServerResponse, error) { + n, ok := ws.node.Get() + if !ok { + return nil, errNodeNotReadyYet + } + + gid, err := ws.GetGroupID(ctx) + if err != nil { + return nil, err + } + if gid != "" { + return nil, status.Errorf(codes.FailedPrecondition, "site is already initialized") + } + + link := ws.GetSetupURL(ctx) + if link != in.Secret { + return nil, status.Errorf(codes.PermissionDenied, "provided setup secret is not valid") + } + + remoteDeviceID, err := getRemoteID(ctx) + if err != nil { + return nil, fmt.Errorf("failed to extract peer ID from headers: %w", err) + } + + _, err = n.AccountForDevice(ctx, remoteDeviceID) + if err != nil { + return nil, fmt.Errorf("couldn't get account ID from device [%s]: %w", remoteDeviceID.String(), err) + } + + db, err := ws.db.Await(ctx) + if err != nil { + return nil, err + } + + conn, release, err := db.Conn(ctx) + if err != nil { + return nil, err + } + defer release() + + _, err = hypersql.EntitiesInsertOrIgnore(conn, in.GroupId) + if err != nil { + return nil, err + } + + if err := sitesql.SetServedGroupID(conn, in.GroupId); err != nil { + return nil, err + } + + return &groups.InitializeServerResponse{}, nil +} + +// GetGroupID returns the group ID this site is serving. +// It's empty if the site is not initialized yet. +func (ws *Website) GetGroupID(ctx context.Context) (string, error) { + db, err := ws.db.Await(ctx) + if err != nil { + return "", err + } + + conn, release, err := db.Conn(ctx) + if err != nil { + return "", fmt.Errorf("Failed to get db connection: %w", err) + } + defer release() + + dbgroup, err := sitesql.GetServedGroupID(conn) + if err != nil { + return "", err + } + + return dbgroup.KVValue, nil +} + +// PublishBlobs publish blobs to the website. +func (ws *Website) PublishBlobs(ctx context.Context, in *groups.PublishBlobsRequest) (*groups.PublishBlobsResponse, error) { + if len(in.Blobs) < 1 { + return nil, fmt.Errorf("Please, provide at least 1 blob to publish") + } + + n, ok := ws.node.Get() + if !ok { + return nil, errNodeNotReadyYet + } + + db, err := ws.db.Await(ctx) + if err != nil { + return nil, err + } + conn, release, err := db.Conn(ctx) + if err != nil { + return nil, fmt.Errorf("Failed to get db connection: %w", err) + } + defer release() + + // Get caller identity + info, ok := rpcpeer.FromContext(ctx) + if !ok { + return nil, fmt.Errorf("no peer info in context for grpc") + } + + pid, err := peer.Decode(info.Addr.String()) + if err != nil { + return nil, err + } + + authorAcc, err := n.AccountForDevice(ctx, pid) + if err != nil { + return nil, fmt.Errorf("couldn't get account ID from device [%s]: %w", pid.String(), err) + } + + // Get the owner's view of the list of members. + groupID, err := sitesql.GetServedGroupID(conn) + if err != nil || groupID.KVValue == "" { + return nil, fmt.Errorf("Error getting groupID on the site, is the site initialized?: %w", err) + } + + edb, err := hypersql.LookupEnsure(conn, storage.LookupResource, groupID.KVValue) + if err != nil { + return nil, fmt.Errorf("Could not get group (%s) resource: %w", groupID.KVValue, err) + } + + groupOwner, err := hypersql.ResourceGetOwner(conn, edb) + if err != nil { + return nil, fmt.Errorf("Could not get the owner of the group %s: %w", groupID.KVValue, err) + } + + pkdb, err := hypersql.LookupEnsure(conn, storage.LookupPublicKey, authorAcc) + if err != nil { + return nil, fmt.Errorf("couldn't get member entity for account [%s]: %w", authorAcc.String(), err) + } + + // See if the caller is in the owner's group + role, err := hypersql.GroupGetRole(conn, edb, groupOwner, pkdb) + if err != nil { + return nil, fmt.Errorf("Could not get role of member %s in group %s: %w", authorAcc.String(), groupID.KVValue, err) + } + + if role == int64(groups.Role_ROLE_UNSPECIFIED) { + return nil, status.Errorf(codes.PermissionDenied, "Caller [%s] does not have enough permissions to publish to this site.", authorAcc.String()) + } + + want := []cid.Cid{} + for _, cIDStr := range in.Blobs { + c, err := cid.Parse(cIDStr) + if err != nil { + return nil, fmt.Errorf("Could not parse provided blob [%s]: %w", cIDStr, err) + } + res, err := hypersql.BlobsHave(conn, c.Hash()) + if err != nil { + return nil, fmt.Errorf("Could not verify if we had blob [%s] or not: %w", c.String(), err) + } + if res.Have == 0 { + want = append(want, c) + } + } + ses := n.Bitswap().NewSession(ctx) + blkCh, err := ses.GetBlocks(ctx, want) + if err != nil { + return nil, fmt.Errorf("Could not get bitswap channel: %w", err) + } + for { + blk, ok := <-blkCh + if !ok { + return &groups.PublishBlobsResponse{}, nil + } + if err := n.Blobs().IPFSBlockstore().Put(ctx, blk); err != nil { + return nil, fmt.Errorf("Could not store block %s", blk.Cid().String()) + } + } +} + +// getRemoteID gets the remote peer id if there is an opened p2p connection between them with context ctx. +func getRemoteID(ctx context.Context) (peer.ID, error) { + info, ok := rpcpeer.FromContext(ctx) + if !ok { + return "", fmt.Errorf("BUG: no peer info in context for grpc") + } + + pid, err := peer.Decode(info.Addr.String()) + if err != nil { + return "", err + } + + return pid, nil +} diff --git a/backend/cmd/mintter-site/sites/sites_test.go b/backend/cmd/mintter-site/sites/sites_test.go new file mode 100644 index 0000000000..d1795de458 --- /dev/null +++ b/backend/cmd/mintter-site/sites/sites_test.go @@ -0,0 +1,99 @@ +package sites + +import ( + "context" + "errors" + "mintter/backend/config" + "mintter/backend/core/coretest" + "mintter/backend/daemon" + groups "mintter/backend/genproto/groups/v1alpha" + "mintter/backend/ipfs" + "mintter/backend/pkg/must" + "net" + "strconv" + "strings" + "testing" + + "github.com/stretchr/testify/require" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" +) + +func TestSiteInit(t *testing.T) { + t.Parallel() + + site := makeTestSite(t, "carol") + ctx := context.Background() + + // Check that we announce our hardcoded web address. + { + wantAnnounceAddrs := must.Do2(ipfs.ParseMultiaddrs(ipfs.DefaultListenAddrsDNS(site.Address.Hostname(), site.Config.P2P.Port))) + require.Equal(t, wantAnnounceAddrs, site.Config.P2P.AnnounceAddrs, "announce addrs don't match") + } + + // Check that our secret setup URL is on the correct domain. + require.True(t, strings.HasPrefix(site.Website.GetSetupURL(ctx), site.Address.String()), "init secret must have a prefix of the announce address") + + alice := daemon.MakeTestApp(t, "alice", daemon.MakeTestConfig(t), true) + + group, err := alice.RPC.Groups.CreateGroup(ctx, &groups.CreateGroupRequest{ + Title: "My test group", + SiteSetupUrl: site.Website.GetSetupURL(ctx), + }) + require.NoError(t, err) + + require.Equal(t, group.Id, must.Do2(site.Website.GetGroupID(ctx)), "site must serve the correct group ID") + + init, err := site.Website.InitializeServer(ctx, &groups.InitializeServerRequest{ + Secret: site.Website.GetSetupURL(ctx), + GroupId: "my-test-group", + }) + require.Nil(t, init) + require.Error(t, err, "subsequent init must fail") + require.Equal(t, codes.FailedPrecondition, status.Code(err), "subsequent init must fail with precondition error") +} + +func makeTestSite(t *testing.T, name string) *App { + ctx, cancel := context.WithCancel(context.Background()) + + user := coretest.NewTester(name) + + cfg := testConfig(t) + dir, err := daemon.InitRepo(cfg.Base.DataDir, user.Device.Wrapped()) + require.NoError(t, err) + + app, err := Load(ctx, "http://127.0.0.1:"+strconv.Itoa(cfg.HTTP.Port), cfg, dir) + require.NoError(t, err) + t.Cleanup(func() { + cancel() + err := app.Wait() + if err != nil { + require.True(t, errors.Is(err, context.Canceled), "unexpected app error: %v", err) + } + }) + + return app +} + +func testConfig(t *testing.T) config.Config { + dir := t.TempDir() + cfg := DefaultConfig() + cfg.Base.DataDir = dir + cfg.HTTP.Port = freePort(t) + cfg.GRPC.Port = 0 + cfg.P2P.Port = freePort(t) + cfg.P2P.BootstrapPeers = nil + cfg.P2P.NoMetrics = true + + return cfg +} + +func freePort(t *testing.T) int { + addr, err := net.ResolveTCPAddr("tcp", "localhost:0") + require.NoError(t, err) + + l, err := net.ListenTCP("tcp", addr) + require.NoError(t, err) + defer l.Close() + return l.Addr().(*net.TCPAddr).Port +} diff --git a/backend/mttnet/sitesql/BUILD.plz b/backend/cmd/mintter-site/sitesql/BUILD.plz similarity index 100% rename from backend/mttnet/sitesql/BUILD.plz rename to backend/cmd/mintter-site/sitesql/BUILD.plz diff --git a/backend/cmd/mintter-site/sitesql/queries.gen.go b/backend/cmd/mintter-site/sitesql/queries.gen.go new file mode 100644 index 0000000000..025300446b --- /dev/null +++ b/backend/cmd/mintter-site/sitesql/queries.gen.go @@ -0,0 +1,62 @@ +// Code generated by sqlitegen. DO NOT EDIT. + +package sitesql + +import ( + "errors" + "fmt" + + "crawshaw.io/sqlite" + "mintter/backend/pkg/sqlitegen" +) + +var _ = errors.New + +func SetServedGroupID(conn *sqlite.Conn, link string) error { + const query = `INSERT OR REPLACE INTO kv (key, value) +VALUES ('site_group_id', :link)` + + before := func(stmt *sqlite.Stmt) { + stmt.SetText(":link", link) + } + + 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: SetServedGroupID: %w", err) + } + + return err +} + +type GetServedGroupIDResult struct { + KVValue string +} + +func GetServedGroupID(conn *sqlite.Conn) (GetServedGroupIDResult, error) { + const query = `SELECT kv.value FROM kv WHERE kv.key ='site_group_id'` + + var out GetServedGroupIDResult + + before := func(stmt *sqlite.Stmt) { + } + + onStep := func(i int, stmt *sqlite.Stmt) error { + if i > 1 { + return errors.New("GetServedGroupID: more than one result return for a single-kind query") + } + + out.KVValue = stmt.ColumnText(0) + return nil + } + + err := sqlitegen.ExecStmt(conn, query, before, onStep) + if err != nil { + err = fmt.Errorf("failed query: GetServedGroupID: %w", err) + } + + return out, err +} diff --git a/backend/cmd/mintter-site/sitesql/queries.gensum b/backend/cmd/mintter-site/sitesql/queries.gensum new file mode 100644 index 0000000000..97e71c6456 --- /dev/null +++ b/backend/cmd/mintter-site/sitesql/queries.gensum @@ -0,0 +1,2 @@ +srcs: aa43be8cc99dd78bbf728cee50b0b5eb +outs: 8758b18717cb7ac28ae1bb1759ead80e diff --git a/backend/cmd/mintter-site/sitesql/queries.go b/backend/cmd/mintter-site/sitesql/queries.go new file mode 100644 index 0000000000..c0b7392a9a --- /dev/null +++ b/backend/cmd/mintter-site/sitesql/queries.go @@ -0,0 +1,49 @@ +// Package sitesql implements all the database related functions. +package sitesql + +import ( + s "mintter/backend/daemon/storage" + "mintter/backend/pkg/sqlitegen" + "mintter/backend/pkg/sqlitegen/qb" + "os" +) + +var _ = generateQueries + +const ( + // SiteRegistrationLinkKey is the column name of the meta table where we store the registration link. + SiteRegistrationLinkKey = "site_registration_link" + // SiteGroupIDKey is the group ID this site is serving. This is populated once the site is remotely initialized with the secret link. + SiteGroupIDKey = "site_group_id" + // SiteGroupVersionKey is the specific versiont of the group this site is serving. This may change through the life of the site as editors update it. + SiteGroupVersionKey = "site_group_version" +) + +//go:generate gorun -tags codegen generateQueries +func generateQueries() error { + code, err := sqlitegen.CodegenQueries("sitesql", + qb.MakeQuery(s.Schema, "SetServedGroupID", sqlitegen.QueryKindExec, + "INSERT OR REPLACE INTO", s.KV, qb.ListColShort( + s.KVKey, + s.KVValue, + ), '\n', + "VALUES", qb.List( + "'"+SiteGroupIDKey+"'", + qb.Var("link", sqlitegen.TypeText), + ), + ), + + qb.MakeQuery(s.Schema, "GetServedGroupID", sqlitegen.QueryKindSingle, + "SELECT", qb.Results( + qb.ResultCol(s.KVValue), + ), + "FROM", s.KV, + "WHERE", s.KVKey, "='"+SiteGroupIDKey+"'", + ), + ) + if err != nil { + return err + } + + return os.WriteFile("queries.gen.go", code, 0600) +} diff --git a/backend/cmd/mintter-site/sitesql/sitesql.go b/backend/cmd/mintter-site/sitesql/sitesql.go new file mode 100644 index 0000000000..25e26f91f1 --- /dev/null +++ b/backend/cmd/mintter-site/sitesql/sitesql.go @@ -0,0 +1,29 @@ +package sitesql + +import ( + "mintter/backend/hyper/hypersql" + + "crawshaw.io/sqlite" +) + +func ensurePublicKey(conn *sqlite.Conn, key []byte) (int64, error) { + res, err := hypersql.PublicKeysLookupID(conn, key) + if err != nil { + return 0, err + } + + if res.PublicKeysID > 0 { + return res.PublicKeysID, nil + } + + ins, err := hypersql.PublicKeysInsert(conn, key) + if err != nil { + return 0, err + } + + if ins.PublicKeysID <= 0 { + panic("BUG: failed to insert key for some reason") + } + + return ins.PublicKeysID, nil +} diff --git a/backend/cmd/mintterd/main.go b/backend/cmd/mintterd/main.go index 5624361efc..2122779a18 100644 --- a/backend/cmd/mintterd/main.go +++ b/backend/cmd/mintterd/main.go @@ -31,7 +31,7 @@ func main() { fs := flag.NewFlagSet("mintterd", flag.ExitOnError) cfg := config.Default() - config.SetupFlags(fs, &cfg) + cfg.BindFlags(fs) // We parse flags twice here, once without the config file setting, and then with it. // This is because we want the config file to be in the repo path, which can be changed @@ -42,11 +42,11 @@ func main() { return err } - if err := cfg.ExpandRepoPath(); err != nil { + if err := cfg.Base.ExpandDataDir(); err != nil { return err } - cfgFile, err := config.EnsureConfigFile(cfg.RepoPath) + cfgFile, err := config.EnsureConfigFile(cfg.Base.DataDir) if err != nil { return err } @@ -67,7 +67,11 @@ func main() { defer sentry.Flush(2 * time.Second) } - app, err := daemon.Load(ctx, cfg, + dir, err := daemon.InitRepo(cfg.Base.DataDir, nil) + if err != nil { + return err + } + app, err := daemon.Load(ctx, cfg, dir, grpc.ChainUnaryInterceptor( otelgrpc.UnaryServerInterceptor(), daemon.GRPCDebugLoggingInterceptor(), diff --git a/backend/cmd/minttergw/main.go b/backend/cmd/minttergw/main.go deleted file mode 100644 index 959372e867..0000000000 --- a/backend/cmd/minttergw/main.go +++ /dev/null @@ -1,126 +0,0 @@ -// Package main implements main script to run mintter-gateway daemon. -package main - -import ( - "context" - "errors" - "flag" - "fmt" - "os" - "strings" - - "mintter/backend/config" - "mintter/backend/core" - "mintter/backend/daemon" - accounts "mintter/backend/genproto/accounts/v1alpha" - protodaemon "mintter/backend/genproto/daemon/v1alpha" - - "google.golang.org/grpc" - "google.golang.org/grpc/codes" - "google.golang.org/grpc/status" - - "github.com/burdiyan/go/mainutil" - "github.com/peterbourgon/ff/v3" -) - -func main() { - const envVarPrefix = "MINTTER" - - mainutil.Run(func() error { - ctx := mainutil.TrapSignals() - - fs := flag.NewFlagSet("gateway", flag.ExitOnError) - - cfg := config.Default() - cfg.P2P.NoListing = true - config.SetupFlags(fs, &cfg) - - // We parse flags twice here, once without the config file setting, and then with it. - // This is because we want the config file to be in the repo path, which can be changed - // with flags or env vars. We don't allow setting a config file explicitly, but the repo path - // can change. We need to know the requested repo path in the first place, and then figure out the config file. - - if err := ff.Parse(fs, os.Args[1:], ff.WithEnvVarPrefix(envVarPrefix)); err != nil { - return err - } - - if err := cfg.ExpandRepoPath(); err != nil { - return err - } - - cfgFile, err := config.EnsureConfigFile(cfg.RepoPath) - if err != nil { - return err - } - - if err := ff.Parse(fs, os.Args[1:], - ff.WithEnvVarPrefix(envVarPrefix), - ff.WithConfigFileParser(ff.PlainParser), - ff.WithConfigFile(cfgFile), - ff.WithAllowMissingConfigFile(false), - ); err != nil { - return err - } - - app, err := daemon.Load(ctx, cfg, daemon.WithMiddleware(gwEssentials)) - if err != nil { - return err - } - - const mnemonicWords = 12 - mnemonic, err := core.NewBIP39Mnemonic(mnemonicWords) - if err != nil { - return err - } - - _, err = app.RPC.Daemon.Register(ctx, &protodaemon.RegisterRequest{ - Mnemonic: mnemonic, - Passphrase: "", - }) - stat, ok := status.FromError(err) - if !ok && stat.Code() != codes.AlreadyExists { - return err - } - - _, err = app.Storage.Identity().Await(ctx) - if err != nil { - return err - } - const alias = "Web gateway" - const bio = "Find me at https://www.mintter.com" - acc, err := app.RPC.Accounts.UpdateProfile(ctx, &accounts.Profile{ - Alias: alias, - Bio: bio, - }) - if err != nil { - return err - } - if acc.Profile.Alias != alias || acc.Profile.Bio != bio { - return fmt.Errorf("unexpected alias/bio. %s", acc.Profile.Alias+". "+acc.Profile.Bio) - } - err = app.Wait() - if errors.Is(err, context.Canceled) { - return nil - } - - return err - }) -} - -// GwEssentials is a middleware to restrict incoming grpc calls to bare minimum for the gateway to work. -func gwEssentials(ctx context.Context, - req interface{}, - info *grpc.UnaryServerInfo, - handler grpc.UnaryHandler) (interface{}, error) { - methodSplitted := strings.Split(info.FullMethod, "/") - if len(methodSplitted) < 2 || (strings.ToLower(methodSplitted[len(methodSplitted)-1]) != "getpublication" && - strings.ToLower(methodSplitted[len(methodSplitted)-1]) != "listcitations" && - strings.ToLower(methodSplitted[len(methodSplitted)-1]) != "getaccount") { - return nil, fmt.Errorf("method: %s not allowed", info.FullMethod) - } - - // Calls the handler - h, err := handler(ctx, req) - - return h, err -} diff --git a/backend/cmd/mkdb/main.go b/backend/cmd/mkdb/main.go new file mode 100644 index 0000000000..ef52fca3e5 --- /dev/null +++ b/backend/cmd/mkdb/main.go @@ -0,0 +1,64 @@ +// Program mkdb is supposed to be executed with `go run` from the root of the repository. +// It will create a (more or less) deterministic snapshot of the current schema of our database, +// which we can then use in tests to verify our migration scripts actually end up where we want them to. +package main + +import ( + "context" + "errors" + "fmt" + "mintter/backend/config" + "mintter/backend/core/coretest" + "mintter/backend/daemon" + "os" + + "github.com/burdiyan/go/mainutil" +) + +func main() { + mainutil.Run(run) +} + +func run() error { + ctx, cancel := context.WithCancel(mainutil.TrapSignals()) + defer cancel() + + alice := coretest.NewTester("alice") + + cfg := config.Default() + cfg.P2P.NoRelay = true + cfg.P2P.BootstrapPeers = nil + cfg.Base.DataDir = "/tmp/mintter-test-db-snapshot" + + if err := os.RemoveAll(cfg.Base.DataDir); err != nil { + return err + } + + if err := os.MkdirAll(cfg.Base.DataDir, 0750); err != nil { + return err + } + + dir, err := daemon.InitRepo(cfg.Base.DataDir, alice.Device.Wrapped()) + if err != nil { + return err + } + + app, err := daemon.Load(ctx, cfg, dir) + if err != nil { + return err + } + + if err := app.RPC.Daemon.RegisterAccount(ctx, alice.Account); err != nil { + return err + } + + cancel() + + err = app.Wait() + fmt.Println("Database has been saved in:", cfg.Base.DataDir) + if errors.Is(err, context.Canceled) { + return nil + } + + return err +} diff --git a/backend/cmd/monitord/server/checks.go b/backend/cmd/monitord/server/checks.go index d6fe7e577d..96fce51c95 100644 --- a/backend/cmd/monitord/server/checks.go +++ b/backend/cmd/monitord/server/checks.go @@ -4,17 +4,13 @@ package server import ( "context" "fmt" - "io" - documents "mintter/backend/genproto/documents/v1alpha" - "net/http" + groups "mintter/backend/daemon/api/groups/v1alpha" "time" - "mintter/backend/mttnet" - peer "github.com/libp2p/go-libp2p/core/peer" peerstore "github.com/libp2p/go-libp2p/core/peerstore" ping "github.com/libp2p/go-libp2p/p2p/protocol/ping" - "google.golang.org/protobuf/encoding/protojson" + "github.com/multiformats/go-multiaddr" ) func (s *Srv) checkP2P(ctx context.Context, peer peer.AddrInfo, numPings int) (time.Duration, error) { @@ -60,44 +56,28 @@ func (s *Srv) checkP2P(ctx context.Context, peer peer.AddrInfo, numPings int) (t } func (s *Srv) checkMintterAddrs(ctx context.Context, hostname, mustInclude string) (info peer.AddrInfo, err error) { - resp, err := s.getSiteInfoHTTP(ctx, hostname) - if err != nil { - return - } - info, err = mttnet.AddrInfoFromStrings(resp.Addresses[0]) // only TCP which is the first one + resp, err := groups.GetSiteInfoHTTP(ctx, nil, hostname) if err != nil { - return + return info, err } - return -} - -func (s *Srv) getSiteInfoHTTP(ctx context.Context, SiteHostname string) (*documents.SiteDiscoveryConfig, error) { - requestURL := fmt.Sprintf("%s/%s", SiteHostname, mttnet.WellKnownPath) - - req, err := http.NewRequestWithContext(ctx, http.MethodGet, requestURL, nil) - if err != nil { - return nil, fmt.Errorf("could not create request to well-known site: %w ", err) + if resp.PeerInfo == nil { + return info, fmt.Errorf("no peer info got from site") } - res, err := http.DefaultClient.Do(req) + pid, err := peer.Decode(resp.PeerInfo.PeerId) if err != nil { - return nil, fmt.Errorf("could not contact to provided site [%s]: %w ", requestURL, err) - } - defer res.Body.Close() - if res.StatusCode < 200 || res.StatusCode > 299 { - return nil, fmt.Errorf("site info url [%s] not working. Status code: %d", requestURL, res.StatusCode) + return info, fmt.Errorf("failed to decode peer ID %s: %w", resp.PeerInfo.PeerId, err) } - data, err := io.ReadAll(res.Body) - if err != nil { - return nil, fmt.Errorf("failed to read json body: %w", err) + info.ID = pid + info.Addrs = make([]multiaddr.Multiaddr, len(resp.PeerInfo.Addrs)) + for i, as := range resp.PeerInfo.Addrs { + info.Addrs[i], err = multiaddr.NewMultiaddr(as) + if err != nil { + return info, err + } } - var resp documents.SiteDiscoveryConfig - - if err := protojson.Unmarshal(data, &resp); err != nil { - return nil, fmt.Errorf("failed to unmarshal JSON body: %w", err) - } - return &resp, nil + return info, nil } diff --git a/backend/config/config.go b/backend/config/config.go index 5d66e6f953..01d484f9a0 100644 --- a/backend/config/config.go +++ b/backend/config/config.go @@ -4,7 +4,6 @@ package config import ( "flag" "fmt" - "io/ioutil" "mintter/backend/ipfs" "os" "path/filepath" @@ -14,50 +13,83 @@ import ( "github.com/multiformats/go-multiaddr" ) -// Config for Mintter daemon. When adding or removing fields, -// adjust the DefaultConfig() and SetupFlags() accordingly. -type Config struct { - HTTPPort int - GRPCPort int - RepoPath string +// Base configuration. +type Base struct { + DataDir string LogLevel string +} - Identity Identity - Lndhub Lndhub - P2P P2P - Site Site - Syncing Syncing +// BindFlags binds the flags to the given FlagSet. +func (c *Base) BindFlags(fs *flag.FlagSet) { + fs.StringVar(&c.DataDir, "data-dir", c.DataDir, "Path to a directory where to store node data") + fs.StringVar(&c.LogLevel, "log-level", c.LogLevel, "Log verbosity debug | info | warning | error") +} + +// ExpandDataDir is used to expand the home directory in the data directory path. +func (c *Base) ExpandDataDir() error { + // We allow homedir expansion in the repo path. + if strings.HasPrefix(c.DataDir, "~") { + homedir, err := os.UserHomeDir() + if err != nil { + return fmt.Errorf("failed to detect home directory: %w", err) + } + c.DataDir = strings.Replace(c.DataDir, "~", homedir, 1) + } + return nil +} + +// Config for our daemon. When adding or removing fields, +// adjust the Default() and BindFlags() accordingly. +type Config struct { + Base + + HTTP HTTP + GRPC GRPC + Lndhub Lndhub + P2P P2P + Syncing Syncing +} + +// BindFlags configures the given FlagSet with the existing values from the given Config +// and prepares the FlagSet to parse the flags into the Config. +// +// This function is assumed to be called after some default values were set on the given config. +// These values will be used as default values in flags. +// See Default() for the default config values. +func (c *Config) BindFlags(fs *flag.FlagSet) { + c.Base.BindFlags(fs) + c.HTTP.BindFlags(fs) + c.GRPC.BindFlags(fs) + c.Lndhub.BindFlags(fs) + c.P2P.BindFlags(fs) + c.Syncing.BindFlags(fs) } // Default creates a new default config. func Default() Config { return Config{ - HTTPPort: 55001, - GRPCPort: 55002, - RepoPath: "~/.mtt", - LogLevel: "debug", + HTTP: HTTP{ + Port: 55001, + }, + GRPC: GRPC{ + Port: 55002, + }, + Base: Base{ + DataDir: "~/.mtt", + LogLevel: "debug", + }, Lndhub: Lndhub{ Mainnet: false, }, - - Identity: Identity{ - DeviceKeyPath: "", - NoAccountWait: false, - }, - P2P: P2P{ BootstrapPeers: ipfs.DefaultBootstrapPeers(), Port: 55000, RelayBackoff: time.Minute * 3, }, - Site: Site{ - InviteTokenExpirationDelay: time.Hour * 24 * 7, - }, Syncing: Syncing{ WarmupDuration: time.Second * 20, Interval: time.Minute, TimeoutPerPeer: time.Minute * 2, - NoInbound: false, }, } } @@ -105,63 +137,23 @@ func newAddrsFlag(val []multiaddr.Multiaddr, p *[]multiaddr.Multiaddr) flag.Valu return (*addrsFlag)(p) } -// SetupFlags configures the given FlagSet with the existing values from the given Config -// and prepares the FlagSet to parse the flags into the Config. -// -// This function is assumed to be called after some default values were set on the given config. -// These values will be used as default values in flags. -// See Default() for the default config values. -func SetupFlags(fs *flag.FlagSet, cfg *Config) { - fs.IntVar(&cfg.HTTPPort, "http-port", cfg.HTTPPort, "Port to expose HTTP Server (including grpc-web)") - fs.IntVar(&cfg.GRPCPort, "grpc-port", cfg.GRPCPort, "Port to expose gRPC server") - fs.StringVar(&cfg.RepoPath, "repo-path", cfg.RepoPath, "Path to where to store node data") - fs.StringVar(&cfg.LogLevel, "log-level", cfg.LogLevel, "Log verbosity debug | info | warning | error") - - fs.StringVar(&cfg.Identity.DeviceKeyPath, "identity.devicekey-path", cfg.Identity.DeviceKeyPath, "Path to to read fixed device private key from") - fs.BoolVar(&cfg.Identity.NoAccountWait, "identity.no-account-wait", cfg.Identity.NoAccountWait, "If set, the daemon auto generates a random Account ID (if not found any in the database) and starts right away") - - fs.BoolVar(&cfg.Lndhub.Mainnet, "lndhub.mainnet", cfg.Lndhub.Mainnet, "Connect to the mainnet lndhub.go server") - - fs.IntVar(&cfg.P2P.Port, "p2p.port", cfg.P2P.Port, "Port to listen for incoming P2P connections") - fs.BoolVar(&cfg.P2P.NoRelay, "p2p.no-relay", cfg.P2P.NoRelay, "Disable libp2p circuit relay") - fs.Var(newAddrsFlag(cfg.P2P.BootstrapPeers, &cfg.P2P.BootstrapPeers), "p2p.bootstrap-peers", "Addresses for bootstrap nodes (comma separated)") - fs.Var(newAddrsFlag(cfg.P2P.AnnounceAddrs, &cfg.P2P.AnnounceAddrs), "p2p.announce-addrs", "Addresses will be announced for this node to be reachable at (comma separated multiaddresses format). overrides no-private-ips") - fs.BoolVar(&cfg.P2P.PublicReachability, "p2p.public-reachability", cfg.P2P.PublicReachability, "Force Reachability to public.") - fs.Var(newAddrsFlag(cfg.P2P.ListenAddrs, &cfg.P2P.ListenAddrs), "p2p.listen-addrs", "Addresses to be listen at (comma separated multiaddresses format)") - fs.BoolVar(&cfg.P2P.NoPrivateIps, "p2p.no-private-ips", cfg.P2P.NoPrivateIps, "Not announce local IPs.") - fs.BoolVar(&cfg.P2P.NoListing, "p2p.disable-listing", cfg.P2P.NoListing, "Disable listing documents when requested (stealth mode)") - fs.BoolVar(&cfg.P2P.NoMetrics, "p2p.no-metrics", cfg.P2P.NoMetrics, "Disable Prometheus metrics collection") - fs.DurationVar(&cfg.P2P.RelayBackoff, "p2p.relay-backoff", cfg.P2P.RelayBackoff, "The time the autorelay waits to reconnect after failing to obtain a reservation with a candidate") - - fs.BoolVar(&cfg.Site.NoAuth, "site.no-auth", cfg.Site.NoAuth, "Disable site authentication") - fs.StringVar(&cfg.Site.Hostname, "site.hostname", cfg.Site.Hostname, "Hostname of the site. If not provided then the daemon does not work as a site") - fs.StringVar(&cfg.Site.Title, "site.title", cfg.Site.Title, "Title of the site. Something brief and human readable to help understand the site") - fs.StringVar(&cfg.Site.OwnerID, "site.owner-id", cfg.Site.OwnerID, "Account ID of the owner of this site. If not provided, the owner ID will be this node's account ID") - fs.DurationVar(&cfg.Site.InviteTokenExpirationDelay, "site.token-expiration-delay", cfg.Site.InviteTokenExpirationDelay, "The expiration time delay when creating a new invite token") - - fs.DurationVar(&cfg.Syncing.WarmupDuration, "syncing.warmup-duration", cfg.Syncing.WarmupDuration, "Time to wait before the first sync loop iteration") - fs.DurationVar(&cfg.Syncing.Interval, "syncing.interval", cfg.Syncing.Interval, "Periodic interval at which sync loop is triggered") - fs.DurationVar(&cfg.Syncing.TimeoutPerPeer, "syncing.timeout-per-peer", cfg.Syncing.TimeoutPerPeer, "Maximum duration for syncing with a single peer") - fs.BoolVar(&cfg.Syncing.NoInbound, "syncing.disable-inbound", cfg.Syncing.NoInbound, "Not syncing inbound content via P2P, only syncs to remote peers. IF this is a site, however still admits content when published") -} - -// ExpandRepoPath is used to expand the home directory in the repo path. -func (c *Config) ExpandRepoPath() error { - // We allow homedir expansion in the repo path. - if strings.HasPrefix(c.RepoPath, "~") { - homedir, err := os.UserHomeDir() - if err != nil { - return fmt.Errorf("failed to detect home directory: %w", err) - } - c.RepoPath = strings.Replace(c.RepoPath, "~", homedir, 1) - } - return nil +// HTTP configuration. +type HTTP struct { + Port int +} + +// BindFlags binds the flags to the given FlagSet. +func (c *HTTP) BindFlags(fs *flag.FlagSet) { + fs.IntVar(&c.Port, "http.port", c.Port, "Port for the HTTP server (including grpc-web)") } -// Identity related config. For field descriptions see SetupFlags(). -type Identity struct { - DeviceKeyPath string - NoAccountWait bool +// GRPC configuration. +type GRPC struct { + Port int +} + +func (c *GRPC) BindFlags(fs *flag.FlagSet) { + fs.IntVar(&c.Port, "grpc.port", c.Port, "Port for the gRPC server") } // Lndhub related config. For field descriptions see SetupFlags(). @@ -169,38 +161,51 @@ type Lndhub struct { Mainnet bool } -// Syncing related config. For field descriptions see SetupFlags(). +// BindFlags binds the flags to the given FlagSet. +func (c *Lndhub) BindFlags(fs *flag.FlagSet) { + fs.BoolVar(&c.Mainnet, "lndhub.mainnet", c.Mainnet, "Connect to the mainnet lndhub.go server") +} + +// Syncing configuration. For field descriptions see SetupFlags(). type Syncing struct { WarmupDuration time.Duration Interval time.Duration TimeoutPerPeer time.Duration - // NoInbound disables syncing content to the remote peer from our peer. - // If false, then documents get synced in both directions. - NoInbound bool + Disabled bool } -// Site configuration. In case the daemon is deployed in a site. -// For field descriptions see SetupFlags(). -type Site struct { - Hostname string - InviteTokenExpirationDelay time.Duration - OwnerID string - Title string - NoAuth bool +// BindFlags binds the flags to the given FlagSet. +func (c *Syncing) BindFlags(fs *flag.FlagSet) { + fs.DurationVar(&c.WarmupDuration, "syncing.warmup-duration", c.WarmupDuration, "Time to wait before the first sync loop iteration") + fs.DurationVar(&c.Interval, "syncing.interval", c.Interval, "Periodic interval at which sync loop is triggered") + fs.DurationVar(&c.TimeoutPerPeer, "syncing.timeout-per-peer", c.TimeoutPerPeer, "Maximum duration for syncing with a single peer") + fs.BoolVar(&c.Disabled, "syncing.disabled", c.Disabled, "Disables periodic syncing") } // P2P configuration. For field descriptions see SetupFlags(). type P2P struct { - Port int - NoRelay bool - BootstrapPeers []multiaddr.Multiaddr - PublicReachability bool - NoPrivateIps bool - NoListing bool - NoMetrics bool - RelayBackoff time.Duration - AnnounceAddrs []multiaddr.Multiaddr - ListenAddrs []multiaddr.Multiaddr + Port int + NoRelay bool + BootstrapPeers []multiaddr.Multiaddr + ForceReachabilityPublic bool + NoPrivateIps bool + NoMetrics bool + RelayBackoff time.Duration + AnnounceAddrs []multiaddr.Multiaddr + ListenAddrs []multiaddr.Multiaddr +} + +// BindFlags binds the flags to the given FlagSet. +func (p2p *P2P) BindFlags(fs *flag.FlagSet) { + fs.IntVar(&p2p.Port, "p2p.port", p2p.Port, "Port to listen for incoming P2P connections") + fs.BoolVar(&p2p.NoRelay, "p2p.no-relay", p2p.NoRelay, "Disable libp2p circuit relay") + fs.Var(newAddrsFlag(p2p.BootstrapPeers, &p2p.BootstrapPeers), "p2p.bootstrap-peers", "Multiaddrs for bootstrap nodes (comma separated)") + fs.Var(newAddrsFlag(p2p.AnnounceAddrs, &p2p.AnnounceAddrs), "p2p.announce-addrs", "Multiaddrs this node will announce as being reachable at (comma separated)") + fs.BoolVar(&p2p.ForceReachabilityPublic, "p2p.force-reachability-public", p2p.ForceReachabilityPublic, "Force the node into thinking it's publicly reachable") + fs.Var(newAddrsFlag(p2p.ListenAddrs, &p2p.ListenAddrs), "p2p.listen-addrs", "Addresses to be listen at (comma separated multiaddresses format)") + fs.BoolVar(&p2p.NoPrivateIps, "p2p.no-private-ips", p2p.NoPrivateIps, "Avoid announcing private IP addresses (ignored when using -p2p.announce-addrs)") + fs.BoolVar(&p2p.NoMetrics, "p2p.no-metrics", p2p.NoMetrics, "Disable Prometheus metrics collection") + fs.DurationVar(&p2p.RelayBackoff, "p2p.relay-backoff", p2p.RelayBackoff, "The time the autorelay waits to reconnect after failing to obtain a reservation with a candidate") } // NoBootstrap indicates whether bootstrap nodes are configured. @@ -226,7 +231,7 @@ func EnsureConfigFile(repoPath string) (filename string, err error) { } if os.IsNotExist(err) { - if err := ioutil.WriteFile(filename, []byte(`# Config file for the mintterd program. + if err := os.WriteFile(filename, []byte(`# Config file for the mintterd program. # You can set any CLI flags here, one per line with a space between key and value. `), 0600); err != nil { return "", err diff --git a/backend/core/coretest/coretest.go b/backend/core/coretest/coretest.go index f28e162d81..66204eb2cc 100644 --- a/backend/core/coretest/coretest.go +++ b/backend/core/coretest/coretest.go @@ -53,7 +53,7 @@ func NewTester(name string) Tester { panic(err) } - dev, err := core.NewKeyPair(core.CodecDeviceKey, dpriv.(*crypto.Ed25519PrivateKey)) + dev, err := core.NewKeyPair(dpriv.(*crypto.Ed25519PrivateKey)) if err != nil { panic(err) } @@ -63,7 +63,7 @@ func NewTester(name string) Tester { panic(err) } - acc, err := core.NewKeyPair(core.CodecAccountKey, apriv.(*crypto.Ed25519PrivateKey)) + acc, err := core.NewKeyPair(apriv.(*crypto.Ed25519PrivateKey)) if err != nil { panic(err) } diff --git a/backend/core/coretest/coretest_test.go b/backend/core/coretest/coretest_test.go index 9974d22668..f025bfaa1e 100644 --- a/backend/core/coretest/coretest_test.go +++ b/backend/core/coretest/coretest_test.go @@ -15,7 +15,6 @@ func TestKeys(t *testing.T) { require.NoError(t, err) require.True(t, alice.Device.ID() == pid) - require.True(t, alice.Device.CID().Equals(peer.ToCid(pid))) } func TestEncoding(t *testing.T) { @@ -24,7 +23,7 @@ func TestEncoding(t *testing.T) { data, err := alice.Account.MarshalBinary() require.NoError(t, err) - pk, err := core.ParsePublicKey(core.CodecAccountKey, data) + pk, err := core.ParsePublicKey(data) require.NoError(t, err) require.Equal(t, alice.Account.String(), pk.String()) } diff --git a/backend/core/crypto.go b/backend/core/crypto.go index 6f1323de79..31e847f4e9 100644 --- a/backend/core/crypto.go +++ b/backend/core/crypto.go @@ -11,14 +11,6 @@ import ( "github.com/ipfs/go-cid" "github.com/libp2p/go-libp2p/core/crypto" "github.com/libp2p/go-libp2p/core/peer" - "github.com/multiformats/go-multihash" -) - -// Multicodecs. -const ( - CodecDeviceKey = cid.Libp2pKey - // TODO: need to register this codec withing the multicodecs repo table. - CodecAccountKey = 1091161161 ) // Ensure interface implementations. @@ -72,15 +64,14 @@ type KeyID = peer.ID // PublicKey is the public part of a KeyPair. type PublicKey struct { - k crypto.PubKey - id KeyID - codec uint64 + k crypto.PubKey + id KeyID abbrev uint64 } // NewPublicKey creates a new public key from an existing Ed25519 public key. -func NewPublicKey(codec uint64, pub crypto.PubKey) (pk PublicKey, err error) { +func NewPublicKey(pub crypto.PubKey) (pk PublicKey, err error) { _, ok := pub.(*crypto.Ed25519PublicKey) if !ok { return pk, fmt.Errorf("only Ed25519 public keys are supported, but got %T", pub) @@ -104,7 +95,6 @@ func NewPublicKey(codec uint64, pub crypto.PubKey) (pk PublicKey, err error) { return PublicKey{ k: pub, id: pid, - codec: codec, abbrev: *(*uint64)(unsafe.Pointer(&b)), }, nil } @@ -122,11 +112,11 @@ func PublicKeyFromCID(c cid.Cid) (pk PublicKey, err error) { return pk, err } - return NewPublicKey(c.Prefix().Codec, pub.(*crypto.Ed25519PublicKey)) + return NewPublicKey(pub.(*crypto.Ed25519PublicKey)) } // ParsePublicKey parses existing libp2p-encoded key material. -func ParsePublicKey(codec uint64, data []byte) (pk PublicKey, err error) { +func ParsePublicKey(data []byte) (pk PublicKey, err error) { pub, err := crypto.UnmarshalPublicKey(data) if err != nil { return pk, err @@ -136,7 +126,7 @@ func ParsePublicKey(codec uint64, data []byte) (pk PublicKey, err error) { return pk, fmt.Errorf("only ed25519 keys are supported") } - return NewPublicKey(codec, pub.(*crypto.Ed25519PublicKey)) + return NewPublicKey(pub.(*crypto.Ed25519PublicKey)) } // Abbrev returns the abbreviated form of the public key, @@ -152,16 +142,6 @@ func (pk PublicKey) PeerID() peer.ID { return pk.id } -// CID returns CID representation of the public key. -func (pk PublicKey) CID() cid.Cid { - mh, err := multihash.Cast([]byte(pk.id)) - if err != nil { - panic(err) - } - - return cid.NewCidV1(pk.codec, mh) -} - // String creates string representation of the public key. func (pk PublicKey) String() string { return pk.Principal().String() @@ -172,11 +152,6 @@ func (pk PublicKey) Principal() Principal { return PrincipalFromPubKey(pk.k) } -// Codec returns multicodec of the public key. -func (pk PublicKey) Codec() uint64 { - return pk.codec -} - // Verify implements Verifier. func (pk PublicKey) Verify(data []byte, s Signature) error { return s.verify(pk.k, data) @@ -205,24 +180,24 @@ type KeyPair struct { } // NewKeyPairRandom creates a new random KeyPair with a given multicodec prefix. -func NewKeyPairRandom(codec uint64) (kp KeyPair, err error) { +func NewKeyPairRandom() (kp KeyPair, err error) { priv, _, err := crypto.GenerateEd25519Key(rand.Reader) if err != nil { return kp, fmt.Errorf("failed to generate device private key: %w", err) } - return NewKeyPair(codec, priv.(*crypto.Ed25519PrivateKey)) + return NewKeyPair(priv.(*crypto.Ed25519PrivateKey)) } // NewKeyPair creates a new KeyPair with a given multicodec prefix from an existing instance // of the private key. At the moment only Ed25519 keys are supported. -func NewKeyPair(codec uint64, priv crypto.PrivKey) (kp KeyPair, err error) { +func NewKeyPair(priv crypto.PrivKey) (kp KeyPair, err error) { _, ok := priv.(*crypto.Ed25519PrivateKey) if !ok { return kp, fmt.Errorf("only ed25519 keys are supported") } - pub, err := NewPublicKey(codec, priv.GetPublic().(*crypto.Ed25519PublicKey)) + pub, err := NewPublicKey(priv.GetPublic().(*crypto.Ed25519PublicKey)) if err != nil { return kp, err } diff --git a/backend/core/identity.go b/backend/core/identity.go index 16bfaaa6ca..297807e26b 100644 --- a/backend/core/identity.go +++ b/backend/core/identity.go @@ -16,14 +16,6 @@ type Identity struct { } func NewIdentity(account PublicKey, device KeyPair) Identity { - if account.Codec() != CodecAccountKey { - panic("not account key") - } - - if device.Codec() != CodecDeviceKey { - panic("not device key") - } - return Identity{ account: account, device: device, @@ -69,7 +61,7 @@ func AccountFromSeed(rand []byte) (KeyPair, error) { return KeyPair{}, err } - return NewKeyPair(CodecAccountKey, priv.(*crypto.Ed25519PrivateKey)) + return NewKeyPair(priv.(*crypto.Ed25519PrivateKey)) } // NewBIP39Mnemonic creates a new random BIP-39 compatible mnemonic words. diff --git a/backend/daemon/api/accounts/v1alpha/accounts.go b/backend/daemon/api/accounts/v1alpha/accounts.go index 5df2344053..e2e8466f30 100644 --- a/backend/daemon/api/accounts/v1alpha/accounts.go +++ b/backend/daemon/api/accounts/v1alpha/accounts.go @@ -10,6 +10,7 @@ import ( "mintter/backend/hyper" "mintter/backend/hyper/hypersql" "mintter/backend/pkg/future" + "strings" "crawshaw.io/sqlite" "github.com/ipfs/go-cid" @@ -193,6 +194,14 @@ func UpdateProfile(ctx context.Context, me core.Identity, blobs *hyper.Storage, patch := map[string]any{} + if in.Alias != "" { + parts := strings.Fields(in.Alias) + if len(parts) != 1 { + return fmt.Errorf("alias must be a single word: got = %q", in.Alias) + } + in.Alias = parts[0] + } + v, ok := e.Get("alias") if (ok && v.(string) != in.Alias) || (!ok && in.Alias != "") { patch["alias"] = in.Alias diff --git a/backend/daemon/api/apis.go b/backend/daemon/api/apis.go index f87348b8cc..f029816098 100644 --- a/backend/daemon/api/apis.go +++ b/backend/daemon/api/apis.go @@ -3,7 +3,6 @@ package api import ( "context" "fmt" - "mintter/backend/config" accounts "mintter/backend/daemon/api/accounts/v1alpha" daemon "mintter/backend/daemon/api/daemon/v1alpha" documents "mintter/backend/daemon/api/documents/v1alpha" @@ -28,7 +27,6 @@ type Server struct { Daemon *daemon.Server Documents *documents.Server Networking *networking.Server - Site *mttnet.Server Entities *entities.Server Groups *groups.Server } @@ -42,7 +40,6 @@ func New( node *future.ReadOnly[*mttnet.Node], sync *future.ReadOnly[*syncing.Service], wallet *wallet.Service, - cfg config.Site, ) Server { doSync := func() error { s, ok := sync.Get() @@ -59,17 +56,14 @@ func New( return nil } - documentsSrv := documents.NewServer(repo.Identity(), db, &lazyDiscoverer{sync: sync, net: node}, nil) - siteSrv := mttnet.NewServer(ctx, cfg, node, documentsSrv, &lazyDiscoverer{sync: sync}) - documentsSrv.RemoteCaller = siteSrv + documentsSrv := documents.NewServer(repo.Identity(), db, &lazyDiscoverer{sync: sync, net: node}) return Server{ Accounts: accounts.NewServer(repo.Identity(), blobs), Daemon: daemon.NewServer(repo, blobs, wallet, doSync), Documents: documentsSrv, Networking: networking.NewServer(node), - Site: siteSrv, Entities: entities.NewServer(blobs, &lazyDiscoverer{sync: sync}), - Groups: groups.NewServer(repo.Identity(), blobs, node), + Groups: groups.NewServer(repo.Identity(), groups.NewSQLiteDB(db), blobs, node), } } diff --git a/backend/daemon/api/daemon/v1alpha/daemon.go b/backend/daemon/api/daemon/v1alpha/daemon.go index fdde4e210b..7d16cbcda1 100644 --- a/backend/daemon/api/daemon/v1alpha/daemon.go +++ b/backend/daemon/api/daemon/v1alpha/daemon.go @@ -92,11 +92,7 @@ func (srv *Server) Register(ctx context.Context, req *daemon.RegisterRequest) (* // RegisterAccount performs registration given an existing account key pair. func (srv *Server) RegisterAccount(ctx context.Context, acc core.KeyPair) error { - if err := srv.repo.CommitAccount(acc.PublicKey); err != nil { - return err - } - - _, err := Register(ctx, srv.blobs, acc, srv.repo.Device().PublicKey, time.Now().UTC()) + _, err := RegisterWithRepo(ctx, srv.repo, srv.blobs, acc, srv.repo.Device().PublicKey, time.Now().UTC()) if err != nil { return err } @@ -108,6 +104,15 @@ func (srv *Server) RegisterAccount(ctx context.Context, acc core.KeyPair) error return nil } +// RegisterWithRepo creates key delegation from account to device and stores the keys in files. +func RegisterWithRepo(ctx context.Context, repo Repo, bs *hyper.Storage, acc core.KeyPair, device core.PublicKey, at time.Time) (cid.Cid, error) { + if err := repo.CommitAccount(acc.PublicKey); err != nil { + return cid.Undef, err + } + + return Register(ctx, bs, acc, device, at) +} + // Register creates key delegation from account to device. func Register(ctx context.Context, bs *hyper.Storage, account core.KeyPair, device core.PublicKey, at time.Time) (cid.Cid, error) { kd, err := hyper.NewKeyDelegation(account, device, time.Now().UTC()) diff --git a/backend/daemon/api/documents/v1alpha/document_model.go b/backend/daemon/api/documents/v1alpha/document_model.go index 1aeddf6131..7dad4f1a4c 100644 --- a/backend/daemon/api/documents/v1alpha/document_model.go +++ b/backend/daemon/api/documents/v1alpha/document_model.go @@ -167,16 +167,6 @@ func (dm *docModel) SetTitle(title string) error { return nil } -func (dm *docModel) SetWebURL(url string) error { - v, ok := dm.e.Get("webURL") - if ok && v.(string) == url { - return nil - } - - dm.patch["webURL"] = url - return nil -} - func (dm *docModel) DeleteBlock(block string) error { _, err := dm.tree.MoveLocal(dm.nextHLC.Pack(), len(dm.tree.localMoves), block, TrashNodeID, "") return err @@ -341,13 +331,6 @@ func (dm *docModel) hydrate(ctx context.Context, blobs *hyper.Storage) (*documen } } - { - v, ok := e.Get("webURL") - if ok { - docpb.WebUrl = v.(string) - } - } - // Loading editors is a bit cumbersome because we need to go over key delegations. { seenAccounts := map[string]struct{}{} diff --git a/backend/daemon/api/documents/v1alpha/documents.go b/backend/daemon/api/documents/v1alpha/documents.go index d031940437..a57d720323 100644 --- a/backend/daemon/api/documents/v1alpha/documents.go +++ b/backend/daemon/api/documents/v1alpha/documents.go @@ -32,30 +32,21 @@ type Discoverer interface { Connect(context.Context, peer.AddrInfo) error } -// RemoteCaller is an interface for not having to pass a full-fledged sites service, -// just the remote functions that need to be called from the local server. -type RemoteCaller interface { - RedeemInviteToken(context.Context, *documents.RedeemInviteTokenRequest) (*documents.RedeemInviteTokenResponse, error) - ListWebPublications(ctx context.Context, in *documents.ListWebPublicationsRequest) (*documents.ListWebPublicationsResponse, error) -} - // Server implements DocumentsServer gRPC API. type Server struct { - db *sqlitex.Pool - me *future.ReadOnly[core.Identity] - disc Discoverer - RemoteCaller RemoteCaller - blobs *hyper.Storage + db *sqlitex.Pool + me *future.ReadOnly[core.Identity] + disc Discoverer + blobs *hyper.Storage } // NewServer creates a new RPC handler. -func NewServer(me *future.ReadOnly[core.Identity], db *sqlitex.Pool, disc Discoverer, remoteCaller RemoteCaller) *Server { +func NewServer(me *future.ReadOnly[core.Identity], db *sqlitex.Pool, disc Discoverer) *Server { srv := &Server{ - db: db, - me: me, - disc: disc, - RemoteCaller: remoteCaller, - blobs: hyper.NewStorage(db, logging.New("mintter/hyper", "debug")), + db: db, + me: me, + disc: disc, + blobs: hyper.NewStorage(db, logging.New("mintter/hyper", "debug")), } return srv @@ -202,10 +193,6 @@ func (api *Server) UpdateDraft(ctx context.Context, in *documents.UpdateDraftReq if err := mut.ReplaceBlock(o.ReplaceBlock); err != nil { return nil, err } - case *documents.DocumentChange_SetWebUrl: - if err := mut.SetWebURL(o.SetWebUrl); err != nil { - return nil, err - } default: panic("BUG: unhandled document change") } @@ -355,6 +342,14 @@ func (api *Server) GetPublication(ctx context.Context, in *documents.GetPublicat return nil, err } + // TODO(burdiyan): if we are doing the discovery without a version, + // we'll wait until timeout because we don't know when to stop looking. + // Ideally we should only be discovering docs with specific version, + // but sometimes we don't want the latest version we can possibly find. + // In those cases, we could at least optimize the UI, and maybe display + // the document dynamically as we're finding it. Although that would require + // a lot of trickery between frontend and backend, it would optimize + // time to the first (more or less) meaningful result. if err := api.disc.DiscoverObject(ctx, eid, version); err != nil { return nil, status.Errorf(codes.NotFound, "failed to discover object %q at version %q", eid, version) } diff --git a/backend/daemon/api/documents/v1alpha/documents_test.go b/backend/daemon/api/documents/v1alpha/documents_test.go index 1e430abb5f..09e55576a7 100644 --- a/backend/daemon/api/documents/v1alpha/documents_test.go +++ b/backend/daemon/api/documents/v1alpha/documents_test.go @@ -89,7 +89,6 @@ func TestUpdateDraft_SimpleAttributes(t *testing.T) { require.Greater(t, draft.UpdateTime.AsTime().UnixMicro(), draft.CreateTime.AsTime().UnixMicro()) updated := updateDraft(ctx, t, api, draft.Id, []*documents.DocumentChange{ {Op: &documents.DocumentChange_SetTitle{SetTitle: "My new document title"}}, - {Op: &documents.DocumentChange_SetWebUrl{SetWebUrl: "https://example.com"}}, }) require.Equal(t, draft.CreateTime, updated.CreateTime) @@ -100,7 +99,6 @@ func TestUpdateDraft_SimpleAttributes(t *testing.T) { testutil.ProtoEqual(t, updated, got, "must get draft that was updated") require.Equal(t, "My new document title", got.Title) - require.Equal(t, "https://example.com", got.WebUrl) // Update again. updated = updateDraft(ctx, t, api, draft.Id, []*documents.DocumentChange{ @@ -111,7 +109,6 @@ func TestUpdateDraft_SimpleAttributes(t *testing.T) { testutil.ProtoEqual(t, updated, got, "must get draft that was updated") require.Equal(t, "My changed title", got.Title) - require.Equal(t, "https://example.com", got.WebUrl) } func TestUpdateDraft_WithBlocks(t *testing.T) { @@ -131,7 +128,6 @@ func TestUpdateDraft_WithBlocks(t *testing.T) { updated := updateDraft(ctx, t, api, draft.Id, []*documents.DocumentChange{ {Op: &documents.DocumentChange_SetTitle{SetTitle: "My new document title"}}, - {Op: &documents.DocumentChange_SetWebUrl{SetWebUrl: "https://example.com"}}, {Op: &documents.DocumentChange_MoveBlock_{MoveBlock: &documents.DocumentChange_MoveBlock{BlockId: "b1"}}}, {Op: &documents.DocumentChange_ReplaceBlock{ReplaceBlock: &documents.Block{ Id: "b1", @@ -147,7 +143,6 @@ func TestUpdateDraft_WithBlocks(t *testing.T) { testutil.ProtoEqual(t, updated, got, "must get draft that was updated") require.Equal(t, "My new document title", got.Title) - require.Equal(t, "https://example.com", got.WebUrl) require.Equal(t, "b1", got.Children[0].Block.Id, "block id must match") require.Nil(t, got.Children[0].Children, "block must not have children if not needed") require.Equal(t, "statement", got.Children[0].Block.Type, "block type must match") @@ -794,14 +789,12 @@ func TestPublisherAndEditors(t *testing.T) { DocumentId: draft.Id, Changes: []*documents.DocumentChange{ {Op: &documents.DocumentChange_SetTitle{SetTitle: "Document title"}}, - {Op: &documents.DocumentChange_SetWebUrl{SetWebUrl: "http://example.com"}}, }, }) require.NoError(t, err) draft, err = api.GetDraft(ctx, &documents.GetDraftRequest{DocumentId: draft.Id}) require.NoError(t, err) - require.Equal(t, "http://example.com", draft.WebUrl) require.Equal(t, "Document title", draft.Title) wantEditors := []string{api.me.MustGet().Account().Principal().String()} require.Equal(t, wantEditors, draft.Editors) @@ -868,7 +861,7 @@ func newTestDocsAPI(t *testing.T, name string) *Server { fut := future.New[core.Identity]() require.NoError(t, fut.Resolve(u.Identity)) - srv := NewServer(fut.ReadOnly, db, nil, nil) + srv := NewServer(fut.ReadOnly, db, nil) bs := hyper.NewStorage(db, logging.New("mintter/hyper", "debug")) _, err := daemon.Register(context.Background(), bs, u.Account, u.Device.PublicKey, time.Now()) require.NoError(t, err) diff --git a/backend/daemon/api/documents/v1alpha/web_publishing.go b/backend/daemon/api/documents/v1alpha/web_publishing.go deleted file mode 100644 index f4552022a8..0000000000 --- a/backend/daemon/api/documents/v1alpha/web_publishing.go +++ /dev/null @@ -1,169 +0,0 @@ -// Package documents provides the implementation of the Documents gRPC API. -package documents - -import ( - context "context" - "fmt" - "mintter/backend/core" - documents "mintter/backend/genproto/documents/v1alpha" - "mintter/backend/mttnet" - "mintter/backend/mttnet/sitesql" - "strings" - - "google.golang.org/grpc/metadata" - "google.golang.org/protobuf/types/known/emptypb" -) - -// AddSite checks if the provided site hostname is a valid Mintter site and if so, add it to the database. -func (api *Server) AddSite(ctx context.Context, in *documents.AddSiteRequest) (*documents.SiteConfig, error) { - if in.Hostname == "" { - return nil, fmt.Errorf("add site: empty hostname provided") - } - if strings.Contains(strings.ToLower(in.Hostname), "notallow") { - return nil, fmt.Errorf("add site: site " + in.Hostname + " is not a valid site") - } - if strings.Contains(strings.ToLower(in.Hostname), "taken") { - return nil, fmt.Errorf("add site: site " + in.Hostname + " already taken") - } - - resp, err := mttnet.GetSiteInfoHttp(in.Hostname) - if err != nil { - return nil, fmt.Errorf("add site: Could not get site [%s] info via http: %w", in.Hostname, err) - } - account, err := core.DecodePrincipal(resp.AccountId) - if err != nil { - return nil, fmt.Errorf("add site: got an invalid accountID [%s]: %w", resp.AccountId, err) - } - - info, err := mttnet.AddrInfoFromStrings(resp.Addresses...) - if err != nil { - return nil, fmt.Errorf("add site: couldn't parse multiaddress: %w", err) - } - - if err = api.disc.Connect(ctx, info); err != nil { - return nil, fmt.Errorf("add site: couldn't connect to the remote site via p2p: %w", err) - } - - conn, cancel, err := api.db.Conn(ctx) - if err != nil { - return nil, fmt.Errorf("add site: Cannot connect to internal db") - } - defer cancel() - - site, err := sitesql.GetSite(conn, in.Hostname) - if err != nil { - return nil, err - } - if site.SitesHostname == in.Hostname { - return nil, fmt.Errorf("add site: site %s was already added", in.Hostname) - } - - // make it a proxy call since we want to talk with the site by attaching headers - header := metadata.New(map[string]string{mttnet.TargetSiteHostnameHeader: in.Hostname}) - ctx = metadata.NewIncomingContext(ctx, header) // Usually, the headers are written by the client in the outgoing context and server receives them in the incoming. But here we are writing the server directly - ctx = context.WithValue(ctx, mttnet.GRPCOriginAcc, resp.AccountId) - var role documents.Member_Role - if in.InviteToken != "" { - res, err := api.RemoteCaller.RedeemInviteToken(ctx, &documents.RedeemInviteTokenRequest{ - Token: in.InviteToken, - }) - if err != nil { - return nil, fmt.Errorf("add site: couldn't redeem the attached token: %w", err) - } - - role = res.Role - } else { - res, err := api.RemoteCaller.RedeemInviteToken(ctx, &documents.RedeemInviteTokenRequest{}) - if err != nil { - return nil, fmt.Errorf("add site: please, contact to the site owner to get an invite token: %w", err) - } - - role = res.Role - } - - if err = sitesql.AddSite(conn, account, strings.Join(resp.Addresses, ","), in.Hostname, int64(role)); err != nil { - return nil, fmt.Errorf("add site: could not insert site in the database: %w", err) - } - - return &documents.SiteConfig{ - Hostname: in.Hostname, - Role: documents.Member_Role(role), - }, nil -} - -// RemoveSite removes locally a previously added site. -func (api *Server) RemoveSite(ctx context.Context, req *documents.RemoveSiteRequest) (*emptypb.Empty, error) { - empty := &emptypb.Empty{} - if req.Hostname == "" { - return empty, fmt.Errorf("empty hostname") - } - - conn, cancel, err := api.db.Conn(ctx) - if err != nil { - return empty, fmt.Errorf("Cannot connect to internal db") - } - defer cancel() - return empty, sitesql.RemoveSite(conn, req.Hostname) -} - -// ListSites lists all the added sites. -func (api *Server) ListSites(ctx context.Context, req *documents.ListSitesRequest) (*documents.ListSitesResponse, error) { - var s []*documents.SiteConfig - conn, cancel, err := api.db.Conn(ctx) - if err != nil { - return &documents.ListSitesResponse{}, fmt.Errorf("Cannot connect to internal db") - } - defer cancel() - sites, err := sitesql.ListSites(conn) - if err != nil { - return &documents.ListSitesResponse{}, fmt.Errorf("Could not list sites: %w", err) - } - for _, info := range sites { - s = append(s, &documents.SiteConfig{ - Hostname: info.SitesHostname, - Role: documents.Member_Role(info.SitesRole), - }) - } - return &documents.ListSitesResponse{ - Sites: s, - }, nil -} - -// ListWebPublicationRecords returns all the sites where a given document has been published to. -func (api *Server) ListWebPublicationRecords(ctx context.Context, req *documents.ListWebPublicationRecordsRequest) (*documents.ListWebPublicationRecordsResponse, error) { - var ret []*documents.WebPublicationRecord - conn, cancel, err := api.db.Conn(ctx) - if err != nil { - return &documents.ListWebPublicationRecordsResponse{}, fmt.Errorf("Cannot connect to internal db") - } - defer cancel() - sites, err := sitesql.ListSites(conn) - if err != nil { - return &documents.ListWebPublicationRecordsResponse{}, fmt.Errorf("Could not list sites: %w", err) - } - for _, siteInfo := range sites { - header := metadata.New(map[string]string{mttnet.TargetSiteHostnameHeader: siteInfo.SitesHostname}) - ctx = metadata.NewIncomingContext(ctx, header) // Usually, the headers are written by the client in the outgoing context and server receives them in the incoming. But here we are writing the server directly - - docs, err := api.RemoteCaller.ListWebPublications(ctx, &documents.ListWebPublicationsRequest{}) - if err != nil { - continue - } - for _, doc := range docs.Publications { - if req.DocumentId == doc.DocumentId && (req.Version == "" || req.Version == doc.Version) { - if doc.Hostname != siteInfo.SitesHostname { - return &documents.ListWebPublicationRecordsResponse{}, fmt.Errorf("found document [%s] in remote site [%s], but the site was added locally as [%s]", req.DocumentId, doc.Hostname, siteInfo.SitesHostname) - } - ret = append(ret, &documents.WebPublicationRecord{ - DocumentId: doc.DocumentId, - Version: doc.Version, - Hostname: doc.Hostname, - Path: doc.Path, - }) - } - } - } - return &documents.ListWebPublicationRecordsResponse{ - Publications: ret, - }, nil -} diff --git a/backend/daemon/api/entities/v1alpha/entities_test.go b/backend/daemon/api/entities/v1alpha/entities_test.go index 69a71e1c3c..c6a6146d2e 100644 --- a/backend/daemon/api/entities/v1alpha/entities_test.go +++ b/backend/daemon/api/entities/v1alpha/entities_test.go @@ -2,6 +2,7 @@ package entities import ( "context" + "fmt" "mintter/backend/core/coretest" daemon "mintter/backend/daemon/api/daemon/v1alpha" "mintter/backend/daemon/storage" @@ -9,6 +10,7 @@ import ( "mintter/backend/hyper" "mintter/backend/pkg/must" "mintter/backend/testutil" + "sync" "testing" "time" @@ -19,6 +21,53 @@ import ( var _ entities.EntitiesServer = (*Server)(nil) +type cache struct { + funcs []onceFunc +} + +type onceFunc struct { + once sync.Once + fn func() string + val string +} + +func (o *onceFunc) Do() string { + o.once.Do(func() { + fmt.Println("doing") + o.val = o.fn() + }) + return o.val +} + +func (c *cache) Q(fn func() string) int { + idx := len(c.funcs) + c.funcs = append(c.funcs, onceFunc{fn: fn}) + return idx +} + +func (c *cache) Query(idx int) string { + return c.funcs[idx].Do() +} + +var c cache + +var ( + qSay = c.Q(func() string { + return "say" + "foo" + "bar" + }) + + qHey = c.Q(func() string { + return fmt.Sprintf("hey %s %s", "foo", "bar") + }) +) + +func BenchmarkCache(b *testing.B) { + for i := 0; i < b.N; i++ { + _ = c.Query(qSay) + _ = c.Query(qHey) + } +} + func TestEntityTimeline(t *testing.T) { t.Parallel() diff --git a/backend/daemon/api/groups/v1alpha/db.go b/backend/daemon/api/groups/v1alpha/db.go new file mode 100644 index 0000000000..3ea77325f2 --- /dev/null +++ b/backend/daemon/api/groups/v1alpha/db.go @@ -0,0 +1,145 @@ +package groups + +import ( + "context" + "fmt" + "mintter/backend/hyper" + "mintter/backend/hyper/hypersql" + "mintter/backend/pkg/dqb" + "time" + + "crawshaw.io/sqlite" + "crawshaw.io/sqlite/sqlitex" + "github.com/ipfs/go-cid" + "github.com/libp2p/go-libp2p/core/peer" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" +) + +// DB is a database for storing sites. +type DB struct { + db *sqlitex.Pool +} + +// NewSQLiteDB creates a new DB backed by a SQLite connection pool. +func NewSQLiteDB(db *sqlitex.Pool) *DB { + return &DB{db: db} +} + +// RecordSiteSync updates the last sync time of a site. +func (db *DB) RecordSiteSync(ctx context.Context, baseURL string, pid peer.ID, now time.Time, ok bool) error { + conn, release, err := db.db.Conn(ctx) + if err != nil { + return err + } + defer release() + + nowts := now.Unix() + + if err := sqlitex.Exec(conn, qRecordSiteSync(), nil, pid.String(), nowts, ok, nowts, baseURL); err != nil { + return err + } + + if conn.Changes() == 0 { + return fmt.Errorf("site %s not found", baseURL) + } + + return nil +} + +var qRecordSiteSync = dqb.Str(` + UPDATE remote_sites SET + peer_id = :pid, + last_sync_time = :now, + last_ok_sync_time = iif(:ok, :now, last_ok_sync_time) + WHERE url = :url; +`) + +// ForEachRelatedBlob collects all the related blobs for a given group and calls fn on each CID. +func (db *DB) ForEachRelatedBlob(ctx context.Context, group hyper.EntityID, fn func(c cid.Cid) error) error { + conn, release, err := db.db.Conn(ctx) + if err != nil { + return err + } + defer release() + + gdb, err := hypersql.EntitiesLookupID(conn, string(group)) + if err != nil { + return err + } + if gdb.EntitiesID == 0 { + return status.Errorf(codes.NotFound, "group %s not found", group) + } + + return sqlitex.Exec(conn, qCollectBlobs(), func(stmt *sqlite.Stmt) error { + var ( + id int64 + codec int64 + multihash []byte + ) + stmt.Scan(&id, &codec, &multihash) + + c := cid.NewCidV1(uint64(codec), multihash) + return fn(c) + }, gdb.EntitiesID) +} + +var qCollectBlobs = dqb.Str(` + WITH RECURSIVE + group_blobs (blob) AS ( + SELECT blob + FROM changes + WHERE entity = :group + UNION + SELECT blob_links.target + FROM blob_links, group_blobs + WHERE blob_links.source = group_blobs.blob + ), + account_entities (entity) AS ( + SELECT DISTINCT accounts.entity + FROM group_blobs + JOIN changes ON changes.blob = group_blobs.blob + JOIN accounts ON accounts.entity = changes.entity + ), + account_blobs (blob) AS ( + SELECT changes.blob + FROM account_entities + JOIN changes ON changes.entity = account_entities.entity + UNION + SELECT blob_links.target + FROM account_blobs + JOIN blob_links ON blob_links.source = account_blobs.blob + ), + all_blobs (blob) AS ( + SELECT blob FROM group_blobs + UNION + SELECT blob FROM account_blobs + ) + SELECT + blobs.id AS id, + blobs.codec AS codec, + blobs.multihash AS multihash + FROM all_blobs + JOIN blobs ON blobs.id = all_blobs.blob + ORDER BY blobs.id ASC; +`) + +func (db *DB) QueryOne(ctx context.Context, sql string, args []any, outs []any) error { + conn, release, err := db.db.Conn(ctx) + if err != nil { + return err + } + defer release() + + var count int + + return sqlitex.Exec(conn, sql, func(stmt *sqlite.Stmt) error { + count++ + if count != 1 { + return fmt.Errorf("expected one row, but got more") + } + + stmt.Scan(outs...) + return nil + }, args...) +} diff --git a/backend/daemon/api/groups/v1alpha/groups.go b/backend/daemon/api/groups/v1alpha/groups.go index c79ee6546e..9679247d95 100644 --- a/backend/daemon/api/groups/v1alpha/groups.go +++ b/backend/daemon/api/groups/v1alpha/groups.go @@ -6,25 +6,30 @@ import ( "context" "encoding/json" "fmt" + "io" "mintter/backend/core" groups "mintter/backend/genproto/groups/v1alpha" - p2p "mintter/backend/genproto/p2p/v1alpha" "mintter/backend/hlc" "mintter/backend/hyper" "mintter/backend/hyper/hypersql" + "mintter/backend/ipfs" "mintter/backend/mttnet" - "mintter/backend/mttnet/sitesql" + "mintter/backend/pkg/dqb" "mintter/backend/pkg/errutil" "mintter/backend/pkg/future" "mintter/backend/pkg/maputil" + "net/http" + "net/url" "strings" "time" "crawshaw.io/sqlite" "crawshaw.io/sqlite/sqlitex" "github.com/ipfs/go-cid" + "github.com/libp2p/go-libp2p/core/peer" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" + "google.golang.org/protobuf/encoding/protojson" "google.golang.org/protobuf/types/known/timestamppb" ) @@ -32,18 +37,125 @@ import ( type Server struct { me *future.ReadOnly[core.Identity] blobs *hyper.Storage + db *DB node *future.ReadOnly[*mttnet.Node] } // NewServer creates a new groups server. -func NewServer(me *future.ReadOnly[core.Identity], blobs *hyper.Storage, node *future.ReadOnly[*mttnet.Node]) *Server { +func NewServer(me *future.ReadOnly[core.Identity], db *DB, blobs *hyper.Storage, node *future.ReadOnly[*mttnet.Node]) *Server { return &Server{ me: me, + db: db, blobs: blobs, node: node, } } +// StartPeriodicSync starts periodic sync of sites. +// It will block until the provided context is canceled. +func (srv *Server) StartPeriodicSync(ctx context.Context, warmup, interval time.Duration) error { + t := time.NewTimer(warmup) + defer t.Stop() + + for { + select { + case <-ctx.Done(): + return ctx.Err() + case <-t.C: + + t.Reset(interval) + } + } +} + +var qGetSite = dqb.Str(` + SELECT + url, + peer_id, + group_id, + group_version, + last_sync_time, + last_ok_sync_time + FROM remote_sites + WHERE url = :url; +`) + +func (srv *Server) syncSite(ctx context.Context, siteURL string, interval time.Duration) error { + var ( + url string + peerID string + groupID string + groupVersion string + lastSyncTime int64 + lastSyncOkTime int64 + ) + if err := srv.db.QueryOne(ctx, qGetSite(), + []any{siteURL}, + []any{&url, &peerID, &groupID, &groupVersion, &lastSyncTime, &lastSyncOkTime}, + ); err != nil { + return err + } + + now := time.Now() + lastSync := time.Unix(lastSyncTime, 0) + + if now.Sub(lastSync) < interval { + return nil + } + + info, err := GetSiteInfoHTTP(ctx, nil, siteURL) + if err != nil { + return fmt.Errorf("failed to get site info: %w", err) + } + + if info.GroupId != groupID { + return fmt.Errorf("group ID mismatch: remote %s != local %s", info.GroupId, groupID) + } + + if info.GroupVersion == groupVersion { + return nil + } + + // otherwise do the sync + // get remote info + // check remote group id correspond with the local one + // get all blobs from site + // push all blobs to site + // get remote version and check if we have heads. If so => skip + // sync with site + // + + // TODO: record sync time in db + // if we don't have version heads - sync everything + // + + // n, err := srv.node.Await(ctx) + // if err != nil { + // return err + // } + + // ai, err := addrInfoFromProto(info.PeerInfo) + // if err != nil { + // return fmt.Errorf("failed to parse peer info: %w", err) + // } + + // // Using libp2p connect instead of mttnet connect to skip the handshake. + // // This way we never actually exchange the site's key delegation, so we won't be + // // syncing with sites that we don't care about using the regular syncing process. + // // + // // TODO(burdiyan): BAD! + // if err := n.Libp2p().Connect(ctx, ai); err != nil { + // return err + // } + + // // client, err := n.SiteClient(ctx, ai.ID) + // // if err != nil { + // // return err + // // } + + return nil +} + // CreateGroup creates a new group. func (srv *Server) CreateGroup(ctx context.Context, in *groups.CreateGroupRequest) (*groups.Group, error) { if in.Title == "" { @@ -77,10 +189,20 @@ func (srv *Server) CreateGroup(ctx context.Context, in *groups.CreateGroupReques return nil, status.Errorf(codes.Unimplemented, "adding members when creating a group is not implemented yet") } + if in.SiteSetupUrl != "" { + siteURL, err := srv.initSiteServer(ctx, in.SiteSetupUrl, eid) + if err != nil { + return nil, err + } + + patch["siteURL"] = siteURL + } + del, err := srv.getDelegation(ctx) if err != nil { return nil, err } + hb, err := e.CreateChange(ts, me.DeviceKey(), del, patch, hyper.WithAction("Create")) if err != nil { return nil, err @@ -90,7 +212,71 @@ func (srv *Server) CreateGroup(ctx context.Context, in *groups.CreateGroupReques return nil, err } - return groupToProto(srv.blobs, e) + return groupToProto(e) +} + +func (srv *Server) initSiteServer(ctx context.Context, setupURL string, groupID hyper.EntityID) (baseURL string, err error) { + n, err := srv.node.Await(ctx) + if err != nil { + return "", err + } + + { + u, err := url.Parse(setupURL) + if err != nil { + return "", fmt.Errorf("failed to parse setup URL %s: %w", setupURL, err) + } + + baseURL = (&url.URL{ + Scheme: u.Scheme, + Host: u.Host, + }).String() + } + + resp, err := GetSiteInfoHTTP(ctx, nil, baseURL) + if err != nil { + return "", fmt.Errorf("could not contact site at %s: %w", baseURL, err) + } + + ai, err := addrInfoFromProto(resp.PeerInfo) + if err != nil { + return "", err + } + + if err := n.Connect(ctx, ai); err != nil { + return "", fmt.Errorf("failed to connect to site via P2P: %w", err) + } + + c, err := n.SiteClient(ctx, ai.ID) + if err != nil { + return "", fmt.Errorf("could not get site rpc client: %w", err) + } + + if _, err := c.InitializeServer(ctx, &groups.InitializeServerRequest{ + Secret: setupURL, + GroupId: string(groupID), + }); err != nil { + return "", fmt.Errorf("could not publish group to site: %w", err) + } + + return baseURL, nil +} + +func addrInfoFromProto(in *groups.PeerInfo) (ai peer.AddrInfo, err error) { + pid, err := peer.Decode(in.PeerId) + if err != nil { + return ai, err + } + + addrs, err := ipfs.ParseMultiaddrs(in.Addrs) + if err != nil { + return ai, fmt.Errorf("failed to parse peer info addrs: %w", err) + } + + return peer.AddrInfo{ + ID: pid, + Addrs: addrs, + }, nil } // GetGroup gets a group. @@ -121,7 +307,7 @@ func (srv *Server) GetGroup(ctx context.Context, in *groups.GetGroupRequest) (*g e = v } - return groupToProto(srv.blobs, e) + return groupToProto(e) } // UpdateGroup updates a group. @@ -180,6 +366,15 @@ func (srv *Server) UpdateGroup(ctx context.Context, in *groups.UpdateGroupReques return nil, err } + if in.SiteSetupUrl != "" { + siteURL, err := srv.initSiteServer(ctx, in.SiteSetupUrl, eid) + if err != nil { + return nil, err + } + + patch["siteURL"] = siteURL + } + hb, err := e.CreateChange(e.NextTimestamp(), me.DeviceKey(), del, patch, hyper.WithAction("Update")) if err != nil { return nil, err @@ -189,7 +384,7 @@ func (srv *Server) UpdateGroup(ctx context.Context, in *groups.UpdateGroupReques return nil, err } - return groupToProto(srv.blobs, e) + return groupToProto(e) } // ListGroups lists groups. @@ -316,69 +511,6 @@ func (srv *Server) ListMembers(ctx context.Context, in *groups.ListMembersReques return resp, nil } -// GetSiteInfo gets information of a local site. -func (srv *Server) GetSiteInfo(ctx context.Context, in *groups.GetSiteInfoRequest) (*groups.GetSiteInfoResponse, error) { - ret := &groups.GetSiteInfoResponse{} - if err := srv.blobs.Query(ctx, func(conn *sqlite.Conn) error { - res, err := sitesql.GetSiteInfo(conn, in.Hostname) - if err != nil { - return fmt.Errorf("No site info available: %w", err) - } - ret.GroupId = res.EntitiesEID - if res.ServedSitesVersion != "" { - ret.Version = res.ServedSitesVersion - } else { - entity, err := srv.blobs.LoadEntity(ctx, hyper.EntityID(res.EntitiesEID)) - if err != nil { - return fmt.Errorf("could not get entity [%s]: %w", res.EntitiesEID, err) - } - ret.Version = entity.Version().String() - } - - ret.OwnerId = core.Principal(res.PublicKeysPrincipal).String() - return nil - }); err != nil { - return nil, err - } - return ret, nil -} - -// ConvertToSite converts a group into a site. P2P group will still work as usual after this call. -func (srv *Server) ConvertToSite(ctx context.Context, in *groups.ConvertToSiteRequest) (*groups.ConvertToSiteResponse, error) { - n, ok := srv.node.Get() - if !ok { - return nil, fmt.Errorf("node not ready yet") - } - - remoteHostname := strings.Split(in.Link, "/secret-invite/")[0] - - info, err := mttnet.GetSiteAddressFromHeaders(remoteHostname) - if err != nil { - return nil, fmt.Errorf("Could not get site [%s] info via http: %w", remoteHostname, err) - } - - if err := n.Connect(ctx, info); err != nil { - return nil, fmt.Errorf("failed to connect to site [%s] with peer info [%s]: %w", remoteHostname, info.String(), err) - } - client, err := n.Client(ctx, info.ID) - if err != nil { - return nil, fmt.Errorf("failed to get a p2p client with node [%s]: %w", info.ID.String(), err) - } - res, err := client.CreateSite(ctx, &p2p.CreateSiteRequest{ - Link: in.Link, - GroupId: in.GroupId, - Version: in.Version, - }) - if err != nil { - return nil, fmt.Errorf("Failed to create a remote site: %w", err) - } - - return &groups.ConvertToSiteResponse{ - OwnerId: res.OwnerId, - Hostname: remoteHostname, - }, nil -} - // ListDocumentGroups lists groups that a document belongs to. func (srv *Server) ListDocumentGroups(ctx context.Context, in *groups.ListDocumentGroupsRequest) (*groups.ListDocumentGroupsResponse, error) { if in.DocumentId == "" { @@ -541,7 +673,7 @@ func (srv *Server) ListAccountGroups(ctx context.Context, in *groups.ListAccount return resp, nil } -func groupToProto(blobs *hyper.Storage, e *hyper.Entity) (*groups.Group, error) { +func groupToProto(e *hyper.Entity) (*groups.Group, error) { createTime, ok := e.AppliedChanges()[0].Data.Patch["createTime"].(int) if !ok { return nil, fmt.Errorf("group entity doesn't have createTime field") @@ -559,6 +691,14 @@ func groupToProto(blobs *hyper.Storage, e *hyper.Entity) (*groups.Group, error) Version: e.Version().String(), UpdateTime: timestamppb.New(e.LastChangeTime().Time()), } + if v, ok := e.Get("siteURL"); ok { + vv, ok := v.(string) + if ok { + gpb.SiteInfo = &groups.Group_SiteInfo{ + BaseUrl: vv, + } + } + } { v, ok := e.Get("title") @@ -622,3 +762,45 @@ func (srv *Server) getDelegation(ctx context.Context) (cid.Cid, error) { return out, nil } + +// GetSiteInfoHTTP gets public information from a site. +// Users can pass nil HTTP client in which case the default global one will be used. +func GetSiteInfoHTTP(ctx context.Context, client *http.Client, siteURL string) (*groups.PublicSiteInfo, error) { + if client == nil { + client = http.DefaultClient + } + + fmt.Println(siteURL) + + if siteURL[len(siteURL)-1] == '/' { + return nil, fmt.Errorf("site URL must not have trailing slash: %s", siteURL) + } + + requestURL := siteURL + "/.well-known/hypermedia-site" + + req, err := http.NewRequestWithContext(ctx, http.MethodGet, requestURL, nil) + if err != nil { + return nil, fmt.Errorf("could not create request to well-known site: %w ", err) + } + + res, err := client.Do(req) + if err != nil { + return nil, fmt.Errorf("could not contact to provided site [%s]: %w ", requestURL, err) + } + defer res.Body.Close() + if res.StatusCode < 200 || res.StatusCode > 299 { + return nil, fmt.Errorf("site info url [%s] not working. Status code: %d", requestURL, res.StatusCode) + } + + data, err := io.ReadAll(res.Body) + if err != nil { + return nil, fmt.Errorf("failed to read json body: %w", err) + } + + resp := &groups.PublicSiteInfo{} + if err := protojson.Unmarshal(data, resp); err != nil { + return nil, fmt.Errorf("failed to unmarshal JSON body: %w", err) + } + + return resp, nil +} diff --git a/backend/daemon/api/groups/v1alpha/groups_test.go b/backend/daemon/api/groups/v1alpha/groups_test.go index a70dbadde3..3f86c04ffe 100644 --- a/backend/daemon/api/groups/v1alpha/groups_test.go +++ b/backend/daemon/api/groups/v1alpha/groups_test.go @@ -552,7 +552,7 @@ func newTestSrv(t *testing.T, name string) *Server { bs := hyper.NewStorage(db, logging.New("mintter/hyper", "debug")) node := future.New[*mttnet.Node]() - srv := NewServer(fut.ReadOnly, bs, node.ReadOnly) + srv := NewServer(fut.ReadOnly, NewSQLiteDB(db), bs, node.ReadOnly) _, err := daemon.Register(context.Background(), bs, u.Account, u.Device.PublicKey, time.Now()) require.NoError(t, err) diff --git a/backend/daemon/api/register.go b/backend/daemon/api/register.go index a7595b71c3..79b5edfe6e 100644 --- a/backend/daemon/api/register.go +++ b/backend/daemon/api/register.go @@ -16,14 +16,12 @@ func (s Server) Register(srv *grpc.Server) { accounts.RegisterAccountsServer(srv, s.Accounts) daemon.RegisterDaemonServer(srv, s.Daemon) - documents.RegisterWebPublishingServer(srv, s.Documents) documents.RegisterContentGraphServer(srv, s.Documents) documents.RegisterDraftsServer(srv, s.Documents) documents.RegisterPublicationsServer(srv, s.Documents) // documents.RegisterCommentsServer(srv, s.Documents) documents.RegisterCommentsServer(srv, documents.UnimplementedCommentsServer{}) documents.RegisterChangesServer(srv, s.Documents) - documents.RegisterWebSiteServer(srv, s.Site) networking.RegisterNetworkingServer(srv, s.Networking) entities.RegisterEntitiesServer(srv, s.Entities) diff --git a/backend/daemon/daemon.go b/backend/daemon/daemon.go index 8a9b826b18..a924c1e599 100644 --- a/backend/daemon/daemon.go +++ b/backend/daemon/daemon.go @@ -4,23 +4,16 @@ package daemon import ( "context" - "encoding/json" "fmt" - "io/ioutil" "net" "net/http" - "os" - "runtime/debug" "strconv" - "strings" "time" "mintter/backend/config" "mintter/backend/core" "mintter/backend/daemon/api" "mintter/backend/daemon/storage" - daemon "mintter/backend/genproto/daemon/v1alpha" - "mintter/backend/graphql" "mintter/backend/hyper" "mintter/backend/ipfs" "mintter/backend/logging" @@ -30,10 +23,10 @@ import ( "mintter/backend/syncing" "mintter/backend/wallet" + groups "mintter/backend/genproto/groups/v1alpha" + "crawshaw.io/sqlite/sqlitex" - "github.com/99designs/gqlgen/graphql/playground" "github.com/gorilla/mux" - "github.com/improbable-eng/grpc-web/go/grpcweb" "github.com/libp2p/go-libp2p/core/crypto" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/collectors" @@ -42,12 +35,9 @@ import ( "go.opentelemetry.io/otel/sdk/trace" "go.uber.org/multierr" "go.uber.org/zap" - "golang.org/x/exp/slices" "golang.org/x/sync/errgroup" "google.golang.org/grpc" - "google.golang.org/grpc/codes" "google.golang.org/grpc/reflection" - "google.golang.org/grpc/status" ) func init() { @@ -88,31 +78,7 @@ type App struct { // futures might not be resolved yet. // // To shut down the app gracefully cancel the provided context and call Wait(). -func Load(ctx context.Context, cfg config.Config, grpcOpt ...grpc.ServerOption) (a *App, err error) { - var deviceKey crypto.PrivKey - if cfg.Identity.DeviceKeyPath != "" { - if _, err := os.Stat(cfg.Identity.DeviceKeyPath); err == nil { - bytes, err := ioutil.ReadFile(cfg.Identity.DeviceKeyPath) - if err != nil { - return nil, err - } - deviceKey, err = crypto.UnmarshalPrivateKey(bytes) - if err != nil { - return nil, err - } - } else { - return nil, err - } - } - r, err := initRepo(cfg, deviceKey) - if err != nil { - return nil, err - } - - return loadApp(ctx, cfg, r, grpcOpt...) -} - -func loadApp(ctx context.Context, cfg config.Config, r *storage.Dir, grpcOpt ...grpc.ServerOption) (a *App, err error) { +func Load(ctx context.Context, cfg config.Config, r *storage.Dir, extraOpts ...interface{}) (a *App, err error) { a = &App{ log: logging.New("mintter/daemon", "debug"), Storage: r, @@ -161,7 +127,7 @@ func loadApp(ctx context.Context, cfg config.Config, r *storage.Dir, grpcOpt ... me := a.Storage.Identity() - a.Net, err = initNetwork(&a.clean, a.g, me, cfg.P2P, a.DB, a.Blobs) + a.Net, err = initNetwork(&a.clean, a.g, me, cfg.P2P, a.DB, a.Blobs, extraOpts...) if err != nil { return nil, err } @@ -173,24 +139,17 @@ func loadApp(ctx context.Context, cfg config.Config, r *storage.Dir, grpcOpt ... a.Wallet = wallet.New(ctx, logging.New("mintter/wallet", "debug"), a.DB, a.Net, me, cfg.Lndhub.Mainnet) - a.GRPCServer, a.GRPCListener, a.RPC, err = initGRPC(ctx, cfg.GRPCPort, &a.clean, a.g, me, a.Storage, a.DB, a.Blobs, a.Net, a.Syncing, a.Wallet, cfg.Site, grpcOpt...) + extraHTTPHandlers := []GenericHandler{} + for _, extra := range extraOpts { + if httpHandler, ok := extra.(GenericHandler); ok { + extraHTTPHandlers = append(extraHTTPHandlers, httpHandler) + } + } + a.GRPCServer, a.GRPCListener, a.RPC, err = initGRPC(ctx, cfg.GRPC.Port, &a.clean, a.g, me, a.Storage, a.DB, a.Blobs, a.Net, a.Syncing, a.Wallet, extraOpts...) if err != nil { return nil, err } - if cfg.Identity.NoAccountWait { - res, err := a.RPC.Daemon.GenMnemonic(ctx, &daemon.GenMnemonicRequest{MnemonicsLength: 12}) - if err != nil { - return nil, fmt.Errorf("Cannot create automatic mnemonics: %w", err) - } - _, err = a.RPC.Daemon.Register(ctx, &daemon.RegisterRequest{Mnemonic: res.Mnemonic, Passphrase: ""}) - stat, ok := status.FromError(err) - - if !ok && stat.Code() != codes.AlreadyExists { - return nil, fmt.Errorf("Cannot register automatic account: %w", err) - } - } - fileManager := ipfs.NewManager(ctx, logging.New("mintter/ipfs", "debug")) // We can't use futures in ipfs.NewManager since we will incur in a @@ -205,7 +164,7 @@ func loadApp(ctx context.Context, cfg config.Config, r *storage.Dir, grpcOpt ... return fileManager.Start(n.Blobs().IPFSBlockstore(), n.Bitswap(), n.Provider()) }) - a.HTTPServer, a.HTTPListener, err = initHTTP(cfg.HTTPPort, a.GRPCServer, &a.clean, a.g, a.DB, a.Net, me, a.Wallet, a.RPC.Site, fileManager) + a.HTTPServer, a.HTTPListener, err = initHTTP(cfg.HTTP.Port, a.GRPCServer, &a.clean, a.g, a.Wallet, fileManager, extraHTTPHandlers...) if err != nil { return nil, err } @@ -221,7 +180,7 @@ func (a *App) setupLogging(ctx context.Context, cfg config.Config) { a.log.Info("DaemonStarted", zap.String("grpcListener", a.GRPCListener.Addr().String()), zap.String("httpListener", a.HTTPListener.Addr().String()), - zap.String("repoPath", cfg.RepoPath), + zap.String("dataDir", cfg.DataDir), ) n, err := a.Net.Await(ctx) @@ -257,12 +216,14 @@ func (a *App) Wait() error { return a.g.Wait() } -func initRepo(cfg config.Config, device crypto.PrivKey) (r *storage.Dir, err error) { +// InitRepo initializes the storage directory. +// Device can be nil in which case a random new device key will be generated. +func InitRepo(dataDir string, device crypto.PrivKey) (r *storage.Dir, err error) { log := logging.New("mintter/repo", "debug") if device == nil { - r, err = storage.New(cfg.RepoPath, log) + r, err = storage.New(dataDir, log) } else { - r, err = storage.NewWithDeviceKey(cfg.RepoPath, log, device) + r, err = storage.NewWithDeviceKey(dataDir, log, device) } if err != nil { return nil, fmt.Errorf("failed to init storage: %w", err) @@ -293,6 +254,7 @@ func initNetwork( cfg config.P2P, db *sqlitex.Pool, blobs *hyper.Storage, + extraServers ...interface{}, ) (*future.ReadOnly[*mttnet.Node], error) { f := future.New[*mttnet.Node]() @@ -314,7 +276,7 @@ func initNetwork( return err } - n, err := mttnet.New(cfg, db, blobs, id, logging.New("mintter/network", "debug")) + n, err := mttnet.New(cfg, db, blobs, id, logging.New("mintter/network", "debug"), extraServers...) if err != nil { return err } @@ -374,16 +336,20 @@ func initSyncing( return err } - svc := syncing.NewService(logging.New("mintter/syncing", "debug"), id, db, blobs, node.Bitswap(), node.Client, cfg.NoInbound) + svc := syncing.NewService(logging.New("mintter/syncing", "debug"), id, db, blobs, node.Bitswap(), node.Client) svc.SetWarmupDuration(cfg.WarmupDuration) svc.SetPeerSyncTimeout(cfg.TimeoutPerPeer) svc.SetSyncInterval(cfg.Interval) - g.Go(func() error { - err := svc.Start(ctx) + if cfg.Disabled { close(done) - return err - }) + } else { + g.Go(func() error { + err := svc.Start(ctx) + close(done) + return err + }) + } if err := f.Resolve(svc); err != nil { return err @@ -407,20 +373,32 @@ func initGRPC( node *future.ReadOnly[*mttnet.Node], sync *future.ReadOnly[*syncing.Service], wallet *wallet.Service, - cfg config.Site, - opts ...grpc.ServerOption, + extras ...interface{}, ) (srv *grpc.Server, lis net.Listener, rpc api.Server, err error) { lis, err = net.Listen("tcp", ":"+strconv.Itoa(port)) if err != nil { return } + opts := []grpc.ServerOption{} + for _, extra := range extras { + if opt, ok := extra.(grpc.ServerOption); ok { + opts = append(opts, opt) + } + } srv = grpc.NewServer(opts...) - rpc = api.New(ctx, repo, pool, blobs, node, sync, wallet, cfg) + rpc = api.New(ctx, repo, pool, blobs, node, sync, wallet) rpc.Register(srv) reflection.Register(srv) + for _, extra := range extras { + if extraServer, ok := extra.(groups.WebsiteServer); ok { + groups.RegisterWebsiteServer(srv, extraServer) + break + } + } + g.Go(func() error { return srv.Serve(lis) }) @@ -479,162 +457,40 @@ func setRoute(m *mux.Router, path string, isPrefix bool, h http.Handler) { } const ( - routePrefix = 1 << 1 - routeNav = 1 << 2 + // RoutePrefix exposes path prefix. + RoutePrefix = 1 << 1 + // RouteNav adds the path to a route nav. + RouteNav = 1 << 2 ) -type router struct { +// Router is a wrapper around mux that can build the navigation menu. +type Router struct { r *mux.Router nav []string } -func (r *router) Handle(path string, h http.Handler, mode int) { +// Handle a route. +func (r *Router) Handle(path string, h http.Handler, mode int) { h = instrumentHTTPHandler(h, path) - if mode&routePrefix != 0 { + if mode&RouteNav != 0 { r.r.PathPrefix(path).Handler(h) } else { r.r.Handle(path, h) } - if mode&routeNav != 0 { + if mode&RouteNav != 0 { r.nav = append(r.nav, path) } } -func (r *router) Index(w http.ResponseWriter, req *http.Request) { +func (r *Router) Index(w http.ResponseWriter, req *http.Request) { for _, route := range r.nav { fmt.Fprintf(w, `
`, route, route) } } -func initHTTP( - port int, - rpc *grpc.Server, - clean *cleanup.Stack, - g *errgroup.Group, - db *sqlitex.Pool, - node *future.ReadOnly[*mttnet.Node], - me *future.ReadOnly[core.Identity], - wallet *wallet.Service, - wellKnownHandler http.Handler, - ipfsHandler ipfs.HTTPHandler, -) (srv *http.Server, lis net.Listener, err error) { - var h http.Handler - { - grpcWebHandler := grpcweb.WrapServer(rpc, grpcweb.WithOriginFunc(func(origin string) bool { - return true - })) - - router := router{r: mux.NewRouter()} - router.Handle("/debug/metrics", promhttp.Handler(), routeNav) - router.Handle("/debug/pprof", http.DefaultServeMux, routePrefix|routeNav) - router.Handle("/debug/vars", http.DefaultServeMux, routePrefix|routeNav) - router.Handle("/debug/grpc", grpcLogsHandler(), routeNav) - router.Handle("/debug/buildinfo", buildInfoHandler(), routeNav) - router.Handle("/graphql", corsMiddleware(graphql.Handler(wallet)), 0) - router.Handle("/playground", playground.Handler("GraphQL Playground", "/graphql"), routeNav) - router.Handle("/"+mttnet.WellKnownPath, wellKnownHandler, routeNav) - router.Handle(ipfs.IPFSRootRoute+ipfs.UploadRoute, http.HandlerFunc(ipfsHandler.UploadFile), 0) - router.Handle(ipfs.IPFSRootRoute+ipfs.GetRoute, http.HandlerFunc(ipfsHandler.GetFile), 0) - - router.r.MatcherFunc(mux.MatcherFunc(func(r *http.Request, match *mux.RouteMatch) bool { - return grpcWebHandler.IsAcceptableGrpcCorsRequest(r) || grpcWebHandler.IsGrpcWebRequest(r) - })).Handler(grpcWebHandler) - - router.Handle("/", http.HandlerFunc(router.Index), 0) - - h = router.r - } - - srv = &http.Server{ - Addr: ":" + strconv.Itoa(port), - ReadHeaderTimeout: 5 * time.Second, - // WriteTimeout: 10 * time.Second, - IdleTimeout: 20 * time.Second, - Handler: h, - } - - lis, err = net.Listen("tcp", srv.Addr) - if err != nil { - return - } - - g.Go(func() error { - err := srv.Serve(lis) - if err == http.ErrServerClosed { - return nil - } - return err - }) - - clean.AddErrFunc(func() error { - return srv.Shutdown(context.Background()) - }) - - return -} - -// corsMiddleware allows different host/origins. -func corsMiddleware(next http.Handler) http.Handler { - return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - // allow cross domain AJAX requests - w.Header().Set("Access-Control-Allow-Origin", "*") - w.Header().Set("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept") - next.ServeHTTP(w, r) - }) -} - // WithMiddleware generates an grpc option with the given middleware. func WithMiddleware(i grpc.UnaryServerInterceptor) grpc.ServerOption { return grpc.UnaryInterceptor(i) } - -// GwEssentials is a middleware to restrict incoming grpc calls to bare minimum for the gateway to work. -func GwEssentials(ctx context.Context, - req interface{}, - info *grpc.UnaryServerInfo, - handler grpc.UnaryHandler) (interface{}, error) { - methodSplitted := strings.Split(info.FullMethod, "/") - if len(methodSplitted) < 2 || (strings.ToLower(methodSplitted[len(methodSplitted)-1]) != "getpublication" && - strings.ToLower(methodSplitted[len(methodSplitted)-1]) != "listcitations" && - strings.ToLower(methodSplitted[len(methodSplitted)-1]) != "getaccount") { - return nil, fmt.Errorf("method: %s not allowed", info.FullMethod) - } - - // Calls the handler - h, err := handler(ctx, req) - - return h, err -} - -func buildInfoHandler() http.Handler { - return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - info, ok := debug.ReadBuildInfo() - if !ok { - http.Error(w, "doesn't support build info", http.StatusExpectationFailed) - return - } - - // Don't want to show information about all the dependencies. - info.Deps = nil - - // Want to support text and json. - wantJSON := slices.Contains(r.Header.Values("Accept"), "application/json") || - r.URL.Query().Get("format") == "json" - - if wantJSON { - w.Header().Set("Content-Type", "application/json") - - enc := json.NewEncoder(w) - enc.SetIndent("", " ") - - if err := enc.Encode(info); err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) - } - } else { - w.Header().Set("Content-Type", "text/plain") - fmt.Fprint(w, info.String()) - } - }) -} diff --git a/backend/daemon/daemon_e2e_test.go b/backend/daemon/daemon_e2e_test.go index c1820bb1c0..f849b75b53 100644 --- a/backend/daemon/daemon_e2e_test.go +++ b/backend/daemon/daemon_e2e_test.go @@ -2,10 +2,7 @@ package daemon import ( "context" - "io/ioutil" - "mintter/backend/config" "mintter/backend/core" - "mintter/backend/core/coretest" accounts "mintter/backend/genproto/accounts/v1alpha" daemon "mintter/backend/genproto/daemon/v1alpha" documents "mintter/backend/genproto/documents/v1alpha" @@ -24,7 +21,6 @@ import ( "golang.org/x/sync/errgroup" "google.golang.org/grpc" "google.golang.org/grpc/credentials/insecure" - "google.golang.org/grpc/metadata" "google.golang.org/protobuf/proto" ) @@ -138,289 +134,6 @@ func TestAPIGetRemotePublication(t *testing.T) { testutil.ProtoEqual(t, publishedDocument, remotePublication, "remote publication doesn't match") } -func TestSite(t *testing.T) { - ctx, cancel := context.WithCancel(context.Background()) - - t.Cleanup(func() { - cancel() - }) - - owner := makeTestApp(t, "alice", makeTestConfig(t), true) - editor := makeTestApp(t, "bob", makeTestConfig(t), true) - editorFriend := makeTestApp(t, "alice-2", makeTestConfig(t), true) - reader := makeTestApp(t, "david", makeTestConfig(t), true) - - siteCfg := makeTestConfig(t) - siteCfg.Site.Hostname = "http://127.0.0.1:59011" - siteCfg.HTTPPort = 59011 - siteCfg.GRPCPort = mttnet.GRPCPort - siteCfg.Identity.NoAccountWait = true - siteCfg.Site.NoAuth = false - siteCfg.Site.Title = "initial Site Title" - siteCfg.Site.OwnerID = owner.Storage.Identity().MustGet().Account().String() - siteCfg.P2P.NoListing = true - siteCfg.Syncing.NoInbound = true - - site := makeTestApp(t, "carol", siteCfg, false) - time.Sleep(500 * time.Millisecond) - - newSite, err := owner.RPC.Documents.AddSite(ctx, &documents.AddSiteRequest{Hostname: siteCfg.Site.Hostname}) - require.NoError(t, err) - require.Equal(t, siteCfg.Site.Hostname, newSite.Hostname) - require.Equal(t, documents.Member_OWNER, newSite.Role) - - _, err = owner.RPC.Documents.AddSite(ctx, &documents.AddSiteRequest{Hostname: siteCfg.Site.Hostname}) - require.Error(t, err, "adding the same site twice must fail") - - // The reader connects to the site via p2p only - _, err = reader.RPC.Networking.Connect(ctx, &networking.ConnectRequest{Addrs: getAddrs(t, site)}) - require.NoError(t, err) - - // The editor and his friend connect to each other - _, err = editorFriend.RPC.Networking.Connect(ctx, &networking.ConnectRequest{Addrs: getAddrs(t, editor)}) - require.NoError(t, err) - - // Adding a site as an editor without token should fail. - _, err = editor.RPC.Documents.AddSite(ctx, &documents.AddSiteRequest{Hostname: siteCfg.Site.Hostname}) - require.Error(t, err) - - // Generate a token for the editor. - header := metadata.New(map[string]string{string(mttnet.TargetSiteHostnameHeader): siteCfg.Site.Hostname}) - ctxWithHeaders := metadata.NewIncomingContext(ctx, header) // Typically, the headers are written by the client in the outgoing context and server receives them in the incoming. But here we are writing the server directly - address := "" - for _, ma := range site.Net.MustGet().AddrInfo().Addrs { - address += " " + ma.String() - } - ctxWithHeaders = context.WithValue(ctxWithHeaders, mttnet.TargetSiteHostnameHeader, site.Storage.Identity().MustGet().Account().String()) - token, err := owner.RPC.Site.CreateInviteToken(ctxWithHeaders, &documents.CreateInviteTokenRequest{Role: documents.Member_EDITOR}) - require.NoError(t, err) - - // Adding a site as an editor with invite token should succeed. - editorSite, err := editor.RPC.Documents.AddSite(ctx, &documents.AddSiteRequest{Hostname: siteCfg.Site.Hostname, InviteToken: token.Token}) - require.NoError(t, err) - require.Equal(t, siteCfg.Site.Hostname, editorSite.Hostname) - require.Equal(t, documents.Member_EDITOR, editorSite.Role) - - // Get initial site info. - siteInfo, err := owner.RPC.Site.GetSiteInfo(ctxWithHeaders, &documents.GetSiteInfoRequest{}) - require.NoError(t, err) - require.Equal(t, "", siteInfo.Description) - require.Equal(t, siteCfg.Site.Hostname, siteInfo.Hostname) - require.Equal(t, siteCfg.Site.OwnerID, siteInfo.Owner) - require.Equal(t, owner.Storage.Identity().MustGet().Account().String(), siteInfo.Owner) - require.Equal(t, siteCfg.Site.Title, siteInfo.Title) - siteAcc, err := site.RPC.Accounts.GetAccount(ctx, &accounts.GetAccountRequest{}) - require.NoError(t, err) - require.Equal(t, "Mintter Site", siteAcc.Profile.Bio) - require.Equal(t, siteCfg.Site.Title, siteAcc.Profile.Alias) - - // Change site info by the editor should fail - const newTitle = "new title" - const newDescription = " new brief description" - _, err = editor.RPC.Site.UpdateSiteInfo(ctxWithHeaders, &documents.UpdateSiteInfoRequest{Title: newTitle, Description: newDescription}) - if siteCfg.Site.NoAuth { - require.NoError(t, err) - } else { - require.Error(t, err) - } - - // Change site info by the owner shouldn't fail - siteInfo, err = owner.RPC.Site.UpdateSiteInfo(ctxWithHeaders, &documents.UpdateSiteInfoRequest{Title: newTitle, Description: newDescription}) - require.NoError(t, err) - require.Equal(t, newDescription, siteInfo.Description) - require.Equal(t, siteCfg.Site.Hostname, siteInfo.Hostname) - require.Equal(t, siteCfg.Site.OwnerID, siteInfo.Owner) - require.Equal(t, owner.Storage.Identity().MustGet().Account().String(), siteInfo.Owner) - require.Equal(t, newTitle, siteInfo.Title) - siteAcc, err = site.RPC.Accounts.GetAccount(ctx, &accounts.GetAccountRequest{}) - require.NoError(t, err) - require.Equal(t, newDescription, siteAcc.Profile.Bio) - require.Equal(t, newTitle, siteAcc.Profile.Alias) - - // Share a document. - sharedDocument := publishDocument(t, ctx, editor) - _, err = editor.RPC.Daemon.ForceSync(ctx, &daemon.ForceSyncRequest{}) - require.NoError(t, err) - _, err = editorFriend.RPC.Daemon.ForceSync(ctx, &daemon.ForceSyncRequest{}) - require.NoError(t, err) - - time.Sleep(500 * time.Millisecond) // Sleeping just to make sure it has time to propagate - - publicationList, err := site.RPC.Documents.ListPublications(ctx, &documents.ListPublicationsRequest{}) - require.NoError(t, err) - require.Len(t, publicationList.Publications, 0, "site must not sync documents with regular periodic sync") - - publicationList, err = editorFriend.RPC.Documents.ListPublications(ctx, &documents.ListPublicationsRequest{}) - require.NoError(t, err) - require.Len(t, publicationList.Publications, 1, "editor friend must have synced the document with the editor") - require.Equal(t, sharedDocument.Version, publicationList.Publications[0].Version) - require.Equal(t, sharedDocument.Document.Author, publicationList.Publications[0].Document.Author) - require.Equal(t, sharedDocument.Document.Id, publicationList.Publications[0].Document.Id) - - const indexPath = "/" - - _, err = editor.RPC.Site.PublishDocument(ctxWithHeaders, &documents.PublishDocumentRequest{ - DocumentId: sharedDocument.Document.Id, - Version: sharedDocument.Version, - Path: indexPath, - }) - require.NoError(t, err) - - // Site should have the document - publicationList, err = site.RPC.Documents.ListPublications(ctx, &documents.ListPublicationsRequest{}) - require.NoError(t, err) - require.Len(t, publicationList.Publications, 1) - require.Equal(t, sharedDocument.Version, publicationList.Publications[0].Version) - require.Equal(t, sharedDocument.Document.Author, publicationList.Publications[0].Document.Author) - require.Equal(t, sharedDocument.Document.Id, publicationList.Publications[0].Document.Id) - - // And owner should see it as well - _, err = site.RPC.Daemon.ForceSync(ctx, &daemon.ForceSyncRequest{}) - require.NoError(t, err) - _, err = owner.RPC.Daemon.ForceSync(ctx, &daemon.ForceSyncRequest{}) - require.NoError(t, err) - time.Sleep(500 * time.Millisecond) // Sleeping just to make sure it has time to propagate - - publicationList, err = owner.RPC.Documents.ListPublications(ctx, &documents.ListPublicationsRequest{}) - require.NoError(t, err) - require.Len(t, publicationList.Publications, 1) - require.Equal(t, sharedDocument.Version, publicationList.Publications[0].Version) - require.Equal(t, sharedDocument.Document.Author, publicationList.Publications[0].Document.Author) - require.Equal(t, sharedDocument.Document.Id, publicationList.Publications[0].Document.Id) - - // But the reader should not have it since its only connected to the site - publicationList, err = reader.RPC.Documents.ListPublications(ctx, &documents.ListPublicationsRequest{}) - require.NoError(t, err) - require.Len(t, publicationList.Publications, 0) - - // Even if he syncs, since NoListing = true site wont sync anything with non members - _, err = reader.RPC.Daemon.ForceSync(ctx, &daemon.ForceSyncRequest{}) - require.NoError(t, err) - time.Sleep(500 * time.Millisecond) // Sleeping just to make sure it has time to propagate - publicationList, err = reader.RPC.Documents.ListPublications(ctx, &documents.ListPublicationsRequest{}) - require.NoError(t, err) - require.Len(t, publicationList.Publications, 0) - - // Owner should view it in the site as published - sitePublications, err := owner.RPC.Site.ListWebPublications(ctxWithHeaders, &documents.ListWebPublicationsRequest{}) - require.NoError(t, err) - require.Len(t, sitePublications.Publications, 1) - require.Equal(t, sharedDocument.Version, sitePublications.Publications[0].Version) - require.Equal(t, siteCfg.Site.Hostname, sitePublications.Publications[0].Hostname) - require.Equal(t, indexPath, sitePublications.Publications[0].Path) - require.Equal(t, sharedDocument.Document.Id, sitePublications.Publications[0].DocumentId) - - // publish same doc to another path - const anotherPath = "another" - _, err = editor.RPC.Site.PublishDocument(ctxWithHeaders, &documents.PublishDocumentRequest{ - DocumentId: sharedDocument.Document.Id, - Version: sharedDocument.Version, - Path: anotherPath, - }) - require.Error(t, err, "must fail to publish same web publication with a different path") - - // publish a different version to another path - const anotherTitle = "New Document title leading to a new version" - newVersion := updateDocumenTitle(t, ctx, owner, sharedDocument.Document.Id, anotherTitle) - require.Equal(t, sharedDocument.Document.Id, newVersion.Document.Id) - - _, err = editor.RPC.Site.PublishDocument(ctxWithHeaders, &documents.PublishDocumentRequest{ - DocumentId: newVersion.Document.Id, - Version: newVersion.Version, - Path: anotherPath, - }) - require.Error(t, err, "must fail to publish web publication with a different version to a different path") - - // publish different version in same path should update the old one - _, err = editor.RPC.Site.PublishDocument(ctxWithHeaders, &documents.PublishDocumentRequest{ - DocumentId: newVersion.Document.Id, - Version: newVersion.Version, - Path: indexPath, - }) - require.Error(t, err, "must fail because editor doesn't have the document") // the editor does not have it, the owner does - - // Get the document from the network, and then try to republish. - wantedDoc, err := editor.RPC.Documents.GetPublication(ctx, &documents.GetPublicationRequest{ - DocumentId: newVersion.Document.Id, - Version: newVersion.Version, - }) - require.NoError(t, err) - require.Equal(t, newVersion.Version, wantedDoc.Version) - require.Equal(t, newVersion.Document.Id, wantedDoc.Document.Id) - - // Now republish - _, err = editor.RPC.Site.PublishDocument(ctxWithHeaders, &documents.PublishDocumentRequest{ - DocumentId: newVersion.Document.Id, - Version: newVersion.Version, - Path: indexPath, - }) - require.NoError(t, err) - doc, err := owner.RPC.Site.GetPath(ctxWithHeaders, &documents.GetPathRequest{Path: indexPath}) - require.NoError(t, err) - require.Equal(t, newVersion.Version, doc.Publication.Version) - require.Equal(t, anotherTitle, doc.Publication.Document.Title) - - // Different author changes the version and republishes to the same path - const anotherAuthorTitle = "Is this a change in authorship? Nope" - noNewAuthor := updateDocumenTitle(t, ctx, editor, newVersion.Document.Id, anotherAuthorTitle) - require.Equal(t, sharedDocument.Document.Author, noNewAuthor.Document.Author) - require.Equal(t, sharedDocument.Document.Id, noNewAuthor.Document.Id) - _, err = editor.RPC.Site.PublishDocument(ctxWithHeaders, &documents.PublishDocumentRequest{ - DocumentId: noNewAuthor.Document.Id, - Version: noNewAuthor.Version, - Path: indexPath, - }) - require.NoError(t, err) - - // Publish another document (owner) and give no time to sync and get it via getpublication in the editor. - newDocument := publishDocument(t, ctx, owner) - require.NoError(t, err) - _, err = owner.RPC.Site.PublishDocument(ctxWithHeaders, &documents.PublishDocumentRequest{ - DocumentId: newDocument.Document.Id, - Version: newDocument.Version, - Path: anotherPath, - }) - require.NoError(t, err) - sitePublications, err = editor.RPC.Site.ListWebPublications(ctxWithHeaders, &documents.ListWebPublicationsRequest{}) - require.NoError(t, err) - require.Len(t, sitePublications.Publications, 2) - - // Unpublish a document we haven't written should fail - _, err = editor.RPC.Site.UnpublishDocument(ctxWithHeaders, &documents.UnpublishDocumentRequest{ - DocumentId: newDocument.Document.Id, - }) - require.Error(t, err) - - // But the owner can unpublish - _, err = owner.RPC.Site.UnpublishDocument(ctxWithHeaders, &documents.UnpublishDocumentRequest{ - DocumentId: newDocument.Document.Id, - }) - require.NoError(t, err) - sitePublications, err = editor.RPC.Site.ListWebPublications(ctxWithHeaders, &documents.ListWebPublicationsRequest{}) - require.NoError(t, err) - require.Len(t, sitePublications.Publications, 1) - require.Equal(t, noNewAuthor.Version, sitePublications.Publications[0].Version) - require.Equal(t, indexPath, sitePublications.Publications[0].Path) - require.Equal(t, noNewAuthor.Document.Id, sitePublications.Publications[0].DocumentId) - - // Publish the previous shared document to the site on a blank path becomes unlisted. but same ID fails - _, err = editor.RPC.Site.PublishDocument(ctxWithHeaders, &documents.PublishDocumentRequest{ - DocumentId: sharedDocument.Document.Id, - Version: sharedDocument.Version, - }) - require.Error(t, err) - _, err = editor.RPC.Site.PublishDocument(ctxWithHeaders, &documents.PublishDocumentRequest{ - DocumentId: newDocument.Document.Id, - Version: newDocument.Version, - }) - require.NoError(t, err) - sitePublications, err = editor.RPC.Site.ListWebPublications(ctxWithHeaders, &documents.ListWebPublicationsRequest{}) - require.NoError(t, err) - require.Len(t, sitePublications.Publications, 2) - _, err = editor.RPC.Site.GetPath(ctxWithHeaders, &documents.GetPathRequest{}) - require.Error(t, err) -} - func TestTrustedChanges(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) @@ -499,74 +212,6 @@ func TestTrustedChanges(t *testing.T) { require.Equal(t, newVersion.Document.Id, publicationList.Publications[0].Document.Id) } -func TestGateway(t *testing.T) { - t.Parallel() - ctx, cancel := context.WithCancel(context.Background()) - - gwConf := makeTestConfig(t) - gwConf.P2P.NoListing = true - - f, err := ioutil.TempFile("", "device.key") - require.NoError(t, err) - t.Cleanup(func() { - f.Close() - }) - - gwConf.Identity.DeviceKeyPath = f.Name() - - var deviceKeyBytes = []byte{8, 1, 18, 64, 213, 180, 8, 59, 161, 75, 15, 92, 212, 94, 225, 82, 81, 11, 32, 200, 62, 46, 190, 105, 121, 14, 176, 107, 195, 113, 153, 176, 198, 163, 215, 226, 79, 46, 215, 228, 133, 153, 14, 142, 52, 115, 21, 73, 202, 121, 204, 223, 53, 117, 164, 225, 248, 106, 231, 151, 180, 246, 107, 137, 227, 212, 98, 140} - bytes, err := f.Write(deviceKeyBytes) - require.NoError(t, err) - require.Equal(t, len(deviceKeyBytes), bytes) - - gw, err := Load(ctx, gwConf, WithMiddleware(GwEssentials)) - require.NoError(t, err) - t.Cleanup(func() { - cancel() - require.Equal(t, context.Canceled, gw.Wait()) - }) - - const mnemonicWords = 12 - mnemonic, err := core.NewBIP39Mnemonic(mnemonicWords) - require.NoError(t, err) - - _, err = gw.RPC.Daemon.Register(ctx, &daemon.RegisterRequest{ - Mnemonic: mnemonic, - Passphrase: "", - }) - require.NoError(t, err) - _, err = gw.Net.Await(ctx) - require.NoError(t, err) - - _, err = gw.Storage.Identity().Await(ctx) - require.NoError(t, err) - // Create new document so the gateway owns at least 1. This one must not be transferred to the requester, since the - // gateway only syncs in one direction (in order not to flood requesters with documents from everybody) - publishDocument(t, ctx, gw) - res, err := gw.RPC.Documents.ListPublications(ctx, &documents.ListPublicationsRequest{}) - require.NoError(t, err) - require.Equal(t, 1, len(res.Publications)) - // Create the publication that will be gotten by the gateway - _, publishedDocument, publisher := makeRemotePublication(t, ctx, gw) - remotePublication, err := gw.RPC.Documents.GetPublication(ctx, &documents.GetPublicationRequest{DocumentId: publishedDocument.Document.Id}) - require.NoError(t, err) - testutil.ProtoEqual(t, publishedDocument, remotePublication, "remote publication doesn't match") - // Gateway now should have two publications, the one created by itself and the one gotten from publisher - pubsGw, err := gw.RPC.Documents.ListPublications(ctx, &documents.ListPublicationsRequest{}) - require.NoError(t, err) - require.Equal(t, 2, len(pubsGw.Publications)) - pubPublisher, err := publisher.RPC.Documents.ListPublications(ctx, &documents.ListPublicationsRequest{}) - require.NoError(t, err) - require.Equal(t, 1, len(pubPublisher.Publications)) - // We force the publisher to sync all the content to see if it does not get the gateway's own article. - _, err = publisher.RPC.Daemon.ForceSync(ctx, &daemon.ForceSyncRequest{}) - require.NoError(t, err) - time.Sleep(time.Second) - pubPublisher, err = publisher.RPC.Documents.ListPublications(ctx, &documents.ListPublicationsRequest{}) - require.NoError(t, err) - require.Equal(t, 1, len(pubPublisher.Publications)) -} - func TestBug_SyncHangs(t *testing.T) { // See: https://github.com/mintterteam/mintter/issues/712. t.Parallel() @@ -885,43 +530,6 @@ func getAddrs(t *testing.T, a *App) []string { return mttnet.AddrInfoToStrings(a.Net.MustGet().AddrInfo()) } -func makeTestApp(t *testing.T, name string, cfg config.Config, register bool) *App { - ctx, cancel := context.WithCancel(context.Background()) - - u := coretest.NewTester(name) - - repo, err := initRepo(cfg, u.Device.Wrapped()) - require.NoError(t, err) - - app, err := loadApp(ctx, cfg, repo) - require.NoError(t, err) - t.Cleanup(func() { - cancel() - require.Equal(t, context.Canceled, app.Wait()) - }) - - if register { - err = app.RPC.Daemon.RegisterAccount(ctx, u.Account) - require.NoError(t, err) - - _, err = app.Net.Await(ctx) - require.NoError(t, err) - - _, err = app.Storage.Identity().Await(ctx) - require.NoError(t, err) - - prof := &accounts.Profile{ - Alias: name, - Bio: name + " bio", - } - acc, err := app.RPC.Accounts.UpdateProfile(ctx, prof) - require.NoError(t, err) - testutil.ProtoEqual(t, prof, acc.Profile, "profile update must return full profile") - } - - return app -} - func makeRemotePublication(t *testing.T, ctx context.Context, dhtProvider *App) (*App, *documents.Publication, *App) { var publisher *App { @@ -989,16 +597,3 @@ func updateDocumenTitle(t *testing.T, ctx context.Context, publisher *App, docID require.NoError(t, err) return published } - -func makeTestConfig(t *testing.T) config.Config { - cfg := config.Default() - - cfg.HTTPPort = 0 - cfg.GRPCPort = 0 - cfg.RepoPath = testutil.MakeRepoPath(t) - cfg.P2P.Port = 0 - cfg.P2P.BootstrapPeers = nil - cfg.P2P.NoRelay = true - cfg.P2P.NoMetrics = true - return cfg -} diff --git a/backend/daemon/daemon_queries_test.go b/backend/daemon/daemon_queries_test.go new file mode 100644 index 0000000000..0974b4e802 --- /dev/null +++ b/backend/daemon/daemon_queries_test.go @@ -0,0 +1,24 @@ +package daemon + +import ( + "mintter/backend/daemon/storage" + "mintter/backend/pkg/dqb" + "testing" + + "github.com/stretchr/testify/require" +) + +func TestDBQueries(t *testing.T) { + // This test is here because this is the most top-level package which we know + // imports all other packages that might have database queries. So all these + // queries would have been registered with the global query store in the dqb package. + // This test makes sure all queries are valid and use correct table and column names. + + t.Parallel() + + db, err := storage.OpenSQLite("file::memory:?mode=memory", 0, 1) + require.NoError(t, err) + defer db.Close() + require.NoError(t, storage.InitSQLiteSchema(db)) + require.NoError(t, dqb.GlobalQueries.Test(db)) +} diff --git a/backend/daemon/daemon_testing.go b/backend/daemon/daemon_testing.go new file mode 100644 index 0000000000..ab23794f61 --- /dev/null +++ b/backend/daemon/daemon_testing.go @@ -0,0 +1,72 @@ +package daemon + +import ( + "context" + "mintter/backend/config" + "mintter/backend/core/coretest" + accounts "mintter/backend/daemon/api/accounts/v1alpha" + "mintter/backend/testutil" + "testing" + + "github.com/stretchr/testify/require" +) + +// MakeTestApp creates a new daemon app for testing. +func MakeTestApp(t *testing.T, name string, cfg config.Config, register bool) *App { + return makeTestApp(t, name, cfg, register) +} + +// MakeTestConfig creates a new default config for testing. +func MakeTestConfig(t *testing.T) config.Config { + return makeTestConfig(t) +} + +func makeTestApp(t *testing.T, name string, cfg config.Config, register bool) *App { + ctx, cancel := context.WithCancel(context.Background()) + + u := coretest.NewTester(name) + + repo, err := InitRepo(cfg.Base.DataDir, u.Device.Wrapped()) + require.NoError(t, err) + + app, err := Load(ctx, cfg, repo) + require.NoError(t, err) + t.Cleanup(func() { + cancel() + require.Equal(t, context.Canceled, app.Wait()) + }) + + if register { + err = app.RPC.Daemon.RegisterAccount(ctx, u.Account) + require.NoError(t, err) + + _, err = app.Net.Await(ctx) + require.NoError(t, err) + + _, err = app.Storage.Identity().Await(ctx) + require.NoError(t, err) + + prof := &accounts.Profile{ + Alias: name, + Bio: name + " bio", + } + acc, err := app.RPC.Accounts.UpdateProfile(ctx, prof) + require.NoError(t, err) + testutil.ProtoEqual(t, prof, acc.Profile, "profile update must return full profile") + } + + return app +} + +func makeTestConfig(t *testing.T) config.Config { + cfg := config.Default() + + cfg.HTTP.Port = 0 + cfg.GRPC.Port = 0 + cfg.Base.DataDir = testutil.MakeRepoPath(t) + cfg.P2P.Port = 0 + cfg.P2P.BootstrapPeers = nil + cfg.P2P.NoRelay = true + cfg.P2P.NoMetrics = true + return cfg +} diff --git a/backend/daemon/http.go b/backend/daemon/http.go new file mode 100644 index 0000000000..00fadfd4ef --- /dev/null +++ b/backend/daemon/http.go @@ -0,0 +1,156 @@ +package daemon + +import ( + "context" + "encoding/json" + "fmt" + "mintter/backend/graphql" + "mintter/backend/ipfs" + "mintter/backend/pkg/cleanup" + "mintter/backend/wallet" + "net" + "net/http" + "runtime/debug" + "strconv" + "time" + + "github.com/99designs/gqlgen/graphql/playground" + "github.com/gorilla/mux" + "github.com/improbable-eng/grpc-web/go/grpcweb" + "github.com/prometheus/client_golang/prometheus/promhttp" + "golang.org/x/exp/slices" + "golang.org/x/sync/errgroup" + "google.golang.org/grpc" +) + +// GenericHandler is to be called bay anyone wanting to register a +// new http handler. +type GenericHandler struct { + // Path where the endpoint will be hosted. + Path string + // HTTP handler. + Handler http.Handler + // RoutePrefix | RouteNav. + Mode int +} + +// setupGraphQLHandlers sets up the GraphQL endpoints. +func setupGraphQLHandlers(r *Router, wallet *wallet.Service) { + r.Handle("/graphql", corsMiddleware(graphql.Handler(wallet)), 0) + r.Handle("/playground", playground.Handler("GraphQL Playground", "/graphql"), RouteNav) +} + +// setupIPFSFileHandlers sets up the IPFS file endpoints for uploading and getting files. +func setupIPFSFileHandlers(r *Router, h ipfs.HTTPHandler) { + r.Handle(ipfs.IPFSRootRoute+ipfs.UploadRoute, http.HandlerFunc(h.UploadFile), 0) + r.Handle(ipfs.IPFSRootRoute+ipfs.GetRoute, http.HandlerFunc(h.GetFile), 0) +} + +// setupDebugHandlers sets up the debug endpoints. +func setupDebugHandlers(r *Router) { + r.Handle("/debug/metrics", promhttp.Handler(), RouteNav) + r.Handle("/debug/pprof", http.DefaultServeMux, RoutePrefix|RouteNav) + r.Handle("/debug/vars", http.DefaultServeMux, RoutePrefix|RouteNav) + r.Handle("/debug/grpc", grpcLogsHandler(), RouteNav) + r.Handle("/debug/buildinfo", buildInfoHandler(), RouteNav) +} + +// setupGRPCWebHandler sets up the gRPC-Web handler. +func setupGRPCWebHandler(r *Router, rpc *grpc.Server) { + grpcWebHandler := grpcweb.WrapServer(rpc, grpcweb.WithOriginFunc(func(origin string) bool { + return true + })) + + r.r.MatcherFunc(mux.MatcherFunc(func(r *http.Request, match *mux.RouteMatch) bool { + return grpcWebHandler.IsAcceptableGrpcCorsRequest(r) || grpcWebHandler.IsGrpcWebRequest(r) + })).Handler(grpcWebHandler) +} + +func initHTTP( + port int, + rpc *grpc.Server, + clean *cleanup.Stack, + g *errgroup.Group, + wallet *wallet.Service, + ipfsHandler ipfs.HTTPHandler, + extraHandlers ...GenericHandler, +) (srv *http.Server, lis net.Listener, err error) { + router := &Router{r: mux.NewRouter()} + + setupDebugHandlers(router) + setupGraphQLHandlers(router, wallet) + setupIPFSFileHandlers(router, ipfsHandler) + setupGRPCWebHandler(router, rpc) + for _, handler := range extraHandlers { + router.Handle(handler.Path, handler.Handler, handler.Mode) + } + router.Handle("/", http.HandlerFunc(router.Index), 0) + + srv = &http.Server{ + Addr: ":" + strconv.Itoa(port), + ReadHeaderTimeout: 5 * time.Second, + // WriteTimeout: 10 * time.Second, + IdleTimeout: 20 * time.Second, + Handler: router.r, + } + + lis, err = net.Listen("tcp", srv.Addr) + if err != nil { + return + } + + g.Go(func() error { + err := srv.Serve(lis) + if err == http.ErrServerClosed { + return nil + } + return err + }) + + clean.AddErrFunc(func() error { + return srv.Shutdown(context.Background()) + }) + + return +} + +// corsMiddleware allows different host/origins. +func corsMiddleware(next http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + // allow cross domain AJAX requests + w.Header().Set("Access-Control-Allow-Origin", "*") + w.Header().Set("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept") + next.ServeHTTP(w, r) + }) +} + +func buildInfoHandler() http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + info, ok := debug.ReadBuildInfo() + if !ok { + http.Error(w, "doesn't support build info", http.StatusExpectationFailed) + return + } + + // Don't want to show information about all the dependencies. + info.Deps = nil + + // Want to support text and json. + wantJSON := slices.Contains(r.Header.Values("Accept"), "application/json") || + r.URL.Query().Get("format") == "json" + + if wantJSON { + w.Header().Set("Content-Type", "application/json") + + enc := json.NewEncoder(w) + enc.SetIndent("", " ") + + if err := enc.Encode(info); err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + } + } else { + w.Header().Set("Content-Type", "text/plain") + fmt.Fprint(w, info.String()) + } + }) +} diff --git a/backend/daemon/storage/migrations.go b/backend/daemon/storage/migrations.go index 2428aedb64..92bcb0f9e5 100644 --- a/backend/daemon/storage/migrations.go +++ b/backend/daemon/storage/migrations.go @@ -51,6 +51,47 @@ var migrations = []migration{ {Version: "2023-08-30.01", Run: func(d *Dir, conn *sqlite.Conn) error { return nil }}, + {Version: "2023-09-12.01", Run: func(d *Dir, conn *sqlite.Conn) error { + return sqlitex.ExecScript(conn, ` + DROP TABLE sites; + DROP TABLE invite_tokens; + DROP TABLE site_members; + DROP TABLE web_publications; + `) + }}, + {Version: "2023-09-18.01", Run: func(d *Dir, conn *sqlite.Conn) error { + return sqlitex.ExecScript(conn, ` + DROP TABLE served_sites; + `) + }}, + {Version: "2023-09-18.02", Run: func(d *Dir, conn *sqlite.Conn) error { + return sqlitex.ExecScript(conn, sqlfmt(` + CREATE TABLE remote_sites ( + url TEXT UNIQUE NOT NULL, + peer_id TEXT NOT NULL, + group_id TEXT NOT NULL, + group_version TEXT NOT NULL, + last_sync_time INTEGER NOT NULL, + last_ok_sync_time INTEGER NOT NULL + ); + `)) + }}, + {Version: "2023-09-19.01", Run: func(d *Dir, conn *sqlite.Conn) error { + return sqlitex.ExecScript(conn, sqlfmt(` + CREATE TABLE accounts ( + entity INTEGER REFERENCES lookup (id) ON DELETE CASCADE NOT NULL, + public_key INTEGER REFERENCES lookup (id) ON DELETE CASCADE NOT NULL, + PRIMARY KEY (entity, public_key) + ); + + CREATE INDEX accounts_by_key ON accounts (public_key, entity); + `)) + }}, + {Version: "2023-09-20.01", Run: func(d *Dir, conn *sqlite.Conn) error { + return sqlitex.ExecScript(conn, sqlfmt(` + DELETE FROM kv WHERE key = 'last_reindex_time'; + `)) + }}, } const ( @@ -91,7 +132,7 @@ func (d *Dir) init() (currentVersion string, err error) { } if d.device.Wrapped() == nil { - kp, err := core.NewKeyPairRandom(core.CodecDeviceKey) + kp, err := core.NewKeyPairRandom() if err != nil { return "", fmt.Errorf("failed to generate random device key: %w", err) } @@ -204,7 +245,7 @@ func (d *Dir) maybeLoadAccountKey() error { return err } - account, err := core.NewPublicKey(core.CodecAccountKey, pub) + account, err := core.NewPublicKey(pub) if err != nil { return err } @@ -275,5 +316,5 @@ func loadDeviceKeyFromFile(dir string) (kp core.KeyPair, err error) { return kp, fmt.Errorf("failed to unmarshal private key for device: %w", err) } - return core.NewKeyPair(core.CodecDeviceKey, pk) + return core.NewKeyPair(pk) } diff --git a/backend/daemon/storage/migrations_test.go b/backend/daemon/storage/migrations_test.go index 354950aba3..d04030e155 100644 --- a/backend/daemon/storage/migrations_test.go +++ b/backend/daemon/storage/migrations_test.go @@ -17,19 +17,6 @@ import ( ) func TestMigrateMatchesFreshSchema(t *testing.T) { - // We made a new breaking change so we have no migrations now. - // We can skip this test until we add at least one new migration, - // in which case we need to generate the initial data dir snapshot, - // and store it in testdata. Then we should apply migrations - // on top of this snapshot and verify that it has the same structure - // as new freshly created data dir. - - if len(migrations) == 1 { - t.SkipNow() - } - - t.Fatalf("We now have some migrations. Fix this text!") - // We have manually snapshot the data dir from before the migration framework was implemented. // It's stored in ./testdata/initial-data-dir. // We want to test that the data dir with all applied migrations matches the data dir created from scratch. @@ -37,7 +24,7 @@ func TestMigrateMatchesFreshSchema(t *testing.T) { // and then compare it with a fresh directory. tmpDir := t.TempDir() - err := copyDir("./testdata/initial-data-dir", tmpDir) + err := copyDir("./testdata/mintter-test-db-snapshot", tmpDir) require.NoError(t, err) oldDir, err := New(tmpDir, zap.NewNop()) diff --git a/backend/daemon/storage/schema.gen.go b/backend/daemon/storage/schema.gen.go index 763dcfab62..1dcf2cf6d4 100644 --- a/backend/daemon/storage/schema.gen.go +++ b/backend/daemon/storage/schema.gen.go @@ -6,6 +6,20 @@ import ( "mintter/backend/pkg/sqlitegen" ) +// Table accounts. +const ( + Accounts sqlitegen.Table = "accounts" + AccountsEntity sqlitegen.Column = "accounts.entity" + AccountsPublicKey sqlitegen.Column = "accounts.public_key" +) + +// Table accounts. Plain strings. +const ( + T_Accounts = "accounts" + C_AccountsEntity = "accounts.entity" + C_AccountsPublicKey = "accounts.public_key" +) + // Table blob_attrs. const ( BlobAttrs sqlitegen.Table = "blob_attrs" @@ -192,22 +206,6 @@ const ( C_HeadsResource = "heads.resource" ) -// Table invite_tokens. -const ( - InviteTokens sqlitegen.Table = "invite_tokens" - InviteTokensExpireTime sqlitegen.Column = "invite_tokens.expire_time" - InviteTokensRole sqlitegen.Column = "invite_tokens.role" - InviteTokensToken sqlitegen.Column = "invite_tokens.token" -) - -// Table invite_tokens. Plain strings. -const ( - T_InviteTokens = "invite_tokens" - C_InviteTokensExpireTime = "invite_tokens.expire_time" - C_InviteTokensRole = "invite_tokens.role" - C_InviteTokensToken = "invite_tokens.token" -) - // Table key_delegations. const ( KeyDelegations sqlitegen.Table = "key_delegations" @@ -304,54 +302,26 @@ const ( C_PublicKeysPrincipal = "public_keys.principal" ) -// Table served_sites. -const ( - ServedSites sqlitegen.Table = "served_sites" - ServedSitesGroupID sqlitegen.Column = "served_sites.group_id" - ServedSitesHostname sqlitegen.Column = "served_sites.hostname" - ServedSitesOwnerID sqlitegen.Column = "served_sites.owner_id" - ServedSitesVersion sqlitegen.Column = "served_sites.version" -) - -// Table served_sites. Plain strings. +// Table remote_sites. const ( - T_ServedSites = "served_sites" - C_ServedSitesGroupID = "served_sites.group_id" - C_ServedSitesHostname = "served_sites.hostname" - C_ServedSitesOwnerID = "served_sites.owner_id" - C_ServedSitesVersion = "served_sites.version" + RemoteSites sqlitegen.Table = "remote_sites" + RemoteSitesGroupID sqlitegen.Column = "remote_sites.group_id" + RemoteSitesGroupVersion sqlitegen.Column = "remote_sites.group_version" + RemoteSitesLastOkSyncTime sqlitegen.Column = "remote_sites.last_ok_sync_time" + RemoteSitesLastSyncTime sqlitegen.Column = "remote_sites.last_sync_time" + RemoteSitesPeerID sqlitegen.Column = "remote_sites.peer_id" + RemoteSitesURL sqlitegen.Column = "remote_sites.url" ) -// Table site_members. +// Table remote_sites. Plain strings. const ( - SiteMembers sqlitegen.Table = "site_members" - SiteMembersAccountID sqlitegen.Column = "site_members.account_id" - SiteMembersRole sqlitegen.Column = "site_members.role" -) - -// Table site_members. Plain strings. -const ( - T_SiteMembers = "site_members" - C_SiteMembersAccountID = "site_members.account_id" - C_SiteMembersRole = "site_members.role" -) - -// Table sites. -const ( - Sites sqlitegen.Table = "sites" - SitesAccountID sqlitegen.Column = "sites.account_id" - SitesAddresses sqlitegen.Column = "sites.addresses" - SitesHostname sqlitegen.Column = "sites.hostname" - SitesRole sqlitegen.Column = "sites.role" -) - -// Table sites. Plain strings. -const ( - T_Sites = "sites" - C_SitesAccountID = "sites.account_id" - C_SitesAddresses = "sites.addresses" - C_SitesHostname = "sites.hostname" - C_SitesRole = "sites.role" + T_RemoteSites = "remote_sites" + C_RemoteSitesGroupID = "remote_sites.group_id" + C_RemoteSitesGroupVersion = "remote_sites.group_version" + C_RemoteSitesLastOkSyncTime = "remote_sites.last_ok_sync_time" + C_RemoteSitesLastSyncTime = "remote_sites.last_sync_time" + C_RemoteSitesPeerID = "remote_sites.peer_id" + C_RemoteSitesURL = "remote_sites.url" ) // Table sqlite_sequence. @@ -406,25 +376,11 @@ const ( C_WalletsType = "wallets.type" ) -// Table web_publications. -const ( - WebPublications sqlitegen.Table = "web_publications" - WebPublicationsEID sqlitegen.Column = "web_publications.eid" - WebPublicationsPath sqlitegen.Column = "web_publications.path" - WebPublicationsVersion sqlitegen.Column = "web_publications.version" -) - -// Table web_publications. Plain strings. -const ( - T_WebPublications = "web_publications" - C_WebPublicationsEID = "web_publications.eid" - C_WebPublicationsPath = "web_publications.path" - C_WebPublicationsVersion = "web_publications.version" -) - // Schema describes SQLite columns. var Schema = sqlitegen.Schema{ Columns: map[sqlitegen.Column]sqlitegen.ColumnInfo{ + AccountsEntity: {Table: Accounts, SQLType: "INTEGER"}, + AccountsPublicKey: {Table: Accounts, SQLType: "INTEGER"}, BlobAttrsAnchor: {Table: BlobAttrs, SQLType: "TEXT"}, BlobAttrsBlob: {Table: BlobAttrs, SQLType: "INTEGER"}, BlobAttrsExtra: {Table: BlobAttrs, SQLType: ""}, @@ -468,9 +424,6 @@ var Schema = sqlitegen.Schema{ HeadsBlob: {Table: Heads, SQLType: "INTEGER"}, HeadsName: {Table: Heads, SQLType: "TEXT"}, HeadsResource: {Table: Heads, SQLType: "INTEGER"}, - InviteTokensExpireTime: {Table: InviteTokens, SQLType: "INTEGER"}, - InviteTokensRole: {Table: InviteTokens, SQLType: "INTEGER"}, - InviteTokensToken: {Table: InviteTokens, SQLType: "TEXT"}, KeyDelegationsBlob: {Table: KeyDelegations, SQLType: "INTEGER"}, KeyDelegationsDelegate: {Table: KeyDelegations, SQLType: ""}, KeyDelegationsIssuer: {Table: KeyDelegations, SQLType: ""}, @@ -489,16 +442,12 @@ var Schema = sqlitegen.Schema{ PublicBlobsViewMultihash: {Table: PublicBlobsView, SQLType: "BLOB"}, PublicKeysID: {Table: PublicKeys, SQLType: "INTEGER"}, PublicKeysPrincipal: {Table: PublicKeys, SQLType: "BLOB"}, - ServedSitesGroupID: {Table: ServedSites, SQLType: "INTEGER"}, - ServedSitesHostname: {Table: ServedSites, SQLType: "TEXT"}, - ServedSitesOwnerID: {Table: ServedSites, SQLType: "INTEGER"}, - ServedSitesVersion: {Table: ServedSites, SQLType: "TEXT"}, - SiteMembersAccountID: {Table: SiteMembers, SQLType: "INTEGER"}, - SiteMembersRole: {Table: SiteMembers, SQLType: "INTEGER"}, - SitesAccountID: {Table: Sites, SQLType: "INTEGER"}, - SitesAddresses: {Table: Sites, SQLType: "TEXT"}, - SitesHostname: {Table: Sites, SQLType: "TEXT"}, - SitesRole: {Table: Sites, SQLType: "INTEGER"}, + RemoteSitesGroupID: {Table: RemoteSites, SQLType: "TEXT"}, + RemoteSitesGroupVersion: {Table: RemoteSites, SQLType: "TEXT"}, + RemoteSitesLastOkSyncTime: {Table: RemoteSites, SQLType: "INTEGER"}, + RemoteSitesLastSyncTime: {Table: RemoteSites, SQLType: "INTEGER"}, + RemoteSitesPeerID: {Table: RemoteSites, SQLType: "TEXT"}, + RemoteSitesURL: {Table: RemoteSites, SQLType: "TEXT"}, SQLiteSequenceName: {Table: SQLiteSequence, SQLType: ""}, SQLiteSequenceSeq: {Table: SQLiteSequence, SQLType: ""}, TrustedAccountsID: {Table: TrustedAccounts, SQLType: "INTEGER"}, @@ -510,8 +459,5 @@ var Schema = sqlitegen.Schema{ WalletsPassword: {Table: Wallets, SQLType: "BLOB"}, WalletsToken: {Table: Wallets, SQLType: "BLOB"}, WalletsType: {Table: Wallets, SQLType: "TEXT"}, - WebPublicationsEID: {Table: WebPublications, SQLType: "TEXT"}, - WebPublicationsPath: {Table: WebPublications, SQLType: "TEXT"}, - WebPublicationsVersion: {Table: WebPublications, SQLType: "TEXT"}, }, } diff --git a/backend/daemon/storage/schema.gensum b/backend/daemon/storage/schema.gensum index 7aa43fe7de..89278961b4 100644 --- a/backend/daemon/storage/schema.gensum +++ b/backend/daemon/storage/schema.gensum @@ -1,2 +1,2 @@ -srcs: ac0e621b7e18d8a7bad3dd5f99dda1e6 -outs: 1668302d9dde81889419d6a3a94b2d8f +srcs: 1bf2bad01aa8878b5b11c49322b14f57 +outs: 4bcbab63b12a9ae9bc23f071a4a317ab diff --git a/backend/daemon/storage/schema.go b/backend/daemon/storage/schema.go index 374cdafa78..61350f9815 100644 --- a/backend/daemon/storage/schema.go +++ b/backend/daemon/storage/schema.go @@ -2,8 +2,6 @@ package storage import ( _ "embed" - "regexp" - "strings" ) // Types for the lookup table. @@ -40,35 +38,3 @@ func init() { col.SQLType = "BLOB" Schema.Columns[BlobAttrsExtra] = col } - -// removeSQLComments is written with the help of ChatGPT, but it seems to work. -// We don't need to store comments in the database file, but we want to use them for ourselves. -func removeSQLComments(sql string) string { - re := regexp.MustCompile(`('[^']*')|--.*|/\*[\s\S]*?\*/`) // Regular expression to match SQL comments and string literals - lines := strings.Split(sql, "\n") // Split SQL statement into lines - outLines := make([]string, 0, len(lines)) - for _, line := range lines { - line = re.ReplaceAllStringFunc(line, func(match string) string { - if strings.HasPrefix(match, "--") { - return "" // Remove single-line comments - } else if strings.HasPrefix(match, "/*") { - return "" // Remove multi-line comments - } else { - return match // Preserve string literals - } - }) - // Lines with only comments end up being empty, and we don't want those. - if strings.TrimSpace(line) == "" { - continue - } - // We don't want trailing new lines, because we'll be joining lines later. - line = strings.Trim(line, "\r\n") - // For more convenient formatting, all of our migration statement would have - // an extra tab at the beginning of the line, we can get rid of it. - if line[0] == '\t' { - line = line[1:] - } - outLines = append(outLines, line) - } - return strings.Join(outLines, "\n") // Join lines back together -} diff --git a/backend/daemon/storage/schema.sql b/backend/daemon/storage/schema.sql index b1956aecbb..12ca474948 100644 --- a/backend/daemon/storage/schema.sql +++ b/backend/daemon/storage/schema.sql @@ -225,71 +225,26 @@ CREATE TABLE wallets ( balance INTEGER DEFAULT 0 ); --- Stores sites that user has manually added -CREATE TABLE sites ( - -- Site unique identification. The hostname of the site with protocol https://example.com - hostname TEXT PRIMARY KEY CHECK(hostname <> ''), - -- The role we play in the site ROLE_UNSPECIFIED = 0 | OWNER = 1 | EDITOR = 2 - role INTEGER NOT NULL DEFAULT 0, - -- P2P addresses to connect to that site in the format of multiaddresses. Space separated. - addresses TEXT NOT NULL CHECK(addresses <> ''), - -- The account ID of the site. We need a previous connection to the site so the - -- actual account is inserted in the accounts table when handshake. - account_id INTEGER REFERENCES lookup (id) ON DELETE CASCADE NOT NULL -) WITHOUT ROWID; - -CREATE INDEX sites_by_account ON sites (account_id); - --- Table that stores all the tokens not yet redeemed inside a site. Although this table is relevant only --- for sites at the beginning, keep in mind that any regular node can be upgraded to a site. -CREATE TABLE invite_tokens ( - -- Unique token identification. Random string. - token TEXT PRIMARY KEY CHECK(token <> ''), - -- The member role for the user that will redeem the token. - -- OWNER = 1 | EDITOR = 2. - role INTEGER NOT NULL CHECK (role != 0), - -- Timestamp since the token will no longer be eligible to be redeemed. Seconds since Jan 1, 1970 - expire_time INTEGER NOT NULL CHECK (expire_time > 0) -) WITHOUT ROWID; - --- Table that stores the role each account has inside a site. Although this table is relevant only --- for sites at the beginning, keep in mind that any regular node can be upgraded to a site. -CREATE TABLE site_members ( - -- The account id that has been linked to a role on this site - account_id INTEGER REFERENCES lookup (id) ON DELETE CASCADE NOT NULL, - -- The role of the site member. - -- OWNER = 1 | EDITOR = 2. - role INTEGER NOT NULL CHECK (role != 0), - PRIMARY KEY (account_id) -) WITHOUT ROWID; - --- We currently only allow one owner per site. -CREATE UNIQUE INDEX idx_site_owner ON site_members (role) WHERE role = 1; - --- Stores all the records published on this site. Although this table is relevant only --- for sites at the beginning, keep in mind that any regular node can be upgraded to a site. -CREATE TABLE web_publications ( - -- Entity ID of the published document. - eid TEXT PRIMARY KEY CHECK (eid <> ''), - -- doc version of the base document published. Not its references. - version TEXT NOT NULL, - -- Path this publication is published to. If NULL is not listed. - path TEXT UNIQUE +-- Stores remote sites and their syncing status. +CREATE TABLE remote_sites ( + -- Values below are stable and are used to validate + -- whether site and group information correspond to each other. + url TEXT UNIQUE NOT NULL, + peer_id TEXT NOT NULL, + group_id TEXT NOT NULL, + -- Values below are updated on each sync and used for caching. + group_version TEXT NOT NULL, + last_sync_time INTEGER NOT NULL, + last_ok_sync_time INTEGER NOT NULL ); --- Stores all the sites served locally. Sites are a a group + domain. --- for sites at the beginning, keep in mind that any regular node can be upgraded to a site. -CREATE TABLE served_sites ( - -- the domain + protocol the site is served in. - hostname TEXT CHECK (hostname <> '') PRIMARY KEY, - -- entity ID of the group the site is associated with. - group_id INTEGER REFERENCES lookup (id) NOT NULL, - -- the version of the group the site is serving. - version TEXT NOT NULL, - -- account id of the owner of the group. - owner_id INTEGER REFERENCES lookup (id) NOT NULL, - -- same version + groupid cannot be published in different histnames. - UNIQUE(group_id, version) ON CONFLICT REPLACE +-- Stores mapping between account public keys +-- and their entity IDs. +CREATE TABLE accounts ( + entity INTEGER REFERENCES lookup (id) ON DELETE CASCADE NOT NULL, + public_key INTEGER REFERENCES lookup (id) ON DELETE CASCADE NOT NULL, + PRIMARY KEY (entity, public_key) ); -CREATE INDEX served_sites_by_owner ON served_sites (owner_id); +-- Index to query entity ID of an account public key. +CREATE INDEX accounts_by_key ON accounts (public_key, entity); diff --git a/backend/daemon/storage/sqlfmt.go b/backend/daemon/storage/sqlfmt.go index 21d43b5c95..841f9258da 100644 --- a/backend/daemon/storage/sqlfmt.go +++ b/backend/daemon/storage/sqlfmt.go @@ -51,3 +51,35 @@ func sqlfmt(text string) string { strings.Replace(text, "\t", " ", -1), ) } + +// removeSQLComments is written with the help of ChatGPT, but it seems to work. +// We don't need to store comments in the database file, but we want to use them for ourselves. +func removeSQLComments(sql string) string { + re := regexp.MustCompile(`('[^']*')|--.*|/\*[\s\S]*?\*/`) // Regular expression to match SQL comments and string literals + lines := strings.Split(sql, "\n") // Split SQL statement into lines + outLines := make([]string, 0, len(lines)) + for _, line := range lines { + line = re.ReplaceAllStringFunc(line, func(match string) string { + if strings.HasPrefix(match, "--") { + return "" // Remove single-line comments + } else if strings.HasPrefix(match, "/*") { + return "" // Remove multi-line comments + } else { + return match // Preserve string literals + } + }) + // Lines with only comments end up being empty, and we don't want those. + if strings.TrimSpace(line) == "" { + continue + } + // We don't want trailing new lines, because we'll be joining lines later. + line = strings.Trim(line, "\r\n") + // For more convenient formatting, all of our migration statement would have + // an extra tab at the beginning of the line, we can get rid of it. + if line[0] == '\t' { + line = line[1:] + } + outLines = append(outLines, line) + } + return strings.Join(outLines, "\n") // Join lines back together +} diff --git a/backend/daemon/storage/storage.go b/backend/daemon/storage/storage.go index e8f7547342..15777e1976 100644 --- a/backend/daemon/storage/storage.go +++ b/backend/daemon/storage/storage.go @@ -41,7 +41,7 @@ func NewWithDeviceKey(path string, log *zap.Logger, pk crypto.PrivKey) (*Dir, er return nil, err } - kp, err := core.NewKeyPair(core.CodecDeviceKey, pk) + kp, err := core.NewKeyPair(pk) if err != nil { return nil, err } diff --git a/backend/daemon/storage/testdata/initial-data-dir/VERSION b/backend/daemon/storage/testdata/initial-data-dir/VERSION deleted file mode 100644 index a770f5aa44..0000000000 --- a/backend/daemon/storage/testdata/initial-data-dir/VERSION +++ /dev/null @@ -1 +0,0 @@ -2023-06-26.01 \ No newline at end of file diff --git a/backend/daemon/storage/testdata/initial-data-dir/keys/libp2p_id_ed25519 b/backend/daemon/storage/testdata/initial-data-dir/keys/libp2p_id_ed25519 deleted file mode 100644 index c782a9cb23..0000000000 --- a/backend/daemon/storage/testdata/initial-data-dir/keys/libp2p_id_ed25519 +++ /dev/null @@ -1 +0,0 @@ -@úE™6ù¦"ÂçZùÏœÕþŸX¡¡>Mò×R yèdæ7Ä^㌛C3õøÉÕp%ª)¸ÑRÖªý_‹…ÓŸ \ No newline at end of file diff --git a/backend/daemon/storage/testdata/initial-data-dir/keys/mintter_id_ed25519.pub b/backend/daemon/storage/testdata/initial-data-dir/keys/mintter_id_ed25519.pub deleted file mode 100644 index f3feeb501e..0000000000 --- a/backend/daemon/storage/testdata/initial-data-dir/keys/mintter_id_ed25519.pub +++ /dev/null @@ -1 +0,0 @@ - _{£¢›llt‘ÒÆD}N󶦜³ÂcšæåXd½LAB5 \ No newline at end of file diff --git a/backend/daemon/storage/testdata/initial-data-dir/mintterd.conf b/backend/daemon/storage/testdata/initial-data-dir/mintterd.conf deleted file mode 100644 index d3026ea215..0000000000 --- a/backend/daemon/storage/testdata/initial-data-dir/mintterd.conf +++ /dev/null @@ -1,2 +0,0 @@ -# Config file for the mintterd program. -# You can set any CLI flags here, one per line with a space between key and value. diff --git a/backend/daemon/storage/testdata/mintter-test-db-snapshot/VERSION b/backend/daemon/storage/testdata/mintter-test-db-snapshot/VERSION new file mode 100644 index 0000000000..cdf931172e --- /dev/null +++ b/backend/daemon/storage/testdata/mintter-test-db-snapshot/VERSION @@ -0,0 +1 @@ +2023-08-30.01 \ No newline at end of file diff --git a/backend/daemon/storage/testdata/initial-data-dir/db/db.sqlite b/backend/daemon/storage/testdata/mintter-test-db-snapshot/db/db.sqlite similarity index 98% rename from backend/daemon/storage/testdata/initial-data-dir/db/db.sqlite rename to backend/daemon/storage/testdata/mintter-test-db-snapshot/db/db.sqlite index 1060506bb8..eb43b2d6fc 100644 Binary files a/backend/daemon/storage/testdata/initial-data-dir/db/db.sqlite and b/backend/daemon/storage/testdata/mintter-test-db-snapshot/db/db.sqlite differ diff --git a/backend/daemon/storage/testdata/initial-data-dir/db/db.sqlite-shm b/backend/daemon/storage/testdata/mintter-test-db-snapshot/db/db.sqlite-shm similarity index 92% rename from backend/daemon/storage/testdata/initial-data-dir/db/db.sqlite-shm rename to backend/daemon/storage/testdata/mintter-test-db-snapshot/db/db.sqlite-shm index 9c837c6235..aed9e57939 100644 Binary files a/backend/daemon/storage/testdata/initial-data-dir/db/db.sqlite-shm and b/backend/daemon/storage/testdata/mintter-test-db-snapshot/db/db.sqlite-shm differ diff --git a/backend/daemon/storage/testdata/initial-data-dir/db/db.sqlite-wal b/backend/daemon/storage/testdata/mintter-test-db-snapshot/db/db.sqlite-wal similarity index 80% rename from backend/daemon/storage/testdata/initial-data-dir/db/db.sqlite-wal rename to backend/daemon/storage/testdata/mintter-test-db-snapshot/db/db.sqlite-wal index ea1c05fef9..22e3f890f0 100644 Binary files a/backend/daemon/storage/testdata/initial-data-dir/db/db.sqlite-wal and b/backend/daemon/storage/testdata/mintter-test-db-snapshot/db/db.sqlite-wal differ diff --git a/backend/daemon/storage/testdata/mintter-test-db-snapshot/keys/libp2p_id_ed25519 b/backend/daemon/storage/testdata/mintter-test-db-snapshot/keys/libp2p_id_ed25519 new file mode 100644 index 0000000000..b8d6c51662 --- /dev/null +++ b/backend/daemon/storage/testdata/mintter-test-db-snapshot/keys/libp2p_id_ed25519 @@ -0,0 +1 @@ +@Õèëû¦ZÄ(\uÝ-w@^°úö¥¦8HHchT»1RA>ý;^×à Bª›g8©÷&ÕãÐñiºŒ•+Ú‘E2‡ \ No newline at end of file diff --git a/backend/daemon/storage/testdata/mintter-test-db-snapshot/keys/mintter_id_ed25519.pub b/backend/daemon/storage/testdata/mintter-test-db-snapshot/keys/mintter_id_ed25519.pub new file mode 100644 index 0000000000..b9f9a3a9ec --- /dev/null +++ b/backend/daemon/storage/testdata/mintter-test-db-snapshot/keys/mintter_id_ed25519.pub @@ -0,0 +1 @@ + êÏZ¾õ ê‹î&šR6ï¹›3A¬0¥Ç"þ` \ No newline at end of file diff --git a/backend/genproto/accounts/v1alpha/accounts.pb.go b/backend/genproto/accounts/v1alpha/accounts.pb.go index 122012ca02..4060fb0973 100644 --- a/backend/genproto/accounts/v1alpha/accounts.pb.go +++ b/backend/genproto/accounts/v1alpha/accounts.pb.go @@ -1,6 +1,6 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.30.0 +// protoc-gen-go v1.31.0 // protoc v3.21.12 // source: accounts/v1alpha/accounts.proto diff --git a/backend/genproto/daemon/v1alpha/daemon.pb.go b/backend/genproto/daemon/v1alpha/daemon.pb.go index 7558dd508c..9dcf3154f3 100644 --- a/backend/genproto/daemon/v1alpha/daemon.pb.go +++ b/backend/genproto/daemon/v1alpha/daemon.pb.go @@ -1,6 +1,6 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.30.0 +// protoc-gen-go v1.31.0 // protoc v3.21.12 // source: daemon/v1alpha/daemon.proto diff --git a/backend/genproto/documents/v1alpha/changes.pb.go b/backend/genproto/documents/v1alpha/changes.pb.go index f8bfa3065c..06d7432849 100644 --- a/backend/genproto/documents/v1alpha/changes.pb.go +++ b/backend/genproto/documents/v1alpha/changes.pb.go @@ -2,7 +2,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.30.0 +// protoc-gen-go v1.31.0 // protoc v3.21.12 // source: documents/v1alpha/changes.proto diff --git a/backend/genproto/documents/v1alpha/comments.pb.go b/backend/genproto/documents/v1alpha/comments.pb.go index 8074771030..3fc841379b 100644 --- a/backend/genproto/documents/v1alpha/comments.pb.go +++ b/backend/genproto/documents/v1alpha/comments.pb.go @@ -1,6 +1,6 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.30.0 +// protoc-gen-go v1.31.0 // protoc v3.21.12 // source: documents/v1alpha/comments.proto diff --git a/backend/genproto/documents/v1alpha/content_graph.pb.go b/backend/genproto/documents/v1alpha/content_graph.pb.go index b764c3fbb5..755fd8698a 100644 --- a/backend/genproto/documents/v1alpha/content_graph.pb.go +++ b/backend/genproto/documents/v1alpha/content_graph.pb.go @@ -1,6 +1,6 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.30.0 +// protoc-gen-go v1.31.0 // protoc v3.21.12 // source: documents/v1alpha/content_graph.proto diff --git a/backend/genproto/documents/v1alpha/documents.pb.go b/backend/genproto/documents/v1alpha/documents.pb.go index f41ee5c0c8..53c03b47b1 100644 --- a/backend/genproto/documents/v1alpha/documents.pb.go +++ b/backend/genproto/documents/v1alpha/documents.pb.go @@ -1,6 +1,6 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.30.0 +// protoc-gen-go v1.31.0 // protoc v3.21.12 // source: documents/v1alpha/documents.proto @@ -300,7 +300,6 @@ type DocumentChange struct { // *DocumentChange_MoveBlock_ // *DocumentChange_ReplaceBlock // *DocumentChange_DeleteBlock - // *DocumentChange_SetWebUrl Op isDocumentChange_Op `protobuf_oneof:"op"` } @@ -371,13 +370,6 @@ func (x *DocumentChange) GetDeleteBlock() string { return "" } -func (x *DocumentChange) GetSetWebUrl() string { - if x, ok := x.GetOp().(*DocumentChange_SetWebUrl); ok { - return x.SetWebUrl - } - return "" -} - type isDocumentChange_Op interface { isDocumentChange_Op() } @@ -402,11 +394,6 @@ type DocumentChange_DeleteBlock struct { DeleteBlock string `protobuf:"bytes,5,opt,name=delete_block,json=deleteBlock,proto3,oneof"` } -type DocumentChange_SetWebUrl struct { - // Sets Web URL where site is published. - SetWebUrl string `protobuf:"bytes,6,opt,name=set_web_url,json=setWebUrl,proto3,oneof"` -} - func (*DocumentChange_SetTitle) isDocumentChange_Op() {} func (*DocumentChange_MoveBlock_) isDocumentChange_Op() {} @@ -415,8 +402,6 @@ func (*DocumentChange_ReplaceBlock) isDocumentChange_Op() {} func (*DocumentChange_DeleteBlock) isDocumentChange_Op() {} -func (*DocumentChange_SetWebUrl) isDocumentChange_Op() {} - // Request to list stored drafts. type ListDraftsRequest struct { state protoimpl.MessageState @@ -918,8 +903,6 @@ type Document struct { Title string `protobuf:"bytes,2,opt,name=title,proto3" json:"title,omitempty"` // Output only. Author ID of the document. Author string `protobuf:"bytes,4,opt,name=author,proto3" json:"author,omitempty"` - // Web URL where this document is claimed to be published at. - WebUrl string `protobuf:"bytes,10,opt,name=web_url,json=webUrl,proto3" json:"web_url,omitempty"` // Output only. Account IDs of all the editors of the document. // Includes the original author as well. Editors []string `protobuf:"bytes,11,rep,name=editors,proto3" json:"editors,omitempty"` @@ -986,13 +969,6 @@ func (x *Document) GetAuthor() string { return "" } -func (x *Document) GetWebUrl() string { - if x != nil { - return x.WebUrl - } - return "" -} - func (x *Document) GetEditors() []string { if x != nil { return x.Editors @@ -1390,7 +1366,7 @@ var file_documents_v1alpha_documents_proto_rawDesc = []byte{ 0x13, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x44, 0x72, 0x61, 0x66, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x49, - 0x64, 0x22, 0x86, 0x03, 0x0a, 0x0e, 0x44, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x43, 0x68, + 0x64, 0x22, 0xe4, 0x02, 0x0a, 0x0e, 0x44, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x1d, 0x0a, 0x09, 0x73, 0x65, 0x74, 0x5f, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x08, 0x73, 0x65, 0x74, 0x54, 0x69, 0x74, 0x6c, 0x65, 0x12, 0x58, 0x0a, 0x0a, 0x6d, 0x6f, 0x76, 0x65, 0x5f, 0x62, 0x6c, 0x6f, 0x63, @@ -1405,208 +1381,204 @@ var file_documents_v1alpha_documents_proto_rawDesc = []byte{ 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x00, 0x52, 0x0c, 0x72, 0x65, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x23, 0x0a, 0x0c, 0x64, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, - 0x48, 0x00, 0x52, 0x0b, 0x64, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, - 0x20, 0x0a, 0x0b, 0x73, 0x65, 0x74, 0x5f, 0x77, 0x65, 0x62, 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x06, - 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x09, 0x73, 0x65, 0x74, 0x57, 0x65, 0x62, 0x55, 0x72, - 0x6c, 0x1a, 0x61, 0x0a, 0x09, 0x4d, 0x6f, 0x76, 0x65, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x19, - 0x0a, 0x08, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x07, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x49, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x70, 0x61, 0x72, - 0x65, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x70, 0x61, 0x72, 0x65, 0x6e, - 0x74, 0x12, 0x21, 0x0a, 0x0c, 0x6c, 0x65, 0x66, 0x74, 0x5f, 0x73, 0x69, 0x62, 0x6c, 0x69, 0x6e, - 0x67, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x6c, 0x65, 0x66, 0x74, 0x53, 0x69, 0x62, - 0x6c, 0x69, 0x6e, 0x67, 0x42, 0x04, 0x0a, 0x02, 0x6f, 0x70, 0x22, 0x4f, 0x0a, 0x11, 0x4c, 0x69, - 0x73, 0x74, 0x44, 0x72, 0x61, 0x66, 0x74, 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, + 0x48, 0x00, 0x52, 0x0b, 0x64, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x1a, + 0x61, 0x0a, 0x09, 0x4d, 0x6f, 0x76, 0x65, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x19, 0x0a, 0x08, + 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, + 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x49, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x70, 0x61, 0x72, 0x65, 0x6e, + 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x12, + 0x21, 0x0a, 0x0c, 0x6c, 0x65, 0x66, 0x74, 0x5f, 0x73, 0x69, 0x62, 0x6c, 0x69, 0x6e, 0x67, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x6c, 0x65, 0x66, 0x74, 0x53, 0x69, 0x62, 0x6c, 0x69, + 0x6e, 0x67, 0x42, 0x04, 0x0a, 0x02, 0x6f, 0x70, 0x22, 0x4f, 0x0a, 0x11, 0x4c, 0x69, 0x73, 0x74, + 0x44, 0x72, 0x61, 0x66, 0x74, 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, 0x83, 0x01, 0x0a, 0x12, 0x4c, 0x69, + 0x73, 0x74, 0x44, 0x72, 0x61, 0x66, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x12, 0x45, 0x0a, 0x09, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x01, 0x20, + 0x03, 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, 0x09, 0x64, 0x6f, + 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 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, 0x09, 0x70, 0x61, 0x67, 0x65, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x22, 0x83, 0x01, 0x0a, 0x12, - 0x4c, 0x69, 0x73, 0x74, 0x44, 0x72, 0x61, 0x66, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x45, 0x0a, 0x09, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x18, - 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x6d, 0x69, 0x6e, 0x74, + 0x52, 0x0d, 0x6e, 0x65, 0x78, 0x74, 0x50, 0x61, 0x67, 0x65, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x22, + 0x36, 0x0a, 0x13, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x44, 0x72, 0x61, 0x66, 0x74, 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, 0x94, 0x01, 0x0a, 0x15, 0x47, 0x65, 0x74, 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, 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, 0x12, 0x21, 0x0a, 0x0c, 0x74, + 0x72, 0x75, 0x73, 0x74, 0x65, 0x64, 0x5f, 0x6f, 0x6e, 0x6c, 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, + 0x08, 0x52, 0x0b, 0x74, 0x72, 0x75, 0x73, 0x74, 0x65, 0x64, 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, 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, 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, 0x09, - 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 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, 0x36, 0x0a, 0x13, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x44, 0x72, 0x61, 0x66, - 0x74, 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, 0x94, 0x01, 0x0a, 0x15, 0x47, 0x65, - 0x74, 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, 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, 0x12, 0x21, 0x0a, - 0x0c, 0x74, 0x72, 0x75, 0x73, 0x74, 0x65, 0x64, 0x5f, 0x6f, 0x6e, 0x6c, 0x79, 0x18, 0x04, 0x20, - 0x01, 0x28, 0x08, 0x52, 0x0b, 0x74, 0x72, 0x75, 0x73, 0x74, 0x65, 0x64, 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, 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, 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, 0xfa, 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, 0x17, 0x0a, 0x07, 0x77, 0x65, 0x62, 0x5f, 0x75, 0x72, 0x6c, - 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x77, 0x65, 0x62, 0x55, 0x72, 0x6c, 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, + 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, 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, 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, + 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, 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, 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, + 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, 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, 0x8b, 0x05, 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, + 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x32, 0x8b, 0x05, 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, 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, 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, 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, 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, + 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, 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, 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, + 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, 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, 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, 0xee, 0x02, 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, + 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, 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, 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, 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, + 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x32, 0xee, 0x02, 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, 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, + 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, 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, 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 ( @@ -1928,7 +1900,6 @@ func file_documents_v1alpha_documents_proto_init() { (*DocumentChange_MoveBlock_)(nil), (*DocumentChange_ReplaceBlock)(nil), (*DocumentChange_DeleteBlock)(nil), - (*DocumentChange_SetWebUrl)(nil), } type x struct{} out := protoimpl.TypeBuilder{ diff --git a/backend/genproto/documents/v1alpha/web_publishing.pb.go b/backend/genproto/documents/v1alpha/web_publishing.pb.go deleted file mode 100644 index e167b40342..0000000000 --- a/backend/genproto/documents/v1alpha/web_publishing.pb.go +++ /dev/null @@ -1,2559 +0,0 @@ -// Code generated by protoc-gen-go. DO NOT EDIT. -// versions: -// protoc-gen-go v1.30.0 -// protoc v3.21.12 -// source: documents/v1alpha/web_publishing.proto - -package documents - -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" -) - -const ( - // Verify that this generated code is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) - // Verify that runtime/protoimpl is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) -) - -// Roles a member of the Mintter Site can have. -type Member_Role int32 - -const ( - // Invalid default value. - Member_ROLE_UNSPECIFIED Member_Role = 0 - // Currently there can only be one owner of the site. - Member_OWNER Member_Role = 1 - // Editors are allowed to push content to the site. - Member_EDITOR Member_Role = 2 -) - -// Enum value maps for Member_Role. -var ( - Member_Role_name = map[int32]string{ - 0: "ROLE_UNSPECIFIED", - 1: "OWNER", - 2: "EDITOR", - } - Member_Role_value = map[string]int32{ - "ROLE_UNSPECIFIED": 0, - "OWNER": 1, - "EDITOR": 2, - } -) - -func (x Member_Role) Enum() *Member_Role { - p := new(Member_Role) - *p = x - return p -} - -func (x Member_Role) String() string { - return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) -} - -func (Member_Role) Descriptor() protoreflect.EnumDescriptor { - return file_documents_v1alpha_web_publishing_proto_enumTypes[0].Descriptor() -} - -func (Member_Role) Type() protoreflect.EnumType { - return &file_documents_v1alpha_web_publishing_proto_enumTypes[0] -} - -func (x Member_Role) Number() protoreflect.EnumNumber { - return protoreflect.EnumNumber(x) -} - -// Deprecated: Use Member_Role.Descriptor instead. -func (Member_Role) EnumDescriptor() ([]byte, []int) { - return file_documents_v1alpha_web_publishing_proto_rawDescGZIP(), []int{7, 0} -} - -// Request to add a site. -type AddSiteRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Required. Site hostname. - Hostname string `protobuf:"bytes,1,opt,name=hostname,proto3" json:"hostname,omitempty"` - // Optional. Invite token for the site. Not needed - // if the site already knows our Account ID. - InviteToken string `protobuf:"bytes,2,opt,name=invite_token,json=inviteToken,proto3" json:"invite_token,omitempty"` -} - -func (x *AddSiteRequest) Reset() { - *x = AddSiteRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_documents_v1alpha_web_publishing_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *AddSiteRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*AddSiteRequest) ProtoMessage() {} - -func (x *AddSiteRequest) ProtoReflect() protoreflect.Message { - mi := &file_documents_v1alpha_web_publishing_proto_msgTypes[0] - 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 AddSiteRequest.ProtoReflect.Descriptor instead. -func (*AddSiteRequest) Descriptor() ([]byte, []int) { - return file_documents_v1alpha_web_publishing_proto_rawDescGZIP(), []int{0} -} - -func (x *AddSiteRequest) GetHostname() string { - if x != nil { - return x.Hostname - } - return "" -} - -func (x *AddSiteRequest) GetInviteToken() string { - if x != nil { - return x.InviteToken - } - return "" -} - -// Request to remove a site from the local app backend. -type RemoveSiteRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Required. Site hostname. - Hostname string `protobuf:"bytes,1,opt,name=hostname,proto3" json:"hostname,omitempty"` -} - -func (x *RemoveSiteRequest) Reset() { - *x = RemoveSiteRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_documents_v1alpha_web_publishing_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *RemoveSiteRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*RemoveSiteRequest) ProtoMessage() {} - -func (x *RemoveSiteRequest) ProtoReflect() protoreflect.Message { - mi := &file_documents_v1alpha_web_publishing_proto_msgTypes[1] - 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 RemoveSiteRequest.ProtoReflect.Descriptor instead. -func (*RemoveSiteRequest) Descriptor() ([]byte, []int) { - return file_documents_v1alpha_web_publishing_proto_rawDescGZIP(), []int{1} -} - -func (x *RemoveSiteRequest) GetHostname() string { - if x != nil { - return x.Hostname - } - return "" -} - -// Request to list configured sites. -type ListSitesRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Optional. Number of items per page. - PageSize int32 `protobuf:"varint,1,opt,name=page_size,json=pageSize,proto3" json:"page_size,omitempty"` - // Optional. Token for a specific page. - PageToken string `protobuf:"bytes,2,opt,name=page_token,json=pageToken,proto3" json:"page_token,omitempty"` -} - -func (x *ListSitesRequest) Reset() { - *x = ListSitesRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_documents_v1alpha_web_publishing_proto_msgTypes[2] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ListSitesRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ListSitesRequest) ProtoMessage() {} - -func (x *ListSitesRequest) ProtoReflect() protoreflect.Message { - mi := &file_documents_v1alpha_web_publishing_proto_msgTypes[2] - 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 ListSitesRequest.ProtoReflect.Descriptor instead. -func (*ListSitesRequest) Descriptor() ([]byte, []int) { - return file_documents_v1alpha_web_publishing_proto_rawDescGZIP(), []int{2} -} - -func (x *ListSitesRequest) GetPageSize() int32 { - if x != nil { - return x.PageSize - } - return 0 -} - -func (x *ListSitesRequest) GetPageToken() string { - if x != nil { - return x.PageToken - } - return "" -} - -// Response with a list of sites. -type ListSitesResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // List of sites. - Sites []*SiteConfig `protobuf:"bytes,1,rep,name=sites,proto3" json:"sites,omitempty"` - // Token for the next page if any. - NextPageToken string `protobuf:"bytes,2,opt,name=next_page_token,json=nextPageToken,proto3" json:"next_page_token,omitempty"` -} - -func (x *ListSitesResponse) Reset() { - *x = ListSitesResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_documents_v1alpha_web_publishing_proto_msgTypes[3] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ListSitesResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ListSitesResponse) ProtoMessage() {} - -func (x *ListSitesResponse) ProtoReflect() protoreflect.Message { - mi := &file_documents_v1alpha_web_publishing_proto_msgTypes[3] - 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 ListSitesResponse.ProtoReflect.Descriptor instead. -func (*ListSitesResponse) Descriptor() ([]byte, []int) { - return file_documents_v1alpha_web_publishing_proto_rawDescGZIP(), []int{3} -} - -func (x *ListSitesResponse) GetSites() []*SiteConfig { - if x != nil { - return x.Sites - } - return nil -} - -func (x *ListSitesResponse) GetNextPageToken() string { - if x != nil { - return x.NextPageToken - } - return "" -} - -// Request to a list publication records for a given document -// among the configured web sites. -type ListWebPublicationRecordsRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Required. Document ID. - DocumentId string `protobuf:"bytes,1,opt,name=document_id,json=documentId,proto3" json:"document_id,omitempty"` - // Optional. Specific version of a document. - Version string `protobuf:"bytes,2,opt,name=version,proto3" json:"version,omitempty"` -} - -func (x *ListWebPublicationRecordsRequest) Reset() { - *x = ListWebPublicationRecordsRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_documents_v1alpha_web_publishing_proto_msgTypes[4] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ListWebPublicationRecordsRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ListWebPublicationRecordsRequest) ProtoMessage() {} - -func (x *ListWebPublicationRecordsRequest) ProtoReflect() protoreflect.Message { - mi := &file_documents_v1alpha_web_publishing_proto_msgTypes[4] - 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 ListWebPublicationRecordsRequest.ProtoReflect.Descriptor instead. -func (*ListWebPublicationRecordsRequest) Descriptor() ([]byte, []int) { - return file_documents_v1alpha_web_publishing_proto_rawDescGZIP(), []int{4} -} - -func (x *ListWebPublicationRecordsRequest) GetDocumentId() string { - if x != nil { - return x.DocumentId - } - return "" -} - -func (x *ListWebPublicationRecordsRequest) GetVersion() string { - if x != nil { - return x.Version - } - return "" -} - -// Response with a list of publication records among the web sites. -type ListWebPublicationRecordsResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Publications []*WebPublicationRecord `protobuf:"bytes,1,rep,name=publications,proto3" json:"publications,omitempty"` -} - -func (x *ListWebPublicationRecordsResponse) Reset() { - *x = ListWebPublicationRecordsResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_documents_v1alpha_web_publishing_proto_msgTypes[5] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ListWebPublicationRecordsResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ListWebPublicationRecordsResponse) ProtoMessage() {} - -func (x *ListWebPublicationRecordsResponse) ProtoReflect() protoreflect.Message { - mi := &file_documents_v1alpha_web_publishing_proto_msgTypes[5] - 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 ListWebPublicationRecordsResponse.ProtoReflect.Descriptor instead. -func (*ListWebPublicationRecordsResponse) Descriptor() ([]byte, []int) { - return file_documents_v1alpha_web_publishing_proto_rawDescGZIP(), []int{5} -} - -func (x *ListWebPublicationRecordsResponse) GetPublications() []*WebPublicationRecord { - if x != nil { - return x.Publications - } - return nil -} - -// Local site configuration. -type SiteConfig struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Hostname of the site. - Hostname string `protobuf:"bytes,1,opt,name=hostname,proto3" json:"hostname,omitempty"` - // Our role on this site. - Role Member_Role `protobuf:"varint,2,opt,name=role,proto3,enum=com.mintter.documents.v1alpha.Member_Role" json:"role,omitempty"` -} - -func (x *SiteConfig) Reset() { - *x = SiteConfig{} - if protoimpl.UnsafeEnabled { - mi := &file_documents_v1alpha_web_publishing_proto_msgTypes[6] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *SiteConfig) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*SiteConfig) ProtoMessage() {} - -func (x *SiteConfig) ProtoReflect() protoreflect.Message { - mi := &file_documents_v1alpha_web_publishing_proto_msgTypes[6] - 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 SiteConfig.ProtoReflect.Descriptor instead. -func (*SiteConfig) Descriptor() ([]byte, []int) { - return file_documents_v1alpha_web_publishing_proto_rawDescGZIP(), []int{6} -} - -func (x *SiteConfig) GetHostname() string { - if x != nil { - return x.Hostname - } - return "" -} - -func (x *SiteConfig) GetRole() Member_Role { - if x != nil { - return x.Role - } - return Member_ROLE_UNSPECIFIED -} - -// Member of the web site. -type Member struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Mintter Account ID of the member. - AccountId string `protobuf:"bytes,1,opt,name=account_id,json=accountId,proto3" json:"account_id,omitempty"` - // Member's role on the site. - Role Member_Role `protobuf:"varint,2,opt,name=role,proto3,enum=com.mintter.documents.v1alpha.Member_Role" json:"role,omitempty"` -} - -func (x *Member) Reset() { - *x = Member{} - if protoimpl.UnsafeEnabled { - mi := &file_documents_v1alpha_web_publishing_proto_msgTypes[7] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *Member) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*Member) ProtoMessage() {} - -func (x *Member) ProtoReflect() protoreflect.Message { - mi := &file_documents_v1alpha_web_publishing_proto_msgTypes[7] - 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 Member.ProtoReflect.Descriptor instead. -func (*Member) Descriptor() ([]byte, []int) { - return file_documents_v1alpha_web_publishing_proto_rawDescGZIP(), []int{7} -} - -func (x *Member) GetAccountId() string { - if x != nil { - return x.AccountId - } - return "" -} - -func (x *Member) GetRole() Member_Role { - if x != nil { - return x.Role - } - return Member_ROLE_UNSPECIFIED -} - -// Information about a Mintter Document published on a Mintter Site. -// One Document ID can be published with different versions and/or -// under different paths on a Mintter Web Site, so it can have -// multiple of these records per site. -type WebPublicationRecord struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - DocumentId string `protobuf:"bytes,1,opt,name=document_id,json=documentId,proto3" json:"document_id,omitempty"` - Version string `protobuf:"bytes,2,opt,name=version,proto3" json:"version,omitempty"` - Hostname string `protobuf:"bytes,3,opt,name=hostname,proto3" json:"hostname,omitempty"` - Path string `protobuf:"bytes,4,opt,name=path,proto3" json:"path,omitempty"` -} - -func (x *WebPublicationRecord) Reset() { - *x = WebPublicationRecord{} - if protoimpl.UnsafeEnabled { - mi := &file_documents_v1alpha_web_publishing_proto_msgTypes[8] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *WebPublicationRecord) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*WebPublicationRecord) ProtoMessage() {} - -func (x *WebPublicationRecord) ProtoReflect() protoreflect.Message { - mi := &file_documents_v1alpha_web_publishing_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 WebPublicationRecord.ProtoReflect.Descriptor instead. -func (*WebPublicationRecord) Descriptor() ([]byte, []int) { - return file_documents_v1alpha_web_publishing_proto_rawDescGZIP(), []int{8} -} - -func (x *WebPublicationRecord) GetDocumentId() string { - if x != nil { - return x.DocumentId - } - return "" -} - -func (x *WebPublicationRecord) GetVersion() string { - if x != nil { - return x.Version - } - return "" -} - -func (x *WebPublicationRecord) GetHostname() string { - if x != nil { - return x.Hostname - } - return "" -} - -func (x *WebPublicationRecord) GetPath() string { - if x != nil { - return x.Path - } - return "" -} - -// Request to create a new invite token. -type CreateInviteTokenRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Required. The role to be associated with the new member after invite is redeemed. - // The server might be configured to limit invites for certain roles, but it's not - // restricted in this API definition. - Role Member_Role `protobuf:"varint,1,opt,name=role,proto3,enum=com.mintter.documents.v1alpha.Member_Role" json:"role,omitempty"` - // Optional. The timestamp after which the invite token will expire if not redeemed. - // If not provided, the server will decide the deadline based on the internal configuration. - ExpireTime *timestamppb.Timestamp `protobuf:"bytes,2,opt,name=expire_time,json=expireTime,proto3" json:"expire_time,omitempty"` -} - -func (x *CreateInviteTokenRequest) Reset() { - *x = CreateInviteTokenRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_documents_v1alpha_web_publishing_proto_msgTypes[9] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *CreateInviteTokenRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*CreateInviteTokenRequest) ProtoMessage() {} - -func (x *CreateInviteTokenRequest) ProtoReflect() protoreflect.Message { - mi := &file_documents_v1alpha_web_publishing_proto_msgTypes[9] - 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 CreateInviteTokenRequest.ProtoReflect.Descriptor instead. -func (*CreateInviteTokenRequest) Descriptor() ([]byte, []int) { - return file_documents_v1alpha_web_publishing_proto_rawDescGZIP(), []int{9} -} - -func (x *CreateInviteTokenRequest) GetRole() Member_Role { - if x != nil { - return x.Role - } - return Member_ROLE_UNSPECIFIED -} - -func (x *CreateInviteTokenRequest) GetExpireTime() *timestamppb.Timestamp { - if x != nil { - return x.ExpireTime - } - return nil -} - -// Request to redeem an invite token. This is the most security-sensitive request, -// because it allows to register new members on the site. The server must obtain -// and verify the relation of the communicating peer with a corresponding Mintter Account. -// After the token is redeemed, a new member on the site must be created, associating -// the Mintter Account of the caller with the role invite token was created for. -type RedeemInviteTokenRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Value of the invite token. - Token string `protobuf:"bytes,1,opt,name=token,proto3" json:"token,omitempty"` -} - -func (x *RedeemInviteTokenRequest) Reset() { - *x = RedeemInviteTokenRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_documents_v1alpha_web_publishing_proto_msgTypes[10] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *RedeemInviteTokenRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*RedeemInviteTokenRequest) ProtoMessage() {} - -func (x *RedeemInviteTokenRequest) ProtoReflect() protoreflect.Message { - mi := &file_documents_v1alpha_web_publishing_proto_msgTypes[10] - 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 RedeemInviteTokenRequest.ProtoReflect.Descriptor instead. -func (*RedeemInviteTokenRequest) Descriptor() ([]byte, []int) { - return file_documents_v1alpha_web_publishing_proto_rawDescGZIP(), []int{10} -} - -func (x *RedeemInviteTokenRequest) GetToken() string { - if x != nil { - return x.Token - } - return "" -} - -// Response after the token is redeemed. -type RedeemInviteTokenResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // The role associated with the redeemed token - Role Member_Role `protobuf:"varint,1,opt,name=role,proto3,enum=com.mintter.documents.v1alpha.Member_Role" json:"role,omitempty"` -} - -func (x *RedeemInviteTokenResponse) Reset() { - *x = RedeemInviteTokenResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_documents_v1alpha_web_publishing_proto_msgTypes[11] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *RedeemInviteTokenResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*RedeemInviteTokenResponse) ProtoMessage() {} - -func (x *RedeemInviteTokenResponse) ProtoReflect() protoreflect.Message { - mi := &file_documents_v1alpha_web_publishing_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 RedeemInviteTokenResponse.ProtoReflect.Descriptor instead. -func (*RedeemInviteTokenResponse) Descriptor() ([]byte, []int) { - return file_documents_v1alpha_web_publishing_proto_rawDescGZIP(), []int{11} -} - -func (x *RedeemInviteTokenResponse) GetRole() Member_Role { - if x != nil { - return x.Role - } - return Member_ROLE_UNSPECIFIED -} - -// Request to get the site info. -type GetSiteInfoRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields -} - -func (x *GetSiteInfoRequest) Reset() { - *x = GetSiteInfoRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_documents_v1alpha_web_publishing_proto_msgTypes[12] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *GetSiteInfoRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*GetSiteInfoRequest) ProtoMessage() {} - -func (x *GetSiteInfoRequest) ProtoReflect() protoreflect.Message { - mi := &file_documents_v1alpha_web_publishing_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 GetSiteInfoRequest.ProtoReflect.Descriptor instead. -func (*GetSiteInfoRequest) Descriptor() ([]byte, []int) { - return file_documents_v1alpha_web_publishing_proto_rawDescGZIP(), []int{12} -} - -// Request to update site info. Doesn't support partial updates. -type UpdateSiteInfoRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Title of the site. - Title string `protobuf:"bytes,1,opt,name=title,proto3" json:"title,omitempty"` - // Description of the site. - Description string `protobuf:"bytes,2,opt,name=description,proto3" json:"description,omitempty"` -} - -func (x *UpdateSiteInfoRequest) Reset() { - *x = UpdateSiteInfoRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_documents_v1alpha_web_publishing_proto_msgTypes[13] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *UpdateSiteInfoRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*UpdateSiteInfoRequest) ProtoMessage() {} - -func (x *UpdateSiteInfoRequest) ProtoReflect() protoreflect.Message { - mi := &file_documents_v1alpha_web_publishing_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 UpdateSiteInfoRequest.ProtoReflect.Descriptor instead. -func (*UpdateSiteInfoRequest) Descriptor() ([]byte, []int) { - return file_documents_v1alpha_web_publishing_proto_rawDescGZIP(), []int{13} -} - -func (x *UpdateSiteInfoRequest) GetTitle() string { - if x != nil { - return x.Title - } - return "" -} - -func (x *UpdateSiteInfoRequest) GetDescription() string { - if x != nil { - return x.Description - } - return "" -} - -// Request to list site members. -type ListMembersRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Optional. Number of items per page. - PageSize int32 `protobuf:"varint,1,opt,name=page_size,json=pageSize,proto3" json:"page_size,omitempty"` - // Optional. Token for a specific page. - PageToken string `protobuf:"bytes,2,opt,name=page_token,json=pageToken,proto3" json:"page_token,omitempty"` -} - -func (x *ListMembersRequest) Reset() { - *x = ListMembersRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_documents_v1alpha_web_publishing_proto_msgTypes[14] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ListMembersRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ListMembersRequest) ProtoMessage() {} - -func (x *ListMembersRequest) ProtoReflect() protoreflect.Message { - mi := &file_documents_v1alpha_web_publishing_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 ListMembersRequest.ProtoReflect.Descriptor instead. -func (*ListMembersRequest) Descriptor() ([]byte, []int) { - return file_documents_v1alpha_web_publishing_proto_rawDescGZIP(), []int{14} -} - -func (x *ListMembersRequest) GetPageSize() int32 { - if x != nil { - return x.PageSize - } - return 0 -} - -func (x *ListMembersRequest) GetPageToken() string { - if x != nil { - return x.PageToken - } - return "" -} - -// Response listing site members. -type ListMembersResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // List of members. - Members []*Member `protobuf:"bytes,1,rep,name=members,proto3" json:"members,omitempty"` - // Optional token for the next page. - NextPageToken string `protobuf:"bytes,2,opt,name=next_page_token,json=nextPageToken,proto3" json:"next_page_token,omitempty"` -} - -func (x *ListMembersResponse) Reset() { - *x = ListMembersResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_documents_v1alpha_web_publishing_proto_msgTypes[15] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ListMembersResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ListMembersResponse) ProtoMessage() {} - -func (x *ListMembersResponse) ProtoReflect() protoreflect.Message { - mi := &file_documents_v1alpha_web_publishing_proto_msgTypes[15] - 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 ListMembersResponse.ProtoReflect.Descriptor instead. -func (*ListMembersResponse) Descriptor() ([]byte, []int) { - return file_documents_v1alpha_web_publishing_proto_rawDescGZIP(), []int{15} -} - -func (x *ListMembersResponse) GetMembers() []*Member { - if x != nil { - return x.Members - } - return nil -} - -func (x *ListMembersResponse) GetNextPageToken() string { - if x != nil { - return x.NextPageToken - } - return "" -} - -// Request to get information about a specific member. -type GetMemberRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Required. Mintter Account ID to get the information for. - AccountId string `protobuf:"bytes,1,opt,name=account_id,json=accountId,proto3" json:"account_id,omitempty"` -} - -func (x *GetMemberRequest) Reset() { - *x = GetMemberRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_documents_v1alpha_web_publishing_proto_msgTypes[16] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *GetMemberRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*GetMemberRequest) ProtoMessage() {} - -func (x *GetMemberRequest) ProtoReflect() protoreflect.Message { - mi := &file_documents_v1alpha_web_publishing_proto_msgTypes[16] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use GetMemberRequest.ProtoReflect.Descriptor instead. -func (*GetMemberRequest) Descriptor() ([]byte, []int) { - return file_documents_v1alpha_web_publishing_proto_rawDescGZIP(), []int{16} -} - -func (x *GetMemberRequest) GetAccountId() string { - if x != nil { - return x.AccountId - } - return "" -} - -// Request to delete an existing member. -type DeleteMemberRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Required. Mintter Account ID of the member to be deleted. - AccountId string `protobuf:"bytes,1,opt,name=account_id,json=accountId,proto3" json:"account_id,omitempty"` -} - -func (x *DeleteMemberRequest) Reset() { - *x = DeleteMemberRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_documents_v1alpha_web_publishing_proto_msgTypes[17] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *DeleteMemberRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*DeleteMemberRequest) ProtoMessage() {} - -func (x *DeleteMemberRequest) ProtoReflect() protoreflect.Message { - mi := &file_documents_v1alpha_web_publishing_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 DeleteMemberRequest.ProtoReflect.Descriptor instead. -func (*DeleteMemberRequest) Descriptor() ([]byte, []int) { - return file_documents_v1alpha_web_publishing_proto_rawDescGZIP(), []int{17} -} - -func (x *DeleteMemberRequest) GetAccountId() string { - if x != nil { - return x.AccountId - } - return "" -} - -// Request to publish a Mintter Document on a Mintter Web Site. -type PublishDocumentRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Required. ID of the document to publish. - DocumentId string `protobuf:"bytes,1,opt,name=document_id,json=documentId,proto3" json:"document_id,omitempty"` - // Required. Specific version of the document to publish. - Version string `protobuf:"bytes,2,opt,name=version,proto3" json:"version,omitempty"` - // Required. Path for the URL of this document on the web site. - Path string `protobuf:"bytes,3,opt,name=path,proto3" json:"path,omitempty"` - // List of other supporting materials that are necessary - // to properly render the document being published. - // Namely, originals that are transcluded (or possibly linked) - // in the document being published. - ReferencedDocuments []*ReferencedDocument `protobuf:"bytes,4,rep,name=referenced_documents,json=referencedDocuments,proto3" json:"referenced_documents,omitempty"` -} - -func (x *PublishDocumentRequest) Reset() { - *x = PublishDocumentRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_documents_v1alpha_web_publishing_proto_msgTypes[18] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *PublishDocumentRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*PublishDocumentRequest) ProtoMessage() {} - -func (x *PublishDocumentRequest) ProtoReflect() protoreflect.Message { - mi := &file_documents_v1alpha_web_publishing_proto_msgTypes[18] - 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 PublishDocumentRequest.ProtoReflect.Descriptor instead. -func (*PublishDocumentRequest) Descriptor() ([]byte, []int) { - return file_documents_v1alpha_web_publishing_proto_rawDescGZIP(), []int{18} -} - -func (x *PublishDocumentRequest) GetDocumentId() string { - if x != nil { - return x.DocumentId - } - return "" -} - -func (x *PublishDocumentRequest) GetVersion() string { - if x != nil { - return x.Version - } - return "" -} - -func (x *PublishDocumentRequest) GetPath() string { - if x != nil { - return x.Path - } - return "" -} - -func (x *PublishDocumentRequest) GetReferencedDocuments() []*ReferencedDocument { - if x != nil { - return x.ReferencedDocuments - } - return nil -} - -// Response when publishing a document. -type PublishDocumentResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields -} - -func (x *PublishDocumentResponse) Reset() { - *x = PublishDocumentResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_documents_v1alpha_web_publishing_proto_msgTypes[19] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *PublishDocumentResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*PublishDocumentResponse) ProtoMessage() {} - -func (x *PublishDocumentResponse) ProtoReflect() protoreflect.Message { - mi := &file_documents_v1alpha_web_publishing_proto_msgTypes[19] - 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 PublishDocumentResponse.ProtoReflect.Descriptor instead. -func (*PublishDocumentResponse) Descriptor() ([]byte, []int) { - return file_documents_v1alpha_web_publishing_proto_rawDescGZIP(), []int{19} -} - -// Request to unpublish a document from a site. -type UnpublishDocumentRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Required. Document ID to unpublish from the web site. - DocumentId string `protobuf:"bytes,1,opt,name=document_id,json=documentId,proto3" json:"document_id,omitempty"` - // Optional. Specific version to unpublish from the web site. - // If empty, all versions matching document_id will be unpublished - Version string `protobuf:"bytes,2,opt,name=version,proto3" json:"version,omitempty"` -} - -func (x *UnpublishDocumentRequest) Reset() { - *x = UnpublishDocumentRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_documents_v1alpha_web_publishing_proto_msgTypes[20] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *UnpublishDocumentRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*UnpublishDocumentRequest) ProtoMessage() {} - -func (x *UnpublishDocumentRequest) ProtoReflect() protoreflect.Message { - mi := &file_documents_v1alpha_web_publishing_proto_msgTypes[20] - 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 UnpublishDocumentRequest.ProtoReflect.Descriptor instead. -func (*UnpublishDocumentRequest) Descriptor() ([]byte, []int) { - return file_documents_v1alpha_web_publishing_proto_rawDescGZIP(), []int{20} -} - -func (x *UnpublishDocumentRequest) GetDocumentId() string { - if x != nil { - return x.DocumentId - } - return "" -} - -func (x *UnpublishDocumentRequest) GetVersion() string { - if x != nil { - return x.Version - } - return "" -} - -// Response after unpublishing a web publication. -type UnpublishDocumentResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields -} - -func (x *UnpublishDocumentResponse) Reset() { - *x = UnpublishDocumentResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_documents_v1alpha_web_publishing_proto_msgTypes[21] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *UnpublishDocumentResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*UnpublishDocumentResponse) ProtoMessage() {} - -func (x *UnpublishDocumentResponse) ProtoReflect() protoreflect.Message { - mi := &file_documents_v1alpha_web_publishing_proto_msgTypes[21] - 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 UnpublishDocumentResponse.ProtoReflect.Descriptor instead. -func (*UnpublishDocumentResponse) Descriptor() ([]byte, []int) { - return file_documents_v1alpha_web_publishing_proto_rawDescGZIP(), []int{21} -} - -// Request to list documents published on a web site. -type ListWebPublicationsRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Number of items per page. - PageSize int32 `protobuf:"varint,1,opt,name=page_size,json=pageSize,proto3" json:"page_size,omitempty"` - // Token for a specific page. - PageToken string `protobuf:"bytes,2,opt,name=page_token,json=pageToken,proto3" json:"page_token,omitempty"` - // Optional. DocumentID of the publication to retrieve. - // If not provided, all publications will be returned - DocumentId string `protobuf:"bytes,3,opt,name=document_id,json=documentId,proto3" json:"document_id,omitempty"` -} - -func (x *ListWebPublicationsRequest) Reset() { - *x = ListWebPublicationsRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_documents_v1alpha_web_publishing_proto_msgTypes[22] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ListWebPublicationsRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ListWebPublicationsRequest) ProtoMessage() {} - -func (x *ListWebPublicationsRequest) ProtoReflect() protoreflect.Message { - mi := &file_documents_v1alpha_web_publishing_proto_msgTypes[22] - 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 ListWebPublicationsRequest.ProtoReflect.Descriptor instead. -func (*ListWebPublicationsRequest) Descriptor() ([]byte, []int) { - return file_documents_v1alpha_web_publishing_proto_rawDescGZIP(), []int{22} -} - -func (x *ListWebPublicationsRequest) GetPageSize() int32 { - if x != nil { - return x.PageSize - } - return 0 -} - -func (x *ListWebPublicationsRequest) GetPageToken() string { - if x != nil { - return x.PageToken - } - return "" -} - -func (x *ListWebPublicationsRequest) GetDocumentId() string { - if x != nil { - return x.DocumentId - } - return "" -} - -// Response of all documents published on a web site. -// A single Document ID can have multiple publication records -// under different paths, and/or with different versions. -type ListWebPublicationsResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Publications []*WebPublicationRecord `protobuf:"bytes,1,rep,name=publications,proto3" json:"publications,omitempty"` -} - -func (x *ListWebPublicationsResponse) Reset() { - *x = ListWebPublicationsResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_documents_v1alpha_web_publishing_proto_msgTypes[23] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ListWebPublicationsResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ListWebPublicationsResponse) ProtoMessage() {} - -func (x *ListWebPublicationsResponse) ProtoReflect() protoreflect.Message { - mi := &file_documents_v1alpha_web_publishing_proto_msgTypes[23] - 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 ListWebPublicationsResponse.ProtoReflect.Descriptor instead. -func (*ListWebPublicationsResponse) Descriptor() ([]byte, []int) { - return file_documents_v1alpha_web_publishing_proto_rawDescGZIP(), []int{23} -} - -func (x *ListWebPublicationsResponse) GetPublications() []*WebPublicationRecord { - if x != nil { - return x.Publications - } - return nil -} - -// Invite token is produced by the owner of the site to invite new members. -type InviteToken struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // The value of the invite token. - Token string `protobuf:"bytes,1,opt,name=token,proto3" json:"token,omitempty"` - // Timestamp after which the token will not be recognized by the site. - ExpireTime *timestamppb.Timestamp `protobuf:"bytes,2,opt,name=expire_time,json=expireTime,proto3" json:"expire_time,omitempty"` -} - -func (x *InviteToken) Reset() { - *x = InviteToken{} - if protoimpl.UnsafeEnabled { - mi := &file_documents_v1alpha_web_publishing_proto_msgTypes[24] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *InviteToken) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*InviteToken) ProtoMessage() {} - -func (x *InviteToken) ProtoReflect() protoreflect.Message { - mi := &file_documents_v1alpha_web_publishing_proto_msgTypes[24] - 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 InviteToken.ProtoReflect.Descriptor instead. -func (*InviteToken) Descriptor() ([]byte, []int) { - return file_documents_v1alpha_web_publishing_proto_rawDescGZIP(), []int{24} -} - -func (x *InviteToken) GetToken() string { - if x != nil { - return x.Token - } - return "" -} - -func (x *InviteToken) GetExpireTime() *timestamppb.Timestamp { - if x != nil { - return x.ExpireTime - } - return nil -} - -// Public-facing information about the Mintter Site. -type SiteInfo struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Hostname under which this site is exposed. - Hostname string `protobuf:"bytes,1,opt,name=hostname,proto3" json:"hostname,omitempty"` - // Title of this site. - Title string `protobuf:"bytes,2,opt,name=title,proto3" json:"title,omitempty"` - // Description of this site. - Description string `protobuf:"bytes,3,opt,name=description,proto3" json:"description,omitempty"` - // Mintter Account ID that is configured as the owner of this site. - Owner string `protobuf:"bytes,4,opt,name=owner,proto3" json:"owner,omitempty"` -} - -func (x *SiteInfo) Reset() { - *x = SiteInfo{} - if protoimpl.UnsafeEnabled { - mi := &file_documents_v1alpha_web_publishing_proto_msgTypes[25] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *SiteInfo) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*SiteInfo) ProtoMessage() {} - -func (x *SiteInfo) ProtoReflect() protoreflect.Message { - mi := &file_documents_v1alpha_web_publishing_proto_msgTypes[25] - 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 SiteInfo.ProtoReflect.Descriptor instead. -func (*SiteInfo) Descriptor() ([]byte, []int) { - return file_documents_v1alpha_web_publishing_proto_rawDescGZIP(), []int{25} -} - -func (x *SiteInfo) GetHostname() string { - if x != nil { - return x.Hostname - } - return "" -} - -func (x *SiteInfo) GetTitle() string { - if x != nil { - return x.Title - } - return "" -} - -func (x *SiteInfo) GetDescription() string { - if x != nil { - return x.Description - } - return "" -} - -func (x *SiteInfo) GetOwner() string { - if x != nil { - return x.Owner - } - return "" -} - -// Response for the /.well-known discovery HTTP page. -type SiteDiscoveryConfig struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Mintter Account ID of the site. - AccountId string `protobuf:"bytes,1,opt,name=account_id,json=accountId,proto3" json:"account_id,omitempty"` - // The PeerID of this P2P node. - PeerId string `protobuf:"bytes,2,opt,name=peer_id,json=peerId,proto3" json:"peer_id,omitempty"` - // The addresses of this site node in multiaddr format. - Addresses []string `protobuf:"bytes,3,rep,name=addresses,proto3" json:"addresses,omitempty"` -} - -func (x *SiteDiscoveryConfig) Reset() { - *x = SiteDiscoveryConfig{} - if protoimpl.UnsafeEnabled { - mi := &file_documents_v1alpha_web_publishing_proto_msgTypes[26] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *SiteDiscoveryConfig) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*SiteDiscoveryConfig) ProtoMessage() {} - -func (x *SiteDiscoveryConfig) ProtoReflect() protoreflect.Message { - mi := &file_documents_v1alpha_web_publishing_proto_msgTypes[26] - 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 SiteDiscoveryConfig.ProtoReflect.Descriptor instead. -func (*SiteDiscoveryConfig) Descriptor() ([]byte, []int) { - return file_documents_v1alpha_web_publishing_proto_rawDescGZIP(), []int{26} -} - -func (x *SiteDiscoveryConfig) GetAccountId() string { - if x != nil { - return x.AccountId - } - return "" -} - -func (x *SiteDiscoveryConfig) GetPeerId() string { - if x != nil { - return x.PeerId - } - return "" -} - -func (x *SiteDiscoveryConfig) GetAddresses() []string { - if x != nil { - return x.Addresses - } - return nil -} - -// Description of "referenced" materials that go along -// with a Mintter Document being published on a Web Site. -type ReferencedDocument struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Required. ID of the document. - DocumentId string `protobuf:"bytes,1,opt,name=document_id,json=documentId,proto3" json:"document_id,omitempty"` - // Required. Specific version of the document. - Version string `protobuf:"bytes,2,opt,name=version,proto3" json:"version,omitempty"` -} - -func (x *ReferencedDocument) Reset() { - *x = ReferencedDocument{} - if protoimpl.UnsafeEnabled { - mi := &file_documents_v1alpha_web_publishing_proto_msgTypes[27] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ReferencedDocument) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ReferencedDocument) ProtoMessage() {} - -func (x *ReferencedDocument) ProtoReflect() protoreflect.Message { - mi := &file_documents_v1alpha_web_publishing_proto_msgTypes[27] - 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 ReferencedDocument.ProtoReflect.Descriptor instead. -func (*ReferencedDocument) Descriptor() ([]byte, []int) { - return file_documents_v1alpha_web_publishing_proto_rawDescGZIP(), []int{27} -} - -func (x *ReferencedDocument) GetDocumentId() string { - if x != nil { - return x.DocumentId - } - return "" -} - -func (x *ReferencedDocument) GetVersion() string { - if x != nil { - return x.Version - } - return "" -} - -type GetPathRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Get doc by path. Empty string === home/root doc. - Path string `protobuf:"bytes,1,opt,name=path,proto3" json:"path,omitempty"` -} - -func (x *GetPathRequest) Reset() { - *x = GetPathRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_documents_v1alpha_web_publishing_proto_msgTypes[28] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *GetPathRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*GetPathRequest) ProtoMessage() {} - -func (x *GetPathRequest) ProtoReflect() protoreflect.Message { - mi := &file_documents_v1alpha_web_publishing_proto_msgTypes[28] - 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 GetPathRequest.ProtoReflect.Descriptor instead. -func (*GetPathRequest) Descriptor() ([]byte, []int) { - return file_documents_v1alpha_web_publishing_proto_rawDescGZIP(), []int{28} -} - -func (x *GetPathRequest) GetPath() string { - if x != nil { - return x.Path - } - return "" -} - -type GetPathResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Publication - Publication *Publication `protobuf:"bytes,1,opt,name=publication,proto3" json:"publication,omitempty"` -} - -func (x *GetPathResponse) Reset() { - *x = GetPathResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_documents_v1alpha_web_publishing_proto_msgTypes[29] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *GetPathResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*GetPathResponse) ProtoMessage() {} - -func (x *GetPathResponse) ProtoReflect() protoreflect.Message { - mi := &file_documents_v1alpha_web_publishing_proto_msgTypes[29] - 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 GetPathResponse.ProtoReflect.Descriptor instead. -func (*GetPathResponse) Descriptor() ([]byte, []int) { - return file_documents_v1alpha_web_publishing_proto_rawDescGZIP(), []int{29} -} - -func (x *GetPathResponse) GetPublication() *Publication { - if x != nil { - return x.Publication - } - return nil -} - -var File_documents_v1alpha_web_publishing_proto protoreflect.FileDescriptor - -var file_documents_v1alpha_web_publishing_proto_rawDesc = []byte{ - 0x0a, 0x26, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x2f, 0x76, 0x31, 0x61, 0x6c, - 0x70, 0x68, 0x61, 0x2f, 0x77, 0x65, 0x62, 0x5f, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x69, - 0x6e, 0x67, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x1d, 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, 0x1a, 0x21, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, - 0x74, 0x73, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2f, 0x64, 0x6f, 0x63, 0x75, 0x6d, - 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1f, 0x67, 0x6f, 0x6f, 0x67, - 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x74, 0x69, 0x6d, 0x65, - 0x73, 0x74, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 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, 0x4f, 0x0a, 0x0e, 0x41, 0x64, 0x64, 0x53, - 0x69, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x68, 0x6f, - 0x73, 0x74, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x68, 0x6f, - 0x73, 0x74, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x69, 0x6e, 0x76, 0x69, 0x74, 0x65, - 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x69, 0x6e, - 0x76, 0x69, 0x74, 0x65, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x22, 0x2f, 0x0a, 0x11, 0x52, 0x65, 0x6d, - 0x6f, 0x76, 0x65, 0x53, 0x69, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1a, - 0x0a, 0x08, 0x68, 0x6f, 0x73, 0x74, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x08, 0x68, 0x6f, 0x73, 0x74, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x4e, 0x0a, 0x10, 0x4c, 0x69, - 0x73, 0x74, 0x53, 0x69, 0x74, 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, 0x7c, 0x0a, 0x11, 0x4c, 0x69, - 0x73, 0x74, 0x53, 0x69, 0x74, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x3f, 0x0a, 0x05, 0x73, 0x69, 0x74, 0x65, 0x73, 0x18, 0x01, 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, 0x53, - 0x69, 0x74, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x05, 0x73, 0x69, 0x74, 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, 0x5d, 0x0a, 0x20, 0x4c, 0x69, 0x73, 0x74, - 0x57, 0x65, 0x62, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, - 0x63, 0x6f, 0x72, 0x64, 0x73, 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, 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, 0x7c, 0x0a, 0x21, 0x4c, 0x69, 0x73, 0x74, 0x57, - 0x65, 0x62, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x63, - 0x6f, 0x72, 0x64, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x57, 0x0a, 0x0c, - 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x03, - 0x28, 0x0b, 0x32, 0x33, 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, 0x57, 0x65, 0x62, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x52, 0x0c, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0x68, 0x0a, 0x0a, 0x53, 0x69, 0x74, 0x65, 0x43, 0x6f, 0x6e, - 0x66, 0x69, 0x67, 0x12, 0x1a, 0x0a, 0x08, 0x68, 0x6f, 0x73, 0x74, 0x6e, 0x61, 0x6d, 0x65, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x68, 0x6f, 0x73, 0x74, 0x6e, 0x61, 0x6d, 0x65, 0x12, - 0x3e, 0x0a, 0x04, 0x72, 0x6f, 0x6c, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 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, 0x4d, 0x65, - 0x6d, 0x62, 0x65, 0x72, 0x2e, 0x52, 0x6f, 0x6c, 0x65, 0x52, 0x04, 0x72, 0x6f, 0x6c, 0x65, 0x22, - 0x9c, 0x01, 0x0a, 0x06, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x1d, 0x0a, 0x0a, 0x61, 0x63, - 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, - 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x49, 0x64, 0x12, 0x3e, 0x0a, 0x04, 0x72, 0x6f, 0x6c, - 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 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, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x2e, 0x52, - 0x6f, 0x6c, 0x65, 0x52, 0x04, 0x72, 0x6f, 0x6c, 0x65, 0x22, 0x33, 0x0a, 0x04, 0x52, 0x6f, 0x6c, - 0x65, 0x12, 0x14, 0x0a, 0x10, 0x52, 0x4f, 0x4c, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, - 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x09, 0x0a, 0x05, 0x4f, 0x57, 0x4e, 0x45, 0x52, - 0x10, 0x01, 0x12, 0x0a, 0x0a, 0x06, 0x45, 0x44, 0x49, 0x54, 0x4f, 0x52, 0x10, 0x02, 0x22, 0x81, - 0x01, 0x0a, 0x14, 0x57, 0x65, 0x62, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 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, 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, 0x1a, 0x0a, 0x08, 0x68, 0x6f, 0x73, 0x74, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x68, 0x6f, 0x73, 0x74, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x12, - 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x70, 0x61, - 0x74, 0x68, 0x22, 0x97, 0x01, 0x0a, 0x18, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x49, 0x6e, 0x76, - 0x69, 0x74, 0x65, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, - 0x3e, 0x0a, 0x04, 0x72, 0x6f, 0x6c, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 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, 0x4d, 0x65, - 0x6d, 0x62, 0x65, 0x72, 0x2e, 0x52, 0x6f, 0x6c, 0x65, 0x52, 0x04, 0x72, 0x6f, 0x6c, 0x65, 0x12, - 0x3b, 0x0a, 0x0b, 0x65, 0x78, 0x70, 0x69, 0x72, 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, 0x65, 0x78, 0x70, 0x69, 0x72, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x22, 0x30, 0x0a, 0x18, - 0x52, 0x65, 0x64, 0x65, 0x65, 0x6d, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x54, 0x6f, 0x6b, 0x65, - 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x6f, 0x6b, 0x65, - 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x22, 0x5b, - 0x0a, 0x19, 0x52, 0x65, 0x64, 0x65, 0x65, 0x6d, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x54, 0x6f, - 0x6b, 0x65, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3e, 0x0a, 0x04, 0x72, - 0x6f, 0x6c, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 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, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, - 0x2e, 0x52, 0x6f, 0x6c, 0x65, 0x52, 0x04, 0x72, 0x6f, 0x6c, 0x65, 0x22, 0x14, 0x0a, 0x12, 0x47, - 0x65, 0x74, 0x53, 0x69, 0x74, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x22, 0x4f, 0x0a, 0x15, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x53, 0x69, 0x74, 0x65, 0x49, - 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x69, - 0x74, 0x6c, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x74, 0x69, 0x74, 0x6c, 0x65, - 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, - 0x6f, 0x6e, 0x22, 0x50, 0x0a, 0x12, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, - 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, 0x7e, 0x0a, 0x13, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x65, 0x6d, 0x62, - 0x65, 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3f, 0x0a, 0x07, 0x6d, - 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x25, 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, 0x4d, 0x65, 0x6d, - 0x62, 0x65, 0x72, 0x52, 0x07, 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, 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, 0x31, 0x0a, 0x10, 0x47, 0x65, 0x74, 0x4d, 0x65, 0x6d, 0x62, 0x65, - 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x61, 0x63, 0x63, 0x6f, - 0x75, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x61, 0x63, - 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x49, 0x64, 0x22, 0x34, 0x0a, 0x13, 0x44, 0x65, 0x6c, 0x65, 0x74, - 0x65, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1d, - 0x0a, 0x0a, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x09, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x49, 0x64, 0x22, 0xcd, 0x01, - 0x0a, 0x16, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x44, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, - 0x74, 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, 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, 0x12, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x03, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x12, 0x64, 0x0a, 0x14, 0x72, 0x65, 0x66, 0x65, 0x72, - 0x65, 0x6e, 0x63, 0x65, 0x64, 0x5f, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x18, - 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 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, 0x52, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x64, - 0x44, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x13, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, - 0x6e, 0x63, 0x65, 0x64, 0x44, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x22, 0x19, 0x0a, - 0x17, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x44, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x55, 0x0a, 0x18, 0x55, 0x6e, 0x70, 0x75, - 0x62, 0x6c, 0x69, 0x73, 0x68, 0x44, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 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, 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, - 0x1b, 0x0a, 0x19, 0x55, 0x6e, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x44, 0x6f, 0x63, 0x75, - 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x79, 0x0a, 0x1a, - 0x4c, 0x69, 0x73, 0x74, 0x57, 0x65, 0x62, 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, 0x1f, 0x0a, 0x0b, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, - 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x64, 0x6f, 0x63, - 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x49, 0x64, 0x22, 0x76, 0x0a, 0x1b, 0x4c, 0x69, 0x73, 0x74, 0x57, - 0x65, 0x62, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x57, 0x0a, 0x0c, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x33, 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, 0x57, 0x65, 0x62, - 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x63, 0x6f, 0x72, - 0x64, 0x52, 0x0c, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, - 0x60, 0x0a, 0x0b, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x14, - 0x0a, 0x05, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x74, - 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x3b, 0x0a, 0x0b, 0x65, 0x78, 0x70, 0x69, 0x72, 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, 0x65, 0x78, 0x70, 0x69, 0x72, 0x65, 0x54, 0x69, 0x6d, - 0x65, 0x22, 0x74, 0x0a, 0x08, 0x53, 0x69, 0x74, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x1a, 0x0a, - 0x08, 0x68, 0x6f, 0x73, 0x74, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x08, 0x68, 0x6f, 0x73, 0x74, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x69, 0x74, - 0x6c, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x12, - 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, - 0x6e, 0x12, 0x14, 0x0a, 0x05, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x05, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x22, 0x6b, 0x0a, 0x13, 0x53, 0x69, 0x74, 0x65, 0x44, - 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x1d, - 0x0a, 0x0a, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x09, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x49, 0x64, 0x12, 0x17, 0x0a, - 0x07, 0x70, 0x65, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, - 0x70, 0x65, 0x65, 0x72, 0x49, 0x64, 0x12, 0x1c, 0x0a, 0x09, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, - 0x73, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x09, 0x61, 0x64, 0x64, 0x72, 0x65, - 0x73, 0x73, 0x65, 0x73, 0x22, 0x4f, 0x0a, 0x12, 0x52, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, - 0x65, 0x64, 0x44, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 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, 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, 0x24, 0x0a, 0x0e, 0x47, 0x65, 0x74, 0x50, 0x61, 0x74, 0x68, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x22, 0x5f, 0x0a, 0x0f, 0x47, - 0x65, 0x74, 0x50, 0x61, 0x74, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4c, - 0x0a, 0x0b, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, - 0x01, 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, - 0x0b, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x32, 0xdd, 0x03, 0x0a, - 0x0d, 0x57, 0x65, 0x62, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x12, 0x63, - 0x0a, 0x07, 0x41, 0x64, 0x64, 0x53, 0x69, 0x74, 0x65, 0x12, 0x2d, 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, 0x64, 0x64, 0x53, 0x69, 0x74, - 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 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, 0x53, 0x69, 0x74, 0x65, 0x43, 0x6f, 0x6e, - 0x66, 0x69, 0x67, 0x12, 0x56, 0x0a, 0x0a, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x53, 0x69, 0x74, - 0x65, 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, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x53, 0x69, 0x74, 0x65, 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, 0x6e, 0x0a, 0x09, 0x4c, - 0x69, 0x73, 0x74, 0x53, 0x69, 0x74, 0x65, 0x73, 0x12, 0x2f, 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, 0x53, 0x69, 0x74, - 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 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, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x69, - 0x74, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x9e, 0x01, 0x0a, 0x19, - 0x4c, 0x69, 0x73, 0x74, 0x57, 0x65, 0x62, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x73, 0x12, 0x3f, 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, 0x57, 0x65, - 0x62, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x63, 0x6f, - 0x72, 0x64, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x40, 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, 0x57, - 0x65, 0x62, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x63, - 0x6f, 0x72, 0x64, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x32, 0xa4, 0x0a, 0x0a, - 0x07, 0x57, 0x65, 0x62, 0x53, 0x69, 0x74, 0x65, 0x12, 0x78, 0x0a, 0x11, 0x43, 0x72, 0x65, 0x61, - 0x74, 0x65, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x54, 0x6f, 0x6b, 0x65, 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, 0x43, 0x72, - 0x65, 0x61, 0x74, 0x65, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x54, 0x6f, 0x6b, 0x65, 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, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x54, 0x6f, 0x6b, - 0x65, 0x6e, 0x12, 0x86, 0x01, 0x0a, 0x11, 0x52, 0x65, 0x64, 0x65, 0x65, 0x6d, 0x49, 0x6e, 0x76, - 0x69, 0x74, 0x65, 0x54, 0x6f, 0x6b, 0x65, 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, 0x52, 0x65, 0x64, 0x65, 0x65, 0x6d, 0x49, - 0x6e, 0x76, 0x69, 0x74, 0x65, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 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, 0x52, 0x65, 0x64, 0x65, 0x65, 0x6d, 0x49, 0x6e, 0x76, 0x69, 0x74, 0x65, 0x54, 0x6f, - 0x6b, 0x65, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x69, 0x0a, 0x0b, 0x47, - 0x65, 0x74, 0x53, 0x69, 0x74, 0x65, 0x49, 0x6e, 0x66, 0x6f, 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, 0x47, 0x65, 0x74, 0x53, 0x69, - 0x74, 0x65, 0x49, 0x6e, 0x66, 0x6f, 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, 0x53, 0x69, - 0x74, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x6f, 0x0a, 0x0e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, - 0x53, 0x69, 0x74, 0x65, 0x49, 0x6e, 0x66, 0x6f, 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, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x53, - 0x69, 0x74, 0x65, 0x49, 0x6e, 0x66, 0x6f, 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, 0x53, - 0x69, 0x74, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x74, 0x0a, 0x0b, 0x4c, 0x69, 0x73, 0x74, 0x4d, - 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 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, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x65, 0x6d, 0x62, 0x65, - 0x72, 0x73, 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, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x65, - 0x6d, 0x62, 0x65, 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x63, 0x0a, - 0x09, 0x47, 0x65, 0x74, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x2f, 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, 0x4d, 0x65, - 0x6d, 0x62, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x25, 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, 0x4d, 0x65, 0x6d, 0x62, - 0x65, 0x72, 0x12, 0x5a, 0x0a, 0x0c, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4d, 0x65, 0x6d, 0x62, - 0x65, 0x72, 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, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 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, 0x80, - 0x01, 0x0a, 0x0f, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x44, 0x6f, 0x63, 0x75, 0x6d, 0x65, - 0x6e, 0x74, 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, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x44, 0x6f, 0x63, 0x75, 0x6d, 0x65, - 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 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, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x73, - 0x68, 0x44, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x86, 0x01, 0x0a, 0x11, 0x55, 0x6e, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x44, - 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 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, 0x55, 0x6e, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x73, - 0x68, 0x44, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 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, 0x55, 0x6e, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x44, 0x6f, 0x63, 0x75, 0x6d, 0x65, - 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x8c, 0x01, 0x0a, 0x13, 0x4c, - 0x69, 0x73, 0x74, 0x57, 0x65, 0x62, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x73, 0x12, 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, 0x57, 0x65, 0x62, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x3a, 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, 0x57, 0x65, 0x62, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x68, 0x0a, 0x07, 0x47, 0x65, 0x74, - 0x50, 0x61, 0x74, 0x68, 0x12, 0x2d, 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, 0x61, 0x74, 0x68, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 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, 0x50, 0x61, 0x74, 0x68, 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 ( - file_documents_v1alpha_web_publishing_proto_rawDescOnce sync.Once - file_documents_v1alpha_web_publishing_proto_rawDescData = file_documents_v1alpha_web_publishing_proto_rawDesc -) - -func file_documents_v1alpha_web_publishing_proto_rawDescGZIP() []byte { - file_documents_v1alpha_web_publishing_proto_rawDescOnce.Do(func() { - file_documents_v1alpha_web_publishing_proto_rawDescData = protoimpl.X.CompressGZIP(file_documents_v1alpha_web_publishing_proto_rawDescData) - }) - return file_documents_v1alpha_web_publishing_proto_rawDescData -} - -var file_documents_v1alpha_web_publishing_proto_enumTypes = make([]protoimpl.EnumInfo, 1) -var file_documents_v1alpha_web_publishing_proto_msgTypes = make([]protoimpl.MessageInfo, 30) -var file_documents_v1alpha_web_publishing_proto_goTypes = []interface{}{ - (Member_Role)(0), // 0: com.mintter.documents.v1alpha.Member.Role - (*AddSiteRequest)(nil), // 1: com.mintter.documents.v1alpha.AddSiteRequest - (*RemoveSiteRequest)(nil), // 2: com.mintter.documents.v1alpha.RemoveSiteRequest - (*ListSitesRequest)(nil), // 3: com.mintter.documents.v1alpha.ListSitesRequest - (*ListSitesResponse)(nil), // 4: com.mintter.documents.v1alpha.ListSitesResponse - (*ListWebPublicationRecordsRequest)(nil), // 5: com.mintter.documents.v1alpha.ListWebPublicationRecordsRequest - (*ListWebPublicationRecordsResponse)(nil), // 6: com.mintter.documents.v1alpha.ListWebPublicationRecordsResponse - (*SiteConfig)(nil), // 7: com.mintter.documents.v1alpha.SiteConfig - (*Member)(nil), // 8: com.mintter.documents.v1alpha.Member - (*WebPublicationRecord)(nil), // 9: com.mintter.documents.v1alpha.WebPublicationRecord - (*CreateInviteTokenRequest)(nil), // 10: com.mintter.documents.v1alpha.CreateInviteTokenRequest - (*RedeemInviteTokenRequest)(nil), // 11: com.mintter.documents.v1alpha.RedeemInviteTokenRequest - (*RedeemInviteTokenResponse)(nil), // 12: com.mintter.documents.v1alpha.RedeemInviteTokenResponse - (*GetSiteInfoRequest)(nil), // 13: com.mintter.documents.v1alpha.GetSiteInfoRequest - (*UpdateSiteInfoRequest)(nil), // 14: com.mintter.documents.v1alpha.UpdateSiteInfoRequest - (*ListMembersRequest)(nil), // 15: com.mintter.documents.v1alpha.ListMembersRequest - (*ListMembersResponse)(nil), // 16: com.mintter.documents.v1alpha.ListMembersResponse - (*GetMemberRequest)(nil), // 17: com.mintter.documents.v1alpha.GetMemberRequest - (*DeleteMemberRequest)(nil), // 18: com.mintter.documents.v1alpha.DeleteMemberRequest - (*PublishDocumentRequest)(nil), // 19: com.mintter.documents.v1alpha.PublishDocumentRequest - (*PublishDocumentResponse)(nil), // 20: com.mintter.documents.v1alpha.PublishDocumentResponse - (*UnpublishDocumentRequest)(nil), // 21: com.mintter.documents.v1alpha.UnpublishDocumentRequest - (*UnpublishDocumentResponse)(nil), // 22: com.mintter.documents.v1alpha.UnpublishDocumentResponse - (*ListWebPublicationsRequest)(nil), // 23: com.mintter.documents.v1alpha.ListWebPublicationsRequest - (*ListWebPublicationsResponse)(nil), // 24: com.mintter.documents.v1alpha.ListWebPublicationsResponse - (*InviteToken)(nil), // 25: com.mintter.documents.v1alpha.InviteToken - (*SiteInfo)(nil), // 26: com.mintter.documents.v1alpha.SiteInfo - (*SiteDiscoveryConfig)(nil), // 27: com.mintter.documents.v1alpha.SiteDiscoveryConfig - (*ReferencedDocument)(nil), // 28: com.mintter.documents.v1alpha.ReferencedDocument - (*GetPathRequest)(nil), // 29: com.mintter.documents.v1alpha.GetPathRequest - (*GetPathResponse)(nil), // 30: com.mintter.documents.v1alpha.GetPathResponse - (*timestamppb.Timestamp)(nil), // 31: google.protobuf.Timestamp - (*Publication)(nil), // 32: com.mintter.documents.v1alpha.Publication - (*emptypb.Empty)(nil), // 33: google.protobuf.Empty -} -var file_documents_v1alpha_web_publishing_proto_depIdxs = []int32{ - 7, // 0: com.mintter.documents.v1alpha.ListSitesResponse.sites:type_name -> com.mintter.documents.v1alpha.SiteConfig - 9, // 1: com.mintter.documents.v1alpha.ListWebPublicationRecordsResponse.publications:type_name -> com.mintter.documents.v1alpha.WebPublicationRecord - 0, // 2: com.mintter.documents.v1alpha.SiteConfig.role:type_name -> com.mintter.documents.v1alpha.Member.Role - 0, // 3: com.mintter.documents.v1alpha.Member.role:type_name -> com.mintter.documents.v1alpha.Member.Role - 0, // 4: com.mintter.documents.v1alpha.CreateInviteTokenRequest.role:type_name -> com.mintter.documents.v1alpha.Member.Role - 31, // 5: com.mintter.documents.v1alpha.CreateInviteTokenRequest.expire_time:type_name -> google.protobuf.Timestamp - 0, // 6: com.mintter.documents.v1alpha.RedeemInviteTokenResponse.role:type_name -> com.mintter.documents.v1alpha.Member.Role - 8, // 7: com.mintter.documents.v1alpha.ListMembersResponse.members:type_name -> com.mintter.documents.v1alpha.Member - 28, // 8: com.mintter.documents.v1alpha.PublishDocumentRequest.referenced_documents:type_name -> com.mintter.documents.v1alpha.ReferencedDocument - 9, // 9: com.mintter.documents.v1alpha.ListWebPublicationsResponse.publications:type_name -> com.mintter.documents.v1alpha.WebPublicationRecord - 31, // 10: com.mintter.documents.v1alpha.InviteToken.expire_time:type_name -> google.protobuf.Timestamp - 32, // 11: com.mintter.documents.v1alpha.GetPathResponse.publication:type_name -> com.mintter.documents.v1alpha.Publication - 1, // 12: com.mintter.documents.v1alpha.WebPublishing.AddSite:input_type -> com.mintter.documents.v1alpha.AddSiteRequest - 2, // 13: com.mintter.documents.v1alpha.WebPublishing.RemoveSite:input_type -> com.mintter.documents.v1alpha.RemoveSiteRequest - 3, // 14: com.mintter.documents.v1alpha.WebPublishing.ListSites:input_type -> com.mintter.documents.v1alpha.ListSitesRequest - 5, // 15: com.mintter.documents.v1alpha.WebPublishing.ListWebPublicationRecords:input_type -> com.mintter.documents.v1alpha.ListWebPublicationRecordsRequest - 10, // 16: com.mintter.documents.v1alpha.WebSite.CreateInviteToken:input_type -> com.mintter.documents.v1alpha.CreateInviteTokenRequest - 11, // 17: com.mintter.documents.v1alpha.WebSite.RedeemInviteToken:input_type -> com.mintter.documents.v1alpha.RedeemInviteTokenRequest - 13, // 18: com.mintter.documents.v1alpha.WebSite.GetSiteInfo:input_type -> com.mintter.documents.v1alpha.GetSiteInfoRequest - 14, // 19: com.mintter.documents.v1alpha.WebSite.UpdateSiteInfo:input_type -> com.mintter.documents.v1alpha.UpdateSiteInfoRequest - 15, // 20: com.mintter.documents.v1alpha.WebSite.ListMembers:input_type -> com.mintter.documents.v1alpha.ListMembersRequest - 17, // 21: com.mintter.documents.v1alpha.WebSite.GetMember:input_type -> com.mintter.documents.v1alpha.GetMemberRequest - 18, // 22: com.mintter.documents.v1alpha.WebSite.DeleteMember:input_type -> com.mintter.documents.v1alpha.DeleteMemberRequest - 19, // 23: com.mintter.documents.v1alpha.WebSite.PublishDocument:input_type -> com.mintter.documents.v1alpha.PublishDocumentRequest - 21, // 24: com.mintter.documents.v1alpha.WebSite.UnpublishDocument:input_type -> com.mintter.documents.v1alpha.UnpublishDocumentRequest - 23, // 25: com.mintter.documents.v1alpha.WebSite.ListWebPublications:input_type -> com.mintter.documents.v1alpha.ListWebPublicationsRequest - 29, // 26: com.mintter.documents.v1alpha.WebSite.GetPath:input_type -> com.mintter.documents.v1alpha.GetPathRequest - 7, // 27: com.mintter.documents.v1alpha.WebPublishing.AddSite:output_type -> com.mintter.documents.v1alpha.SiteConfig - 33, // 28: com.mintter.documents.v1alpha.WebPublishing.RemoveSite:output_type -> google.protobuf.Empty - 4, // 29: com.mintter.documents.v1alpha.WebPublishing.ListSites:output_type -> com.mintter.documents.v1alpha.ListSitesResponse - 6, // 30: com.mintter.documents.v1alpha.WebPublishing.ListWebPublicationRecords:output_type -> com.mintter.documents.v1alpha.ListWebPublicationRecordsResponse - 25, // 31: com.mintter.documents.v1alpha.WebSite.CreateInviteToken:output_type -> com.mintter.documents.v1alpha.InviteToken - 12, // 32: com.mintter.documents.v1alpha.WebSite.RedeemInviteToken:output_type -> com.mintter.documents.v1alpha.RedeemInviteTokenResponse - 26, // 33: com.mintter.documents.v1alpha.WebSite.GetSiteInfo:output_type -> com.mintter.documents.v1alpha.SiteInfo - 26, // 34: com.mintter.documents.v1alpha.WebSite.UpdateSiteInfo:output_type -> com.mintter.documents.v1alpha.SiteInfo - 16, // 35: com.mintter.documents.v1alpha.WebSite.ListMembers:output_type -> com.mintter.documents.v1alpha.ListMembersResponse - 8, // 36: com.mintter.documents.v1alpha.WebSite.GetMember:output_type -> com.mintter.documents.v1alpha.Member - 33, // 37: com.mintter.documents.v1alpha.WebSite.DeleteMember:output_type -> google.protobuf.Empty - 20, // 38: com.mintter.documents.v1alpha.WebSite.PublishDocument:output_type -> com.mintter.documents.v1alpha.PublishDocumentResponse - 22, // 39: com.mintter.documents.v1alpha.WebSite.UnpublishDocument:output_type -> com.mintter.documents.v1alpha.UnpublishDocumentResponse - 24, // 40: com.mintter.documents.v1alpha.WebSite.ListWebPublications:output_type -> com.mintter.documents.v1alpha.ListWebPublicationsResponse - 30, // 41: com.mintter.documents.v1alpha.WebSite.GetPath:output_type -> com.mintter.documents.v1alpha.GetPathResponse - 27, // [27:42] is the sub-list for method output_type - 12, // [12:27] is the sub-list for method input_type - 12, // [12:12] is the sub-list for extension type_name - 12, // [12:12] is the sub-list for extension extendee - 0, // [0:12] is the sub-list for field type_name -} - -func init() { file_documents_v1alpha_web_publishing_proto_init() } -func file_documents_v1alpha_web_publishing_proto_init() { - if File_documents_v1alpha_web_publishing_proto != nil { - return - } - file_documents_v1alpha_documents_proto_init() - if !protoimpl.UnsafeEnabled { - file_documents_v1alpha_web_publishing_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*AddSiteRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_documents_v1alpha_web_publishing_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*RemoveSiteRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_documents_v1alpha_web_publishing_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ListSitesRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_documents_v1alpha_web_publishing_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ListSitesResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_documents_v1alpha_web_publishing_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ListWebPublicationRecordsRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_documents_v1alpha_web_publishing_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ListWebPublicationRecordsResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_documents_v1alpha_web_publishing_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SiteConfig); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_documents_v1alpha_web_publishing_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Member); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_documents_v1alpha_web_publishing_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*WebPublicationRecord); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_documents_v1alpha_web_publishing_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*CreateInviteTokenRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_documents_v1alpha_web_publishing_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*RedeemInviteTokenRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_documents_v1alpha_web_publishing_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*RedeemInviteTokenResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_documents_v1alpha_web_publishing_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetSiteInfoRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_documents_v1alpha_web_publishing_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*UpdateSiteInfoRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_documents_v1alpha_web_publishing_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ListMembersRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_documents_v1alpha_web_publishing_proto_msgTypes[15].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ListMembersResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_documents_v1alpha_web_publishing_proto_msgTypes[16].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetMemberRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_documents_v1alpha_web_publishing_proto_msgTypes[17].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DeleteMemberRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_documents_v1alpha_web_publishing_proto_msgTypes[18].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*PublishDocumentRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_documents_v1alpha_web_publishing_proto_msgTypes[19].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*PublishDocumentResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_documents_v1alpha_web_publishing_proto_msgTypes[20].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*UnpublishDocumentRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_documents_v1alpha_web_publishing_proto_msgTypes[21].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*UnpublishDocumentResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_documents_v1alpha_web_publishing_proto_msgTypes[22].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ListWebPublicationsRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_documents_v1alpha_web_publishing_proto_msgTypes[23].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ListWebPublicationsResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_documents_v1alpha_web_publishing_proto_msgTypes[24].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*InviteToken); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_documents_v1alpha_web_publishing_proto_msgTypes[25].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SiteInfo); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_documents_v1alpha_web_publishing_proto_msgTypes[26].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SiteDiscoveryConfig); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_documents_v1alpha_web_publishing_proto_msgTypes[27].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ReferencedDocument); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_documents_v1alpha_web_publishing_proto_msgTypes[28].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetPathRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_documents_v1alpha_web_publishing_proto_msgTypes[29].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetPathResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_documents_v1alpha_web_publishing_proto_rawDesc, - NumEnums: 1, - NumMessages: 30, - NumExtensions: 0, - NumServices: 2, - }, - GoTypes: file_documents_v1alpha_web_publishing_proto_goTypes, - DependencyIndexes: file_documents_v1alpha_web_publishing_proto_depIdxs, - EnumInfos: file_documents_v1alpha_web_publishing_proto_enumTypes, - MessageInfos: file_documents_v1alpha_web_publishing_proto_msgTypes, - }.Build() - File_documents_v1alpha_web_publishing_proto = out.File - file_documents_v1alpha_web_publishing_proto_rawDesc = nil - file_documents_v1alpha_web_publishing_proto_goTypes = nil - file_documents_v1alpha_web_publishing_proto_depIdxs = nil -} diff --git a/backend/genproto/documents/v1alpha/web_publishing_grpc.pb.go b/backend/genproto/documents/v1alpha/web_publishing_grpc.pb.go deleted file mode 100644 index 5f8563b8e2..0000000000 --- a/backend/genproto/documents/v1alpha/web_publishing_grpc.pb.go +++ /dev/null @@ -1,698 +0,0 @@ -// Code generated by protoc-gen-go-grpc. DO NOT EDIT. -// versions: -// - protoc-gen-go-grpc v1.2.0 -// - protoc v3.21.12 -// source: documents/v1alpha/web_publishing.proto - -package documents - -import ( - context "context" - 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 -// is compatible with the grpc package it is being compiled against. -// Requires gRPC-Go v1.32.0 or later. -const _ = grpc.SupportPackageIsVersion7 - -// WebPublishingClient is the client API for WebPublishing service. -// -// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. -type WebPublishingClient interface { - // Adds a site configuration to the local app backend. - AddSite(ctx context.Context, in *AddSiteRequest, opts ...grpc.CallOption) (*SiteConfig, error) - // Removes site configuration from the local app backend. - RemoveSite(ctx context.Context, in *RemoveSiteRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) - // Lists configured sites. - ListSites(ctx context.Context, in *ListSitesRequest, opts ...grpc.CallOption) (*ListSitesResponse, error) - // Lists web publication records for a given document among the configured web sites. - ListWebPublicationRecords(ctx context.Context, in *ListWebPublicationRecordsRequest, opts ...grpc.CallOption) (*ListWebPublicationRecordsResponse, error) -} - -type webPublishingClient struct { - cc grpc.ClientConnInterface -} - -func NewWebPublishingClient(cc grpc.ClientConnInterface) WebPublishingClient { - return &webPublishingClient{cc} -} - -func (c *webPublishingClient) AddSite(ctx context.Context, in *AddSiteRequest, opts ...grpc.CallOption) (*SiteConfig, error) { - out := new(SiteConfig) - err := c.cc.Invoke(ctx, "/com.mintter.documents.v1alpha.WebPublishing/AddSite", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *webPublishingClient) RemoveSite(ctx context.Context, in *RemoveSiteRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) { - out := new(emptypb.Empty) - err := c.cc.Invoke(ctx, "/com.mintter.documents.v1alpha.WebPublishing/RemoveSite", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *webPublishingClient) ListSites(ctx context.Context, in *ListSitesRequest, opts ...grpc.CallOption) (*ListSitesResponse, error) { - out := new(ListSitesResponse) - err := c.cc.Invoke(ctx, "/com.mintter.documents.v1alpha.WebPublishing/ListSites", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *webPublishingClient) ListWebPublicationRecords(ctx context.Context, in *ListWebPublicationRecordsRequest, opts ...grpc.CallOption) (*ListWebPublicationRecordsResponse, error) { - out := new(ListWebPublicationRecordsResponse) - err := c.cc.Invoke(ctx, "/com.mintter.documents.v1alpha.WebPublishing/ListWebPublicationRecords", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -// WebPublishingServer is the server API for WebPublishing service. -// All implementations should embed UnimplementedWebPublishingServer -// for forward compatibility -type WebPublishingServer interface { - // Adds a site configuration to the local app backend. - AddSite(context.Context, *AddSiteRequest) (*SiteConfig, error) - // Removes site configuration from the local app backend. - RemoveSite(context.Context, *RemoveSiteRequest) (*emptypb.Empty, error) - // Lists configured sites. - ListSites(context.Context, *ListSitesRequest) (*ListSitesResponse, error) - // Lists web publication records for a given document among the configured web sites. - ListWebPublicationRecords(context.Context, *ListWebPublicationRecordsRequest) (*ListWebPublicationRecordsResponse, error) -} - -// UnimplementedWebPublishingServer should be embedded to have forward compatible implementations. -type UnimplementedWebPublishingServer struct { -} - -func (UnimplementedWebPublishingServer) AddSite(context.Context, *AddSiteRequest) (*SiteConfig, error) { - return nil, status.Errorf(codes.Unimplemented, "method AddSite not implemented") -} -func (UnimplementedWebPublishingServer) RemoveSite(context.Context, *RemoveSiteRequest) (*emptypb.Empty, error) { - return nil, status.Errorf(codes.Unimplemented, "method RemoveSite not implemented") -} -func (UnimplementedWebPublishingServer) ListSites(context.Context, *ListSitesRequest) (*ListSitesResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method ListSites not implemented") -} -func (UnimplementedWebPublishingServer) ListWebPublicationRecords(context.Context, *ListWebPublicationRecordsRequest) (*ListWebPublicationRecordsResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method ListWebPublicationRecords not implemented") -} - -// UnsafeWebPublishingServer may be embedded to opt out of forward compatibility for this service. -// Use of this interface is not recommended, as added methods to WebPublishingServer will -// result in compilation errors. -type UnsafeWebPublishingServer interface { - mustEmbedUnimplementedWebPublishingServer() -} - -func RegisterWebPublishingServer(s grpc.ServiceRegistrar, srv WebPublishingServer) { - s.RegisterService(&WebPublishing_ServiceDesc, srv) -} - -func _WebPublishing_AddSite_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(AddSiteRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(WebPublishingServer).AddSite(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/com.mintter.documents.v1alpha.WebPublishing/AddSite", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(WebPublishingServer).AddSite(ctx, req.(*AddSiteRequest)) - } - return interceptor(ctx, in, info, handler) -} - -func _WebPublishing_RemoveSite_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(RemoveSiteRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(WebPublishingServer).RemoveSite(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/com.mintter.documents.v1alpha.WebPublishing/RemoveSite", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(WebPublishingServer).RemoveSite(ctx, req.(*RemoveSiteRequest)) - } - return interceptor(ctx, in, info, handler) -} - -func _WebPublishing_ListSites_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(ListSitesRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(WebPublishingServer).ListSites(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/com.mintter.documents.v1alpha.WebPublishing/ListSites", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(WebPublishingServer).ListSites(ctx, req.(*ListSitesRequest)) - } - return interceptor(ctx, in, info, handler) -} - -func _WebPublishing_ListWebPublicationRecords_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(ListWebPublicationRecordsRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(WebPublishingServer).ListWebPublicationRecords(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/com.mintter.documents.v1alpha.WebPublishing/ListWebPublicationRecords", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(WebPublishingServer).ListWebPublicationRecords(ctx, req.(*ListWebPublicationRecordsRequest)) - } - return interceptor(ctx, in, info, handler) -} - -// WebPublishing_ServiceDesc is the grpc.ServiceDesc for WebPublishing service. -// It's only intended for direct use with grpc.RegisterService, -// and not to be introspected or modified (even as a copy) -var WebPublishing_ServiceDesc = grpc.ServiceDesc{ - ServiceName: "com.mintter.documents.v1alpha.WebPublishing", - HandlerType: (*WebPublishingServer)(nil), - Methods: []grpc.MethodDesc{ - { - MethodName: "AddSite", - Handler: _WebPublishing_AddSite_Handler, - }, - { - MethodName: "RemoveSite", - Handler: _WebPublishing_RemoveSite_Handler, - }, - { - MethodName: "ListSites", - Handler: _WebPublishing_ListSites_Handler, - }, - { - MethodName: "ListWebPublicationRecords", - Handler: _WebPublishing_ListWebPublicationRecords_Handler, - }, - }, - Streams: []grpc.StreamDesc{}, - Metadata: "documents/v1alpha/web_publishing.proto", -} - -// WebSiteClient is the client API for WebSite service. -// -// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. -type WebSiteClient interface { - // Creates a new invite token for registering a new member. - // Protected. Must require authentication. - CreateInviteToken(ctx context.Context, in *CreateInviteTokenRequest, opts ...grpc.CallOption) (*InviteToken, error) - // Redeems a previously created invite token to register a new member. - RedeemInviteToken(ctx context.Context, in *RedeemInviteTokenRequest, opts ...grpc.CallOption) (*RedeemInviteTokenResponse, error) - // Gets public-facing site information. - GetSiteInfo(ctx context.Context, in *GetSiteInfoRequest, opts ...grpc.CallOption) (*SiteInfo, error) - // Updates public-facing site information. Doesn't support partial updates, - // hence all the fields must be provided. - // Protected. Must require authentication. - UpdateSiteInfo(ctx context.Context, in *UpdateSiteInfoRequest, opts ...grpc.CallOption) (*SiteInfo, error) - // Lists registered members on the site. - // May be protected or public depending on the privacy policies of the web site. - ListMembers(ctx context.Context, in *ListMembersRequest, opts ...grpc.CallOption) (*ListMembersResponse, error) - // Gets information about a specific member. - // May be protected or public depending on the privacy policies of the web site. - GetMember(ctx context.Context, in *GetMemberRequest, opts ...grpc.CallOption) (*Member, error) - // Deletes an existing member. - // Protected. Must require authentication. - DeleteMember(ctx context.Context, in *DeleteMemberRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) - // Publishes a Mintter Document on the remote web server along with any supporting materials. - PublishDocument(ctx context.Context, in *PublishDocumentRequest, opts ...grpc.CallOption) (*PublishDocumentResponse, error) - // Unpublishes a previously published Document. - UnpublishDocument(ctx context.Context, in *UnpublishDocumentRequest, opts ...grpc.CallOption) (*UnpublishDocumentResponse, error) - // list all the published documents - ListWebPublications(ctx context.Context, in *ListWebPublicationsRequest, opts ...grpc.CallOption) (*ListWebPublicationsResponse, error) - // Get the document published at a given path. - GetPath(ctx context.Context, in *GetPathRequest, opts ...grpc.CallOption) (*GetPathResponse, error) -} - -type webSiteClient struct { - cc grpc.ClientConnInterface -} - -func NewWebSiteClient(cc grpc.ClientConnInterface) WebSiteClient { - return &webSiteClient{cc} -} - -func (c *webSiteClient) CreateInviteToken(ctx context.Context, in *CreateInviteTokenRequest, opts ...grpc.CallOption) (*InviteToken, error) { - out := new(InviteToken) - err := c.cc.Invoke(ctx, "/com.mintter.documents.v1alpha.WebSite/CreateInviteToken", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *webSiteClient) RedeemInviteToken(ctx context.Context, in *RedeemInviteTokenRequest, opts ...grpc.CallOption) (*RedeemInviteTokenResponse, error) { - out := new(RedeemInviteTokenResponse) - err := c.cc.Invoke(ctx, "/com.mintter.documents.v1alpha.WebSite/RedeemInviteToken", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *webSiteClient) GetSiteInfo(ctx context.Context, in *GetSiteInfoRequest, opts ...grpc.CallOption) (*SiteInfo, error) { - out := new(SiteInfo) - err := c.cc.Invoke(ctx, "/com.mintter.documents.v1alpha.WebSite/GetSiteInfo", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *webSiteClient) UpdateSiteInfo(ctx context.Context, in *UpdateSiteInfoRequest, opts ...grpc.CallOption) (*SiteInfo, error) { - out := new(SiteInfo) - err := c.cc.Invoke(ctx, "/com.mintter.documents.v1alpha.WebSite/UpdateSiteInfo", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *webSiteClient) ListMembers(ctx context.Context, in *ListMembersRequest, opts ...grpc.CallOption) (*ListMembersResponse, error) { - out := new(ListMembersResponse) - err := c.cc.Invoke(ctx, "/com.mintter.documents.v1alpha.WebSite/ListMembers", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *webSiteClient) GetMember(ctx context.Context, in *GetMemberRequest, opts ...grpc.CallOption) (*Member, error) { - out := new(Member) - err := c.cc.Invoke(ctx, "/com.mintter.documents.v1alpha.WebSite/GetMember", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *webSiteClient) DeleteMember(ctx context.Context, in *DeleteMemberRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) { - out := new(emptypb.Empty) - err := c.cc.Invoke(ctx, "/com.mintter.documents.v1alpha.WebSite/DeleteMember", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *webSiteClient) PublishDocument(ctx context.Context, in *PublishDocumentRequest, opts ...grpc.CallOption) (*PublishDocumentResponse, error) { - out := new(PublishDocumentResponse) - err := c.cc.Invoke(ctx, "/com.mintter.documents.v1alpha.WebSite/PublishDocument", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *webSiteClient) UnpublishDocument(ctx context.Context, in *UnpublishDocumentRequest, opts ...grpc.CallOption) (*UnpublishDocumentResponse, error) { - out := new(UnpublishDocumentResponse) - err := c.cc.Invoke(ctx, "/com.mintter.documents.v1alpha.WebSite/UnpublishDocument", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *webSiteClient) ListWebPublications(ctx context.Context, in *ListWebPublicationsRequest, opts ...grpc.CallOption) (*ListWebPublicationsResponse, error) { - out := new(ListWebPublicationsResponse) - err := c.cc.Invoke(ctx, "/com.mintter.documents.v1alpha.WebSite/ListWebPublications", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *webSiteClient) GetPath(ctx context.Context, in *GetPathRequest, opts ...grpc.CallOption) (*GetPathResponse, error) { - out := new(GetPathResponse) - err := c.cc.Invoke(ctx, "/com.mintter.documents.v1alpha.WebSite/GetPath", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -// WebSiteServer is the server API for WebSite service. -// All implementations should embed UnimplementedWebSiteServer -// for forward compatibility -type WebSiteServer interface { - // Creates a new invite token for registering a new member. - // Protected. Must require authentication. - CreateInviteToken(context.Context, *CreateInviteTokenRequest) (*InviteToken, error) - // Redeems a previously created invite token to register a new member. - RedeemInviteToken(context.Context, *RedeemInviteTokenRequest) (*RedeemInviteTokenResponse, error) - // Gets public-facing site information. - GetSiteInfo(context.Context, *GetSiteInfoRequest) (*SiteInfo, error) - // Updates public-facing site information. Doesn't support partial updates, - // hence all the fields must be provided. - // Protected. Must require authentication. - UpdateSiteInfo(context.Context, *UpdateSiteInfoRequest) (*SiteInfo, error) - // Lists registered members on the site. - // May be protected or public depending on the privacy policies of the web site. - ListMembers(context.Context, *ListMembersRequest) (*ListMembersResponse, error) - // Gets information about a specific member. - // May be protected or public depending on the privacy policies of the web site. - GetMember(context.Context, *GetMemberRequest) (*Member, error) - // Deletes an existing member. - // Protected. Must require authentication. - DeleteMember(context.Context, *DeleteMemberRequest) (*emptypb.Empty, error) - // Publishes a Mintter Document on the remote web server along with any supporting materials. - PublishDocument(context.Context, *PublishDocumentRequest) (*PublishDocumentResponse, error) - // Unpublishes a previously published Document. - UnpublishDocument(context.Context, *UnpublishDocumentRequest) (*UnpublishDocumentResponse, error) - // list all the published documents - ListWebPublications(context.Context, *ListWebPublicationsRequest) (*ListWebPublicationsResponse, error) - // Get the document published at a given path. - GetPath(context.Context, *GetPathRequest) (*GetPathResponse, error) -} - -// UnimplementedWebSiteServer should be embedded to have forward compatible implementations. -type UnimplementedWebSiteServer struct { -} - -func (UnimplementedWebSiteServer) CreateInviteToken(context.Context, *CreateInviteTokenRequest) (*InviteToken, error) { - return nil, status.Errorf(codes.Unimplemented, "method CreateInviteToken not implemented") -} -func (UnimplementedWebSiteServer) RedeemInviteToken(context.Context, *RedeemInviteTokenRequest) (*RedeemInviteTokenResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method RedeemInviteToken not implemented") -} -func (UnimplementedWebSiteServer) GetSiteInfo(context.Context, *GetSiteInfoRequest) (*SiteInfo, error) { - return nil, status.Errorf(codes.Unimplemented, "method GetSiteInfo not implemented") -} -func (UnimplementedWebSiteServer) UpdateSiteInfo(context.Context, *UpdateSiteInfoRequest) (*SiteInfo, error) { - return nil, status.Errorf(codes.Unimplemented, "method UpdateSiteInfo not implemented") -} -func (UnimplementedWebSiteServer) ListMembers(context.Context, *ListMembersRequest) (*ListMembersResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method ListMembers not implemented") -} -func (UnimplementedWebSiteServer) GetMember(context.Context, *GetMemberRequest) (*Member, error) { - return nil, status.Errorf(codes.Unimplemented, "method GetMember not implemented") -} -func (UnimplementedWebSiteServer) DeleteMember(context.Context, *DeleteMemberRequest) (*emptypb.Empty, error) { - return nil, status.Errorf(codes.Unimplemented, "method DeleteMember not implemented") -} -func (UnimplementedWebSiteServer) PublishDocument(context.Context, *PublishDocumentRequest) (*PublishDocumentResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method PublishDocument not implemented") -} -func (UnimplementedWebSiteServer) UnpublishDocument(context.Context, *UnpublishDocumentRequest) (*UnpublishDocumentResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method UnpublishDocument not implemented") -} -func (UnimplementedWebSiteServer) ListWebPublications(context.Context, *ListWebPublicationsRequest) (*ListWebPublicationsResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method ListWebPublications not implemented") -} -func (UnimplementedWebSiteServer) GetPath(context.Context, *GetPathRequest) (*GetPathResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method GetPath not implemented") -} - -// UnsafeWebSiteServer may be embedded to opt out of forward compatibility for this service. -// Use of this interface is not recommended, as added methods to WebSiteServer will -// result in compilation errors. -type UnsafeWebSiteServer interface { - mustEmbedUnimplementedWebSiteServer() -} - -func RegisterWebSiteServer(s grpc.ServiceRegistrar, srv WebSiteServer) { - s.RegisterService(&WebSite_ServiceDesc, srv) -} - -func _WebSite_CreateInviteToken_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(CreateInviteTokenRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(WebSiteServer).CreateInviteToken(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/com.mintter.documents.v1alpha.WebSite/CreateInviteToken", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(WebSiteServer).CreateInviteToken(ctx, req.(*CreateInviteTokenRequest)) - } - return interceptor(ctx, in, info, handler) -} - -func _WebSite_RedeemInviteToken_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(RedeemInviteTokenRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(WebSiteServer).RedeemInviteToken(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/com.mintter.documents.v1alpha.WebSite/RedeemInviteToken", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(WebSiteServer).RedeemInviteToken(ctx, req.(*RedeemInviteTokenRequest)) - } - return interceptor(ctx, in, info, handler) -} - -func _WebSite_GetSiteInfo_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(GetSiteInfoRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(WebSiteServer).GetSiteInfo(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/com.mintter.documents.v1alpha.WebSite/GetSiteInfo", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(WebSiteServer).GetSiteInfo(ctx, req.(*GetSiteInfoRequest)) - } - return interceptor(ctx, in, info, handler) -} - -func _WebSite_UpdateSiteInfo_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(UpdateSiteInfoRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(WebSiteServer).UpdateSiteInfo(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/com.mintter.documents.v1alpha.WebSite/UpdateSiteInfo", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(WebSiteServer).UpdateSiteInfo(ctx, req.(*UpdateSiteInfoRequest)) - } - return interceptor(ctx, in, info, handler) -} - -func _WebSite_ListMembers_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(ListMembersRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(WebSiteServer).ListMembers(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/com.mintter.documents.v1alpha.WebSite/ListMembers", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(WebSiteServer).ListMembers(ctx, req.(*ListMembersRequest)) - } - return interceptor(ctx, in, info, handler) -} - -func _WebSite_GetMember_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(GetMemberRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(WebSiteServer).GetMember(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/com.mintter.documents.v1alpha.WebSite/GetMember", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(WebSiteServer).GetMember(ctx, req.(*GetMemberRequest)) - } - return interceptor(ctx, in, info, handler) -} - -func _WebSite_DeleteMember_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(DeleteMemberRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(WebSiteServer).DeleteMember(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/com.mintter.documents.v1alpha.WebSite/DeleteMember", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(WebSiteServer).DeleteMember(ctx, req.(*DeleteMemberRequest)) - } - return interceptor(ctx, in, info, handler) -} - -func _WebSite_PublishDocument_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(PublishDocumentRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(WebSiteServer).PublishDocument(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/com.mintter.documents.v1alpha.WebSite/PublishDocument", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(WebSiteServer).PublishDocument(ctx, req.(*PublishDocumentRequest)) - } - return interceptor(ctx, in, info, handler) -} - -func _WebSite_UnpublishDocument_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(UnpublishDocumentRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(WebSiteServer).UnpublishDocument(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/com.mintter.documents.v1alpha.WebSite/UnpublishDocument", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(WebSiteServer).UnpublishDocument(ctx, req.(*UnpublishDocumentRequest)) - } - return interceptor(ctx, in, info, handler) -} - -func _WebSite_ListWebPublications_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(ListWebPublicationsRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(WebSiteServer).ListWebPublications(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/com.mintter.documents.v1alpha.WebSite/ListWebPublications", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(WebSiteServer).ListWebPublications(ctx, req.(*ListWebPublicationsRequest)) - } - return interceptor(ctx, in, info, handler) -} - -func _WebSite_GetPath_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(GetPathRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(WebSiteServer).GetPath(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/com.mintter.documents.v1alpha.WebSite/GetPath", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(WebSiteServer).GetPath(ctx, req.(*GetPathRequest)) - } - return interceptor(ctx, in, info, handler) -} - -// WebSite_ServiceDesc is the grpc.ServiceDesc for WebSite service. -// It's only intended for direct use with grpc.RegisterService, -// and not to be introspected or modified (even as a copy) -var WebSite_ServiceDesc = grpc.ServiceDesc{ - ServiceName: "com.mintter.documents.v1alpha.WebSite", - HandlerType: (*WebSiteServer)(nil), - Methods: []grpc.MethodDesc{ - { - MethodName: "CreateInviteToken", - Handler: _WebSite_CreateInviteToken_Handler, - }, - { - MethodName: "RedeemInviteToken", - Handler: _WebSite_RedeemInviteToken_Handler, - }, - { - MethodName: "GetSiteInfo", - Handler: _WebSite_GetSiteInfo_Handler, - }, - { - MethodName: "UpdateSiteInfo", - Handler: _WebSite_UpdateSiteInfo_Handler, - }, - { - MethodName: "ListMembers", - Handler: _WebSite_ListMembers_Handler, - }, - { - MethodName: "GetMember", - Handler: _WebSite_GetMember_Handler, - }, - { - MethodName: "DeleteMember", - Handler: _WebSite_DeleteMember_Handler, - }, - { - MethodName: "PublishDocument", - Handler: _WebSite_PublishDocument_Handler, - }, - { - MethodName: "UnpublishDocument", - Handler: _WebSite_UnpublishDocument_Handler, - }, - { - MethodName: "ListWebPublications", - Handler: _WebSite_ListWebPublications_Handler, - }, - { - MethodName: "GetPath", - Handler: _WebSite_GetPath_Handler, - }, - }, - Streams: []grpc.StreamDesc{}, - Metadata: "documents/v1alpha/web_publishing.proto", -} diff --git a/backend/genproto/entities/v1alpha/entities.pb.go b/backend/genproto/entities/v1alpha/entities.pb.go index 7fbdb64ddc..9641c96539 100644 --- a/backend/genproto/entities/v1alpha/entities.pb.go +++ b/backend/genproto/entities/v1alpha/entities.pb.go @@ -1,6 +1,6 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.30.0 +// protoc-gen-go v1.31.0 // protoc v3.21.12 // source: entities/v1alpha/entities.proto diff --git a/backend/genproto/groups/v1alpha/groups.pb.go b/backend/genproto/groups/v1alpha/groups.pb.go index 2aa05549e4..3f0e696b32 100644 --- a/backend/genproto/groups/v1alpha/groups.pb.go +++ b/backend/genproto/groups/v1alpha/groups.pb.go @@ -1,6 +1,6 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.30.0 +// protoc-gen-go v1.31.0 // protoc v3.21.12 // source: groups/v1alpha/groups.proto @@ -88,6 +88,9 @@ type CreateGroupRequest struct { // Optional. List of initial members for the new group. // Members can also be managed with separate requests after group is already created. Members map[string]Role `protobuf:"bytes,3,rep,name=members,proto3" json:"members,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"varint,2,opt,name=value,proto3,enum=com.mintter.groups.v1alpha.Role"` + // Optional. Secret setup URL that is provided during site server deployment. + // I.e. a place on the Web where this group has to be published. + SiteSetupUrl string `protobuf:"bytes,4,opt,name=site_setup_url,json=siteSetupUrl,proto3" json:"site_setup_url,omitempty"` } func (x *CreateGroupRequest) Reset() { @@ -143,6 +146,13 @@ func (x *CreateGroupRequest) GetMembers() map[string]Role { return nil } +func (x *CreateGroupRequest) GetSiteSetupUrl() string { + if x != nil { + return x.SiteSetupUrl + } + return "" +} + // Request to get a group. type GetGroupRequest struct { state protoimpl.MessageState @@ -233,6 +243,9 @@ type UpdateGroupRequest struct { // To unpublish content set the value to an empty string for a given pretty path. // Only updated records have to be sent, not all the content of the group. UpdatedContent map[string]string `protobuf:"bytes,5,rep,name=updated_content,json=updatedContent,proto3" json:"updated_content,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` + // Optional. Secret setup URL that is provided during site server deployment. + // I.e. a place on the Web where this group has to be published. + SiteSetupUrl string `protobuf:"bytes,6,opt,name=site_setup_url,json=siteSetupUrl,proto3" json:"site_setup_url,omitempty"` } func (x *UpdateGroupRequest) Reset() { @@ -302,6 +315,13 @@ func (x *UpdateGroupRequest) GetUpdatedContent() map[string]string { return nil } +func (x *UpdateGroupRequest) GetSiteSetupUrl() string { + if x != nil { + return x.SiteSetupUrl + } + return "" +} + // Request to list members. type ListMembersRequest struct { state protoimpl.MessageState @@ -700,267 +720,6 @@ func (x *ListGroupsResponse) GetNextPageToken() string { return "" } -// Makes a site out of an existing group. -type ConvertToSiteRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Required. Secret link provided by the site deployment script. - Link string `protobuf:"bytes,1,opt,name=link,proto3" json:"link,omitempty"` - // Required. Group ID to convert to a site - GroupId string `protobuf:"bytes,2,opt,name=group_id,json=groupId,proto3" json:"group_id,omitempty"` - // Optional. Version of the group to be converted. Latest - // version if not provided - Version string `protobuf:"bytes,3,opt,name=version,proto3" json:"version,omitempty"` -} - -func (x *ConvertToSiteRequest) Reset() { - *x = ConvertToSiteRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_groups_v1alpha_groups_proto_msgTypes[9] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ConvertToSiteRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ConvertToSiteRequest) ProtoMessage() {} - -func (x *ConvertToSiteRequest) ProtoReflect() protoreflect.Message { - mi := &file_groups_v1alpha_groups_proto_msgTypes[9] - 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 ConvertToSiteRequest.ProtoReflect.Descriptor instead. -func (*ConvertToSiteRequest) Descriptor() ([]byte, []int) { - return file_groups_v1alpha_groups_proto_rawDescGZIP(), []int{9} -} - -func (x *ConvertToSiteRequest) GetLink() string { - if x != nil { - return x.Link - } - return "" -} - -func (x *ConvertToSiteRequest) GetGroupId() string { - if x != nil { - return x.GroupId - } - return "" -} - -func (x *ConvertToSiteRequest) GetVersion() string { - if x != nil { - return x.Version - } - return "" -} - -// Response to convert to site. -type ConvertToSiteResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Account of the sites owner. - OwnerId string `protobuf:"bytes,1,opt,name=owner_id,json=ownerId,proto3" json:"owner_id,omitempty"` - // Hostname of the site. - Hostname string `protobuf:"bytes,2,opt,name=hostname,proto3" json:"hostname,omitempty"` -} - -func (x *ConvertToSiteResponse) Reset() { - *x = ConvertToSiteResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_groups_v1alpha_groups_proto_msgTypes[10] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ConvertToSiteResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ConvertToSiteResponse) ProtoMessage() {} - -func (x *ConvertToSiteResponse) ProtoReflect() protoreflect.Message { - mi := &file_groups_v1alpha_groups_proto_msgTypes[10] - 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 ConvertToSiteResponse.ProtoReflect.Descriptor instead. -func (*ConvertToSiteResponse) Descriptor() ([]byte, []int) { - return file_groups_v1alpha_groups_proto_rawDescGZIP(), []int{10} -} - -func (x *ConvertToSiteResponse) GetOwnerId() string { - if x != nil { - return x.OwnerId - } - return "" -} - -func (x *ConvertToSiteResponse) GetHostname() string { - if x != nil { - return x.Hostname - } - return "" -} - -// Request to get site info. -type GetSiteInfoRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Required. hostname where the site is published. - Hostname string `protobuf:"bytes,1,opt,name=hostname,proto3" json:"hostname,omitempty"` - // Optional. Maximum number of members to return. - PageSize int32 `protobuf:"varint,2,opt,name=page_size,json=pageSize,proto3" json:"page_size,omitempty"` - // Optional. Page token to continue listing members from. - PageToken string `protobuf:"bytes,3,opt,name=page_token,json=pageToken,proto3" json:"page_token,omitempty"` -} - -func (x *GetSiteInfoRequest) Reset() { - *x = GetSiteInfoRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_groups_v1alpha_groups_proto_msgTypes[11] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *GetSiteInfoRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*GetSiteInfoRequest) ProtoMessage() {} - -func (x *GetSiteInfoRequest) ProtoReflect() protoreflect.Message { - mi := &file_groups_v1alpha_groups_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 GetSiteInfoRequest.ProtoReflect.Descriptor instead. -func (*GetSiteInfoRequest) Descriptor() ([]byte, []int) { - return file_groups_v1alpha_groups_proto_rawDescGZIP(), []int{11} -} - -func (x *GetSiteInfoRequest) GetHostname() string { - if x != nil { - return x.Hostname - } - return "" -} - -func (x *GetSiteInfoRequest) GetPageSize() int32 { - if x != nil { - return x.PageSize - } - return 0 -} - -func (x *GetSiteInfoRequest) GetPageToken() string { - if x != nil { - return x.PageToken - } - return "" -} - -// Response to get site info. -type GetSiteInfoResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // ID of the group the site is serving. - GroupId string `protobuf:"bytes,1,opt,name=group_id,json=groupId,proto3" json:"group_id,omitempty"` - // Current Version of the group that the site is serving. - // Empty means last version. - Version string `protobuf:"bytes,2,opt,name=version,proto3" json:"version,omitempty"` - // Owner's account of the site. - OwnerId string `protobuf:"bytes,3,opt,name=owner_id,json=ownerId,proto3" json:"owner_id,omitempty"` -} - -func (x *GetSiteInfoResponse) Reset() { - *x = GetSiteInfoResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_groups_v1alpha_groups_proto_msgTypes[12] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *GetSiteInfoResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*GetSiteInfoResponse) ProtoMessage() {} - -func (x *GetSiteInfoResponse) ProtoReflect() protoreflect.Message { - mi := &file_groups_v1alpha_groups_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 GetSiteInfoResponse.ProtoReflect.Descriptor instead. -func (*GetSiteInfoResponse) Descriptor() ([]byte, []int) { - return file_groups_v1alpha_groups_proto_rawDescGZIP(), []int{12} -} - -func (x *GetSiteInfoResponse) GetGroupId() string { - if x != nil { - return x.GroupId - } - return "" -} - -func (x *GetSiteInfoResponse) GetVersion() string { - if x != nil { - return x.Version - } - return "" -} - -func (x *GetSiteInfoResponse) GetOwnerId() string { - if x != nil { - return x.OwnerId - } - return "" -} - // Request to list groups for a document. type ListDocumentGroupsRequest struct { state protoimpl.MessageState @@ -979,7 +738,7 @@ type ListDocumentGroupsRequest struct { func (x *ListDocumentGroupsRequest) Reset() { *x = ListDocumentGroupsRequest{} if protoimpl.UnsafeEnabled { - mi := &file_groups_v1alpha_groups_proto_msgTypes[13] + mi := &file_groups_v1alpha_groups_proto_msgTypes[9] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -992,7 +751,7 @@ func (x *ListDocumentGroupsRequest) String() string { func (*ListDocumentGroupsRequest) ProtoMessage() {} func (x *ListDocumentGroupsRequest) ProtoReflect() protoreflect.Message { - mi := &file_groups_v1alpha_groups_proto_msgTypes[13] + mi := &file_groups_v1alpha_groups_proto_msgTypes[9] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1005,7 +764,7 @@ func (x *ListDocumentGroupsRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ListDocumentGroupsRequest.ProtoReflect.Descriptor instead. func (*ListDocumentGroupsRequest) Descriptor() ([]byte, []int) { - return file_groups_v1alpha_groups_proto_rawDescGZIP(), []int{13} + return file_groups_v1alpha_groups_proto_rawDescGZIP(), []int{9} } func (x *ListDocumentGroupsRequest) GetDocumentId() string { @@ -1044,7 +803,7 @@ type ListDocumentGroupsResponse struct { func (x *ListDocumentGroupsResponse) Reset() { *x = ListDocumentGroupsResponse{} if protoimpl.UnsafeEnabled { - mi := &file_groups_v1alpha_groups_proto_msgTypes[14] + mi := &file_groups_v1alpha_groups_proto_msgTypes[10] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1057,7 +816,7 @@ func (x *ListDocumentGroupsResponse) String() string { func (*ListDocumentGroupsResponse) ProtoMessage() {} func (x *ListDocumentGroupsResponse) ProtoReflect() protoreflect.Message { - mi := &file_groups_v1alpha_groups_proto_msgTypes[14] + mi := &file_groups_v1alpha_groups_proto_msgTypes[10] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1070,7 +829,7 @@ func (x *ListDocumentGroupsResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ListDocumentGroupsResponse.ProtoReflect.Descriptor instead. func (*ListDocumentGroupsResponse) Descriptor() ([]byte, []int) { - return file_groups_v1alpha_groups_proto_rawDescGZIP(), []int{14} + return file_groups_v1alpha_groups_proto_rawDescGZIP(), []int{10} } func (x *ListDocumentGroupsResponse) GetItems() []*ListDocumentGroupsResponse_Item { @@ -1105,7 +864,7 @@ type ListAccountGroupsRequest struct { func (x *ListAccountGroupsRequest) Reset() { *x = ListAccountGroupsRequest{} if protoimpl.UnsafeEnabled { - mi := &file_groups_v1alpha_groups_proto_msgTypes[15] + mi := &file_groups_v1alpha_groups_proto_msgTypes[11] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1118,7 +877,7 @@ func (x *ListAccountGroupsRequest) String() string { func (*ListAccountGroupsRequest) ProtoMessage() {} func (x *ListAccountGroupsRequest) ProtoReflect() protoreflect.Message { - mi := &file_groups_v1alpha_groups_proto_msgTypes[15] + mi := &file_groups_v1alpha_groups_proto_msgTypes[11] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1131,7 +890,7 @@ func (x *ListAccountGroupsRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ListAccountGroupsRequest.ProtoReflect.Descriptor instead. func (*ListAccountGroupsRequest) Descriptor() ([]byte, []int) { - return file_groups_v1alpha_groups_proto_rawDescGZIP(), []int{15} + return file_groups_v1alpha_groups_proto_rawDescGZIP(), []int{11} } func (x *ListAccountGroupsRequest) GetAccountId() string { @@ -1170,7 +929,7 @@ type ListAccountGroupsResponse struct { func (x *ListAccountGroupsResponse) Reset() { *x = ListAccountGroupsResponse{} if protoimpl.UnsafeEnabled { - mi := &file_groups_v1alpha_groups_proto_msgTypes[16] + mi := &file_groups_v1alpha_groups_proto_msgTypes[12] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1183,7 +942,7 @@ func (x *ListAccountGroupsResponse) String() string { func (*ListAccountGroupsResponse) ProtoMessage() {} func (x *ListAccountGroupsResponse) ProtoReflect() protoreflect.Message { - mi := &file_groups_v1alpha_groups_proto_msgTypes[16] + mi := &file_groups_v1alpha_groups_proto_msgTypes[12] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1196,7 +955,7 @@ func (x *ListAccountGroupsResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ListAccountGroupsResponse.ProtoReflect.Descriptor instead. func (*ListAccountGroupsResponse) Descriptor() ([]byte, []int) { - return file_groups_v1alpha_groups_proto_rawDescGZIP(), []int{16} + return file_groups_v1alpha_groups_proto_rawDescGZIP(), []int{12} } func (x *ListAccountGroupsResponse) GetItems() []*ListAccountGroupsResponse_Item { @@ -1234,12 +993,14 @@ type Group struct { Version string `protobuf:"bytes,6,opt,name=version,proto3" json:"version,omitempty"` // Timestamp of the version of the group. UpdateTime *timestamppb.Timestamp `protobuf:"bytes,7,opt,name=update_time,json=updateTime,proto3" json:"update_time,omitempty"` + // Optional. Site-related information for groups that are published to sites. + SiteInfo *Group_SiteInfo `protobuf:"bytes,8,opt,name=site_info,json=siteInfo,proto3" json:"site_info,omitempty"` } func (x *Group) Reset() { *x = Group{} if protoimpl.UnsafeEnabled { - mi := &file_groups_v1alpha_groups_proto_msgTypes[17] + mi := &file_groups_v1alpha_groups_proto_msgTypes[13] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1252,7 +1013,7 @@ func (x *Group) String() string { func (*Group) ProtoMessage() {} func (x *Group) ProtoReflect() protoreflect.Message { - mi := &file_groups_v1alpha_groups_proto_msgTypes[17] + mi := &file_groups_v1alpha_groups_proto_msgTypes[13] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1265,7 +1026,7 @@ func (x *Group) ProtoReflect() protoreflect.Message { // Deprecated: Use Group.ProtoReflect.Descriptor instead. func (*Group) Descriptor() ([]byte, []int) { - return file_groups_v1alpha_groups_proto_rawDescGZIP(), []int{17} + return file_groups_v1alpha_groups_proto_rawDescGZIP(), []int{13} } func (x *Group) GetId() string { @@ -1317,6 +1078,13 @@ func (x *Group) GetUpdateTime() *timestamppb.Timestamp { return nil } +func (x *Group) GetSiteInfo() *Group_SiteInfo { + if x != nil { + return x.SiteInfo + } + return nil +} + type ListDocumentGroupsResponse_Item struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -1338,7 +1106,7 @@ type ListDocumentGroupsResponse_Item struct { func (x *ListDocumentGroupsResponse_Item) Reset() { *x = ListDocumentGroupsResponse_Item{} if protoimpl.UnsafeEnabled { - mi := &file_groups_v1alpha_groups_proto_msgTypes[23] + mi := &file_groups_v1alpha_groups_proto_msgTypes[19] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1351,7 +1119,7 @@ func (x *ListDocumentGroupsResponse_Item) String() string { func (*ListDocumentGroupsResponse_Item) ProtoMessage() {} func (x *ListDocumentGroupsResponse_Item) ProtoReflect() protoreflect.Message { - mi := &file_groups_v1alpha_groups_proto_msgTypes[23] + mi := &file_groups_v1alpha_groups_proto_msgTypes[19] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1364,7 +1132,7 @@ func (x *ListDocumentGroupsResponse_Item) ProtoReflect() protoreflect.Message { // Deprecated: Use ListDocumentGroupsResponse_Item.ProtoReflect.Descriptor instead. func (*ListDocumentGroupsResponse_Item) Descriptor() ([]byte, []int) { - return file_groups_v1alpha_groups_proto_rawDescGZIP(), []int{14, 0} + return file_groups_v1alpha_groups_proto_rawDescGZIP(), []int{10, 0} } func (x *ListDocumentGroupsResponse_Item) GetGroupId() string { @@ -1414,7 +1182,7 @@ type ListAccountGroupsResponse_Item struct { func (x *ListAccountGroupsResponse_Item) Reset() { *x = ListAccountGroupsResponse_Item{} if protoimpl.UnsafeEnabled { - mi := &file_groups_v1alpha_groups_proto_msgTypes[24] + mi := &file_groups_v1alpha_groups_proto_msgTypes[20] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1427,7 +1195,7 @@ func (x *ListAccountGroupsResponse_Item) String() string { func (*ListAccountGroupsResponse_Item) ProtoMessage() {} func (x *ListAccountGroupsResponse_Item) ProtoReflect() protoreflect.Message { - mi := &file_groups_v1alpha_groups_proto_msgTypes[24] + mi := &file_groups_v1alpha_groups_proto_msgTypes[20] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1440,7 +1208,7 @@ func (x *ListAccountGroupsResponse_Item) ProtoReflect() protoreflect.Message { // Deprecated: Use ListAccountGroupsResponse_Item.ProtoReflect.Descriptor instead. func (*ListAccountGroupsResponse_Item) Descriptor() ([]byte, []int) { - return file_groups_v1alpha_groups_proto_rawDescGZIP(), []int{16, 0} + return file_groups_v1alpha_groups_proto_rawDescGZIP(), []int{12, 0} } func (x *ListAccountGroupsResponse_Item) GetGroup() *Group { @@ -1457,6 +1225,83 @@ func (x *ListAccountGroupsResponse_Item) GetRole() Role { return Role_ROLE_UNSPECIFIED } +// Extra metadata about Site Groups. +type Group_SiteInfo struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Base Web URL of the Site where the Group is being published to. + BaseUrl string `protobuf:"bytes,1,opt,name=base_url,json=baseUrl,proto3" json:"base_url,omitempty"` + // Timestamp of the last sync of the Group's content with the Site. + // This field will be updated regardless of whether we were able to sync or not. + LastSyncTime *timestamppb.Timestamp `protobuf:"bytes,2,opt,name=last_sync_time,json=lastSyncTime,proto3" json:"last_sync_time,omitempty"` + // Timestamp of the last successful sync of the Group's content with the Site. + LastOkSyncTime *timestamppb.Timestamp `protobuf:"bytes,3,opt,name=last_ok_sync_time,json=lastOkSyncTime,proto3" json:"last_ok_sync_time,omitempty"` + // Version of the Group as per the Site. + Version string `protobuf:"bytes,4,opt,name=version,proto3" json:"version,omitempty"` +} + +func (x *Group_SiteInfo) Reset() { + *x = Group_SiteInfo{} + if protoimpl.UnsafeEnabled { + mi := &file_groups_v1alpha_groups_proto_msgTypes[21] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Group_SiteInfo) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Group_SiteInfo) ProtoMessage() {} + +func (x *Group_SiteInfo) ProtoReflect() protoreflect.Message { + mi := &file_groups_v1alpha_groups_proto_msgTypes[21] + 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 Group_SiteInfo.ProtoReflect.Descriptor instead. +func (*Group_SiteInfo) Descriptor() ([]byte, []int) { + return file_groups_v1alpha_groups_proto_rawDescGZIP(), []int{13, 0} +} + +func (x *Group_SiteInfo) GetBaseUrl() string { + if x != nil { + return x.BaseUrl + } + return "" +} + +func (x *Group_SiteInfo) GetLastSyncTime() *timestamppb.Timestamp { + if x != nil { + return x.LastSyncTime + } + return nil +} + +func (x *Group_SiteInfo) GetLastOkSyncTime() *timestamppb.Timestamp { + if x != nil { + return x.LastOkSyncTime + } + return nil +} + +func (x *Group_SiteInfo) GetVersion() string { + if x != nil { + return x.Version + } + return "" +} + var File_groups_v1alpha_groups_proto protoreflect.FileDescriptor var file_groups_v1alpha_groups_proto_rawDesc = []byte{ @@ -1465,7 +1310,7 @@ var file_groups_v1alpha_groups_proto_rawDesc = []byte{ 0x6f, 0x6d, 0x2e, 0x6d, 0x69, 0x6e, 0x74, 0x74, 0x65, 0x72, 0x2e, 0x67, 0x72, 0x6f, 0x75, 0x70, 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, 0x81, 0x02, 0x0a, 0x12, 0x43, + 0x74, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xa7, 0x02, 0x0a, 0x12, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, @@ -1476,277 +1321,260 @@ var file_groups_v1alpha_groups_proto_rawDesc = []byte{ 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x07, 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, - 0x1a, 0x5c, 0x0a, 0x0c, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, - 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, - 0x65, 0x79, 0x12, 0x36, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x0e, 0x32, 0x20, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x6d, 0x69, 0x6e, 0x74, 0x74, 0x65, 0x72, 0x2e, - 0x67, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x52, - 0x6f, 0x6c, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x3b, - 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x47, 0x72, 0x6f, 0x75, 0x70, 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, 0xde, 0x03, 0x0a, 0x12, - 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 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, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, - 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, - 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x6b, 0x0a, 0x0f, 0x75, 0x70, - 0x64, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x18, 0x04, 0x20, - 0x03, 0x28, 0x0b, 0x32, 0x42, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x6d, 0x69, 0x6e, 0x74, 0x74, 0x65, - 0x72, 0x2e, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, - 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x4d, 0x65, 0x6d, 0x62, 0x65, - 0x72, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0e, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, - 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x12, 0x6b, 0x0a, 0x0f, 0x75, 0x70, 0x64, 0x61, 0x74, - 0x65, 0x64, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, - 0x32, 0x42, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x6d, 0x69, 0x6e, 0x74, 0x74, 0x65, 0x72, 0x2e, 0x67, - 0x72, 0x6f, 0x75, 0x70, 0x73, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x55, 0x70, - 0x64, 0x61, 0x74, 0x65, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x45, - 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0e, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x43, 0x6f, 0x6e, - 0x74, 0x65, 0x6e, 0x74, 0x1a, 0x63, 0x0a, 0x13, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x4d, - 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, - 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x36, 0x0a, - 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x20, 0x2e, 0x63, - 0x6f, 0x6d, 0x2e, 0x6d, 0x69, 0x6e, 0x74, 0x74, 0x65, 0x72, 0x2e, 0x67, 0x72, 0x6f, 0x75, 0x70, - 0x73, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x52, 0x6f, 0x6c, 0x65, 0x52, 0x05, - 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x41, 0x0a, 0x13, 0x55, 0x70, 0x64, - 0x61, 0x74, 0x65, 0x64, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 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, 0x7a, 0x0a, 0x12, - 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 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, 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, 0x1b, 0x0a, 0x09, - 0x70, 0x61, 0x67, 0x65, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x03, 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, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x70, - 0x61, 0x67, 0x65, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x22, 0x9d, 0x02, 0x0a, 0x13, 0x4c, 0x69, 0x73, - 0x74, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x12, 0x28, 0x0a, 0x10, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x5f, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, - 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x6f, 0x77, 0x6e, 0x65, - 0x72, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x49, 0x64, 0x12, 0x56, 0x0a, 0x07, 0x6d, 0x65, - 0x6d, 0x62, 0x65, 0x72, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x3c, 0x2e, 0x63, 0x6f, - 0x6d, 0x2e, 0x6d, 0x69, 0x6e, 0x74, 0x74, 0x65, 0x72, 0x2e, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x73, - 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x65, 0x6d, - 0x62, 0x65, 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x4d, 0x65, 0x6d, - 0x62, 0x65, 0x72, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x07, 0x6d, 0x65, 0x6d, 0x62, 0x65, - 0x72, 0x73, 0x12, 0x26, 0x0a, 0x0f, 0x6e, 0x65, 0x78, 0x74, 0x5f, 0x70, 0x61, 0x67, 0x65, 0x5f, - 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x6e, 0x65, 0x78, - 0x74, 0x50, 0x61, 0x67, 0x65, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x1a, 0x5c, 0x0a, 0x0c, 0x4d, 0x65, - 0x6d, 0x62, 0x65, 0x72, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, - 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x36, 0x0a, 0x05, - 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x20, 0x2e, 0x63, 0x6f, - 0x6d, 0x2e, 0x6d, 0x69, 0x6e, 0x74, 0x74, 0x65, 0x72, 0x2e, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x73, - 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x52, 0x6f, 0x6c, 0x65, 0x52, 0x05, 0x76, + 0x12, 0x24, 0x0a, 0x0e, 0x73, 0x69, 0x74, 0x65, 0x5f, 0x73, 0x65, 0x74, 0x75, 0x70, 0x5f, 0x75, + 0x72, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x73, 0x69, 0x74, 0x65, 0x53, 0x65, + 0x74, 0x75, 0x70, 0x55, 0x72, 0x6c, 0x1a, 0x5c, 0x0a, 0x0c, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, + 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x36, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, + 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x20, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x6d, 0x69, + 0x6e, 0x74, 0x74, 0x65, 0x72, 0x2e, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x2e, 0x76, 0x31, 0x61, + 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x52, 0x6f, 0x6c, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, + 0x3a, 0x02, 0x38, 0x01, 0x22, 0x3b, 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x47, 0x72, 0x6f, 0x75, 0x70, + 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, 0x84, 0x04, 0x0a, 0x12, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x47, 0x72, 0x6f, 0x75, + 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 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, 0x20, + 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, + 0x12, 0x6b, 0x0a, 0x0f, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x6d, 0x65, 0x6d, 0x62, + 0x65, 0x72, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x42, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, + 0x6d, 0x69, 0x6e, 0x74, 0x74, 0x65, 0x72, 0x2e, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x2e, 0x76, + 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x47, 0x72, 0x6f, + 0x75, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, + 0x64, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0e, 0x75, + 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x12, 0x6b, 0x0a, + 0x0f, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, + 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x42, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x6d, 0x69, 0x6e, + 0x74, 0x74, 0x65, 0x72, 0x2e, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x2e, 0x76, 0x31, 0x61, 0x6c, + 0x70, 0x68, 0x61, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x43, 0x6f, + 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0e, 0x75, 0x70, 0x64, 0x61, + 0x74, 0x65, 0x64, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x12, 0x24, 0x0a, 0x0e, 0x73, 0x69, + 0x74, 0x65, 0x5f, 0x73, 0x65, 0x74, 0x75, 0x70, 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x06, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x0c, 0x73, 0x69, 0x74, 0x65, 0x53, 0x65, 0x74, 0x75, 0x70, 0x55, 0x72, 0x6c, + 0x1a, 0x63, 0x0a, 0x13, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x4d, 0x65, 0x6d, 0x62, 0x65, + 0x72, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x36, 0x0a, 0x05, 0x76, 0x61, 0x6c, + 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x20, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x6d, + 0x69, 0x6e, 0x74, 0x74, 0x65, 0x72, 0x2e, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x2e, 0x76, 0x31, + 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x52, 0x6f, 0x6c, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, + 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x41, 0x0a, 0x13, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, + 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 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, 0x7a, 0x0a, 0x12, 0x4c, 0x69, 0x73, 0x74, - 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, + 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 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, 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, 0x1b, 0x0a, 0x09, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x03, 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, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x70, 0x61, 0x67, 0x65, 0x54, - 0x6f, 0x6b, 0x65, 0x6e, 0x22, 0xd1, 0x01, 0x0a, 0x13, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x6f, 0x6e, - 0x74, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x56, 0x0a, 0x07, - 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x3c, 0x2e, - 0x63, 0x6f, 0x6d, 0x2e, 0x6d, 0x69, 0x6e, 0x74, 0x74, 0x65, 0x72, 0x2e, 0x67, 0x72, 0x6f, 0x75, - 0x70, 0x73, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x43, - 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x43, - 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x07, 0x63, 0x6f, 0x6e, - 0x74, 0x65, 0x6e, 0x74, 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, 0x1a, 0x3a, 0x0a, 0x0c, - 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 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, 0x4f, 0x0a, 0x11, 0x4c, 0x69, 0x73, 0x74, - 0x47, 0x72, 0x6f, 0x75, 0x70, 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, 0x77, 0x0a, 0x12, 0x4c, 0x69, 0x73, - 0x74, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x39, 0x0a, 0x06, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, - 0x21, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x6d, 0x69, 0x6e, 0x74, 0x74, 0x65, 0x72, 0x2e, 0x67, 0x72, - 0x6f, 0x75, 0x70, 0x73, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x47, 0x72, 0x6f, - 0x75, 0x70, 0x52, 0x06, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x12, 0x26, 0x0a, 0x0f, 0x6e, 0x65, + 0x6f, 0x6b, 0x65, 0x6e, 0x22, 0x9d, 0x02, 0x0a, 0x13, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x65, 0x6d, + 0x62, 0x65, 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x28, 0x0a, 0x10, + 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x5f, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x69, 0x64, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x41, 0x63, 0x63, + 0x6f, 0x75, 0x6e, 0x74, 0x49, 0x64, 0x12, 0x56, 0x0a, 0x07, 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, + 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x3c, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x6d, 0x69, + 0x6e, 0x74, 0x74, 0x65, 0x72, 0x2e, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x2e, 0x76, 0x31, 0x61, + 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, + 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x07, 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x12, 0x26, + 0x0a, 0x0f, 0x6e, 0x65, 0x78, 0x74, 0x5f, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x74, 0x6f, 0x6b, 0x65, + 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x6e, 0x65, 0x78, 0x74, 0x50, 0x61, 0x67, + 0x65, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x1a, 0x5c, 0x0a, 0x0c, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, + 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x36, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, + 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x20, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x6d, 0x69, + 0x6e, 0x74, 0x74, 0x65, 0x72, 0x2e, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x2e, 0x76, 0x31, 0x61, + 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x52, 0x6f, 0x6c, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, + 0x3a, 0x02, 0x38, 0x01, 0x22, 0x7a, 0x0a, 0x12, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x6f, 0x6e, 0x74, + 0x65, 0x6e, 0x74, 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, 0x12, 0x1b, 0x0a, 0x09, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x73, 0x69, 0x7a, + 0x65, 0x18, 0x03, 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, + 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x70, 0x61, 0x67, 0x65, 0x54, 0x6f, 0x6b, 0x65, 0x6e, + 0x22, 0xd1, 0x01, 0x0a, 0x13, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x56, 0x0a, 0x07, 0x63, 0x6f, 0x6e, 0x74, + 0x65, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x3c, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, + 0x6d, 0x69, 0x6e, 0x74, 0x74, 0x65, 0x72, 0x2e, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x2e, 0x76, + 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, + 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x65, + 0x6e, 0x74, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, + 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, 0x1a, 0x3a, 0x0a, 0x0c, 0x43, 0x6f, 0x6e, 0x74, + 0x65, 0x6e, 0x74, 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, 0x4f, 0x0a, 0x11, 0x4c, 0x69, 0x73, 0x74, 0x47, 0x72, 0x6f, 0x75, + 0x70, 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, 0x77, 0x0a, 0x12, 0x4c, 0x69, 0x73, 0x74, 0x47, 0x72, 0x6f, + 0x75, 0x70, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x39, 0x0a, 0x06, 0x67, + 0x72, 0x6f, 0x75, 0x70, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x63, 0x6f, + 0x6d, 0x2e, 0x6d, 0x69, 0x6e, 0x74, 0x74, 0x65, 0x72, 0x2e, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x73, + 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x52, 0x06, + 0x67, 0x72, 0x6f, 0x75, 0x70, 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, 0x78, + 0x0a, 0x19, 0x4c, 0x69, 0x73, 0x74, 0x44, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x47, 0x72, + 0x6f, 0x75, 0x70, 0x73, 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, 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, 0x22, 0xc2, 0x02, 0x0a, 0x1a, 0x4c, 0x69, 0x73, + 0x74, 0x44, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x51, 0x0a, 0x05, 0x69, 0x74, 0x65, 0x6d, 0x73, + 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x3b, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x6d, 0x69, 0x6e, + 0x74, 0x74, 0x65, 0x72, 0x2e, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x2e, 0x76, 0x31, 0x61, 0x6c, + 0x70, 0x68, 0x61, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x44, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, + 0x47, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x49, + 0x74, 0x65, 0x6d, 0x52, 0x05, 0x69, 0x74, 0x65, 0x6d, 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, 0x5f, 0x0a, 0x14, 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x74, 0x54, 0x6f, 0x53, - 0x69, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6c, 0x69, - 0x6e, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6c, 0x69, 0x6e, 0x6b, 0x12, 0x19, - 0x0a, 0x08, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x07, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x49, 0x64, 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, 0x22, 0x4e, 0x0a, 0x15, 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x74, 0x54, 0x6f, - 0x53, 0x69, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x19, 0x0a, 0x08, - 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, - 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x49, 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x68, 0x6f, 0x73, 0x74, 0x6e, - 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x68, 0x6f, 0x73, 0x74, 0x6e, - 0x61, 0x6d, 0x65, 0x22, 0x6c, 0x0a, 0x12, 0x47, 0x65, 0x74, 0x53, 0x69, 0x74, 0x65, 0x49, 0x6e, - 0x66, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x68, 0x6f, 0x73, - 0x74, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x68, 0x6f, 0x73, - 0x74, 0x6e, 0x61, 0x6d, 0x65, 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, 0x22, 0x65, 0x0a, 0x13, 0x47, 0x65, 0x74, 0x53, 0x69, 0x74, 0x65, 0x49, 0x6e, 0x66, 0x6f, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x19, 0x0a, 0x08, 0x67, 0x72, 0x6f, 0x75, - 0x70, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x67, 0x72, 0x6f, 0x75, - 0x70, 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, 0x19, 0x0a, - 0x08, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x07, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x49, 0x64, 0x22, 0x78, 0x0a, 0x19, 0x4c, 0x69, 0x73, 0x74, - 0x44, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x73, 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, 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, 0x22, 0xc2, 0x02, 0x0a, 0x1a, 0x4c, 0x69, 0x73, 0x74, 0x44, 0x6f, 0x63, 0x75, 0x6d, - 0x65, 0x6e, 0x74, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x51, 0x0a, 0x05, 0x69, 0x74, 0x65, 0x6d, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, - 0x32, 0x3b, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x6d, 0x69, 0x6e, 0x74, 0x74, 0x65, 0x72, 0x2e, 0x67, - 0x72, 0x6f, 0x75, 0x70, 0x73, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x4c, 0x69, - 0x73, 0x74, 0x44, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x73, + 0x65, 0x6e, 0x1a, 0xa8, 0x01, 0x0a, 0x04, 0x49, 0x74, 0x65, 0x6d, 0x12, 0x19, 0x0a, 0x08, 0x67, + 0x72, 0x6f, 0x75, 0x70, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x67, + 0x72, 0x6f, 0x75, 0x70, 0x49, 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, + 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x63, 0x68, 0x61, 0x6e, 0x67, + 0x65, 0x49, 0x64, 0x12, 0x3b, 0x0a, 0x0b, 0x63, 0x68, 0x61, 0x6e, 0x67, 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, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x54, 0x69, 0x6d, 0x65, + 0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, + 0x70, 0x61, 0x74, 0x68, 0x12, 0x17, 0x0a, 0x07, 0x72, 0x61, 0x77, 0x5f, 0x75, 0x72, 0x6c, 0x18, + 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x61, 0x77, 0x55, 0x72, 0x6c, 0x22, 0x75, 0x0a, + 0x18, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x47, 0x72, 0x6f, 0x75, + 0x70, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x61, 0x63, 0x63, + 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x61, + 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x49, 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, 0x22, 0x8c, 0x02, 0x0a, 0x19, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x63, 0x63, + 0x6f, 0x75, 0x6e, 0x74, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x50, 0x0a, 0x05, 0x69, 0x74, 0x65, 0x6d, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, + 0x0b, 0x32, 0x3a, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x6d, 0x69, 0x6e, 0x74, 0x74, 0x65, 0x72, 0x2e, + 0x67, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x4c, + 0x69, 0x73, 0x74, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x49, 0x74, 0x65, 0x6d, 0x52, 0x05, 0x69, 0x74, 0x65, 0x6d, 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, 0x1a, 0xa8, 0x01, 0x0a, - 0x04, 0x49, 0x74, 0x65, 0x6d, 0x12, 0x19, 0x0a, 0x08, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x5f, 0x69, - 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x49, 0x64, - 0x12, 0x1b, 0x0a, 0x09, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x08, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x49, 0x64, 0x12, 0x3b, 0x0a, - 0x0b, 0x63, 0x68, 0x61, 0x6e, 0x67, 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, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, - 0x74, 0x68, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x12, 0x17, - 0x0a, 0x07, 0x72, 0x61, 0x77, 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x06, 0x72, 0x61, 0x77, 0x55, 0x72, 0x6c, 0x22, 0x75, 0x0a, 0x18, 0x4c, 0x69, 0x73, 0x74, 0x41, - 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x69, - 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, - 0x49, 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, 0x22, 0x8c, - 0x02, 0x0a, 0x19, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x47, 0x72, - 0x6f, 0x75, 0x70, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x50, 0x0a, 0x05, - 0x69, 0x74, 0x65, 0x6d, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x3a, 0x2e, 0x63, 0x6f, + 0x65, 0x78, 0x74, 0x50, 0x61, 0x67, 0x65, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x1a, 0x75, 0x0a, 0x04, + 0x49, 0x74, 0x65, 0x6d, 0x12, 0x37, 0x0a, 0x05, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x6d, 0x69, 0x6e, 0x74, 0x74, 0x65, + 0x72, 0x2e, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, + 0x2e, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x52, 0x05, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x12, 0x34, 0x0a, + 0x04, 0x72, 0x6f, 0x6c, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x20, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x6d, 0x69, 0x6e, 0x74, 0x74, 0x65, 0x72, 0x2e, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x73, - 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x63, 0x63, - 0x6f, 0x75, 0x6e, 0x74, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x2e, 0x49, 0x74, 0x65, 0x6d, 0x52, 0x05, 0x69, 0x74, 0x65, 0x6d, 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, 0x1a, 0x75, 0x0a, 0x04, 0x49, 0x74, 0x65, 0x6d, 0x12, 0x37, - 0x0a, 0x05, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, - 0x63, 0x6f, 0x6d, 0x2e, 0x6d, 0x69, 0x6e, 0x74, 0x74, 0x65, 0x72, 0x2e, 0x67, 0x72, 0x6f, 0x75, - 0x70, 0x73, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x47, 0x72, 0x6f, 0x75, 0x70, - 0x52, 0x05, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x12, 0x34, 0x0a, 0x04, 0x72, 0x6f, 0x6c, 0x65, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x20, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x6d, 0x69, 0x6e, 0x74, + 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x52, 0x6f, 0x6c, 0x65, 0x52, 0x04, 0x72, + 0x6f, 0x6c, 0x65, 0x22, 0xa1, 0x04, 0x0a, 0x05, 0x47, 0x72, 0x6f, 0x75, 0x70, 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, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, + 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, + 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x28, 0x0a, 0x10, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x5f, 0x61, + 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x0e, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x49, 0x64, 0x12, + 0x3b, 0x0a, 0x0b, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x05, + 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, 0x18, 0x0a, 0x07, + 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x76, + 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 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, 0x47, 0x0a, 0x09, 0x73, 0x69, 0x74, 0x65, 0x5f, 0x69, 0x6e, 0x66, 0x6f, + 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x6d, 0x69, 0x6e, + 0x74, 0x74, 0x65, 0x72, 0x2e, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x2e, 0x76, 0x31, 0x61, 0x6c, + 0x70, 0x68, 0x61, 0x2e, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x2e, 0x53, 0x69, 0x74, 0x65, 0x49, 0x6e, + 0x66, 0x6f, 0x52, 0x08, 0x73, 0x69, 0x74, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x1a, 0xc8, 0x01, 0x0a, + 0x08, 0x53, 0x69, 0x74, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x19, 0x0a, 0x08, 0x62, 0x61, 0x73, + 0x65, 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x62, 0x61, 0x73, + 0x65, 0x55, 0x72, 0x6c, 0x12, 0x40, 0x0a, 0x0e, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x73, 0x79, 0x6e, + 0x63, 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, 0x0c, 0x6c, 0x61, 0x73, 0x74, 0x53, 0x79, + 0x6e, 0x63, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x45, 0x0a, 0x11, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x6f, + 0x6b, 0x5f, 0x73, 0x79, 0x6e, 0x63, 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, 0x0e, 0x6c, + 0x61, 0x73, 0x74, 0x4f, 0x6b, 0x53, 0x79, 0x6e, 0x63, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x18, 0x0a, + 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, + 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x2a, 0x33, 0x0a, 0x04, 0x52, 0x6f, 0x6c, 0x65, 0x12, + 0x14, 0x0a, 0x10, 0x52, 0x4f, 0x4c, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, + 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x09, 0x0a, 0x05, 0x4f, 0x57, 0x4e, 0x45, 0x52, 0x10, 0x01, + 0x12, 0x0a, 0x0a, 0x06, 0x45, 0x44, 0x49, 0x54, 0x4f, 0x52, 0x10, 0x02, 0x32, 0xfe, 0x06, 0x0a, + 0x06, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x12, 0x60, 0x0a, 0x0b, 0x43, 0x72, 0x65, 0x61, 0x74, + 0x65, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x12, 0x2e, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x6d, 0x69, 0x6e, + 0x74, 0x74, 0x65, 0x72, 0x2e, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x2e, 0x76, 0x31, 0x61, 0x6c, + 0x70, 0x68, 0x61, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x6d, 0x69, 0x6e, + 0x74, 0x74, 0x65, 0x72, 0x2e, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x2e, 0x76, 0x31, 0x61, 0x6c, + 0x70, 0x68, 0x61, 0x2e, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x12, 0x5a, 0x0a, 0x08, 0x47, 0x65, 0x74, + 0x47, 0x72, 0x6f, 0x75, 0x70, 0x12, 0x2b, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x6d, 0x69, 0x6e, 0x74, 0x74, 0x65, 0x72, 0x2e, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, - 0x68, 0x61, 0x2e, 0x52, 0x6f, 0x6c, 0x65, 0x52, 0x04, 0x72, 0x6f, 0x6c, 0x65, 0x22, 0x8d, 0x02, - 0x0a, 0x05, 0x47, 0x72, 0x6f, 0x75, 0x70, 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, 0x20, 0x0a, - 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, - 0x28, 0x0a, 0x10, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x5f, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, - 0x5f, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x6f, 0x77, 0x6e, 0x65, 0x72, - 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x49, 0x64, 0x12, 0x3b, 0x0a, 0x0b, 0x63, 0x72, 0x65, - 0x61, 0x74, 0x65, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x05, 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, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, - 0x6e, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, - 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, 0x2a, 0x33, 0x0a, - 0x04, 0x52, 0x6f, 0x6c, 0x65, 0x12, 0x14, 0x0a, 0x10, 0x52, 0x4f, 0x4c, 0x45, 0x5f, 0x55, 0x4e, - 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x09, 0x0a, 0x05, 0x4f, - 0x57, 0x4e, 0x45, 0x52, 0x10, 0x01, 0x12, 0x0a, 0x0a, 0x06, 0x45, 0x44, 0x49, 0x54, 0x4f, 0x52, - 0x10, 0x02, 0x32, 0xe4, 0x08, 0x0a, 0x06, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x12, 0x60, 0x0a, - 0x0b, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x12, 0x2e, 0x2e, 0x63, - 0x6f, 0x6d, 0x2e, 0x6d, 0x69, 0x6e, 0x74, 0x74, 0x65, 0x72, 0x2e, 0x67, 0x72, 0x6f, 0x75, 0x70, - 0x73, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, - 0x47, 0x72, 0x6f, 0x75, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x63, - 0x6f, 0x6d, 0x2e, 0x6d, 0x69, 0x6e, 0x74, 0x74, 0x65, 0x72, 0x2e, 0x67, 0x72, 0x6f, 0x75, 0x70, - 0x73, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x12, - 0x5a, 0x0a, 0x08, 0x47, 0x65, 0x74, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x12, 0x2b, 0x2e, 0x63, 0x6f, - 0x6d, 0x2e, 0x6d, 0x69, 0x6e, 0x74, 0x74, 0x65, 0x72, 0x2e, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x73, - 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x47, 0x65, 0x74, 0x47, 0x72, 0x6f, 0x75, - 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x6d, - 0x69, 0x6e, 0x74, 0x74, 0x65, 0x72, 0x2e, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x2e, 0x76, 0x31, - 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x12, 0x60, 0x0a, 0x0b, 0x55, - 0x70, 0x64, 0x61, 0x74, 0x65, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x12, 0x2e, 0x2e, 0x63, 0x6f, 0x6d, - 0x2e, 0x6d, 0x69, 0x6e, 0x74, 0x74, 0x65, 0x72, 0x2e, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x2e, - 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x47, 0x72, - 0x6f, 0x75, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x63, 0x6f, 0x6d, - 0x2e, 0x6d, 0x69, 0x6e, 0x74, 0x74, 0x65, 0x72, 0x2e, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x2e, - 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x12, 0x6e, 0x0a, - 0x0b, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x12, 0x2e, 0x2e, 0x63, - 0x6f, 0x6d, 0x2e, 0x6d, 0x69, 0x6e, 0x74, 0x74, 0x65, 0x72, 0x2e, 0x67, 0x72, 0x6f, 0x75, 0x70, - 0x73, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x65, - 0x6d, 0x62, 0x65, 0x72, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2f, 0x2e, 0x63, - 0x6f, 0x6d, 0x2e, 0x6d, 0x69, 0x6e, 0x74, 0x74, 0x65, 0x72, 0x2e, 0x67, 0x72, 0x6f, 0x75, 0x70, - 0x73, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x65, - 0x6d, 0x62, 0x65, 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6e, 0x0a, - 0x0b, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x12, 0x2e, 0x2e, 0x63, - 0x6f, 0x6d, 0x2e, 0x6d, 0x69, 0x6e, 0x74, 0x74, 0x65, 0x72, 0x2e, 0x67, 0x72, 0x6f, 0x75, 0x70, - 0x73, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x6f, - 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2f, 0x2e, 0x63, - 0x6f, 0x6d, 0x2e, 0x6d, 0x69, 0x6e, 0x74, 0x74, 0x65, 0x72, 0x2e, 0x67, 0x72, 0x6f, 0x75, 0x70, - 0x73, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x6f, - 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6b, 0x0a, - 0x0a, 0x4c, 0x69, 0x73, 0x74, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x12, 0x2d, 0x2e, 0x63, 0x6f, - 0x6d, 0x2e, 0x6d, 0x69, 0x6e, 0x74, 0x74, 0x65, 0x72, 0x2e, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x73, - 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x47, 0x72, 0x6f, - 0x75, 0x70, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2e, 0x2e, 0x63, 0x6f, 0x6d, - 0x2e, 0x6d, 0x69, 0x6e, 0x74, 0x74, 0x65, 0x72, 0x2e, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x2e, - 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x47, 0x72, 0x6f, 0x75, - 0x70, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x74, 0x0a, 0x0d, 0x43, 0x6f, - 0x6e, 0x76, 0x65, 0x72, 0x74, 0x54, 0x6f, 0x53, 0x69, 0x74, 0x65, 0x12, 0x30, 0x2e, 0x63, 0x6f, + 0x68, 0x61, 0x2e, 0x47, 0x65, 0x74, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x6d, 0x69, 0x6e, 0x74, 0x74, 0x65, 0x72, + 0x2e, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, + 0x47, 0x72, 0x6f, 0x75, 0x70, 0x12, 0x60, 0x0a, 0x0b, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x47, + 0x72, 0x6f, 0x75, 0x70, 0x12, 0x2e, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x6d, 0x69, 0x6e, 0x74, 0x74, + 0x65, 0x72, 0x2e, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, + 0x61, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x6d, 0x69, 0x6e, 0x74, 0x74, + 0x65, 0x72, 0x2e, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, + 0x61, 0x2e, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x12, 0x6e, 0x0a, 0x0b, 0x4c, 0x69, 0x73, 0x74, 0x4d, + 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x12, 0x2e, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x6d, 0x69, 0x6e, + 0x74, 0x74, 0x65, 0x72, 0x2e, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x2e, 0x76, 0x31, 0x61, 0x6c, + 0x70, 0x68, 0x61, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2f, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x6d, 0x69, 0x6e, + 0x74, 0x74, 0x65, 0x72, 0x2e, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x2e, 0x76, 0x31, 0x61, 0x6c, + 0x70, 0x68, 0x61, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6e, 0x0a, 0x0b, 0x4c, 0x69, 0x73, 0x74, 0x43, + 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x12, 0x2e, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x6d, 0x69, 0x6e, + 0x74, 0x74, 0x65, 0x72, 0x2e, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x2e, 0x76, 0x31, 0x61, 0x6c, + 0x70, 0x68, 0x61, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2f, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x6d, 0x69, 0x6e, + 0x74, 0x74, 0x65, 0x72, 0x2e, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x2e, 0x76, 0x31, 0x61, 0x6c, + 0x70, 0x68, 0x61, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6b, 0x0a, 0x0a, 0x4c, 0x69, 0x73, 0x74, 0x47, + 0x72, 0x6f, 0x75, 0x70, 0x73, 0x12, 0x2d, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x6d, 0x69, 0x6e, 0x74, + 0x74, 0x65, 0x72, 0x2e, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, + 0x68, 0x61, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2e, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x6d, 0x69, 0x6e, 0x74, 0x74, + 0x65, 0x72, 0x2e, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, + 0x61, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x83, 0x01, 0x0a, 0x12, 0x4c, 0x69, 0x73, 0x74, 0x44, 0x6f, 0x63, + 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x12, 0x35, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x6d, 0x69, 0x6e, 0x74, 0x74, 0x65, 0x72, 0x2e, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x73, - 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x74, - 0x54, 0x6f, 0x53, 0x69, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x31, 0x2e, - 0x63, 0x6f, 0x6d, 0x2e, 0x6d, 0x69, 0x6e, 0x74, 0x74, 0x65, 0x72, 0x2e, 0x67, 0x72, 0x6f, 0x75, - 0x70, 0x73, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x43, 0x6f, 0x6e, 0x76, 0x65, - 0x72, 0x74, 0x54, 0x6f, 0x53, 0x69, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x12, 0x6e, 0x0a, 0x0b, 0x47, 0x65, 0x74, 0x53, 0x69, 0x74, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x12, - 0x2e, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x6d, 0x69, 0x6e, 0x74, 0x74, 0x65, 0x72, 0x2e, 0x67, 0x72, - 0x6f, 0x75, 0x70, 0x73, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x47, 0x65, 0x74, - 0x53, 0x69, 0x74, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x2f, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x6d, 0x69, 0x6e, 0x74, 0x74, 0x65, 0x72, 0x2e, 0x67, 0x72, - 0x6f, 0x75, 0x70, 0x73, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x47, 0x65, 0x74, - 0x53, 0x69, 0x74, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x12, 0x83, 0x01, 0x0a, 0x12, 0x4c, 0x69, 0x73, 0x74, 0x44, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, - 0x74, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x12, 0x35, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x6d, 0x69, - 0x6e, 0x74, 0x74, 0x65, 0x72, 0x2e, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x2e, 0x76, 0x31, 0x61, - 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x44, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, - 0x74, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x36, - 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x6d, 0x69, 0x6e, 0x74, 0x74, 0x65, 0x72, 0x2e, 0x67, 0x72, 0x6f, - 0x75, 0x70, 0x73, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x4c, 0x69, 0x73, 0x74, - 0x44, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x80, 0x01, 0x0a, 0x11, 0x4c, 0x69, 0x73, 0x74, 0x41, - 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x12, 0x34, 0x2e, 0x63, - 0x6f, 0x6d, 0x2e, 0x6d, 0x69, 0x6e, 0x74, 0x74, 0x65, 0x72, 0x2e, 0x67, 0x72, 0x6f, 0x75, 0x70, - 0x73, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x63, - 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x35, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x6d, 0x69, 0x6e, 0x74, 0x74, 0x65, 0x72, + 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x44, 0x6f, 0x63, + 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x36, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x6d, 0x69, 0x6e, 0x74, 0x74, 0x65, 0x72, 0x2e, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, - 0x4c, 0x69, 0x73, 0x74, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x47, 0x72, 0x6f, 0x75, 0x70, - 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x30, 0x5a, 0x2e, 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, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x2f, 0x76, 0x31, 0x61, - 0x6c, 0x70, 0x68, 0x61, 0x3b, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x33, + 0x4c, 0x69, 0x73, 0x74, 0x44, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x47, 0x72, 0x6f, 0x75, + 0x70, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x80, 0x01, 0x0a, 0x11, 0x4c, + 0x69, 0x73, 0x74, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x73, + 0x12, 0x34, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x6d, 0x69, 0x6e, 0x74, 0x74, 0x65, 0x72, 0x2e, 0x67, + 0x72, 0x6f, 0x75, 0x70, 0x73, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x4c, 0x69, + 0x73, 0x74, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x35, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x6d, 0x69, 0x6e, + 0x74, 0x74, 0x65, 0x72, 0x2e, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x2e, 0x76, 0x31, 0x61, 0x6c, + 0x70, 0x68, 0x61, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x47, + 0x72, 0x6f, 0x75, 0x70, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x30, 0x5a, + 0x2e, 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, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x73, + 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x3b, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x62, + 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -1762,7 +1590,7 @@ func file_groups_v1alpha_groups_proto_rawDescGZIP() []byte { } var file_groups_v1alpha_groups_proto_enumTypes = make([]protoimpl.EnumInfo, 1) -var file_groups_v1alpha_groups_proto_msgTypes = make([]protoimpl.MessageInfo, 25) +var file_groups_v1alpha_groups_proto_msgTypes = make([]protoimpl.MessageInfo, 22) var file_groups_v1alpha_groups_proto_goTypes = []interface{}{ (Role)(0), // 0: com.mintter.groups.v1alpha.Role (*CreateGroupRequest)(nil), // 1: com.mintter.groups.v1alpha.CreateGroupRequest @@ -1774,66 +1602,62 @@ var file_groups_v1alpha_groups_proto_goTypes = []interface{}{ (*ListContentResponse)(nil), // 7: com.mintter.groups.v1alpha.ListContentResponse (*ListGroupsRequest)(nil), // 8: com.mintter.groups.v1alpha.ListGroupsRequest (*ListGroupsResponse)(nil), // 9: com.mintter.groups.v1alpha.ListGroupsResponse - (*ConvertToSiteRequest)(nil), // 10: com.mintter.groups.v1alpha.ConvertToSiteRequest - (*ConvertToSiteResponse)(nil), // 11: com.mintter.groups.v1alpha.ConvertToSiteResponse - (*GetSiteInfoRequest)(nil), // 12: com.mintter.groups.v1alpha.GetSiteInfoRequest - (*GetSiteInfoResponse)(nil), // 13: com.mintter.groups.v1alpha.GetSiteInfoResponse - (*ListDocumentGroupsRequest)(nil), // 14: com.mintter.groups.v1alpha.ListDocumentGroupsRequest - (*ListDocumentGroupsResponse)(nil), // 15: com.mintter.groups.v1alpha.ListDocumentGroupsResponse - (*ListAccountGroupsRequest)(nil), // 16: com.mintter.groups.v1alpha.ListAccountGroupsRequest - (*ListAccountGroupsResponse)(nil), // 17: com.mintter.groups.v1alpha.ListAccountGroupsResponse - (*Group)(nil), // 18: com.mintter.groups.v1alpha.Group - nil, // 19: com.mintter.groups.v1alpha.CreateGroupRequest.MembersEntry - nil, // 20: com.mintter.groups.v1alpha.UpdateGroupRequest.UpdatedMembersEntry - nil, // 21: com.mintter.groups.v1alpha.UpdateGroupRequest.UpdatedContentEntry - nil, // 22: com.mintter.groups.v1alpha.ListMembersResponse.MembersEntry - nil, // 23: com.mintter.groups.v1alpha.ListContentResponse.ContentEntry - (*ListDocumentGroupsResponse_Item)(nil), // 24: com.mintter.groups.v1alpha.ListDocumentGroupsResponse.Item - (*ListAccountGroupsResponse_Item)(nil), // 25: com.mintter.groups.v1alpha.ListAccountGroupsResponse.Item - (*timestamppb.Timestamp)(nil), // 26: google.protobuf.Timestamp + (*ListDocumentGroupsRequest)(nil), // 10: com.mintter.groups.v1alpha.ListDocumentGroupsRequest + (*ListDocumentGroupsResponse)(nil), // 11: com.mintter.groups.v1alpha.ListDocumentGroupsResponse + (*ListAccountGroupsRequest)(nil), // 12: com.mintter.groups.v1alpha.ListAccountGroupsRequest + (*ListAccountGroupsResponse)(nil), // 13: com.mintter.groups.v1alpha.ListAccountGroupsResponse + (*Group)(nil), // 14: com.mintter.groups.v1alpha.Group + nil, // 15: com.mintter.groups.v1alpha.CreateGroupRequest.MembersEntry + nil, // 16: com.mintter.groups.v1alpha.UpdateGroupRequest.UpdatedMembersEntry + nil, // 17: com.mintter.groups.v1alpha.UpdateGroupRequest.UpdatedContentEntry + nil, // 18: com.mintter.groups.v1alpha.ListMembersResponse.MembersEntry + nil, // 19: com.mintter.groups.v1alpha.ListContentResponse.ContentEntry + (*ListDocumentGroupsResponse_Item)(nil), // 20: com.mintter.groups.v1alpha.ListDocumentGroupsResponse.Item + (*ListAccountGroupsResponse_Item)(nil), // 21: com.mintter.groups.v1alpha.ListAccountGroupsResponse.Item + (*Group_SiteInfo)(nil), // 22: com.mintter.groups.v1alpha.Group.SiteInfo + (*timestamppb.Timestamp)(nil), // 23: google.protobuf.Timestamp } var file_groups_v1alpha_groups_proto_depIdxs = []int32{ - 19, // 0: com.mintter.groups.v1alpha.CreateGroupRequest.members:type_name -> com.mintter.groups.v1alpha.CreateGroupRequest.MembersEntry - 20, // 1: com.mintter.groups.v1alpha.UpdateGroupRequest.updated_members:type_name -> com.mintter.groups.v1alpha.UpdateGroupRequest.UpdatedMembersEntry - 21, // 2: com.mintter.groups.v1alpha.UpdateGroupRequest.updated_content:type_name -> com.mintter.groups.v1alpha.UpdateGroupRequest.UpdatedContentEntry - 22, // 3: com.mintter.groups.v1alpha.ListMembersResponse.members:type_name -> com.mintter.groups.v1alpha.ListMembersResponse.MembersEntry - 23, // 4: com.mintter.groups.v1alpha.ListContentResponse.content:type_name -> com.mintter.groups.v1alpha.ListContentResponse.ContentEntry - 18, // 5: com.mintter.groups.v1alpha.ListGroupsResponse.groups:type_name -> com.mintter.groups.v1alpha.Group - 24, // 6: com.mintter.groups.v1alpha.ListDocumentGroupsResponse.items:type_name -> com.mintter.groups.v1alpha.ListDocumentGroupsResponse.Item - 25, // 7: com.mintter.groups.v1alpha.ListAccountGroupsResponse.items:type_name -> com.mintter.groups.v1alpha.ListAccountGroupsResponse.Item - 26, // 8: com.mintter.groups.v1alpha.Group.create_time:type_name -> google.protobuf.Timestamp - 26, // 9: com.mintter.groups.v1alpha.Group.update_time:type_name -> google.protobuf.Timestamp - 0, // 10: com.mintter.groups.v1alpha.CreateGroupRequest.MembersEntry.value:type_name -> com.mintter.groups.v1alpha.Role - 0, // 11: com.mintter.groups.v1alpha.UpdateGroupRequest.UpdatedMembersEntry.value:type_name -> com.mintter.groups.v1alpha.Role - 0, // 12: com.mintter.groups.v1alpha.ListMembersResponse.MembersEntry.value:type_name -> com.mintter.groups.v1alpha.Role - 26, // 13: com.mintter.groups.v1alpha.ListDocumentGroupsResponse.Item.change_time:type_name -> google.protobuf.Timestamp - 18, // 14: com.mintter.groups.v1alpha.ListAccountGroupsResponse.Item.group:type_name -> com.mintter.groups.v1alpha.Group - 0, // 15: com.mintter.groups.v1alpha.ListAccountGroupsResponse.Item.role:type_name -> com.mintter.groups.v1alpha.Role - 1, // 16: com.mintter.groups.v1alpha.Groups.CreateGroup:input_type -> com.mintter.groups.v1alpha.CreateGroupRequest - 2, // 17: com.mintter.groups.v1alpha.Groups.GetGroup:input_type -> com.mintter.groups.v1alpha.GetGroupRequest - 3, // 18: com.mintter.groups.v1alpha.Groups.UpdateGroup:input_type -> com.mintter.groups.v1alpha.UpdateGroupRequest - 4, // 19: com.mintter.groups.v1alpha.Groups.ListMembers:input_type -> com.mintter.groups.v1alpha.ListMembersRequest - 6, // 20: com.mintter.groups.v1alpha.Groups.ListContent:input_type -> com.mintter.groups.v1alpha.ListContentRequest - 8, // 21: com.mintter.groups.v1alpha.Groups.ListGroups:input_type -> com.mintter.groups.v1alpha.ListGroupsRequest - 10, // 22: com.mintter.groups.v1alpha.Groups.ConvertToSite:input_type -> com.mintter.groups.v1alpha.ConvertToSiteRequest - 12, // 23: com.mintter.groups.v1alpha.Groups.GetSiteInfo:input_type -> com.mintter.groups.v1alpha.GetSiteInfoRequest - 14, // 24: com.mintter.groups.v1alpha.Groups.ListDocumentGroups:input_type -> com.mintter.groups.v1alpha.ListDocumentGroupsRequest - 16, // 25: com.mintter.groups.v1alpha.Groups.ListAccountGroups:input_type -> com.mintter.groups.v1alpha.ListAccountGroupsRequest - 18, // 26: com.mintter.groups.v1alpha.Groups.CreateGroup:output_type -> com.mintter.groups.v1alpha.Group - 18, // 27: com.mintter.groups.v1alpha.Groups.GetGroup:output_type -> com.mintter.groups.v1alpha.Group - 18, // 28: com.mintter.groups.v1alpha.Groups.UpdateGroup:output_type -> com.mintter.groups.v1alpha.Group - 5, // 29: com.mintter.groups.v1alpha.Groups.ListMembers:output_type -> com.mintter.groups.v1alpha.ListMembersResponse - 7, // 30: com.mintter.groups.v1alpha.Groups.ListContent:output_type -> com.mintter.groups.v1alpha.ListContentResponse - 9, // 31: com.mintter.groups.v1alpha.Groups.ListGroups:output_type -> com.mintter.groups.v1alpha.ListGroupsResponse - 11, // 32: com.mintter.groups.v1alpha.Groups.ConvertToSite:output_type -> com.mintter.groups.v1alpha.ConvertToSiteResponse - 13, // 33: com.mintter.groups.v1alpha.Groups.GetSiteInfo:output_type -> com.mintter.groups.v1alpha.GetSiteInfoResponse - 15, // 34: com.mintter.groups.v1alpha.Groups.ListDocumentGroups:output_type -> com.mintter.groups.v1alpha.ListDocumentGroupsResponse - 17, // 35: com.mintter.groups.v1alpha.Groups.ListAccountGroups:output_type -> com.mintter.groups.v1alpha.ListAccountGroupsResponse - 26, // [26:36] is the sub-list for method output_type - 16, // [16:26] is the sub-list for method input_type - 16, // [16:16] is the sub-list for extension type_name - 16, // [16:16] is the sub-list for extension extendee - 0, // [0:16] is the sub-list for field type_name + 15, // 0: com.mintter.groups.v1alpha.CreateGroupRequest.members:type_name -> com.mintter.groups.v1alpha.CreateGroupRequest.MembersEntry + 16, // 1: com.mintter.groups.v1alpha.UpdateGroupRequest.updated_members:type_name -> com.mintter.groups.v1alpha.UpdateGroupRequest.UpdatedMembersEntry + 17, // 2: com.mintter.groups.v1alpha.UpdateGroupRequest.updated_content:type_name -> com.mintter.groups.v1alpha.UpdateGroupRequest.UpdatedContentEntry + 18, // 3: com.mintter.groups.v1alpha.ListMembersResponse.members:type_name -> com.mintter.groups.v1alpha.ListMembersResponse.MembersEntry + 19, // 4: com.mintter.groups.v1alpha.ListContentResponse.content:type_name -> com.mintter.groups.v1alpha.ListContentResponse.ContentEntry + 14, // 5: com.mintter.groups.v1alpha.ListGroupsResponse.groups:type_name -> com.mintter.groups.v1alpha.Group + 20, // 6: com.mintter.groups.v1alpha.ListDocumentGroupsResponse.items:type_name -> com.mintter.groups.v1alpha.ListDocumentGroupsResponse.Item + 21, // 7: com.mintter.groups.v1alpha.ListAccountGroupsResponse.items:type_name -> com.mintter.groups.v1alpha.ListAccountGroupsResponse.Item + 23, // 8: com.mintter.groups.v1alpha.Group.create_time:type_name -> google.protobuf.Timestamp + 23, // 9: com.mintter.groups.v1alpha.Group.update_time:type_name -> google.protobuf.Timestamp + 22, // 10: com.mintter.groups.v1alpha.Group.site_info:type_name -> com.mintter.groups.v1alpha.Group.SiteInfo + 0, // 11: com.mintter.groups.v1alpha.CreateGroupRequest.MembersEntry.value:type_name -> com.mintter.groups.v1alpha.Role + 0, // 12: com.mintter.groups.v1alpha.UpdateGroupRequest.UpdatedMembersEntry.value:type_name -> com.mintter.groups.v1alpha.Role + 0, // 13: com.mintter.groups.v1alpha.ListMembersResponse.MembersEntry.value:type_name -> com.mintter.groups.v1alpha.Role + 23, // 14: com.mintter.groups.v1alpha.ListDocumentGroupsResponse.Item.change_time:type_name -> google.protobuf.Timestamp + 14, // 15: com.mintter.groups.v1alpha.ListAccountGroupsResponse.Item.group:type_name -> com.mintter.groups.v1alpha.Group + 0, // 16: com.mintter.groups.v1alpha.ListAccountGroupsResponse.Item.role:type_name -> com.mintter.groups.v1alpha.Role + 23, // 17: com.mintter.groups.v1alpha.Group.SiteInfo.last_sync_time:type_name -> google.protobuf.Timestamp + 23, // 18: com.mintter.groups.v1alpha.Group.SiteInfo.last_ok_sync_time:type_name -> google.protobuf.Timestamp + 1, // 19: com.mintter.groups.v1alpha.Groups.CreateGroup:input_type -> com.mintter.groups.v1alpha.CreateGroupRequest + 2, // 20: com.mintter.groups.v1alpha.Groups.GetGroup:input_type -> com.mintter.groups.v1alpha.GetGroupRequest + 3, // 21: com.mintter.groups.v1alpha.Groups.UpdateGroup:input_type -> com.mintter.groups.v1alpha.UpdateGroupRequest + 4, // 22: com.mintter.groups.v1alpha.Groups.ListMembers:input_type -> com.mintter.groups.v1alpha.ListMembersRequest + 6, // 23: com.mintter.groups.v1alpha.Groups.ListContent:input_type -> com.mintter.groups.v1alpha.ListContentRequest + 8, // 24: com.mintter.groups.v1alpha.Groups.ListGroups:input_type -> com.mintter.groups.v1alpha.ListGroupsRequest + 10, // 25: com.mintter.groups.v1alpha.Groups.ListDocumentGroups:input_type -> com.mintter.groups.v1alpha.ListDocumentGroupsRequest + 12, // 26: com.mintter.groups.v1alpha.Groups.ListAccountGroups:input_type -> com.mintter.groups.v1alpha.ListAccountGroupsRequest + 14, // 27: com.mintter.groups.v1alpha.Groups.CreateGroup:output_type -> com.mintter.groups.v1alpha.Group + 14, // 28: com.mintter.groups.v1alpha.Groups.GetGroup:output_type -> com.mintter.groups.v1alpha.Group + 14, // 29: com.mintter.groups.v1alpha.Groups.UpdateGroup:output_type -> com.mintter.groups.v1alpha.Group + 5, // 30: com.mintter.groups.v1alpha.Groups.ListMembers:output_type -> com.mintter.groups.v1alpha.ListMembersResponse + 7, // 31: com.mintter.groups.v1alpha.Groups.ListContent:output_type -> com.mintter.groups.v1alpha.ListContentResponse + 9, // 32: com.mintter.groups.v1alpha.Groups.ListGroups:output_type -> com.mintter.groups.v1alpha.ListGroupsResponse + 11, // 33: com.mintter.groups.v1alpha.Groups.ListDocumentGroups:output_type -> com.mintter.groups.v1alpha.ListDocumentGroupsResponse + 13, // 34: com.mintter.groups.v1alpha.Groups.ListAccountGroups:output_type -> com.mintter.groups.v1alpha.ListAccountGroupsResponse + 27, // [27:35] is the sub-list for method output_type + 19, // [19:27] is the sub-list for method input_type + 19, // [19:19] is the sub-list for extension type_name + 19, // [19:19] is the sub-list for extension extendee + 0, // [0:19] is the sub-list for field type_name } func init() { file_groups_v1alpha_groups_proto_init() } @@ -1951,7 +1775,7 @@ func file_groups_v1alpha_groups_proto_init() { } } file_groups_v1alpha_groups_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ConvertToSiteRequest); i { + switch v := v.(*ListDocumentGroupsRequest); i { case 0: return &v.state case 1: @@ -1963,7 +1787,7 @@ func file_groups_v1alpha_groups_proto_init() { } } file_groups_v1alpha_groups_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ConvertToSiteResponse); i { + switch v := v.(*ListDocumentGroupsResponse); i { case 0: return &v.state case 1: @@ -1975,7 +1799,7 @@ func file_groups_v1alpha_groups_proto_init() { } } file_groups_v1alpha_groups_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetSiteInfoRequest); i { + switch v := v.(*ListAccountGroupsRequest); i { case 0: return &v.state case 1: @@ -1987,7 +1811,7 @@ func file_groups_v1alpha_groups_proto_init() { } } file_groups_v1alpha_groups_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetSiteInfoResponse); i { + switch v := v.(*ListAccountGroupsResponse); i { case 0: return &v.state case 1: @@ -1999,43 +1823,7 @@ func file_groups_v1alpha_groups_proto_init() { } } file_groups_v1alpha_groups_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ListDocumentGroupsRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_groups_v1alpha_groups_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ListDocumentGroupsResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_groups_v1alpha_groups_proto_msgTypes[15].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ListAccountGroupsRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_groups_v1alpha_groups_proto_msgTypes[16].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ListAccountGroupsResponse); i { + switch v := v.(*Group); i { case 0: return &v.state case 1: @@ -2046,8 +1834,8 @@ func file_groups_v1alpha_groups_proto_init() { return nil } } - file_groups_v1alpha_groups_proto_msgTypes[17].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Group); i { + file_groups_v1alpha_groups_proto_msgTypes[19].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ListDocumentGroupsResponse_Item); i { case 0: return &v.state case 1: @@ -2058,8 +1846,8 @@ func file_groups_v1alpha_groups_proto_init() { return nil } } - file_groups_v1alpha_groups_proto_msgTypes[23].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ListDocumentGroupsResponse_Item); i { + file_groups_v1alpha_groups_proto_msgTypes[20].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ListAccountGroupsResponse_Item); i { case 0: return &v.state case 1: @@ -2070,8 +1858,8 @@ func file_groups_v1alpha_groups_proto_init() { return nil } } - file_groups_v1alpha_groups_proto_msgTypes[24].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ListAccountGroupsResponse_Item); i { + file_groups_v1alpha_groups_proto_msgTypes[21].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Group_SiteInfo); i { case 0: return &v.state case 1: @@ -2089,7 +1877,7 @@ func file_groups_v1alpha_groups_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_groups_v1alpha_groups_proto_rawDesc, NumEnums: 1, - NumMessages: 25, + NumMessages: 22, NumExtensions: 0, NumServices: 1, }, diff --git a/backend/genproto/groups/v1alpha/groups_grpc.pb.go b/backend/genproto/groups/v1alpha/groups_grpc.pb.go index 4823ff164c..9e9d140ff4 100644 --- a/backend/genproto/groups/v1alpha/groups_grpc.pb.go +++ b/backend/genproto/groups/v1alpha/groups_grpc.pb.go @@ -34,10 +34,6 @@ type GroupsClient interface { ListContent(ctx context.Context, in *ListContentRequest, opts ...grpc.CallOption) (*ListContentResponse, error) // Lists groups. ListGroups(ctx context.Context, in *ListGroupsRequest, opts ...grpc.CallOption) (*ListGroupsResponse, error) - // Converts a group to a site. P2P group will continue to work. - ConvertToSite(ctx context.Context, in *ConvertToSiteRequest, opts ...grpc.CallOption) (*ConvertToSiteResponse, error) - // Gets information about a site. - GetSiteInfo(ctx context.Context, in *GetSiteInfoRequest, opts ...grpc.CallOption) (*GetSiteInfoResponse, error) // Lists groups that a document is published to. ListDocumentGroups(ctx context.Context, in *ListDocumentGroupsRequest, opts ...grpc.CallOption) (*ListDocumentGroupsResponse, error) // Lists groups that an account is a member of. @@ -106,24 +102,6 @@ func (c *groupsClient) ListGroups(ctx context.Context, in *ListGroupsRequest, op return out, nil } -func (c *groupsClient) ConvertToSite(ctx context.Context, in *ConvertToSiteRequest, opts ...grpc.CallOption) (*ConvertToSiteResponse, error) { - out := new(ConvertToSiteResponse) - err := c.cc.Invoke(ctx, "/com.mintter.groups.v1alpha.Groups/ConvertToSite", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *groupsClient) GetSiteInfo(ctx context.Context, in *GetSiteInfoRequest, opts ...grpc.CallOption) (*GetSiteInfoResponse, error) { - out := new(GetSiteInfoResponse) - err := c.cc.Invoke(ctx, "/com.mintter.groups.v1alpha.Groups/GetSiteInfo", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - func (c *groupsClient) ListDocumentGroups(ctx context.Context, in *ListDocumentGroupsRequest, opts ...grpc.CallOption) (*ListDocumentGroupsResponse, error) { out := new(ListDocumentGroupsResponse) err := c.cc.Invoke(ctx, "/com.mintter.groups.v1alpha.Groups/ListDocumentGroups", in, out, opts...) @@ -158,10 +136,6 @@ type GroupsServer interface { ListContent(context.Context, *ListContentRequest) (*ListContentResponse, error) // Lists groups. ListGroups(context.Context, *ListGroupsRequest) (*ListGroupsResponse, error) - // Converts a group to a site. P2P group will continue to work. - ConvertToSite(context.Context, *ConvertToSiteRequest) (*ConvertToSiteResponse, error) - // Gets information about a site. - GetSiteInfo(context.Context, *GetSiteInfoRequest) (*GetSiteInfoResponse, error) // Lists groups that a document is published to. ListDocumentGroups(context.Context, *ListDocumentGroupsRequest) (*ListDocumentGroupsResponse, error) // Lists groups that an account is a member of. @@ -190,12 +164,6 @@ func (UnimplementedGroupsServer) ListContent(context.Context, *ListContentReques func (UnimplementedGroupsServer) ListGroups(context.Context, *ListGroupsRequest) (*ListGroupsResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method ListGroups not implemented") } -func (UnimplementedGroupsServer) ConvertToSite(context.Context, *ConvertToSiteRequest) (*ConvertToSiteResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method ConvertToSite not implemented") -} -func (UnimplementedGroupsServer) GetSiteInfo(context.Context, *GetSiteInfoRequest) (*GetSiteInfoResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method GetSiteInfo not implemented") -} func (UnimplementedGroupsServer) ListDocumentGroups(context.Context, *ListDocumentGroupsRequest) (*ListDocumentGroupsResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method ListDocumentGroups not implemented") } @@ -322,42 +290,6 @@ func _Groups_ListGroups_Handler(srv interface{}, ctx context.Context, dec func(i return interceptor(ctx, in, info, handler) } -func _Groups_ConvertToSite_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(ConvertToSiteRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(GroupsServer).ConvertToSite(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/com.mintter.groups.v1alpha.Groups/ConvertToSite", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(GroupsServer).ConvertToSite(ctx, req.(*ConvertToSiteRequest)) - } - return interceptor(ctx, in, info, handler) -} - -func _Groups_GetSiteInfo_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(GetSiteInfoRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(GroupsServer).GetSiteInfo(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/com.mintter.groups.v1alpha.Groups/GetSiteInfo", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(GroupsServer).GetSiteInfo(ctx, req.(*GetSiteInfoRequest)) - } - return interceptor(ctx, in, info, handler) -} - func _Groups_ListDocumentGroups_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(ListDocumentGroupsRequest) if err := dec(in); err != nil { @@ -425,14 +357,6 @@ var Groups_ServiceDesc = grpc.ServiceDesc{ MethodName: "ListGroups", Handler: _Groups_ListGroups_Handler, }, - { - MethodName: "ConvertToSite", - Handler: _Groups_ConvertToSite_Handler, - }, - { - MethodName: "GetSiteInfo", - Handler: _Groups_GetSiteInfo_Handler, - }, { MethodName: "ListDocumentGroups", Handler: _Groups_ListDocumentGroups_Handler, diff --git a/backend/genproto/groups/v1alpha/website.pb.go b/backend/genproto/groups/v1alpha/website.pb.go new file mode 100644 index 0000000000..742d531a1a --- /dev/null +++ b/backend/genproto/groups/v1alpha/website.pb.go @@ -0,0 +1,595 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.31.0 +// protoc v3.21.12 +// source: groups/v1alpha/website.proto + +package groups + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +// Request for getting the public site information. +type GetSiteInfoRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *GetSiteInfoRequest) Reset() { + *x = GetSiteInfoRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_groups_v1alpha_website_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetSiteInfoRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetSiteInfoRequest) ProtoMessage() {} + +func (x *GetSiteInfoRequest) ProtoReflect() protoreflect.Message { + mi := &file_groups_v1alpha_website_proto_msgTypes[0] + 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 GetSiteInfoRequest.ProtoReflect.Descriptor instead. +func (*GetSiteInfoRequest) Descriptor() ([]byte, []int) { + return file_groups_v1alpha_website_proto_rawDescGZIP(), []int{0} +} + +// Request for initializing the site. +type InitializeServerRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Required. The secret provided during the site deployment process. + // It's a trust-on-first-use, one-time-use secret that is used for the initial site setup, + // during which the site remembers the groups that it must serve, and who is the owner of the site. + Secret string `protobuf:"bytes,1,opt,name=secret,proto3" json:"secret,omitempty"` + // Required. ID of the group that should be served on this site. + GroupId string `protobuf:"bytes,2,opt,name=group_id,json=groupId,proto3" json:"group_id,omitempty"` +} + +func (x *InitializeServerRequest) Reset() { + *x = InitializeServerRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_groups_v1alpha_website_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *InitializeServerRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*InitializeServerRequest) ProtoMessage() {} + +func (x *InitializeServerRequest) ProtoReflect() protoreflect.Message { + mi := &file_groups_v1alpha_website_proto_msgTypes[1] + 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 InitializeServerRequest.ProtoReflect.Descriptor instead. +func (*InitializeServerRequest) Descriptor() ([]byte, []int) { + return file_groups_v1alpha_website_proto_rawDescGZIP(), []int{1} +} + +func (x *InitializeServerRequest) GetSecret() string { + if x != nil { + return x.Secret + } + return "" +} + +func (x *InitializeServerRequest) GetGroupId() string { + if x != nil { + return x.GroupId + } + return "" +} + +// Response for initializing the site. +type InitializeServerResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *InitializeServerResponse) Reset() { + *x = InitializeServerResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_groups_v1alpha_website_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *InitializeServerResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*InitializeServerResponse) ProtoMessage() {} + +func (x *InitializeServerResponse) ProtoReflect() protoreflect.Message { + mi := &file_groups_v1alpha_website_proto_msgTypes[2] + 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 InitializeServerResponse.ProtoReflect.Descriptor instead. +func (*InitializeServerResponse) Descriptor() ([]byte, []int) { + return file_groups_v1alpha_website_proto_rawDescGZIP(), []int{2} +} + +// Request for publishing blobs. +type PublishBlobsRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // List of blob CIDs that we expect to be available on the site. + Blobs []string `protobuf:"bytes,1,rep,name=blobs,proto3" json:"blobs,omitempty"` +} + +func (x *PublishBlobsRequest) Reset() { + *x = PublishBlobsRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_groups_v1alpha_website_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *PublishBlobsRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PublishBlobsRequest) ProtoMessage() {} + +func (x *PublishBlobsRequest) ProtoReflect() protoreflect.Message { + mi := &file_groups_v1alpha_website_proto_msgTypes[3] + 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 PublishBlobsRequest.ProtoReflect.Descriptor instead. +func (*PublishBlobsRequest) Descriptor() ([]byte, []int) { + return file_groups_v1alpha_website_proto_rawDescGZIP(), []int{3} +} + +func (x *PublishBlobsRequest) GetBlobs() []string { + if x != nil { + return x.Blobs + } + return nil +} + +// Response for publishing blobs. +type PublishBlobsResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *PublishBlobsResponse) Reset() { + *x = PublishBlobsResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_groups_v1alpha_website_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *PublishBlobsResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PublishBlobsResponse) ProtoMessage() {} + +func (x *PublishBlobsResponse) ProtoReflect() protoreflect.Message { + mi := &file_groups_v1alpha_website_proto_msgTypes[4] + 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 PublishBlobsResponse.ProtoReflect.Descriptor instead. +func (*PublishBlobsResponse) Descriptor() ([]byte, []int) { + return file_groups_v1alpha_website_proto_rawDescGZIP(), []int{4} +} + +// Publicly available information about the website. +type PublicSiteInfo struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // P2P information for the website. + PeerInfo *PeerInfo `protobuf:"bytes,1,opt,name=peer_info,json=peerInfo,proto3" json:"peer_info,omitempty"` + // Group ID being served on the site. + // Can be empty if site is not initialized yet. + GroupId string `protobuf:"bytes,2,opt,name=group_id,json=groupId,proto3" json:"group_id,omitempty"` + // Version of the group according to the website server. + GroupVersion string `protobuf:"bytes,3,opt,name=group_version,json=groupVersion,proto3" json:"group_version,omitempty"` +} + +func (x *PublicSiteInfo) Reset() { + *x = PublicSiteInfo{} + if protoimpl.UnsafeEnabled { + mi := &file_groups_v1alpha_website_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *PublicSiteInfo) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PublicSiteInfo) ProtoMessage() {} + +func (x *PublicSiteInfo) ProtoReflect() protoreflect.Message { + mi := &file_groups_v1alpha_website_proto_msgTypes[5] + 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 PublicSiteInfo.ProtoReflect.Descriptor instead. +func (*PublicSiteInfo) Descriptor() ([]byte, []int) { + return file_groups_v1alpha_website_proto_rawDescGZIP(), []int{5} +} + +func (x *PublicSiteInfo) GetPeerInfo() *PeerInfo { + if x != nil { + return x.PeerInfo + } + return nil +} + +func (x *PublicSiteInfo) GetGroupId() string { + if x != nil { + return x.GroupId + } + return "" +} + +func (x *PublicSiteInfo) GetGroupVersion() string { + if x != nil { + return x.GroupVersion + } + return "" +} + +// Peer information for P2P network. +type PeerInfo struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Libp2p peer ID. + PeerId string `protobuf:"bytes,1,opt,name=peer_id,json=peerId,proto3" json:"peer_id,omitempty"` + // Multiaddrs for the peer, + // without the peer ID, + // in order to use it with libp2p AddrInfo API. + Addrs []string `protobuf:"bytes,2,rep,name=addrs,proto3" json:"addrs,omitempty"` + // Mintter Account ID of the site. + AccountId string `protobuf:"bytes,3,opt,name=account_id,json=accountId,proto3" json:"account_id,omitempty"` +} + +func (x *PeerInfo) Reset() { + *x = PeerInfo{} + if protoimpl.UnsafeEnabled { + mi := &file_groups_v1alpha_website_proto_msgTypes[6] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *PeerInfo) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PeerInfo) ProtoMessage() {} + +func (x *PeerInfo) ProtoReflect() protoreflect.Message { + mi := &file_groups_v1alpha_website_proto_msgTypes[6] + 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 PeerInfo.ProtoReflect.Descriptor instead. +func (*PeerInfo) Descriptor() ([]byte, []int) { + return file_groups_v1alpha_website_proto_rawDescGZIP(), []int{6} +} + +func (x *PeerInfo) GetPeerId() string { + if x != nil { + return x.PeerId + } + return "" +} + +func (x *PeerInfo) GetAddrs() []string { + if x != nil { + return x.Addrs + } + return nil +} + +func (x *PeerInfo) GetAccountId() string { + if x != nil { + return x.AccountId + } + return "" +} + +var File_groups_v1alpha_website_proto protoreflect.FileDescriptor + +var file_groups_v1alpha_website_proto_rawDesc = []byte{ + 0x0a, 0x1c, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, + 0x2f, 0x77, 0x65, 0x62, 0x73, 0x69, 0x74, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x1a, + 0x63, 0x6f, 0x6d, 0x2e, 0x6d, 0x69, 0x6e, 0x74, 0x74, 0x65, 0x72, 0x2e, 0x67, 0x72, 0x6f, 0x75, + 0x70, 0x73, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x22, 0x14, 0x0a, 0x12, 0x47, 0x65, + 0x74, 0x53, 0x69, 0x74, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x22, 0x4c, 0x0a, 0x17, 0x49, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x53, 0x65, + 0x72, 0x76, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x73, + 0x65, 0x63, 0x72, 0x65, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x65, 0x63, + 0x72, 0x65, 0x74, 0x12, 0x19, 0x0a, 0x08, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x5f, 0x69, 0x64, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x49, 0x64, 0x22, 0x1a, + 0x0a, 0x18, 0x49, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x53, 0x65, 0x72, 0x76, + 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2b, 0x0a, 0x13, 0x50, 0x75, + 0x62, 0x6c, 0x69, 0x73, 0x68, 0x42, 0x6c, 0x6f, 0x62, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x12, 0x14, 0x0a, 0x05, 0x62, 0x6c, 0x6f, 0x62, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, + 0x52, 0x05, 0x62, 0x6c, 0x6f, 0x62, 0x73, 0x22, 0x16, 0x0a, 0x14, 0x50, 0x75, 0x62, 0x6c, 0x69, + 0x73, 0x68, 0x42, 0x6c, 0x6f, 0x62, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, + 0x93, 0x01, 0x0a, 0x0e, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x53, 0x69, 0x74, 0x65, 0x49, 0x6e, + 0x66, 0x6f, 0x12, 0x41, 0x0a, 0x09, 0x70, 0x65, 0x65, 0x72, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x6d, 0x69, 0x6e, 0x74, + 0x74, 0x65, 0x72, 0x2e, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, + 0x68, 0x61, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x08, 0x70, 0x65, 0x65, + 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x19, 0x0a, 0x08, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x5f, 0x69, + 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x49, 0x64, + 0x12, 0x23, 0x0a, 0x0d, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, + 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x56, 0x65, + 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x58, 0x0a, 0x08, 0x50, 0x65, 0x65, 0x72, 0x49, 0x6e, 0x66, + 0x6f, 0x12, 0x17, 0x0a, 0x07, 0x70, 0x65, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x06, 0x70, 0x65, 0x65, 0x72, 0x49, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x61, 0x64, + 0x64, 0x72, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x05, 0x61, 0x64, 0x64, 0x72, 0x73, + 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, 0x32, + 0xe6, 0x02, 0x0a, 0x07, 0x57, 0x65, 0x62, 0x73, 0x69, 0x74, 0x65, 0x12, 0x69, 0x0a, 0x0b, 0x47, + 0x65, 0x74, 0x53, 0x69, 0x74, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x2e, 0x2e, 0x63, 0x6f, 0x6d, + 0x2e, 0x6d, 0x69, 0x6e, 0x74, 0x74, 0x65, 0x72, 0x2e, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x2e, + 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x69, 0x74, 0x65, 0x49, + 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x63, 0x6f, 0x6d, + 0x2e, 0x6d, 0x69, 0x6e, 0x74, 0x74, 0x65, 0x72, 0x2e, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x2e, + 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x53, 0x69, + 0x74, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x7d, 0x0a, 0x10, 0x49, 0x6e, 0x69, 0x74, 0x69, 0x61, + 0x6c, 0x69, 0x7a, 0x65, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x12, 0x33, 0x2e, 0x63, 0x6f, 0x6d, + 0x2e, 0x6d, 0x69, 0x6e, 0x74, 0x74, 0x65, 0x72, 0x2e, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x2e, + 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x49, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, 0x69, + 0x7a, 0x65, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x34, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x6d, 0x69, 0x6e, 0x74, 0x74, 0x65, 0x72, 0x2e, 0x67, 0x72, + 0x6f, 0x75, 0x70, 0x73, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x49, 0x6e, 0x69, + 0x74, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x71, 0x0a, 0x0c, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, + 0x42, 0x6c, 0x6f, 0x62, 0x73, 0x12, 0x2f, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x6d, 0x69, 0x6e, 0x74, + 0x74, 0x65, 0x72, 0x2e, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, + 0x68, 0x61, 0x2e, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x42, 0x6c, 0x6f, 0x62, 0x73, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x30, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x6d, 0x69, 0x6e, + 0x74, 0x74, 0x65, 0x72, 0x2e, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x2e, 0x76, 0x31, 0x61, 0x6c, + 0x70, 0x68, 0x61, 0x2e, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x42, 0x6c, 0x6f, 0x62, 0x73, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x30, 0x5a, 0x2e, 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, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x2f, 0x76, 0x31, 0x61, 0x6c, + 0x70, 0x68, 0x61, 0x3b, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x33, +} + +var ( + file_groups_v1alpha_website_proto_rawDescOnce sync.Once + file_groups_v1alpha_website_proto_rawDescData = file_groups_v1alpha_website_proto_rawDesc +) + +func file_groups_v1alpha_website_proto_rawDescGZIP() []byte { + file_groups_v1alpha_website_proto_rawDescOnce.Do(func() { + file_groups_v1alpha_website_proto_rawDescData = protoimpl.X.CompressGZIP(file_groups_v1alpha_website_proto_rawDescData) + }) + return file_groups_v1alpha_website_proto_rawDescData +} + +var file_groups_v1alpha_website_proto_msgTypes = make([]protoimpl.MessageInfo, 7) +var file_groups_v1alpha_website_proto_goTypes = []interface{}{ + (*GetSiteInfoRequest)(nil), // 0: com.mintter.groups.v1alpha.GetSiteInfoRequest + (*InitializeServerRequest)(nil), // 1: com.mintter.groups.v1alpha.InitializeServerRequest + (*InitializeServerResponse)(nil), // 2: com.mintter.groups.v1alpha.InitializeServerResponse + (*PublishBlobsRequest)(nil), // 3: com.mintter.groups.v1alpha.PublishBlobsRequest + (*PublishBlobsResponse)(nil), // 4: com.mintter.groups.v1alpha.PublishBlobsResponse + (*PublicSiteInfo)(nil), // 5: com.mintter.groups.v1alpha.PublicSiteInfo + (*PeerInfo)(nil), // 6: com.mintter.groups.v1alpha.PeerInfo +} +var file_groups_v1alpha_website_proto_depIdxs = []int32{ + 6, // 0: com.mintter.groups.v1alpha.PublicSiteInfo.peer_info:type_name -> com.mintter.groups.v1alpha.PeerInfo + 0, // 1: com.mintter.groups.v1alpha.Website.GetSiteInfo:input_type -> com.mintter.groups.v1alpha.GetSiteInfoRequest + 1, // 2: com.mintter.groups.v1alpha.Website.InitializeServer:input_type -> com.mintter.groups.v1alpha.InitializeServerRequest + 3, // 3: com.mintter.groups.v1alpha.Website.PublishBlobs:input_type -> com.mintter.groups.v1alpha.PublishBlobsRequest + 5, // 4: com.mintter.groups.v1alpha.Website.GetSiteInfo:output_type -> com.mintter.groups.v1alpha.PublicSiteInfo + 2, // 5: com.mintter.groups.v1alpha.Website.InitializeServer:output_type -> com.mintter.groups.v1alpha.InitializeServerResponse + 4, // 6: com.mintter.groups.v1alpha.Website.PublishBlobs:output_type -> com.mintter.groups.v1alpha.PublishBlobsResponse + 4, // [4:7] is the sub-list for method output_type + 1, // [1:4] is the sub-list for method input_type + 1, // [1:1] is the sub-list for extension type_name + 1, // [1:1] is the sub-list for extension extendee + 0, // [0:1] is the sub-list for field type_name +} + +func init() { file_groups_v1alpha_website_proto_init() } +func file_groups_v1alpha_website_proto_init() { + if File_groups_v1alpha_website_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_groups_v1alpha_website_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GetSiteInfoRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_groups_v1alpha_website_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*InitializeServerRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_groups_v1alpha_website_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*InitializeServerResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_groups_v1alpha_website_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*PublishBlobsRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_groups_v1alpha_website_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*PublishBlobsResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_groups_v1alpha_website_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*PublicSiteInfo); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_groups_v1alpha_website_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*PeerInfo); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_groups_v1alpha_website_proto_rawDesc, + NumEnums: 0, + NumMessages: 7, + NumExtensions: 0, + NumServices: 1, + }, + GoTypes: file_groups_v1alpha_website_proto_goTypes, + DependencyIndexes: file_groups_v1alpha_website_proto_depIdxs, + MessageInfos: file_groups_v1alpha_website_proto_msgTypes, + }.Build() + File_groups_v1alpha_website_proto = out.File + file_groups_v1alpha_website_proto_rawDesc = nil + file_groups_v1alpha_website_proto_goTypes = nil + file_groups_v1alpha_website_proto_depIdxs = nil +} diff --git a/backend/genproto/groups/v1alpha/website_grpc.pb.go b/backend/genproto/groups/v1alpha/website_grpc.pb.go new file mode 100644 index 0000000000..6f974c0785 --- /dev/null +++ b/backend/genproto/groups/v1alpha/website_grpc.pb.go @@ -0,0 +1,183 @@ +// Code generated by protoc-gen-go-grpc. DO NOT EDIT. +// versions: +// - protoc-gen-go-grpc v1.2.0 +// - protoc v3.21.12 +// source: groups/v1alpha/website.proto + +package groups + +import ( + context "context" + grpc "google.golang.org/grpc" + codes "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" +) + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +// Requires gRPC-Go v1.32.0 or later. +const _ = grpc.SupportPackageIsVersion7 + +// WebsiteClient is the client API for Website service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. +type WebsiteClient interface { + // Gets the public information about the website. + // This information is also available as JSON over HTTP on `/.well-known/hypermedia-site`. + GetSiteInfo(ctx context.Context, in *GetSiteInfoRequest, opts ...grpc.CallOption) (*PublicSiteInfo, error) + // Initializes the server to become a website for a specific group. + InitializeServer(ctx context.Context, in *InitializeServerRequest, opts ...grpc.CallOption) (*InitializeServerResponse, error) + // Publishes blobs to the website. + PublishBlobs(ctx context.Context, in *PublishBlobsRequest, opts ...grpc.CallOption) (*PublishBlobsResponse, error) +} + +type websiteClient struct { + cc grpc.ClientConnInterface +} + +func NewWebsiteClient(cc grpc.ClientConnInterface) WebsiteClient { + return &websiteClient{cc} +} + +func (c *websiteClient) GetSiteInfo(ctx context.Context, in *GetSiteInfoRequest, opts ...grpc.CallOption) (*PublicSiteInfo, error) { + out := new(PublicSiteInfo) + err := c.cc.Invoke(ctx, "/com.mintter.groups.v1alpha.Website/GetSiteInfo", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *websiteClient) InitializeServer(ctx context.Context, in *InitializeServerRequest, opts ...grpc.CallOption) (*InitializeServerResponse, error) { + out := new(InitializeServerResponse) + err := c.cc.Invoke(ctx, "/com.mintter.groups.v1alpha.Website/InitializeServer", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *websiteClient) PublishBlobs(ctx context.Context, in *PublishBlobsRequest, opts ...grpc.CallOption) (*PublishBlobsResponse, error) { + out := new(PublishBlobsResponse) + err := c.cc.Invoke(ctx, "/com.mintter.groups.v1alpha.Website/PublishBlobs", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// WebsiteServer is the server API for Website service. +// All implementations should embed UnimplementedWebsiteServer +// for forward compatibility +type WebsiteServer interface { + // Gets the public information about the website. + // This information is also available as JSON over HTTP on `/.well-known/hypermedia-site`. + GetSiteInfo(context.Context, *GetSiteInfoRequest) (*PublicSiteInfo, error) + // Initializes the server to become a website for a specific group. + InitializeServer(context.Context, *InitializeServerRequest) (*InitializeServerResponse, error) + // Publishes blobs to the website. + PublishBlobs(context.Context, *PublishBlobsRequest) (*PublishBlobsResponse, error) +} + +// UnimplementedWebsiteServer should be embedded to have forward compatible implementations. +type UnimplementedWebsiteServer struct { +} + +func (UnimplementedWebsiteServer) GetSiteInfo(context.Context, *GetSiteInfoRequest) (*PublicSiteInfo, error) { + return nil, status.Errorf(codes.Unimplemented, "method GetSiteInfo not implemented") +} +func (UnimplementedWebsiteServer) InitializeServer(context.Context, *InitializeServerRequest) (*InitializeServerResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method InitializeServer not implemented") +} +func (UnimplementedWebsiteServer) PublishBlobs(context.Context, *PublishBlobsRequest) (*PublishBlobsResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method PublishBlobs not implemented") +} + +// UnsafeWebsiteServer may be embedded to opt out of forward compatibility for this service. +// Use of this interface is not recommended, as added methods to WebsiteServer will +// result in compilation errors. +type UnsafeWebsiteServer interface { + mustEmbedUnimplementedWebsiteServer() +} + +func RegisterWebsiteServer(s grpc.ServiceRegistrar, srv WebsiteServer) { + s.RegisterService(&Website_ServiceDesc, srv) +} + +func _Website_GetSiteInfo_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(GetSiteInfoRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(WebsiteServer).GetSiteInfo(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/com.mintter.groups.v1alpha.Website/GetSiteInfo", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(WebsiteServer).GetSiteInfo(ctx, req.(*GetSiteInfoRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Website_InitializeServer_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(InitializeServerRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(WebsiteServer).InitializeServer(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/com.mintter.groups.v1alpha.Website/InitializeServer", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(WebsiteServer).InitializeServer(ctx, req.(*InitializeServerRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Website_PublishBlobs_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(PublishBlobsRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(WebsiteServer).PublishBlobs(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/com.mintter.groups.v1alpha.Website/PublishBlobs", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(WebsiteServer).PublishBlobs(ctx, req.(*PublishBlobsRequest)) + } + return interceptor(ctx, in, info, handler) +} + +// Website_ServiceDesc is the grpc.ServiceDesc for Website service. +// It's only intended for direct use with grpc.RegisterService, +// and not to be introspected or modified (even as a copy) +var Website_ServiceDesc = grpc.ServiceDesc{ + ServiceName: "com.mintter.groups.v1alpha.Website", + HandlerType: (*WebsiteServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "GetSiteInfo", + Handler: _Website_GetSiteInfo_Handler, + }, + { + MethodName: "InitializeServer", + Handler: _Website_InitializeServer_Handler, + }, + { + MethodName: "PublishBlobs", + Handler: _Website_PublishBlobs_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "groups/v1alpha/website.proto", +} diff --git a/backend/genproto/networking/v1alpha/networking.pb.go b/backend/genproto/networking/v1alpha/networking.pb.go index ccd892ed3c..73effa908f 100644 --- a/backend/genproto/networking/v1alpha/networking.pb.go +++ b/backend/genproto/networking/v1alpha/networking.pb.go @@ -1,6 +1,6 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.30.0 +// protoc-gen-go v1.31.0 // protoc v3.21.12 // source: networking/v1alpha/networking.proto diff --git a/backend/genproto/p2p/v1alpha/p2p.pb.go b/backend/genproto/p2p/v1alpha/p2p.pb.go index 53faa82300..668665aa62 100644 --- a/backend/genproto/p2p/v1alpha/p2p.pb.go +++ b/backend/genproto/p2p/v1alpha/p2p.pb.go @@ -1,6 +1,6 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.30.0 +// protoc-gen-go v1.31.0 // protoc v3.21.12 // source: p2p/v1alpha/p2p.proto @@ -342,132 +342,6 @@ func (x *RequestInvoiceResponse) GetPayReq() string { return "" } -// Links a server and a group. -type CreateSiteRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Secret link provided by the deployment script. - Link string `protobuf:"bytes,1,opt,name=link,proto3" json:"link,omitempty"` - // ID of the group to be served. - GroupId string `protobuf:"bytes,2,opt,name=group_id,json=groupId,proto3" json:"group_id,omitempty"` - // Optional version of the group to be served. - // If empty, latest version is assumed. - Version string `protobuf:"bytes,3,opt,name=version,proto3" json:"version,omitempty"` -} - -func (x *CreateSiteRequest) Reset() { - *x = CreateSiteRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_p2p_v1alpha_p2p_proto_msgTypes[6] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *CreateSiteRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*CreateSiteRequest) ProtoMessage() {} - -func (x *CreateSiteRequest) ProtoReflect() protoreflect.Message { - mi := &file_p2p_v1alpha_p2p_proto_msgTypes[6] - 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 CreateSiteRequest.ProtoReflect.Descriptor instead. -func (*CreateSiteRequest) Descriptor() ([]byte, []int) { - return file_p2p_v1alpha_p2p_proto_rawDescGZIP(), []int{6} -} - -func (x *CreateSiteRequest) GetLink() string { - if x != nil { - return x.Link - } - return "" -} - -func (x *CreateSiteRequest) GetGroupId() string { - if x != nil { - return x.GroupId - } - return "" -} - -func (x *CreateSiteRequest) GetVersion() string { - if x != nil { - return x.Version - } - return "" -} - -// Create site response -type CreateSiteResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Owner of the site. - OwnerId string `protobuf:"bytes,1,opt,name=owner_id,json=ownerId,proto3" json:"owner_id,omitempty"` - // ID of the site. - GroupId string `protobuf:"bytes,2,opt,name=group_id,json=groupId,proto3" json:"group_id,omitempty"` -} - -func (x *CreateSiteResponse) Reset() { - *x = CreateSiteResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_p2p_v1alpha_p2p_proto_msgTypes[7] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *CreateSiteResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*CreateSiteResponse) ProtoMessage() {} - -func (x *CreateSiteResponse) ProtoReflect() protoreflect.Message { - mi := &file_p2p_v1alpha_p2p_proto_msgTypes[7] - 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 CreateSiteResponse.ProtoReflect.Descriptor instead. -func (*CreateSiteResponse) Descriptor() ([]byte, []int) { - return file_p2p_v1alpha_p2p_proto_rawDescGZIP(), []int{7} -} - -func (x *CreateSiteResponse) GetOwnerId() string { - if x != nil { - return x.OwnerId - } - return "" -} - -func (x *CreateSiteResponse) GetGroupId() string { - if x != nil { - return x.GroupId - } - return "" -} - var File_p2p_v1alpha_p2p_proto protoreflect.FileDescriptor var file_p2p_v1alpha_p2p_proto_rawDesc = []byte{ @@ -503,48 +377,30 @@ var file_p2p_v1alpha_p2p_proto_rawDesc = []byte{ 0x61, 0x67, 0x65, 0x48, 0x61, 0x73, 0x68, 0x22, 0x31, 0x0a, 0x16, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x49, 0x6e, 0x76, 0x6f, 0x69, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x17, 0x0a, 0x07, 0x70, 0x61, 0x79, 0x5f, 0x72, 0x65, 0x71, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x06, 0x70, 0x61, 0x79, 0x52, 0x65, 0x71, 0x22, 0x5c, 0x0a, 0x11, 0x43, 0x72, - 0x65, 0x61, 0x74, 0x65, 0x53, 0x69, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, - 0x12, 0x0a, 0x04, 0x6c, 0x69, 0x6e, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6c, - 0x69, 0x6e, 0x6b, 0x12, 0x19, 0x0a, 0x08, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x5f, 0x69, 0x64, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x49, 0x64, 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, 0x22, 0x4a, 0x0a, 0x12, 0x43, 0x72, 0x65, 0x61, - 0x74, 0x65, 0x53, 0x69, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x19, - 0x0a, 0x08, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x07, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x49, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x67, 0x72, 0x6f, - 0x75, 0x70, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x67, 0x72, 0x6f, - 0x75, 0x70, 0x49, 0x64, 0x32, 0xa6, 0x03, 0x0a, 0x03, 0x50, 0x32, 0x50, 0x12, 0x5b, 0x0a, 0x09, - 0x48, 0x61, 0x6e, 0x64, 0x73, 0x68, 0x61, 0x6b, 0x65, 0x12, 0x26, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, - 0x6d, 0x69, 0x6e, 0x74, 0x74, 0x65, 0x72, 0x2e, 0x70, 0x32, 0x70, 0x2e, 0x76, 0x31, 0x61, 0x6c, - 0x70, 0x68, 0x61, 0x2e, 0x48, 0x61, 0x6e, 0x64, 0x73, 0x68, 0x61, 0x6b, 0x65, 0x49, 0x6e, 0x66, - 0x6f, 0x1a, 0x26, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x6d, 0x69, 0x6e, 0x74, 0x74, 0x65, 0x72, 0x2e, - 0x70, 0x32, 0x70, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x48, 0x61, 0x6e, 0x64, - 0x73, 0x68, 0x61, 0x6b, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x68, 0x0a, 0x0b, 0x4c, 0x69, 0x73, - 0x74, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x12, 0x2b, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x6d, - 0x69, 0x6e, 0x74, 0x74, 0x65, 0x72, 0x2e, 0x70, 0x32, 0x70, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, - 0x68, 0x61, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2c, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x6d, 0x69, 0x6e, 0x74, - 0x74, 0x65, 0x72, 0x2e, 0x70, 0x32, 0x70, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, - 0x4c, 0x69, 0x73, 0x74, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x12, 0x71, 0x0a, 0x0e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x49, 0x6e, - 0x76, 0x6f, 0x69, 0x63, 0x65, 0x12, 0x2e, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x6d, 0x69, 0x6e, 0x74, - 0x74, 0x65, 0x72, 0x2e, 0x70, 0x32, 0x70, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x49, 0x6e, 0x76, 0x6f, 0x69, 0x63, 0x65, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2f, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x6d, 0x69, 0x6e, 0x74, - 0x74, 0x65, 0x72, 0x2e, 0x70, 0x32, 0x70, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x49, 0x6e, 0x76, 0x6f, 0x69, 0x63, 0x65, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x65, 0x0a, 0x0a, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, - 0x53, 0x69, 0x74, 0x65, 0x12, 0x2a, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x6d, 0x69, 0x6e, 0x74, 0x74, - 0x65, 0x72, 0x2e, 0x70, 0x32, 0x70, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x43, - 0x72, 0x65, 0x61, 0x74, 0x65, 0x53, 0x69, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x2b, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x6d, 0x69, 0x6e, 0x74, 0x74, 0x65, 0x72, 0x2e, 0x70, - 0x32, 0x70, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, - 0x65, 0x53, 0x69, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x2a, 0x5a, - 0x28, 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, 0x70, 0x32, 0x70, 0x2f, 0x76, 0x31, - 0x61, 0x6c, 0x70, 0x68, 0x61, 0x3b, 0x70, 0x32, 0x70, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x33, + 0x28, 0x09, 0x52, 0x06, 0x70, 0x61, 0x79, 0x52, 0x65, 0x71, 0x32, 0xbf, 0x02, 0x0a, 0x03, 0x50, + 0x32, 0x50, 0x12, 0x5b, 0x0a, 0x09, 0x48, 0x61, 0x6e, 0x64, 0x73, 0x68, 0x61, 0x6b, 0x65, 0x12, + 0x26, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x6d, 0x69, 0x6e, 0x74, 0x74, 0x65, 0x72, 0x2e, 0x70, 0x32, + 0x70, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x48, 0x61, 0x6e, 0x64, 0x73, 0x68, + 0x61, 0x6b, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x1a, 0x26, 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x6d, 0x69, + 0x6e, 0x74, 0x74, 0x65, 0x72, 0x2e, 0x70, 0x32, 0x70, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, + 0x61, 0x2e, 0x48, 0x61, 0x6e, 0x64, 0x73, 0x68, 0x61, 0x6b, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x12, + 0x68, 0x0a, 0x0b, 0x4c, 0x69, 0x73, 0x74, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x12, 0x2b, + 0x2e, 0x63, 0x6f, 0x6d, 0x2e, 0x6d, 0x69, 0x6e, 0x74, 0x74, 0x65, 0x72, 0x2e, 0x70, 0x32, 0x70, + 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4f, 0x62, 0x6a, + 0x65, 0x63, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2c, 0x2e, 0x63, 0x6f, + 0x6d, 0x2e, 0x6d, 0x69, 0x6e, 0x74, 0x74, 0x65, 0x72, 0x2e, 0x70, 0x32, 0x70, 0x2e, 0x76, 0x31, + 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, + 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x71, 0x0a, 0x0e, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x49, 0x6e, 0x76, 0x6f, 0x69, 0x63, 0x65, 0x12, 0x2e, 0x2e, 0x63, 0x6f, + 0x6d, 0x2e, 0x6d, 0x69, 0x6e, 0x74, 0x74, 0x65, 0x72, 0x2e, 0x70, 0x32, 0x70, 0x2e, 0x76, 0x31, + 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x49, 0x6e, 0x76, + 0x6f, 0x69, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2f, 0x2e, 0x63, 0x6f, + 0x6d, 0x2e, 0x6d, 0x69, 0x6e, 0x74, 0x74, 0x65, 0x72, 0x2e, 0x70, 0x32, 0x70, 0x2e, 0x76, 0x31, + 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x49, 0x6e, 0x76, + 0x6f, 0x69, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x2a, 0x5a, 0x28, + 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, 0x70, 0x32, 0x70, 0x2f, 0x76, 0x31, 0x61, + 0x6c, 0x70, 0x68, 0x61, 0x3b, 0x70, 0x32, 0x70, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -559,7 +415,7 @@ func file_p2p_v1alpha_p2p_proto_rawDescGZIP() []byte { return file_p2p_v1alpha_p2p_proto_rawDescData } -var file_p2p_v1alpha_p2p_proto_msgTypes = make([]protoimpl.MessageInfo, 8) +var file_p2p_v1alpha_p2p_proto_msgTypes = make([]protoimpl.MessageInfo, 6) var file_p2p_v1alpha_p2p_proto_goTypes = []interface{}{ (*HandshakeInfo)(nil), // 0: com.mintter.p2p.v1alpha.HandshakeInfo (*ListObjectsRequest)(nil), // 1: com.mintter.p2p.v1alpha.ListObjectsRequest @@ -567,21 +423,17 @@ var file_p2p_v1alpha_p2p_proto_goTypes = []interface{}{ (*Object)(nil), // 3: com.mintter.p2p.v1alpha.Object (*RequestInvoiceRequest)(nil), // 4: com.mintter.p2p.v1alpha.RequestInvoiceRequest (*RequestInvoiceResponse)(nil), // 5: com.mintter.p2p.v1alpha.RequestInvoiceResponse - (*CreateSiteRequest)(nil), // 6: com.mintter.p2p.v1alpha.CreateSiteRequest - (*CreateSiteResponse)(nil), // 7: com.mintter.p2p.v1alpha.CreateSiteResponse } var file_p2p_v1alpha_p2p_proto_depIdxs = []int32{ 3, // 0: com.mintter.p2p.v1alpha.ListObjectsResponse.objects:type_name -> com.mintter.p2p.v1alpha.Object 0, // 1: com.mintter.p2p.v1alpha.P2P.Handshake:input_type -> com.mintter.p2p.v1alpha.HandshakeInfo 1, // 2: com.mintter.p2p.v1alpha.P2P.ListObjects:input_type -> com.mintter.p2p.v1alpha.ListObjectsRequest 4, // 3: com.mintter.p2p.v1alpha.P2P.RequestInvoice:input_type -> com.mintter.p2p.v1alpha.RequestInvoiceRequest - 6, // 4: com.mintter.p2p.v1alpha.P2P.CreateSite:input_type -> com.mintter.p2p.v1alpha.CreateSiteRequest - 0, // 5: com.mintter.p2p.v1alpha.P2P.Handshake:output_type -> com.mintter.p2p.v1alpha.HandshakeInfo - 2, // 6: com.mintter.p2p.v1alpha.P2P.ListObjects:output_type -> com.mintter.p2p.v1alpha.ListObjectsResponse - 5, // 7: com.mintter.p2p.v1alpha.P2P.RequestInvoice:output_type -> com.mintter.p2p.v1alpha.RequestInvoiceResponse - 7, // 8: com.mintter.p2p.v1alpha.P2P.CreateSite:output_type -> com.mintter.p2p.v1alpha.CreateSiteResponse - 5, // [5:9] is the sub-list for method output_type - 1, // [1:5] is the sub-list for method input_type + 0, // 4: com.mintter.p2p.v1alpha.P2P.Handshake:output_type -> com.mintter.p2p.v1alpha.HandshakeInfo + 2, // 5: com.mintter.p2p.v1alpha.P2P.ListObjects:output_type -> com.mintter.p2p.v1alpha.ListObjectsResponse + 5, // 6: com.mintter.p2p.v1alpha.P2P.RequestInvoice:output_type -> com.mintter.p2p.v1alpha.RequestInvoiceResponse + 4, // [4:7] is the sub-list for method output_type + 1, // [1:4] is the sub-list for method input_type 1, // [1:1] is the sub-list for extension type_name 1, // [1:1] is the sub-list for extension extendee 0, // [0:1] is the sub-list for field type_name @@ -665,30 +517,6 @@ func file_p2p_v1alpha_p2p_proto_init() { return nil } } - file_p2p_v1alpha_p2p_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*CreateSiteRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_p2p_v1alpha_p2p_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*CreateSiteResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } } type x struct{} out := protoimpl.TypeBuilder{ @@ -696,7 +524,7 @@ func file_p2p_v1alpha_p2p_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_p2p_v1alpha_p2p_proto_rawDesc, NumEnums: 0, - NumMessages: 8, + NumMessages: 6, NumExtensions: 0, NumServices: 1, }, diff --git a/backend/genproto/p2p/v1alpha/p2p_grpc.pb.go b/backend/genproto/p2p/v1alpha/p2p_grpc.pb.go index 57488cb5e1..239758cf5d 100644 --- a/backend/genproto/p2p/v1alpha/p2p_grpc.pb.go +++ b/backend/genproto/p2p/v1alpha/p2p_grpc.pb.go @@ -34,8 +34,6 @@ type P2PClient interface { ListObjects(ctx context.Context, in *ListObjectsRequest, opts ...grpc.CallOption) (*ListObjectsResponse, error) // Request a peer to issue a lightning BOLT-11 invoice RequestInvoice(ctx context.Context, in *RequestInvoiceRequest, opts ...grpc.CallOption) (*RequestInvoiceResponse, error) - // CreateSite tells a server which group it should serve. - CreateSite(ctx context.Context, in *CreateSiteRequest, opts ...grpc.CallOption) (*CreateSiteResponse, error) } type p2PClient struct { @@ -73,15 +71,6 @@ func (c *p2PClient) RequestInvoice(ctx context.Context, in *RequestInvoiceReques return out, nil } -func (c *p2PClient) CreateSite(ctx context.Context, in *CreateSiteRequest, opts ...grpc.CallOption) (*CreateSiteResponse, error) { - out := new(CreateSiteResponse) - err := c.cc.Invoke(ctx, "/com.mintter.p2p.v1alpha.P2P/CreateSite", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - // P2PServer is the server API for P2P service. // All implementations should embed UnimplementedP2PServer // for forward compatibility @@ -98,8 +87,6 @@ type P2PServer interface { ListObjects(context.Context, *ListObjectsRequest) (*ListObjectsResponse, error) // Request a peer to issue a lightning BOLT-11 invoice RequestInvoice(context.Context, *RequestInvoiceRequest) (*RequestInvoiceResponse, error) - // CreateSite tells a server which group it should serve. - CreateSite(context.Context, *CreateSiteRequest) (*CreateSiteResponse, error) } // UnimplementedP2PServer should be embedded to have forward compatible implementations. @@ -115,9 +102,6 @@ func (UnimplementedP2PServer) ListObjects(context.Context, *ListObjectsRequest) func (UnimplementedP2PServer) RequestInvoice(context.Context, *RequestInvoiceRequest) (*RequestInvoiceResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method RequestInvoice not implemented") } -func (UnimplementedP2PServer) CreateSite(context.Context, *CreateSiteRequest) (*CreateSiteResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method CreateSite not implemented") -} // UnsafeP2PServer may be embedded to opt out of forward compatibility for this service. // Use of this interface is not recommended, as added methods to P2PServer will @@ -184,24 +168,6 @@ func _P2P_RequestInvoice_Handler(srv interface{}, ctx context.Context, dec func( return interceptor(ctx, in, info, handler) } -func _P2P_CreateSite_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(CreateSiteRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(P2PServer).CreateSite(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/com.mintter.p2p.v1alpha.P2P/CreateSite", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(P2PServer).CreateSite(ctx, req.(*CreateSiteRequest)) - } - return interceptor(ctx, in, info, handler) -} - // P2P_ServiceDesc is the grpc.ServiceDesc for P2P service. // It's only intended for direct use with grpc.RegisterService, // and not to be introspected or modified (even as a copy) @@ -221,10 +187,6 @@ var P2P_ServiceDesc = grpc.ServiceDesc{ MethodName: "RequestInvoice", Handler: _P2P_RequestInvoice_Handler, }, - { - MethodName: "CreateSite", - Handler: _P2P_CreateSite_Handler, - }, }, Streams: []grpc.StreamDesc{}, Metadata: "p2p/v1alpha/p2p.proto", diff --git a/backend/hyper/entity.go b/backend/hyper/entity.go index b577c91134..0bf6fbe38e 100644 --- a/backend/hyper/entity.go +++ b/backend/hyper/entity.go @@ -307,7 +307,7 @@ func NewChange(eid EntityID, deps []cid.Cid, ts hlc.Time, signer core.KeyPair, d return hb, fmt.Errorf("failed to sign change: %w", err) } - hb, err = EncodeBlob(ch.Type, ch) + hb, err = EncodeBlob(ch) if err != nil { return hb, err } diff --git a/backend/hyper/entity_test.go b/backend/hyper/entity_test.go index 37dad76dff..7f3b2eb0f3 100644 --- a/backend/hyper/entity_test.go +++ b/backend/hyper/entity_test.go @@ -27,7 +27,6 @@ func TestEntity(t *testing.T) { }) require.NoError(t, err) - require.Equal(t, TypeChange, ch.Type) require.Nil(t, ch.Decoded.(Change).Deps) name, _ = e.Get("name") diff --git a/backend/hyper/hyper.go b/backend/hyper/hyper.go index 64595f78e9..7dc0b1f743 100644 --- a/backend/hyper/hyper.go +++ b/backend/hyper/hyper.go @@ -15,8 +15,8 @@ import ( blocks "github.com/ipfs/go-block-format" "github.com/ipfs/go-cid" cbornode "github.com/ipfs/go-ipld-cbor" + dagpb "github.com/ipld/go-codec-dagpb" "github.com/multiformats/go-multicodec" - "github.com/multiformats/go-multihash" "go.uber.org/zap" ) @@ -26,16 +26,27 @@ type BlobType string // Storage is an indexing blob storage. type Storage struct { db *sqlitex.Pool - bs *blockStore + bs *indexingBlockStore log *zap.Logger + + *indexer } // NewStorage creates a new blob storage. func NewStorage(db *sqlitex.Pool, log *zap.Logger) *Storage { - return &Storage{ + bs := newBlockstore(db) + + idx := &indexer{ db: db, - bs: newBlockstore(db), log: log, + bs: bs, + } + + return &Storage{ + db: db, + bs: &indexingBlockStore{blockStore: bs, indexBlob: idx.indexBlob}, + log: log, + indexer: idx, } } @@ -70,8 +81,10 @@ func (bs *Storage) SaveBlob(ctx context.Context, blob Blob) error { } defer release() + codec, hash := ipfs.DecodeCID(blob.CID) + return sqlitex.WithTx(conn, func() error { - id, exists, err := bs.bs.putBlock(conn, 0, uint64(blob.Codec), blob.Hash, blob.Data) + id, exists, err := bs.bs.putBlock(conn, 0, uint64(codec), hash, blob.Data) if err != nil { return err } @@ -81,7 +94,7 @@ func (bs *Storage) SaveBlob(ctx context.Context, blob Blob) error { return nil } - if err := bs.indexBlob(conn, id, blob); err != nil { + if err := bs.indexBlob(conn, id, blob.CID, blob.Decoded); err != nil { return fmt.Errorf("failed to index blob %s: %w", blob.CID, err) } @@ -122,8 +135,10 @@ func (bs *Storage) SaveDraftBlob(ctx context.Context, eid EntityID, blob Blob) e } defer release() + codec, hash := ipfs.DecodeCID(blob.CID) + return sqlitex.WithTx(conn, func() error { - id, exists, err := bs.bs.putBlock(conn, 0, uint64(blob.Codec), blob.Hash, blob.Data) + id, exists, err := bs.bs.putBlock(conn, 0, uint64(codec), hash, blob.Data) if err != nil { return err } @@ -133,7 +148,7 @@ func (bs *Storage) SaveDraftBlob(ctx context.Context, eid EntityID, blob Blob) e return nil } - if err := bs.indexBlob(conn, id, blob); err != nil { + if err := bs.indexBlob(conn, id, blob.CID, blob.Decoded); err != nil { return fmt.Errorf("failed to index blob %s: %w", blob.CID, err) } @@ -283,7 +298,9 @@ func (bs *Storage) ReplaceDraftBlob(ctx context.Context, eid EntityID, old cid.C return err } - id, exists, err := bs.bs.putBlock(conn, oldid, uint64(blob.Codec), blob.Hash, blob.Data) + codec, hash := ipfs.DecodeCID(blob.CID) + + id, exists, err := bs.bs.putBlock(conn, oldid, uint64(codec), hash, blob.Data) if err != nil { return fmt.Errorf("replace draft blob error when insert: %w", err) } @@ -293,7 +310,7 @@ func (bs *Storage) ReplaceDraftBlob(ctx context.Context, eid EntityID, old cid.C return nil } - if err := bs.indexBlob(conn, id, blob); err != nil { + if err := bs.indexBlob(conn, id, blob.CID, blob.Decoded); err != nil { return fmt.Errorf("failed to index blob %s: %w", blob.CID, err) } @@ -343,31 +360,23 @@ func (bs *Storage) IPFSBlockstore() blockstore.Blockstore { // Blob is a structural artifact. type Blob struct { - Type BlobType CID cid.Cid - Codec multicodec.Code - Hash multihash.Multihash Data []byte Decoded any } // EncodeBlob produces a Blob from any object. -func EncodeBlob(t BlobType, v any) (hb Blob, err error) { +func EncodeBlob(v any) (hb Blob, err error) { data, err := cbornode.DumpObject(v) if err != nil { - return hb, fmt.Errorf("failed to encode blob with type %s: %w", t, err) + return hb, fmt.Errorf("failed to encode blob %T: %w", v, err) } - codec := multicodec.DagCbor - - blk := ipfs.NewBlock(uint64(codec), data) + blk := ipfs.NewBlock(uint64(multicodec.DagCbor), data) c := blk.Cid() return Blob{ - Type: t, CID: c, - Codec: codec, - Hash: c.Hash(), Data: data, Decoded: v, }, nil @@ -379,44 +388,109 @@ var errNotHyperBlob = errors.New("not a hyper blob") func DecodeBlob(c cid.Cid, data []byte) (hb Blob, err error) { codec := c.Prefix().Codec - if codec != uint64(multicodec.DagCbor) { - return hb, fmt.Errorf("%s: %w", c, errNotHyperBlob) - } - - var v struct { - Type string `cbor:"@type"` - } - if err := cbor.Unmarshal(data, &v); err != nil { - var vv any - if err := cbornode.DecodeInto(data, &vv); err != nil { - panic(err) + switch multicodec.Code(codec) { + case multicodec.DagPb: + b := dagpb.Type.PBNode.NewBuilder() + if err := dagpb.DecodeBytes(b, data); err != nil { + return hb, fmt.Errorf("failed to decode dagpb node %s: %w", c, err) } - return hb, fmt.Errorf("failed to infer hyper blob %s: %w", c, err) - } - - switch BlobType(v.Type) { - case TypeKeyDelegation: - var v KeyDelegation - if err := cbornode.DecodeInto(data, &v); err != nil { - return hb, err + hb.Decoded = b.Build() + case multicodec.DagCbor: + var v struct { + Type string `cbor:"@type"` } - hb.Decoded = v - case TypeChange: - var v Change - if err := cbornode.DecodeInto(data, &v); err != nil { - return hb, err + if err := cbor.Unmarshal(data, &v); err != nil { + return hb, fmt.Errorf("failed to infer hyper blob %s: %w", c, err) + } + + switch BlobType(v.Type) { + case TypeKeyDelegation: + var v KeyDelegation + if err := cbornode.DecodeInto(data, &v); err != nil { + return hb, err + } + hb.Decoded = v + case TypeChange: + var v Change + if err := cbornode.DecodeInto(data, &v); err != nil { + return hb, err + } + hb.Decoded = v + default: + return hb, fmt.Errorf("unknown hyper blob type: '%s'", v.Type) } - hb.Decoded = v default: - return hb, fmt.Errorf("unknown hyper blob type: '%s'", v.Type) + return hb, fmt.Errorf("%s: %w", c, errNotHyperBlob) } - hb.Type = BlobType(v.Type) hb.CID = c - hb.Codec = multicodec.Code(codec) - hb.Hash = c.Hash() hb.Data = data return hb, nil } + +type indexingBlockStore struct { + *blockStore + indexBlob func(conn *sqlite.Conn, id int64, c cid.Cid, blob any) error +} + +func (b *indexingBlockStore) Put(ctx context.Context, block blocks.Block) error { + conn, release, err := b.db.Conn(ctx) + if err != nil { + return err + } + defer release() + + return sqlitex.WithTx(conn, func() error { + codec, hash := ipfs.DecodeCID(block.Cid()) + id, exists, err := b.putBlock(conn, 0, codec, hash, block.RawData()) + if err != nil { + return err + } + + if exists || !isIndexable(multicodec.Code(codec)) { + return nil + } + + hb, err := DecodeBlob(block.Cid(), block.RawData()) + if err != nil { + return err + } + return b.indexBlob(conn, id, hb.CID, hb.Decoded) + }) +} + +// PutMany implements blockstore.Blockstore interface. +func (b *indexingBlockStore) PutMany(ctx context.Context, blocks []blocks.Block) error { + conn, release, err := b.db.Conn(ctx) + if err != nil { + return err + } + defer release() + + return sqlitex.WithTx(conn, func() error { + for _, blk := range blocks { + codec, hash := ipfs.DecodeCID(blk.Cid()) + id, exists, err := b.putBlock(conn, 0, codec, hash, blk.RawData()) + if err != nil { + return err + } + + if exists || !isIndexable(multicodec.Code(codec)) { + continue + } + + hb, err := DecodeBlob(blk.Cid(), blk.RawData()) + if err != nil { + return err + } + + if err := b.indexBlob(conn, id, hb.CID, hb.Decoded); err != nil { + return err + } + } + + return nil + }) +} diff --git a/backend/hyper/hypersql/queries.manual.go b/backend/hyper/hypersql/queries.manual.go index 97c9cd7194..1e0bdc7570 100644 --- a/backend/hyper/hypersql/queries.manual.go +++ b/backend/hyper/hypersql/queries.manual.go @@ -3,6 +3,7 @@ package hypersql import ( "fmt" "mintter/backend/daemon/storage" + "mintter/backend/pkg/dqb" "crawshaw.io/sqlite" "crawshaw.io/sqlite/sqlitex" @@ -158,3 +159,21 @@ func GroupGetRole(conn *sqlite.Conn, resource, owner, member int64) (int64, erro return role, nil } + +// SitesInsertOrIgnore inserts a site if it doesn't exist. +func SitesInsertOrIgnore(conn *sqlite.Conn, baseURL, groupID string) error { + return sqlitex.Exec(conn, qSitesInsertOrIgnore(), nil, baseURL, groupID) +} + +var qSitesInsertOrIgnore = dqb.Str(` + INSERT OR IGNORE INTO remote_sites (url, group_id) VALUES (?, ?); +`) + +// AccountsInsertOrIgnore inserts an account if it doesn't exist. +func AccountsInsertOrIgnore(conn *sqlite.Conn, entity, publicKey int64) error { + return sqlitex.Exec(conn, qAccountsInsertOrIgnore(), nil, entity, publicKey) +} + +var qAccountsInsertOrIgnore = dqb.Str(` + INSERT OR IGNORE INTO accounts (entity, public_key) VALUES (?, ?); +`) diff --git a/backend/hyper/indexing.go b/backend/hyper/indexing.go index 4a2834d039..ac821fdd3c 100644 --- a/backend/hyper/indexing.go +++ b/backend/hyper/indexing.go @@ -18,14 +18,24 @@ import ( "crawshaw.io/sqlite/sqlitex" "github.com/ipfs/go-cid" cbornode "github.com/ipfs/go-ipld-cbor" + dagpb "github.com/ipld/go-codec-dagpb" + "github.com/ipld/go-ipld-prime" + cidlink "github.com/ipld/go-ipld-prime/linking/cid" + "github.com/ipld/go-ipld-prime/traversal" "github.com/multiformats/go-multicodec" "go.uber.org/zap" "golang.org/x/exp/slices" "google.golang.org/protobuf/encoding/protojson" ) +type indexer struct { + db *sqlitex.Pool + log *zap.Logger + bs *blockStore +} + // Reindex forces deletes all the information derived from the blobs and reindexes them. -func (bs *Storage) Reindex(ctx context.Context) (err error) { +func (bs *indexer) Reindex(ctx context.Context) (err error) { conn, release, err := bs.db.Conn(ctx) if err != nil { return err @@ -35,7 +45,7 @@ func (bs *Storage) Reindex(ctx context.Context) (err error) { return bs.reindex(conn) } -func (bs *Storage) reindex(conn *sqlite.Conn) (err error) { +func (bs *indexer) reindex(conn *sqlite.Conn) (err error) { start := time.Now() bs.log.Debug("ReindexingStarted") defer func() { @@ -61,8 +71,8 @@ func (bs *Storage) reindex(conn *sqlite.Conn) (err error) { buf := make([]byte, 0, 1024*1024) // 1MB preallocated slice to reuse for decompressing. if err := sqlitex.ExecTransient(conn, q, func(stmt *sqlite.Stmt) error { codec := stmt.ColumnInt64(stmt.ColumnIndex(storage.BlobsCodec.ShortName())) - // We only know how to index dag-cbor blobs. - if codec != int64(multicodec.DagCbor) { + + if !isIndexable(multicodec.Code(codec)) { return nil } @@ -85,7 +95,7 @@ func (bs *Storage) reindex(conn *sqlite.Conn) (err error) { return nil } - return bs.indexBlob(conn, id, hb) + return bs.indexBlob(conn, id, hb.CID, hb.Decoded) }); err != nil { return err } @@ -99,7 +109,7 @@ func (bs *Storage) reindex(conn *sqlite.Conn) (err error) { } // MaybeReindex will trigger reindexing if it's needed. -func (bs *Storage) MaybeReindex(ctx context.Context) error { +func (bs *indexer) MaybeReindex(ctx context.Context) error { conn, release, err := bs.db.Conn(ctx) if err != nil { return err @@ -121,140 +131,224 @@ func (bs *Storage) MaybeReindex(ctx context.Context) error { // indexBlob is an uber-function that knows about all types of blobs we want to index. // This is probably a bad idea to put here, but for now it's easier to work with that way. // TODO(burdiyan): eventually we might want to make this package agnostic to blob types. -func (bs *Storage) indexBlob(conn *sqlite.Conn, id int64, blob Blob) error { - switch v := blob.Decoded.(type) { +func (bs *indexer) indexBlob(conn *sqlite.Conn, id int64, c cid.Cid, blobData any) error { + switch v := blobData.(type) { + case ipld.Node: + return bs.indexDagPB(conn, id, c, v) case KeyDelegation: - // Validate key delegation. - { - if v.Purpose != DelegationPurposeRegistration { - return fmt.Errorf("unknown key delegation purpose %q", v.Purpose) - } + return bs.indexKeyDelegation(conn, id, c, v) + case Change: + return bs.indexChange(conn, id, c, v) + } - if _, err := v.Issuer.Libp2pKey(); err != nil { - return fmt.Errorf("key delegation issuer is not a valid libp2p public key: %w", err) - } + return nil +} - if _, err := v.Delegate.Libp2pKey(); err != nil { - return fmt.Errorf("key delegation delegate is not a valid libp2p public key: %w", err) - } +func (bs *indexer) indexDagPB(conn *sqlite.Conn, id int64, c cid.Cid, v ipld.Node) error { + return traversal.WalkLocal(v, func(prog traversal.Progress, n ipld.Node) error { + pblink, ok := n.(dagpb.PBLink) + if !ok { + return nil } - iss, err := hypersql.LookupEnsure(conn, storage.LookupPublicKey, v.Issuer) - if err != nil { - return err + c, ok := pblink.Hash.Link().(cidlink.Link) + if !ok { + return fmt.Errorf("link is not CID: %v", pblink.Hash) } - del, err := hypersql.LookupEnsure(conn, storage.LookupPublicKey, v.Delegate) - if err != nil { - return err + rel := "dagpb/chunk" + if pblink.Name.Exists() { + rel = "dagpb/" + pblink.Name.Must().String() } - // We know issuer is an account when delegation purpose is registration. - accEntity := EntityID("hm://a/" + v.Issuer.String()) - if _, err := hypersql.LookupEnsure(conn, storage.LookupResource, accEntity); err != nil { + target, err := bs.ensureBlob(conn, c.Cid) + if err != nil { return err } - if err := hypersql.BlobAttrsInsert(conn, id, "kd/issuer", "", true, iss, nil, 0); err != nil { - return err + return hypersql.BlobLinksInsertOrIgnore(conn, id, rel, target) + }) +} + +func (bs *indexer) indexKeyDelegation(conn *sqlite.Conn, id int64, c cid.Cid, v KeyDelegation) error { + // Validate key delegation. + { + if v.Purpose != DelegationPurposeRegistration { + return fmt.Errorf("unknown key delegation purpose %q", v.Purpose) } - if err := hypersql.BlobAttrsInsert(conn, id, "kd/delegate", "", true, del, nil, 0); err != nil { - return err + if _, err := v.Issuer.Libp2pKey(); err != nil { + return fmt.Errorf("key delegation issuer is not a valid libp2p public key: %w", err) } - case Change: - // TODO(burdiyan): ensure there's only one change that brings an entity into life. - iss, err := hypersql.KeyDelegationsGetIssuer(conn, v.Delegation.Hash()) - if err != nil { - return err + if _, err := v.Delegate.Libp2pKey(); err != nil { + return fmt.Errorf("key delegation delegate is not a valid libp2p public key: %w", err) } - if iss.KeyDelegationsIssuer == 0 { - // Try to get the issuer from the actual blob. This can happen when we are reindexing all the blobs, - // and we happen to index a change before the key delegation. + } - blk, err := bs.bs.get(conn, v.Delegation) - if err != nil { - return err - } + iss, err := hypersql.LookupEnsure(conn, storage.LookupPublicKey, v.Issuer) + if err != nil { + return err + } - var del KeyDelegation - if err := cbornode.DecodeInto(blk.RawData(), &del); err != nil { - return fmt.Errorf("failed to decode key delegation when indexing change %s: %w", blob.CID, err) - } + del, err := hypersql.LookupEnsure(conn, storage.LookupPublicKey, v.Delegate) + if err != nil { + return err + } - iss.KeyDelegationsIssuer, err = bs.ensurePublicKey(conn, del.Issuer) - if err != nil { - return err - } + // We know issuer is an account when delegation purpose is registration. + accEntity := EntityID("hm://a/" + v.Issuer.String()) + edb, err := hypersql.LookupEnsure(conn, storage.LookupResource, accEntity) + if err != nil { + return err + } - if iss.KeyDelegationsIssuer == 0 { - return fmt.Errorf("missing key delegation info %s of change %s", v.Delegation, blob.CID) - } - } + if err := hypersql.AccountsInsertOrIgnore(conn, edb, iss); err != nil { + return err + } - // TODO(burdiyan): remove this when all the tests are fixed. Sometimes CBOR codec decodes into - // different types than what was encoded, and we might not have accounted for that during indexing. - // So we re-encode the patch here to make sure. - // This is of course very wasteful. - { - data, err := cbornode.DumpObject(v.Patch) - if err != nil { - return err - } - v.Patch = nil + if err := hypersql.BlobAttrsInsert(conn, id, "kd/issuer", "", true, iss, nil, 0); err != nil { + return err + } - if err := cbornode.DecodeInto(data, &v.Patch); err != nil { - return err - } - } + if err := hypersql.BlobAttrsInsert(conn, id, "kd/delegate", "", true, del, nil, 0); err != nil { + return err + } - isspk, err := hypersql.PublicKeysLookupPrincipal(conn, iss.KeyDelegationsIssuer) + return nil +} + +func (bs *indexer) indexChange(conn *sqlite.Conn, id int64, c cid.Cid, v Change) error { + // TODO(burdiyan): ensure there's only one change that brings an entity into life. + + iss, err := hypersql.KeyDelegationsGetIssuer(conn, v.Delegation.Hash()) + if err != nil { + return err + } + if iss.KeyDelegationsIssuer == 0 { + // Try to get the issuer from the actual blob. This can happen when we are reindexing all the blobs, + // and we happen to index a change before the key delegation. + + blk, err := bs.bs.get(conn, v.Delegation) if err != nil { return err } - // ensure entity - eid, err := bs.ensureEntity(conn, v.Entity) + var del KeyDelegation + if err := cbornode.DecodeInto(blk.RawData(), &del); err != nil { + return fmt.Errorf("failed to decode key delegation when indexing change %s: %w", c, err) + } + + iss.KeyDelegationsIssuer, err = bs.ensurePublicKey(conn, del.Issuer) if err != nil { return err } - if err := hypersql.BlobAttrsInsert(conn, id, "resource/id", "", true, eid, nil, v.HLCTime.Pack()); err != nil { - return err + if iss.KeyDelegationsIssuer == 0 { + return fmt.Errorf("missing key delegation info %s of change %s", v.Delegation, c) } + } - for _, dep := range v.Deps { - res, err := hypersql.BlobsGetSize(conn, dep.Hash()) - if err != nil { - return err - } - if res.BlobsSize < 0 || res.BlobsID == 0 { - return fmt.Errorf("missing causal dependency %s of change %s", dep, blob.CID) - } + delid, err := hypersql.BlobsGetSize(conn, v.Delegation.Hash()) + if err != nil { + return err + } + if delid.BlobsID == 0 { + return fmt.Errorf("missing key delegation %s of change %s", v.Delegation, c) + } - if err := hypersql.BlobLinksInsertOrIgnore(conn, id, "change/dep", res.BlobsID); err != nil { - return fmt.Errorf("failed to link dependency %s of change %s: %w", dep, blob.CID, err) - } + if err := hypersql.BlobLinksInsertOrIgnore(conn, id, "change/auth", delid.BlobsID); err != nil { + return fmt.Errorf("failed to link key delegation %s of change %s: %w", v.Delegation, c, err) + } + + // TODO(burdiyan): remove this when all the tests are fixed. Sometimes CBOR codec decodes into + // different types than what was encoded, and we might not have accounted for that during indexing. + // So we re-encode the patch here to make sure. + // This is of course very wasteful. + { + data, err := cbornode.DumpObject(v.Patch) + if err != nil { + return err } + v.Patch = nil - if err := hypersql.ChangesInsertOrIgnore(conn, id, eid, v.HLCTime.Pack(), iss.KeyDelegationsIssuer); err != nil { + if err := cbornode.DecodeInto(data, &v.Patch); err != nil { return err } + } + + isspk, err := hypersql.PublicKeysLookupPrincipal(conn, iss.KeyDelegationsIssuer) + if err != nil { + return err + } + + // ensure entity + eid, err := bs.ensureEntity(conn, v.Entity) + if err != nil { + return err + } - if v.Entity.HasPrefix("hm://d/") { - return bs.indexDocumentChange(conn, id, isspk.PublicKeysPrincipal, blob.CID, v) + if err := hypersql.BlobAttrsInsert(conn, id, "resource/id", "", true, eid, nil, v.HLCTime.Pack()); err != nil { + return err + } + + for _, dep := range v.Deps { + res, err := hypersql.BlobsGetSize(conn, dep.Hash()) + if err != nil { + return err + } + if res.BlobsSize < 0 || res.BlobsID == 0 { + return fmt.Errorf("missing causal dependency %s of change %s", dep, c) } - if v.Entity.HasPrefix("hm://g/") { - return bs.indexGroupChange(conn, id, isspk.PublicKeysPrincipal, blob.CID, v) + if err := hypersql.BlobLinksInsertOrIgnore(conn, id, "change/dep", res.BlobsID); err != nil { + return fmt.Errorf("failed to link dependency %s of change %s: %w", dep, c, err) } } + if err := hypersql.ChangesInsertOrIgnore(conn, id, eid, v.HLCTime.Pack(), iss.KeyDelegationsIssuer); err != nil { + return err + } + + if v.Entity.HasPrefix("hm://d/") { + return bs.indexDocumentChange(conn, id, isspk.PublicKeysPrincipal, c, v) + } + + if v.Entity.HasPrefix("hm://g/") { + return bs.indexGroupChange(conn, id, isspk.PublicKeysPrincipal, c, v) + } + + if v.Entity.HasPrefix("hm://a/") { + return bs.indexAccountChange(conn, id, isspk.PublicKeysPrincipal, c, v) + } + return nil } -func (bs *Storage) ensureEntity(conn *sqlite.Conn, eid EntityID) (int64, error) { +func (bs *indexer) ensureBlob(conn *sqlite.Conn, c cid.Cid) (int64, error) { + codec, hash := ipfs.DecodeCID(c) + + size, err := hypersql.BlobsGetSize(conn, hash) + if err != nil { + return 0, err + } + + if size.BlobsID != 0 { + return size.BlobsID, nil + } + + ins, err := hypersql.BlobsInsert(conn, 0, hash, int64(codec), nil, -1) + if err != nil { + return 0, err + } + if ins.BlobsID == 0 { + return 0, fmt.Errorf("failed to ensure blob %s after insert", c) + } + + return ins.BlobsID, nil +} + +func (bs *indexer) ensureEntity(conn *sqlite.Conn, eid EntityID) (int64, error) { look, err := hypersql.EntitiesLookupID(conn, string(eid)) if err != nil { return 0, err @@ -274,7 +368,7 @@ func (bs *Storage) ensureEntity(conn *sqlite.Conn, eid EntityID) (int64, error) return ins.EntitiesID, nil } -func (bs *Storage) ensurePublicKey(conn *sqlite.Conn, key core.Principal) (int64, error) { +func (bs *indexer) ensurePublicKey(conn *sqlite.Conn, key core.Principal) (int64, error) { res, err := hypersql.PublicKeysLookupID(conn, key) if err != nil { return 0, err @@ -296,7 +390,7 @@ func (bs *Storage) ensurePublicKey(conn *sqlite.Conn, key core.Principal) (int64 return ins.PublicKeysID, nil } -func (bs *Storage) indexGroupChange(conn *sqlite.Conn, blobID int64, author core.Principal, c cid.Cid, ch Change) error { +func (bs *indexer) indexGroupChange(conn *sqlite.Conn, blobID int64, author core.Principal, c cid.Cid, ch Change) error { hlc := ch.HLCTime.Pack() // Validate group change. @@ -394,29 +488,53 @@ func (bs *Storage) indexGroupChange(conn *sqlite.Conn, blobID int64, author core } if ch.Patch["members"] != nil && !isOwner { - return fmt.Errorf("group members can only be updated by an owner") + return fmt.Errorf("group members can only be updated by the owner") + } + + if ch.Patch["siteURL"] != nil && !isOwner { + return fmt.Errorf("group siteURL can only be updated by the owner") } default: return fmt.Errorf("unknown group action %q", ch.Action) } } - title, ok := ch.Patch["title"].(string) - if ok { + if title, ok := ch.Patch["title"].(string); ok { if err := hypersql.BlobAttrsInsert(conn, blobID, "resource/title", "", false, title, nil, hlc); err != nil { return err } } - desc, ok := ch.Patch["description"].(string) - if ok { + if desc, ok := ch.Patch["description"].(string); ok { if err := hypersql.BlobAttrsInsert(conn, blobID, "resource/description", "", false, desc, nil, hlc); err != nil { return err } } - content, ok := ch.Patch["content"].(map[string]any) - if ok { + if siteURL, ok := ch.Patch["siteURL"].(string); ok { + u, err := url.Parse(siteURL) + if err != nil { + return fmt.Errorf("failed to parse site URL %s: %w", siteURL, err) + } + + if u.Scheme != "http" && u.Scheme != "https" { + return fmt.Errorf("site URL must have http or https scheme, got %s", siteURL) + } + + if siteURL != (&url.URL{Scheme: u.Scheme, Host: u.Host}).String() { + return fmt.Errorf("site URL must have only scheme and host, got %s", siteURL) + } + + if err := hypersql.BlobAttrsInsert(conn, blobID, "group/site-url", "", false, siteURL, nil, hlc); err != nil { + return err + } + + if err := hypersql.SitesInsertOrIgnore(conn, siteURL, string(ch.Entity)); err != nil { + return err + } + } + + if content, ok := ch.Patch["content"].(map[string]any); ok { for path, v := range content { rawURL, ok := v.(string) if !ok { @@ -430,8 +548,7 @@ func (bs *Storage) indexGroupChange(conn *sqlite.Conn, blobID int64, author core } } - members, ok := ch.Patch["members"].(map[string]any) - if ok { + if members, ok := ch.Patch["members"].(map[string]any); ok { for k, v := range members { acc, err := core.DecodePrincipal(k) if err != nil { @@ -461,7 +578,52 @@ func (bs *Storage) indexGroupChange(conn *sqlite.Conn, blobID int64, author core return nil } -func (bs *Storage) indexDocumentChange(conn *sqlite.Conn, blobID int64, author core.Principal, c cid.Cid, ch Change) error { +func (bs *indexer) indexAccountChange(conn *sqlite.Conn, blobID int64, author core.Principal, c cid.Cid, ch Change) error { + if "hm://a/"+author.String() != string(ch.Entity) { + return fmt.Errorf("author %s is not allowed to modify account entity %s", author.String(), ch.Entity) + } + + if ch.Patch == nil { + return fmt.Errorf("account changes must have patches") + } + + pkdb, err := hypersql.LookupEnsure(conn, storage.LookupPublicKey, author) + if err != nil { + return err + } + + edb, err := hypersql.LookupEnsure(conn, storage.LookupResource, ch.Entity) + if err != nil { + return err + } + + if err := hypersql.AccountsInsertOrIgnore(conn, edb, pkdb); err != nil { + return err + } + + hlc := ch.HLCTime.Pack() + + if v, ok := ch.Patch["avatar"].(cid.Cid); ok { + target, err := bs.ensureBlob(conn, v) + if err != nil { + return err + } + + if err := hypersql.BlobLinksInsertOrIgnore(conn, blobID, "href/avatar", target); err != nil { + return err + } + } + + if v, ok := ch.Patch["alias"].(string); ok { + if err := hypersql.BlobAttrsInsert(conn, blobID, "account/alias", "", false, v, nil, hlc); err != nil { + return err + } + } + + return nil +} + +func (bs *indexer) indexDocumentChange(conn *sqlite.Conn, blobID int64, author core.Principal, c cid.Cid, ch Change) error { hlc := ch.HLCTime.Pack() // Validate document change. @@ -579,7 +741,7 @@ type LinkData struct { TargetVersion string `json:"v,omitempty"` } -func (bs *Storage) indexURL(conn *sqlite.Conn, blobID int64, key, anchor, rawURL string, ts int64) error { +func (bs *indexer) indexURL(conn *sqlite.Conn, blobID int64, key, anchor, rawURL string, ts int64) error { if rawURL == "" { return nil } @@ -645,8 +807,37 @@ func (bs *Storage) indexURL(conn *sqlite.Conn, blobID int64, key, anchor, rawURL } } case "ipfs": - // TODO: parse ipfs links + c, err := cid.Decode(u.Hostname()) + if err != nil { + return fmt.Errorf("failed to parse IPFS URL %s: %w", rawURL, err) + } + + target, err := bs.ensureBlob(conn, c) + if err != nil { + return err + } + + if err := hypersql.BlobLinksInsertOrIgnore(conn, blobID, key, target); err != nil { + return err + } } return nil } + +type indexData struct { + Blob cid.Cid +} + +func isIndexable[T multicodec.Code | cid.Cid](v T) bool { + var code multicodec.Code + + switch v := any(v).(type) { + case multicodec.Code: + code = v + case cid.Cid: + code = multicodec.Code(v.Prefix().Codec) + } + + return code == multicodec.DagCbor || code == multicodec.DagPb +} diff --git a/backend/hyper/terra.go b/backend/hyper/terra.go index 4d16a84c79..f2b0723dc9 100644 --- a/backend/hyper/terra.go +++ b/backend/hyper/terra.go @@ -113,7 +113,7 @@ func (kd KeyDelegation) Verify() error { // Blob encodes the delegation into a blob. func (kd KeyDelegation) Blob() Blob { - hb, err := EncodeBlob(TypeKeyDelegation, kd) + hb, err := EncodeBlob(kd) if err != nil { panic(err) } diff --git a/backend/ipfs/libp2p.go b/backend/ipfs/libp2p.go index 1db31bb55e..92495e56f6 100644 --- a/backend/ipfs/libp2p.go +++ b/backend/ipfs/libp2p.go @@ -301,3 +301,14 @@ func DefaultListenAddrs(port int) []string { "/ip6/::/udp/" + portstr + "/quic-v1/webtransport", } } + +// DefaultListenAddrsDNS creates the default listening addresses for a DNS name and port. +func DefaultListenAddrsDNS(hostname string, port int) []string { + portstr := strconv.Itoa(port) + return []string{ + "/dns4/" + hostname + "/tcp/" + portstr, + "/dns4/" + hostname + "/udp/" + portstr + "/quic", + "/dns4/" + hostname + "/udp/" + portstr + "/quic-v1", + "/dns4/" + hostname + "/udp/" + portstr + "/quic-v1/webtransport", + } +} diff --git a/backend/lndhub/lndhub_test.go b/backend/lndhub/lndhub_test.go index 69f397e832..331a9c4ef7 100644 --- a/backend/lndhub/lndhub_test.go +++ b/backend/lndhub/lndhub_test.go @@ -45,17 +45,17 @@ func TestCreate(t *testing.T) { defer cancel() identity := future.New[core.Identity]() lndHubClient := NewClient(context.Background(), &http.Client{}, pool, identity.ReadOnly, mintterDomain, lnaddressDomain) - keypair, err := core.NewKeyPairRandom(core.CodecDeviceKey) + keypair, err := core.NewKeyPairRandom() require.NoError(t, err) priv, pub, err := crypto.GenerateEd25519Key(nil) require.NoError(t, err) pubkeyBytes, err := pub.Raw() require.NoError(t, err) - pubkey, err := core.NewPublicKey(core.CodecAccountKey, pub.(*crypto.Ed25519PublicKey)) + pubkey, err := core.NewPublicKey(pub.(*crypto.Ed25519PublicKey)) require.NoError(t, err) - login := pubkey.CID().String() + login := pubkey.Principal().String() passwordBytes, err := priv.Sign([]byte(SigninMessage)) password := hex.EncodeToString(passwordBytes) require.NoError(t, err) diff --git a/backend/mttnet/client.go b/backend/mttnet/client.go index 4eb0b8b44e..a4cc0d6735 100644 --- a/backend/mttnet/client.go +++ b/backend/mttnet/client.go @@ -4,7 +4,6 @@ import ( "context" "fmt" "mintter/backend/core" - site "mintter/backend/genproto/documents/v1alpha" p2p "mintter/backend/genproto/p2p/v1alpha" "net" "sync" @@ -67,16 +66,6 @@ func (c *Client) Dial(ctx context.Context, pid peer.ID) (p2p.P2PClient, error) { return p2p.NewP2PClient(conn), nil } -// DialSite dials a remote site a remote peer and provide and RPC client instance. -func (c *Client) DialSite(ctx context.Context, siteDeviceID peer.ID) (site.WebSiteClient, error) { - conn, err := c.dialPeer(ctx, siteDeviceID) - if err != nil { - return nil, err - } - - return site.NewWebSiteClient(conn), nil -} - // Close the Client and all the open connections and streams gracefully. func (c *Client) Close() (err error) { c.mu.Lock() diff --git a/backend/mttnet/connect.go b/backend/mttnet/connect.go index a5b473350b..9efccdd5ff 100644 --- a/backend/mttnet/connect.go +++ b/backend/mttnet/connect.go @@ -156,11 +156,8 @@ func (n *Node) verifyHandshake(ctx context.Context, pid peer.ID, pb *p2p.Handsha var errDialSelf = errors.New("can't dial self") // Handshake gets called by the remote peer who initiates the connection. -func (srv *Server) Handshake(ctx context.Context, in *p2p.HandshakeInfo) (*p2p.HandshakeInfo, error) { - n, ok := srv.Node.Get() - if !ok { - return nil, fmt.Errorf("Node not ready yet") - } +func (srv *rpcMux) Handshake(ctx context.Context, in *p2p.HandshakeInfo) (*p2p.HandshakeInfo, error) { + n := srv.Node info, ok := rpcpeer.FromContext(ctx) if !ok { panic("BUG: no peer info in context for grpc") diff --git a/backend/mttnet/list_objects.go b/backend/mttnet/list_objects.go index 70bdb464d4..d867f86413 100644 --- a/backend/mttnet/list_objects.go +++ b/backend/mttnet/list_objects.go @@ -2,56 +2,18 @@ package mttnet import ( "context" - "fmt" - site "mintter/backend/genproto/documents/v1alpha" p2p "mintter/backend/genproto/p2p/v1alpha" "mintter/backend/hyper" "mintter/backend/hyper/hypersql" - "mintter/backend/mttnet/sitesql" "crawshaw.io/sqlite" "github.com/ipfs/go-cid" - "go.uber.org/zap" "golang.org/x/exp/maps" ) // ListObjects lists all the local objects. -func (srv *Server) ListObjects(ctx context.Context, in *p2p.ListObjectsRequest) (*p2p.ListObjectsResponse, error) { - n, err := srv.Node.Await(ctx) - if err != nil { - return nil, fmt.Errorf("node is not ready yet: %w", err) - } - - if n.cfg.NoListing && srv.Site.hostname == "" { - return &p2p.ListObjectsResponse{}, nil - } - - if srv.Site.hostname != "" { //means this is a site. Sites don't sync out to every peer. Only peers that are subscribed to that site if NoLIsting is true - remoteDeviceID, err := getRemoteID(ctx) - if err != nil { - n.log.Warn("Couldn't get remote caller in ListObjects.", zap.Error(err)) - return nil, fmt.Errorf("couldn't get account ID from device [%s]: %w", remoteDeviceID.String(), err) - } - - remotAcc, err := n.AccountForDevice(ctx, remoteDeviceID) - if err != nil { - return nil, fmt.Errorf("couldn't get account ID from device [%s]: %w", remoteDeviceID.String(), err) - } - - conn, cancel, err := n.db.Conn(ctx) - if err != nil { - return nil, fmt.Errorf("Cannot connect to internal db: %w", err) - } - defer cancel() - - role, err := sitesql.GetMemberRole(conn, remotAcc) - if (err != nil || role == site.Member_ROLE_UNSPECIFIED) && n.cfg.NoListing { - n.log.Debug("Not serving content to remote peer since is not a site member", zap.String("remote AccountID", remotAcc.String()), - zap.Error(err), zap.Int("Role", int(role))) - return &p2p.ListObjectsResponse{}, nil - } - n.log.Debug("Allowing site content", zap.String("remote AccountID", remotAcc.String()), zap.Int("role", int(role)), zap.Bool("noListing", n.cfg.NoListing)) - } +func (srv *rpcMux) ListObjects(ctx context.Context, in *p2p.ListObjectsRequest) (*p2p.ListObjectsResponse, error) { + n := srv.Node objs := map[hyper.EntityID]*p2p.Object{} diff --git a/backend/mttnet/mttnet.go b/backend/mttnet/mttnet.go index acc08fda75..fd9413c151 100644 --- a/backend/mttnet/mttnet.go +++ b/backend/mttnet/mttnet.go @@ -3,22 +3,17 @@ package mttnet import ( "context" - "crypto/rand" - "encoding/base64" "fmt" "io" "mintter/backend/config" "mintter/backend/core" - site "mintter/backend/genproto/documents/v1alpha" + groups "mintter/backend/genproto/groups/v1alpha" p2p "mintter/backend/genproto/p2p/v1alpha" "mintter/backend/hyper" "mintter/backend/hyper/hypersql" "mintter/backend/ipfs" - "mintter/backend/mttnet/sitesql" "mintter/backend/pkg/cleanup" - "mintter/backend/pkg/future" "mintter/backend/pkg/must" - "strings" "time" "crawshaw.io/sqlite" @@ -56,6 +51,18 @@ const ( var userAgent = "mintter/